22
33# Adapted from 
44# https://github.com/lm-sys/FastChat/blob/168ccc29d3f7edc50823016105c024fe2282732a/fastchat/protocol/openai_api_protocol.py 
5+ import  json 
56import  re 
67import  time 
78from  argparse  import  Namespace 
@@ -139,12 +140,30 @@ class JsonSchemaResponseFormat(OpenAIBaseModel):
139140    strict : Optional [bool ] =  None 
140141
141142
143+ class  StructuralTag (OpenAIBaseModel ):
144+     begin : str 
145+     # schema is the field, but that causes conflicts with pydantic so 
146+     # instead use structural_tag_schema with an alias 
147+     structural_tag_schema : Optional [dict [str , Any ]] =  Field (default = None ,
148+                                                             alias = "schema" )
149+     end : str 
150+ 
151+ 
152+ class  StructuralTagResponseFormat (OpenAIBaseModel ):
153+     type : Literal ["structural_tag" ]
154+     structures : list [StructuralTag ]
155+     triggers : list [str ]
156+ 
157+ 
142158class  ResponseFormat (OpenAIBaseModel ):
143-     # type must be "json_schema", "json_object" or "text" 
159+     # type must be "json_schema", "json_object",  or "text" 
144160    type : Literal ["text" , "json_object" , "json_schema" ]
145161    json_schema : Optional [JsonSchemaResponseFormat ] =  None 
146162
147163
164+ AnyResponseFormat  =  Union [ResponseFormat , StructuralTagResponseFormat ]
165+ 
166+ 
148167class  StreamOptions (OpenAIBaseModel ):
149168    include_usage : Optional [bool ] =  True 
150169    continuous_usage_stats : Optional [bool ] =  False 
@@ -227,7 +246,7 @@ class ChatCompletionRequest(OpenAIBaseModel):
227246    max_completion_tokens : Optional [int ] =  None 
228247    n : Optional [int ] =  1 
229248    presence_penalty : Optional [float ] =  0.0 
230-     response_format : Optional [ResponseFormat ] =  None 
249+     response_format : Optional [AnyResponseFormat ] =  None 
231250    seed : Optional [int ] =  Field (None , ge = _LONG_INFO .min , le = _LONG_INFO .max )
232251    stop : Optional [Union [str , list [str ]]] =  Field (default_factory = list )
233252    stream : Optional [bool ] =  False 
@@ -340,6 +359,11 @@ class ChatCompletionRequest(OpenAIBaseModel):
340359        description = (
341360            "If specified, the output will follow the context free grammar." ),
342361    )
362+     structural_tag : Optional [str ] =  Field (
363+         default = None ,
364+         description = (
365+             "If specified, the output will follow the structural tag schema." ),
366+     )
343367    guided_decoding_backend : Optional [str ] =  Field (
344368        default = None ,
345369        description = (
@@ -476,6 +500,12 @@ def to_sampling_params(
476500                json_schema  =  self .response_format .json_schema 
477501                assert  json_schema  is  not None 
478502                self .guided_json  =  json_schema .json_schema 
503+             elif  self .response_format .type  ==  "structural_tag" :
504+                 structural_tag  =  self .response_format 
505+                 assert  structural_tag  is  not None  and  isinstance (
506+                     structural_tag , StructuralTagResponseFormat )
507+                 s_tag_obj  =  structural_tag .model_dump (by_alias = True )
508+                 self .structural_tag  =  json .dumps (s_tag_obj )
479509
480510        guided_decoding  =  GuidedDecodingParams .from_optional (
481511            json = self ._get_guided_json_from_tool () or  self .guided_json ,
@@ -485,6 +515,7 @@ def to_sampling_params(
485515            json_object = guided_json_object ,
486516            backend = self .guided_decoding_backend ,
487517            whitespace_pattern = self .guided_whitespace_pattern ,
518+             structural_tag = self .structural_tag ,
488519        )
489520
490521        return  SamplingParams .from_optional (
@@ -742,12 +773,13 @@ class CompletionRequest(OpenAIBaseModel):
742773            "If true (the default), special tokens (e.g. BOS) will be added to " 
743774            "the prompt." ),
744775    )
745-     response_format : Optional [ResponseFormat ] =  Field (
776+     response_format : Optional [AnyResponseFormat ] =  Field (
746777        default = None ,
747-         description = 
748-         ("Similar to chat completion, this parameter specifies the format of " 
749-          "output. Only {'type': 'json_object'}, {'type': 'json_schema'} or " 
750-          "{'type': 'text' } is supported." ),
778+         description = (
779+             "Similar to chat completion, this parameter specifies the format " 
780+             "of output. Only {'type': 'json_object'}, {'type': 'json_schema'}" 
781+             ", {'type': 'structural_tag'}, or {'type': 'text' } is supported." 
782+         ),
751783    )
752784    guided_json : Optional [Union [str , dict , BaseModel ]] =  Field (
753785        default = None ,
0 commit comments