docs(comments): 注释中文化 · internal/runtime/model + internal/services/backthink(54 文件,纯替换)
- 只翻注释/文档字符串:`go/scanner` 剥注释后按 token 序列+literal 逐 token 比对,**54/54 文件 SAME**;
改动文件总行数与 HEAD 漂移 = 0(严格 1:1,无合并/拆行)
- 裁决编号与 design 节号逐字保留(03.4.1/03.4.2/03.4.3/14.4.1/14.4.5/07.4.2-4、design/04 §3.1/§3.2 等);
`chat_template_kwargs` / `enable_thinking` / `reasoning_effort` / `thinking:{type}` 字段名与形状说明未动
- 存疑译法(已登记):`persona` 在叙事语境用「角色」、标识符语境保留 `persona`(仓库既有模块本身混用);
`rung`→「级」;`provider` 存在「提供商/提供者」两种落笔(可按需一键统一)
- 复核:build/vet 绿 + 两包测试绿;gofmt 干净;残留英文注释 0 条
- 既有存量(未修,只报告):`model/anthropic_test.go` 612 行 >500;`applyAnthropicEvent` 115 行 >80
This commit is contained in:
1 parent
f5cf117482
commit
3dc1232bc2
54 files changed
+1923
-1923
No files matched your search
@@ -14,25 +14,25 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
||||
)
|
||||
|
||||
// Wire constraints for the OpenAI-compatible /chat/completions protocol.
|
||||
// OpenAI 兼容 /chat/completions 协议的线格式约束。
|
||||
const (
|
||||
// sseDataPrefix marks an SSE event line carrying a JSON payload.
|
||||
// sseDataPrefix 标记携带 JSON 负载的 SSE 事件行。
|
||||
sseDataPrefix = "data: "
|
||||
// sseDone is the terminal SSE sentinel.
|
||||
// sseDone 是终止用的 SSE 哨兵。
|
||||
sseDone = "[DONE]"
|
||||
// sseBufInit is the initial bufio.Scanner read buffer size.
|
||||
// sseBufInit 是 bufio.Scanner 的初始读缓冲大小。
|
||||
sseBufInit = 64 * 1024
|
||||
// maxSSELineBytes caps a single SSE event line.
|
||||
// maxSSELineBytes 限制单条 SSE 事件行的长度。
|
||||
maxSSELineBytes = 1024 * 1024
|
||||
// errBodyCap bounds how much of an error body is read for the message.
|
||||
// errBodyCap 限制为取出消息而读取的错误响应体大小。
|
||||
errBodyCap = 512
|
||||
// defaultHTTPTimeout bounds a single provider call when Options.Timeout is 0.
|
||||
// defaultHTTPTimeout 在 Options.Timeout 为 0 时约束单次提供商调用。
|
||||
defaultHTTPTimeout = 180 * time.Second
|
||||
)
|
||||
|
||||
// OpenAIChatAdapter calls an OpenAI-compatible /chat/completions endpoint. It is
|
||||
// constructed from a config.LLMConfig and implements Adapter for both
|
||||
// non-streaming and token-level SSE streaming.
|
||||
// OpenAIChatAdapter 调用 OpenAI 兼容的 /chat/completions 端点。它由
|
||||
// config.LLMConfig 构建,同时实现非流式与 token 级 SSE 流式的
|
||||
// Adapter。
|
||||
type OpenAIChatAdapter struct {
|
||||
name string
|
||||
baseURL string
|
||||
@@ -40,39 +40,39 @@ type OpenAIChatAdapter struct {
|
||||
model string
|
||||
client *http.Client
|
||||
recorder Recorder
|
||||
// reasoningKind is this endpoint's configured reasoning-switch shape
|
||||
// (models.json group reasoning.kind / LLM_REASONING_KIND, 裁决 03.4.2/08.4.1).
|
||||
// Empty means "auto": infer the vendor from the model name/base URL and send
|
||||
// nothing when the shape is ambiguous.
|
||||
// reasoningKind 是本端点已配置的推理开关形状
|
||||
// (models.json 组的 reasoning.kind / LLM_REASONING_KIND,裁决 03.4.2/08.4.1)。
|
||||
// 为空表示 "auto":按模型名/base URL 推断厂商,
|
||||
// 形状含糊时什么都不发。
|
||||
reasoningKind string
|
||||
// log reports reasoning_effort validation and ignored thinking directives. It
|
||||
// is never nil: a discard logger tagged with this adapter's source is
|
||||
// installed when the caller supplies none, so a decision is always traceable.
|
||||
// log 上报 reasoning_effort 校验与被忽略的思考指令。它
|
||||
// 永不为 nil:调用方未提供时,会装入一个带有本适配器来源
|
||||
// 标记的丢弃式日志器,因此每个决定都可追溯。
|
||||
log *slog.Logger
|
||||
}
|
||||
|
||||
// OpenAIOption configures an OpenAIChatAdapter.
|
||||
// OpenAIOption 用于配置 OpenAIChatAdapter。
|
||||
type OpenAIOption func(*OpenAIChatAdapter)
|
||||
|
||||
// WithHTTPClient overrides the default HTTP client (used to inject mocks or a
|
||||
// tuned transport in tests and production).
|
||||
// WithHTTPClient 覆盖默认 HTTP 客户端(用于在测试与生产中
|
||||
// 注入 mock 或调优过的 transport)。
|
||||
func WithHTTPClient(c *http.Client) OpenAIOption {
|
||||
return func(a *OpenAIChatAdapter) { a.client = c }
|
||||
}
|
||||
|
||||
// WithRecorder wires a per-call Recorder for CallRecord accounting.
|
||||
// WithRecorder 装入按调用计账的 Recorder,用于 CallRecord 统计。
|
||||
func WithRecorder(r Recorder) OpenAIOption {
|
||||
return func(a *OpenAIChatAdapter) { a.recorder = r }
|
||||
}
|
||||
|
||||
// WithModel overrides the adapter's default model name.
|
||||
// WithModel 覆盖适配器的默认模型名。
|
||||
func WithModel(m string) OpenAIOption {
|
||||
return func(a *OpenAIChatAdapter) { a.model = m }
|
||||
}
|
||||
|
||||
// WithOpenAILogger attaches the logger used to report reasoning_effort
|
||||
// validation and ignored thinking directives. A nil logger is ignored so the
|
||||
// discard default stays in place.
|
||||
// WithOpenAILogger 挂上用于上报 reasoning_effort 校验与
|
||||
// 被忽略思考指令的日志器。nil 日志器会被忽略,
|
||||
// 从而保留丢弃式的默认值。
|
||||
func WithOpenAILogger(l *slog.Logger) OpenAIOption {
|
||||
return func(a *OpenAIChatAdapter) {
|
||||
if l != nil {
|
||||
@@ -81,12 +81,12 @@ func WithOpenAILogger(l *slog.Logger) OpenAIOption {
|
||||
}
|
||||
}
|
||||
|
||||
// NewOpenAIChat builds an adapter from a supplier config. baseURL is trimmed of
|
||||
// any trailing slash before the /chat/completions path is appended. The
|
||||
// endpoint's configured reasoning shape (cfg.ReasoningKind) travels with the
|
||||
// adapter so every chain built from the same config — the group's chain, its
|
||||
// per-persona chain and the local rung — resolves its reasoning switches the
|
||||
// same way.
|
||||
// NewOpenAIChat 由供应商配置构建适配器。baseURL 会先去掉
|
||||
// 末尾斜杠,再拼接 /chat/completions 路径。
|
||||
// 端点已配置的推理形状(cfg.ReasoningKind)随
|
||||
// 适配器一起走,因此由同一份配置构建的每条链——组链、
|
||||
// 它的按角色链以及本地级——都以
|
||||
// 相同方式解出自己的推理开关。
|
||||
func NewOpenAIChat(cfg config.LLMConfig, opts ...OpenAIOption) *OpenAIChatAdapter {
|
||||
a := &OpenAIChatAdapter{
|
||||
name: "openai",
|
||||
@@ -106,10 +106,10 @@ func NewOpenAIChat(cfg config.LLMConfig, opts ...OpenAIOption) *OpenAIChatAdapte
|
||||
return a
|
||||
}
|
||||
|
||||
// Name returns the adapter identifier.
|
||||
// Name 返回适配器标识。
|
||||
func (a *OpenAIChatAdapter) Name() string { return a.name }
|
||||
|
||||
// Chat performs a non-streaming completion.
|
||||
// Chat 执行一次非流式补全。
|
||||
func (a *OpenAIChatAdapter) Chat(ctx context.Context, req Request, opts Options) (Response, error) {
|
||||
start := time.Now()
|
||||
if a.baseURL == "" {
|
||||
@@ -147,8 +147,8 @@ func (a *OpenAIChatAdapter) Chat(ctx context.Context, req Request, opts Options)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// ChatStream streams structured events via onEvent and returns the aggregated
|
||||
// response with usage when the provider reports it in the final chunk.
|
||||
// ChatStream 通过 onEvent 流出结构化事件,并在提供商于
|
||||
// 末块上报用量时返回带用量的聚合响应。
|
||||
func (a *OpenAIChatAdapter) ChatStream(ctx context.Context, req Request, onEvent func(StreamEvent)) (Response, error) {
|
||||
start := time.Now()
|
||||
if a.baseURL == "" {
|
||||
@@ -184,7 +184,7 @@ func (a *OpenAIChatAdapter) ChatStream(ctx context.Context, req Request, onEvent
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// withCallTimeout wraps ctx with opts.Timeout when it is positive.
|
||||
// withCallTimeout 在 opts.Timeout 为正时用该超时包裹 ctx。
|
||||
func withCallTimeout(parent context.Context, opts Options) (context.Context, context.CancelFunc) {
|
||||
if opts.Timeout > 0 {
|
||||
return context.WithTimeout(parent, opts.Timeout)
|
||||
@@ -192,7 +192,7 @@ func withCallTimeout(parent context.Context, opts Options) (context.Context, con
|
||||
return parent, func() {}
|
||||
}
|
||||
|
||||
// resolveModel returns the effective model name.
|
||||
// resolveModel 返回实际生效的模型名。
|
||||
func (a *OpenAIChatAdapter) resolveModel(req Request) (string, error) {
|
||||
if req.Model != "" {
|
||||
return req.Model, nil
|
||||
@@ -203,7 +203,7 @@ func (a *OpenAIChatAdapter) resolveModel(req Request) (string, error) {
|
||||
return "", ErrNoModel
|
||||
}
|
||||
|
||||
// endpoint returns the full /chat/completions URL.
|
||||
// endpoint 返回完整的 /chat/completions URL。
|
||||
func (a *OpenAIChatAdapter) endpoint() string {
|
||||
return a.baseURL + "/chat/completions"
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user