优化代码
This commit is contained in:
1 parent
3553790475
commit
eda7e8bc96
23 files changed
+3113
-342
No files matched your search
@@ -1,11 +1,36 @@
|
||||
// Package llm 提供与 OpenAI 兼容接口的大模型通信能力(含视觉与流式)。
|
||||
// Package llm 提供大模型通信能力(含视觉与流式),
|
||||
// 支持 OpenAI Chat Completions 与 Anthropic Messages 两种接口格式。
|
||||
package llm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 接口格式。它决定请求体结构、鉴权头与流式事件的解析方式,
|
||||
// 也是配置里唯一需要用户先选的东西。
|
||||
const (
|
||||
// FormatOpenAI 是 OpenAI Chat Completions 兼容格式(POST {base}/chat/completions)。
|
||||
FormatOpenAI = "openai"
|
||||
// FormatAnthropic 是 Anthropic Messages 兼容格式(POST {base}/v1/messages)。
|
||||
FormatAnthropic = "anthropic"
|
||||
)
|
||||
|
||||
// FormatLabel 返回接口格式的中文名,供界面显示。
|
||||
func FormatLabel(format string) string {
|
||||
switch format {
|
||||
case FormatAnthropic:
|
||||
return "Anthropic 兼容"
|
||||
default:
|
||||
return "OpenAI 兼容"
|
||||
}
|
||||
}
|
||||
|
||||
// Formats 返回全部受支持的接口格式,顺序即界面下拉顺序。
|
||||
func Formats() []string { return []string{FormatOpenAI, FormatAnthropic} }
|
||||
|
||||
// Role 是消息角色。
|
||||
type Role string
|
||||
|
||||
@@ -36,12 +61,21 @@ func (u *Usage) Add(o Usage) {
|
||||
u.TotalTokens += o.TotalTokens
|
||||
}
|
||||
|
||||
// DeltaFunc 接收流式增量文本,返回 error 可中断请求。
|
||||
type DeltaFunc func(delta string) error
|
||||
// Delta 是一次流式增量。
|
||||
// Text 是正式回答,Reasoning 是模型吐出来的思考过程;两者都按原样透传,
|
||||
// 服务端吐什么、界面就显示什么。
|
||||
type Delta struct {
|
||||
Text string
|
||||
Reasoning string
|
||||
}
|
||||
|
||||
// Options 描述一个模型接入点。
|
||||
// DeltaFunc 接收流式增量,返回 error 可中断请求。
|
||||
type DeltaFunc func(delta Delta) error
|
||||
|
||||
// Options 描述一个模型的接入参数。
|
||||
type Options struct {
|
||||
Name string
|
||||
Format string
|
||||
BaseURL string
|
||||
APIKey string
|
||||
Model string
|
||||
@@ -51,7 +85,6 @@ type Options struct {
|
||||
}
|
||||
|
||||
// Provider 是大模型服务的最小抽象。
|
||||
// 目前只有 OpenAI 兼容实现,其它私有协议按此接口新增即可。
|
||||
type Provider interface {
|
||||
// Chat 发起一次流式对话,system 为系统提示词。
|
||||
Chat(ctx context.Context, system string, msgs []Message, fn DeltaFunc) (Usage, error)
|
||||
@@ -59,13 +92,33 @@ type Provider interface {
|
||||
Ping(ctx context.Context) error
|
||||
}
|
||||
|
||||
// New 根据接入点创建 Provider。
|
||||
// New 根据模型配置创建 Provider,按 Format 分派到对应协议实现。
|
||||
func New(opts Options) (Provider, error) {
|
||||
if opts.BaseURL == "" {
|
||||
return nil, fmt.Errorf("模型接入点缺少 BaseURL")
|
||||
return nil, fmt.Errorf("模型配置缺少 BaseURL")
|
||||
}
|
||||
if opts.Model == "" {
|
||||
return nil, fmt.Errorf("模型接入点 %s 缺少 model", opts.Name)
|
||||
return nil, fmt.Errorf("模型 %s 缺少模型名", opts.Name)
|
||||
}
|
||||
switch opts.Format {
|
||||
case "", FormatOpenAI:
|
||||
return newOpenAI(opts), nil
|
||||
case FormatAnthropic:
|
||||
return newAnthropic(opts), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("未知的接口格式 %q", opts.Format)
|
||||
}
|
||||
}
|
||||
|
||||
// newHTTPClient 返回不设总超时的客户端:流式响应可能持续很久,由 ctx 控制。
|
||||
func newHTTPClient() *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
MaxIdleConns: 8,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
ForceAttemptHTTP2: true,
|
||||
TLSHandshakeTimeout: 15 * time.Second,
|
||||
},
|
||||
}
|
||||
return newOpenAI(opts), nil
|
||||
}
|
||||
Reference in new issue
Block a user