75 lines
2.5 KiB
Python
75 lines
2.5 KiB
Python
|
|
from typing import Dict, List, Optional
|
||
|
|
from guardrails.logger import logger
|
||
|
|
from guardrails.types.pydantic import ModelOrListOfModels
|
||
|
|
|
||
|
|
|
||
|
|
# takes processed schema and converts it to a openai tool object
|
||
|
|
def schema_to_tool(schema: Dict) -> dict:
|
||
|
|
tool = {
|
||
|
|
"type": "function",
|
||
|
|
"function": {
|
||
|
|
"name": "gd_response_tool",
|
||
|
|
"description": "A tool for generating responses to guardrails."
|
||
|
|
" It must be called last in every response.",
|
||
|
|
"parameters": schema,
|
||
|
|
"required": schema.get("required") or [],
|
||
|
|
},
|
||
|
|
}
|
||
|
|
return tool
|
||
|
|
|
||
|
|
|
||
|
|
def set_additional_properties_false_iteratively(schema):
|
||
|
|
stack = [schema]
|
||
|
|
while stack:
|
||
|
|
current = stack.pop()
|
||
|
|
if isinstance(current, dict):
|
||
|
|
if "properties" in current:
|
||
|
|
current["required"] = list(
|
||
|
|
current["properties"].keys()
|
||
|
|
) # this has to be set
|
||
|
|
if "maximum" in current:
|
||
|
|
logger.warn("Property maximum is not supported. Dropping")
|
||
|
|
current.pop("maximum") # the api does not like these set
|
||
|
|
if "minimum" in current:
|
||
|
|
logger.warn("Property maximum is not supported. Dropping")
|
||
|
|
current.pop("minimum") # the api does not like these set
|
||
|
|
if "default" in current:
|
||
|
|
logger.warn("Property default is not supported. Marking field Required")
|
||
|
|
current.pop("default") # the api does not like these set
|
||
|
|
for prop in current.values():
|
||
|
|
stack.append(prop)
|
||
|
|
elif isinstance(current, list):
|
||
|
|
for prop in current:
|
||
|
|
stack.append(prop)
|
||
|
|
if (
|
||
|
|
isinstance(current, dict)
|
||
|
|
and "additionalProperties" not in current
|
||
|
|
and "type" in current
|
||
|
|
and current["type"] == "object"
|
||
|
|
):
|
||
|
|
current["additionalProperties"] = False # the api needs these set
|
||
|
|
|
||
|
|
|
||
|
|
def json_function_calling_tool(
|
||
|
|
schema: Dict,
|
||
|
|
tools: Optional[List] = None,
|
||
|
|
) -> List:
|
||
|
|
tools = tools or []
|
||
|
|
tools.append(schema_to_tool(schema)) # type: ignore
|
||
|
|
return tools
|
||
|
|
|
||
|
|
|
||
|
|
def output_format_json_schema(schema: ModelOrListOfModels) -> dict:
|
||
|
|
parsed_schema = schema.model_json_schema() # type: ignore
|
||
|
|
|
||
|
|
set_additional_properties_false_iteratively(parsed_schema)
|
||
|
|
|
||
|
|
return {
|
||
|
|
"type": "json_schema",
|
||
|
|
"json_schema": {
|
||
|
|
"name": parsed_schema["title"],
|
||
|
|
"schema": parsed_schema,
|
||
|
|
"strict": True,
|
||
|
|
}, # type: ignore
|
||
|
|
}
|