Added support for OpenAI-compatible structured output
This commit is contained in:
@@ -113,6 +113,13 @@ func (c *OpenAICompatibleClient) Generate(ctx context.Context, req domain.Genera
|
||||
if req.Target.TopP != 0 {
|
||||
wireReq.TopP = &req.Target.TopP
|
||||
}
|
||||
if req.StructuredOutput != nil {
|
||||
responseFormat, err := toOpenAIResponseFormat(req.StructuredOutput)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: %v", ErrInvalidRequest, err)
|
||||
}
|
||||
wireReq.ResponseFormat = responseFormat
|
||||
}
|
||||
|
||||
payload, err := json.Marshal(wireReq)
|
||||
if err != nil {
|
||||
@@ -181,11 +188,12 @@ func (c *OpenAICompatibleClient) Generate(ctx context.Context, req domain.Genera
|
||||
}
|
||||
|
||||
type openAIChatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []openAIChatMessage `json:"messages"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
MaxTokens *int `json:"max_tokens,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
Model string `json:"model"`
|
||||
Messages []openAIChatMessage `json:"messages"`
|
||||
Temperature *float64 `json:"temperature,omitempty"`
|
||||
MaxTokens *int `json:"max_tokens,omitempty"`
|
||||
TopP *float64 `json:"top_p,omitempty"`
|
||||
ResponseFormat *openAIResponseFormat `json:"response_format,omitempty"`
|
||||
}
|
||||
|
||||
type openAIChatMessage struct {
|
||||
@@ -203,3 +211,43 @@ type openAIChatResponse struct {
|
||||
TotalTokens int `json:"total_tokens"`
|
||||
} `json:"usage"`
|
||||
}
|
||||
|
||||
type openAIResponseFormat struct {
|
||||
Type string `json:"type"`
|
||||
JSONSchema *openAIJSONSchemaEnvelope `json:"json_schema,omitempty"`
|
||||
}
|
||||
|
||||
type openAIJSONSchemaEnvelope struct {
|
||||
Name string `json:"name"`
|
||||
Strict bool `json:"strict"`
|
||||
Schema any `json:"schema"`
|
||||
}
|
||||
|
||||
func toOpenAIResponseFormat(spec *domain.StructuredOutputSpec) (*openAIResponseFormat, error) {
|
||||
if spec == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
switch spec.Type {
|
||||
case domain.StructuredOutputJSONSchema:
|
||||
if spec.JSONSchema == nil {
|
||||
return nil, errors.New("json_schema structured output requires schema payload")
|
||||
}
|
||||
if strings.TrimSpace(spec.JSONSchema.Name) == "" {
|
||||
return nil, errors.New("json_schema structured output requires non-empty schema name")
|
||||
}
|
||||
if spec.JSONSchema.Schema == nil {
|
||||
return nil, errors.New("json_schema structured output requires schema document")
|
||||
}
|
||||
return &openAIResponseFormat{
|
||||
Type: "json_schema",
|
||||
JSONSchema: &openAIJSONSchemaEnvelope{
|
||||
Name: spec.JSONSchema.Name,
|
||||
Strict: spec.JSONSchema.Strict,
|
||||
Schema: spec.JSONSchema.Schema,
|
||||
},
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported structured output type %q", spec.Type)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user