初始提交:OCI 面板后端(含 GenAI 网关一期)

This commit is contained in:
Wang Defa
2026-07-09 15:31:04 +08:00
commit b9a3e97e84
168 changed files with 31794 additions and 0 deletions
+165
View File
@@ -0,0 +1,165 @@
package aiwire
import (
"encoding/json"
"strings"
)
// MessagesRequest 是 Anthropic /v1/messages 请求体。
type MessagesRequest struct {
Model string `json:"model"`
MaxTokens int `json:"max_tokens"`
System json.RawMessage `json:"system,omitempty"`
Messages []AnthMessage `json:"messages"`
StopSequences []string `json:"stop_sequences,omitempty"`
Temperature *float64 `json:"temperature,omitempty"`
TopP *float64 `json:"top_p,omitempty"`
TopK *int `json:"top_k,omitempty"`
Stream bool `json:"stream,omitempty"`
Tools []AnthTool `json:"tools,omitempty"`
ToolChoice json.RawMessage `json:"tool_choice,omitempty"`
Metadata json.RawMessage `json:"metadata,omitempty"`
Thinking json.RawMessage `json:"thinking,omitempty"`
}
// SystemText 把顶层 system(string 或块数组)拍平为文本。
func (r MessagesRequest) SystemText() string {
if len(r.System) == 0 {
return ""
}
var s string
if err := json.Unmarshal(r.System, &s); err == nil {
return s
}
var blocks []AnthBlock
if err := json.Unmarshal(r.System, &blocks); err != nil {
return ""
}
var sb strings.Builder
for _, b := range blocks {
if b.Type == "text" {
sb.WriteString(b.Text)
}
}
return sb.String()
}
// AnthMessage 是 Anthropic 消息;Content 兼容 string 与块数组。
type AnthMessage struct {
Role string `json:"role"`
Content AnthContent `json:"content"`
}
// AnthContent 是 string | []AnthBlock 联合。
type AnthContent struct {
Text string
Blocks []AnthBlock
isArray bool
}
func (c *AnthContent) 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.Blocks)
}
return json.Unmarshal(b, &c.Text)
}
func (c AnthContent) MarshalJSON() ([]byte, error) {
if c.isArray {
return json.Marshal(c.Blocks)
}
return json.Marshal(c.Text)
}
// AllBlocks 统一为块数组视图(字符串形态包装为单 text 块)。
func (c AnthContent) AllBlocks() []AnthBlock {
if c.isArray {
return c.Blocks
}
if c.Text == "" {
return nil
}
return []AnthBlock{{Type: "text", Text: c.Text}}
}
// AnthBlock 是内容块;按 Type 取字段(text / tool_use / tool_result / image / thinking)。
type AnthBlock struct {
Type string `json:"type"`
Text string `json:"text,omitempty"`
// tool_use
ID string `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Input json.RawMessage `json:"input,omitempty"`
// tool_result
ToolUseID string `json:"tool_use_id,omitempty"`
Content json.RawMessage `json:"content,omitempty"`
IsError bool `json:"is_error,omitempty"`
// image
Source json.RawMessage `json:"source,omitempty"`
}
// ResultText 把 tool_result 的 content(string 或块数组)拍平为文本。
func (b AnthBlock) ResultText() string {
if len(b.Content) == 0 {
return ""
}
var s string
if err := json.Unmarshal(b.Content, &s); err == nil {
return s
}
var blocks []AnthBlock
if err := json.Unmarshal(b.Content, &blocks); err != nil {
return string(b.Content)
}
var sb strings.Builder
for _, blk := range blocks {
if blk.Type == "text" {
sb.WriteString(blk.Text)
}
}
return sb.String()
}
// AnthTool 是 Anthropic 工具定义(input_schema 即 JSON Schema)。
type AnthTool struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
InputSchema json.RawMessage `json:"input_schema,omitempty"`
}
// MessagesResponse 是非流式响应体。
type MessagesResponse struct {
ID string `json:"id"`
Type string `json:"type"`
Role string `json:"role"`
Model string `json:"model"`
Content []AnthBlock `json:"content"`
StopReason string `json:"stop_reason"`
StopSequence *string `json:"stop_sequence"`
Usage AnthUsage `json:"usage"`
}
// AnthUsage 是 Anthropic 用量结构。
type AnthUsage struct {
InputTokens int `json:"input_tokens"`
OutputTokens int `json:"output_tokens"`
// CacheReadInputTokens 是缓存命中读取数;OCI 隐式缓存无「写入」计数,cache_creation 恒缺
CacheReadInputTokens int `json:"cache_read_input_tokens,omitempty"`
}
// AnthErrorBody 是 Anthropic 格式错误响应。
type AnthErrorBody struct {
Type string `json:"type"`
Error AnthErrorDetail `json:"error"`
}
// AnthErrorDetail 是错误明细。
type AnthErrorDetail struct {
Type string `json:"type"`
Message string `json:"message"`
}