1616class RequestTransformer :
1717 """Трансформер запросов из OpenAI в GigaChat формат"""
1818
19+ @staticmethod
20+ def _resolve_schema_refs (schema : Dict [str , Any ]) -> Dict [str , Any ]:
21+ """
22+ Разрешает $ref ссылки и anyOf/oneOf в JSON schema.
23+ GigaChat не поддерживает $ref/$defs и anyOf/oneOf, поэтому нужно
24+ развернуть схему и упростить Optional типы.
25+ """
26+
27+ def resolve (obj : Any , defs : Dict [str , Any ]) -> Any :
28+ if isinstance (obj , dict ):
29+ # Handle $ref
30+ if "$ref" in obj :
31+ ref_path = obj ["$ref" ]
32+ # Parse reference like '#/$defs/Step'
33+ if ref_path .startswith ("#/$defs/" ):
34+ ref_name = ref_path .split ("/" )[- 1 ]
35+ if ref_name in defs :
36+ # Return resolved definition (recursively resolve)
37+ resolved = defs [ref_name ].copy ()
38+ return resolve (resolved , defs )
39+ return obj
40+
41+ # Handle anyOf/oneOf (typically from Optional types)
42+ # Pydantic generates: anyOf: [{actual_type}, {type: "null"}]
43+ for union_key in ("anyOf" , "oneOf" ):
44+ if union_key in obj :
45+ variants = obj [union_key ]
46+ # Find non-null variant
47+ non_null_variants = [
48+ v for v in variants if v .get ("type" ) != "null"
49+ ]
50+ if non_null_variants :
51+ # Take the first non-null variant and merge with other props
52+ result = resolve (non_null_variants [0 ], defs )
53+ # Preserve other properties like 'default', 'title', 'description'
54+ for key , value in obj .items ():
55+ if (
56+ key not in (union_key , "$defs" )
57+ and key not in result
58+ ):
59+ result [key ] = resolve (value , defs )
60+ return result
61+ # If all are null, just return null type
62+ return {"type" : "null" }
63+
64+ # Recursively process dict, skipping $defs
65+ return {
66+ key : resolve (value , defs )
67+ for key , value in obj .items ()
68+ if key != "$defs"
69+ }
70+
71+ elif isinstance (obj , list ):
72+ return [resolve (item , defs ) for item in obj ]
73+
74+ return obj
75+
76+ defs = schema .get ("$defs" , {})
77+ return resolve (schema , defs )
78+
1979 @staticmethod
2080 def _ensure_json_object_str (value : Any ) -> str :
2181 """
@@ -247,10 +307,13 @@ def _apply_json_schema_as_function(
247307 transformed : Dict , schema_name : str , schema : Dict
248308 ) -> None :
249309 """Применяет JSON schema как function call для structured output"""
310+ # Разрешаем $ref/$defs ссылки, т.к. GigaChat их не поддерживает
311+ resolved_schema = RequestTransformer ._resolve_schema_refs (schema )
312+
250313 function_def = {
251314 "name" : schema_name ,
252315 "description" : f"Output response in structured format: { schema_name } " ,
253- "parameters" : schema ,
316+ "parameters" : resolved_schema ,
254317 }
255318
256319 if "functions" not in transformed :
@@ -271,6 +334,7 @@ def transform_chat_parameters(self, data: Dict) -> Dict:
271334 schema = json_schema .get ("schema" )
272335 self ._apply_json_schema_as_function (transformed , schema_name , schema )
273336 else :
337+ print (response_format )
274338 transformed ["response_format" ] = {
275339 "type" : response_format .get ("type" ),
276340 ** response_format .get ("json_schema" , {}),
0 commit comments