// Package aiwire 定义 AI 网关的线格式类型:OpenAI Chat Completions(兼作网关内部 // 中间表示 IR,因 OCI GENERIC 格式即其镜像)与 Anthropic Messages。零内部依赖, // oci 层与 service 层共同引用。 package aiwire import ( "encoding/json" "strings" ) // ChatRequest 是 OpenAI /v1/chat/completions 请求体;TopK 为 OCI/Anthropic 扩展字段。 type ChatRequest struct { Model string `json:"model"` Messages []ChatMessage `json:"messages"` MaxTokens *int `json:"max_tokens,omitempty"` MaxCompletionTokens *int `json:"max_completion_tokens,omitempty"` Temperature *float64 `json:"temperature,omitempty"` TopP *float64 `json:"top_p,omitempty"` TopK *int `json:"top_k,omitempty"` FrequencyPenalty *float64 `json:"frequency_penalty,omitempty"` PresencePenalty *float64 `json:"presence_penalty,omitempty"` Stop StringList `json:"stop,omitempty"` Seed *int `json:"seed,omitempty"` N *int `json:"n,omitempty"` Stream bool `json:"stream,omitempty"` StreamOptions *StreamOptions `json:"stream_options,omitempty"` Tools []Tool `json:"tools,omitempty"` ToolChoice json.RawMessage `json:"tool_choice,omitempty"` ResponseFormat *ResponseFormat `json:"response_format,omitempty"` ReasoningEffort string `json:"reasoning_effort,omitempty"` } // StringList 兼容 OpenAI stop 的 string 与 []string 两种线格式。 type StringList []string func (s *StringList) UnmarshalJSON(b []byte) error { if len(b) > 0 && b[0] == '"' { var one string if err := json.Unmarshal(b, &one); err != nil { return err } *s = StringList{one} return nil } var many []string if err := json.Unmarshal(b, &many); err != nil { return err } *s = many return nil } // StreamOptions 控制流式末尾是否附带 usage 事件。 type StreamOptions struct { IncludeUsage bool `json:"include_usage"` } // ChatMessage 是请求与非流式响应共用的消息结构。 type ChatMessage struct { Role string `json:"role"` Content Content `json:"content"` Name string `json:"name,omitempty"` ToolCalls []ToolCall `json:"tool_calls,omitempty"` ToolCallID string `json:"tool_call_id,omitempty"` } // Content 兼容 string 与多模态块数组两种线格式;一期仅透传文本。 type Content struct { // Text 在原始值为字符串时填充 Text string // Parts 在原始值为数组时填充 Parts []ContentPart // isArray 记录原始形态,序列化时保形 isArray bool } // ContentPart 是块数组中的一段;text 与 image_url 被网关处理,其余类型拒绝。 type ContentPart struct { Type string `json:"type"` Text string `json:"text,omitempty"` ImageURL *ImageURL `json:"image_url,omitempty"` } // ImageURL 是 image_url 块负载;url 为 data URI(base64)或公网地址,与 OCI ImageUrl 同构。 type ImageURL struct { URL string `json:"url"` Detail string `json:"detail,omitempty"` } func (c *Content) UnmarshalJSON(b []byte) error { trimmed := strings.TrimSpace(string(b)) if trimmed == "null" { return nil } if len(trimmed) > 0 && trimmed[0] == '[' { c.isArray = true return json.Unmarshal(b, &c.Parts) } return json.Unmarshal(b, &c.Text) } func (c Content) MarshalJSON() ([]byte, error) { if c.isArray { return json.Marshal(c.Parts) } return json.Marshal(c.Text) } // NewTextContent 构造字符串形态的内容。 func NewTextContent(text string) Content { return Content{Text: text} } // NewPartsContent 构造块数组形态的内容(多模态消息用)。 func NewPartsContent(parts []ContentPart) Content { return Content{Parts: parts, isArray: true} } // JoinText 返回全部文本内容(数组形态拼接 text 块)。 func (c Content) JoinText() string { if !c.isArray { return c.Text } var sb strings.Builder for _, p := range c.Parts { if p.Type == "" || p.Type == "text" { sb.WriteString(p.Text) } } return sb.String() } // HasUnsupported 报告是否含网关无法承接的内容块(text / image_url 之外的类型)。 func (c Content) HasUnsupported() bool { for _, p := range c.Parts { switch p.Type { case "", "text": case "image_url": if p.ImageURL == nil || p.ImageURL.URL == "" { return true } default: return true } } return false } // Tool 是 function 工具定义。 type Tool struct { Type string `json:"type"` Function FunctionDef `json:"function"` } // FunctionDef 描述工具的名称与 JSON Schema 参数。 type FunctionDef struct { Name string `json:"name"` Description string `json:"description,omitempty"` Parameters json.RawMessage `json:"parameters,omitempty"` } // ToolCall 是助手消息中的工具调用。 type ToolCall struct { ID string `json:"id"` Type string `json:"type"` Function FunctionCall `json:"function"` } // FunctionCall 携带调用名与 JSON 编码的实参。 type FunctionCall struct { Name string `json:"name"` Arguments string `json:"arguments"` } // ResponseFormat 对应 response_format(json_object / json_schema)。 type ResponseFormat struct { Type string `json:"type"` JSONSchema json.RawMessage `json:"json_schema,omitempty"` } // ChatResponse 是非流式响应体。 type ChatResponse struct { ID string `json:"id"` Object string `json:"object"` Created int64 `json:"created"` Model string `json:"model"` Choices []Choice `json:"choices"` Usage *Usage `json:"usage,omitempty"` } // Choice 是一条候选回复。 type Choice struct { Index int `json:"index"` Message ChatMessage `json:"message"` FinishReason string `json:"finish_reason"` } // Usage 是 token 用量。 type Usage struct { PromptTokens int `json:"prompt_tokens"` CompletionTokens int `json:"completion_tokens"` TotalTokens int `json:"total_tokens"` // PromptTokensDetails 携带缓存命中细分;OCI 为隐式 prompt 缓存,只有读取计数 PromptTokensDetails *PromptTokensDetails `json:"prompt_tokens_details,omitempty"` } // PromptTokensDetails 是输入 token 细分(OpenAI prompt_tokens_details 同构)。 type PromptTokensDetails struct { CachedTokens int `json:"cached_tokens"` } // CachedTokens 返回缓存命中读取的 token 数;无细分时为 0。 func (u *Usage) CachedTokens() int { if u == nil || u.PromptTokensDetails == nil { return 0 } return u.PromptTokensDetails.CachedTokens } // ChatChunk 是流式增量事件体(chat.completion.chunk)。 type ChatChunk struct { ID string `json:"id"` Object string `json:"object"` Created int64 `json:"created"` Model string `json:"model"` Choices []ChunkChoice `json:"choices"` Usage *Usage `json:"usage,omitempty"` } // ChunkChoice 是流式事件中的增量候选。 type ChunkChoice struct { Index int `json:"index"` Delta Delta `json:"delta"` FinishReason *string `json:"finish_reason"` } // Delta 是流式增量内容;Content 为纯文本片段。 type Delta struct { Role string `json:"role,omitempty"` Content string `json:"content,omitempty"` ToolCalls []ToolCallDelta `json:"tool_calls,omitempty"` } // ToolCallDelta 是工具调用的流式片段;Index 标识聚合目标。 type ToolCallDelta struct { Index int `json:"index"` ID string `json:"id,omitempty"` Type string `json:"type,omitempty"` Function FunctionCallDelta `json:"function"` } // FunctionCallDelta 是函数名 / 实参的增量片段。 type FunctionCallDelta struct { Name string `json:"name,omitempty"` Arguments string `json:"arguments,omitempty"` } // Model 是 /v1/models 列表项。 type Model struct { ID string `json:"id"` Object string `json:"object"` Created int64 `json:"created"` OwnedBy string `json:"owned_by"` } // ModelList 是 /v1/models 响应体。 type ModelList struct { Object string `json:"object"` Data []Model `json:"data"` } // ErrorBody 是 OpenAI 格式错误响应。 type ErrorBody struct { Error ErrorDetail `json:"error"` } // ErrorDetail 是错误明细。 type ErrorDetail struct { Message string `json:"message"` Type string `json:"type"` Code string `json:"code,omitempty"` }