Spaces:
Running
Running
| // Copyright 2025 The ODML Authors. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| namespace litert::lm { | |
| namespace { | |
| absl::StatusOr<std::string> FormatObjectAsFc( | |
| const nlohmann::ordered_json& object, absl::string_view escape_tag) { | |
| if (!object.is_object()) { | |
| return absl::InvalidArgumentError( | |
| std::string("Object must be a JSON object. Got: ") + | |
| object.type_name()); | |
| } | |
| std::stringstream ss; | |
| ss << "{"; | |
| int count = 0; | |
| for (const auto& [key, value] : object.items()) { | |
| ASSIGN_OR_RETURN(std::string value_str, FormatValueAsFc(value, escape_tag)); | |
| ss << key << ":" << value_str; | |
| count += 1; | |
| if (count < object.size()) { | |
| ss << ","; | |
| } | |
| } | |
| ss << "}"; | |
| return ss.str(); | |
| } | |
| absl::StatusOr<std::string> FormatArrayAsFc(const nlohmann::ordered_json& array, | |
| absl::string_view escape_tag) { | |
| if (!array.is_array()) { | |
| return absl::InvalidArgumentError( | |
| std::string("Array must be a JSON array. Got ") + array.type_name()); | |
| } | |
| std::stringstream ss; | |
| ss << "["; | |
| int count = 0; | |
| for (const auto& element : array) { | |
| ASSIGN_OR_RETURN(std::string element_str, | |
| FormatValueAsFc(element, escape_tag)); | |
| ss << element_str; | |
| count += 1; | |
| if (count < array.size()) { | |
| ss << ","; | |
| } | |
| } | |
| ss << "]"; | |
| return ss.str(); | |
| } | |
| nlohmann::ordered_json UppercaseTypes(const nlohmann::ordered_json& object) { | |
| nlohmann::ordered_json new_object = object; | |
| if (new_object.is_object()) { | |
| for (auto it = new_object.begin(); it != new_object.end(); ++it) { | |
| if (it.key() == "type" && it.value().is_string()) { | |
| std::string type_str = it.value().get<std::string>(); | |
| if (type_str == "string" || type_str == "number" || | |
| type_str == "integer" || type_str == "object" || | |
| type_str == "array" || type_str == "boolean" || | |
| type_str == "null") { | |
| it.value() = absl::AsciiStrToUpper(type_str); | |
| } | |
| } | |
| // Recursively apply to nested objects and arrays. | |
| if (it.value().is_object() || it.value().is_array()) { | |
| it.value() = UppercaseTypes(it.value()); | |
| } | |
| } | |
| } else if (new_object.is_array()) { | |
| for (auto& element : new_object) { | |
| // Recursively apply to elements that are objects or arrays. | |
| if (element.is_object() || element.is_array()) { | |
| element = UppercaseTypes(element); | |
| } | |
| } | |
| } | |
| return new_object; | |
| } | |
| } // namespace | |
| absl::StatusOr<std::string> FormatValueAsFc(const nlohmann::ordered_json& value, | |
| absl::string_view escape_tag) { | |
| std::stringstream ss; | |
| if (value.is_null()) { | |
| ss << "null"; | |
| } else if (value.is_string()) { | |
| ss << escape_tag << value.get<std::string>() << escape_tag; | |
| } else if (value.is_number()) { | |
| ss << value.dump(); | |
| } else if (value.is_boolean()) { | |
| ss << value.dump(); | |
| } else if (value.is_object()) { | |
| ASSIGN_OR_RETURN(std::string object_str, | |
| FormatObjectAsFc(value, escape_tag)); | |
| ss << object_str; | |
| } else if (value.is_array()) { | |
| ASSIGN_OR_RETURN(std::string array_str, FormatArrayAsFc(value, escape_tag)); | |
| ss << array_str; | |
| } else { | |
| return absl::InvalidArgumentError( | |
| std::string( | |
| "Value is not a supported type. Supported types are null, string, " | |
| "number, boolean, object, array. Got: ") + | |
| value.type_name()); | |
| } | |
| return ss.str(); | |
| } | |
| absl::StatusOr<std::string> FormatToolAsFc(const nlohmann::ordered_json& tool, | |
| absl::string_view escape_tag) { | |
| if (!tool.is_object()) { | |
| return absl::InvalidArgumentError( | |
| std::string("Tool must be a JSON object. Got: ") + tool.type_name()); | |
| } | |
| const nlohmann::ordered_json& function = | |
| tool.contains("function") ? tool["function"] : tool; | |
| if (!function.contains("name") || !function["name"].is_string()) { | |
| return absl::InvalidArgumentError( | |
| "Tool name is required and must be a string."); | |
| } | |
| nlohmann::ordered_json fields = UppercaseTypes(function); | |
| fields.erase("name"); | |
| std::stringstream ss; | |
| ASSIGN_OR_RETURN(std::string fields_str, | |
| FormatObjectAsFc(fields, escape_tag)); | |
| ss << "declaration:" << function["name"].get<std::string>() << fields_str; | |
| return ss.str(); | |
| } | |
| } // namespace litert::lm | |