relay

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: AGPL-3.0 Imports: 10 Imported by: 0

Documentation

Overview

Package relay 是转发内核:把客户端方言的请求体转换成上游方言,把上游的响应体 转换回客户端方言,并在两个方向上原样带出转换损耗的诊断。

内核是纯函数式的,不发网络请求、不读配置:上游地址、鉴权、重试都在 channel 与 server 层。同方言不走转换,本包在两方言相同时直接返回 passthrough 标记, 只按字节定点改顶层 model 一个字段而不重新序列化 —— 逐字节保留未建模字段只有 在不经过 JSON 往返时才成立。

Index

Constants

View Source
const DefaultClaudeMaxTokens = 4096

DefaultClaudeMaxTokens 是 OpenAI 或 Gemini 转 Claude 时,源请求未带 max_tokens 时补的默认值。Claude Messages 要求该字段,缺失即 400。

Variables

View Source
var ErrSameDialect = errors.New("relay: 源方言与目标方言相同,应按字节透传")

ErrSameDialect 表示两个方言相同,无需转换。

Functions

func SetMediaResolver

func SetMediaResolver(resolver MediaResolver)

SetMediaResolver 注册媒体解析能力。

这是一个进程级的全局设置,只能在启动阶段调用一次。它与 RelayKit 的对应函数是 同一个开关,因此同一进程内只需要有一处设置。核心包提供这个入口,是为了让调用方 不必自己依赖 RelayKit。

Types

type Diagnostic

type Diagnostic struct {
	// Code 是机器可读的原因标识。
	Code string
	// Path 是出问题的字段路径,可能为空。
	Path string
	// Message 是给人看的说明。
	Message string
	// Severity 是级别。
	Severity Severity
	// From 与 To 是这一跳的源方言与目标方言。
	From dialect.Name
	To   dialect.Name
}

Diagnostic 是一条转换损耗。

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine 是转换内核。可以并发使用。

func NewEngine

func NewEngine(opts Options) *Engine

NewEngine 按选项创建内核。

func (*Engine) NewStream

func (e *Engine) NewStream(from, to dialect.Name, originModel, upstreamModel string, opts StreamOptions) (*Stream, error)

NewStream 创建转换会话。

from 是渠道方言,to 是客户端方言。两方言相同时返回 ErrSameDialect:那种情况 应当按字节管道转发,经过 JSON 往返会丢掉未建模字段。

func (*Engine) ParseModel

func (e *Engine) ParseModel(model string) (string, *Reasoning)

ParseModel 按需剥离模型名尾缀。

未打开 ModelSuffix 时原样返回,状态为 nil。打开时识别各家已知尾缀,返回 基础模型名与推理状态;识别不出尾缀时同样原样返回。

调用方应当用返回的基础模型名去匹配路由规则,再去发请求。

func (*Engine) PrepareRequest

func (e *Engine) PrepareRequest(ctx context.Context, req Request) (*Prepared, error)

PrepareRequest 生成发给上游的请求体。

两方言相同时返回 Passthrough 为真的结果,不做 DTO 建模;但只要规则给了与 客户端模型名不同的上游名,顶层 model 字段仍会被定点改写,见 setModelField。

func (*Engine) PrepareResponse

func (e *Engine) PrepareResponse(ctx context.Context, resp Response) (*PreparedResponse, error)

PrepareResponse 把上游非流式响应转换回客户端方言。

type LossPolicy

type LossPolicy string

LossPolicy 决定请求转换遇到工具语义损耗时怎么处理。

const (
	// LossPolicyAllow 是默认值:照常完成转换,每条损耗都记进诊断。
	LossPolicyAllow LossPolicy = "allow"
	// LossPolicySafe 在 error 级诊断时把请求转换判为失败。
	LossPolicySafe LossPolicy = "safe"
	// LossPolicyStrict 在任何诊断下都把请求转换判为失败。
	LossPolicyStrict LossPolicy = "strict"
)

type MediaResolver

type MediaResolver struct {
	// GetBase64Data 按来源取回内容,返回 base64 数据与它的 MIME 类型。
	GetBase64Data func(ctx context.Context, source MediaSource) (base64Data string, mimeType string, err error)
	// DecodeBase64FileData 解析一段 data URL,返回它的 MIME 类型与 base64 数据。
	DecodeBase64FileData func(dataURL string) (mimeType string, base64Data string, err error)
}

MediaResolver 提供跨协议转换时需要下载图片与解析 data URL 的能力。

内核本身不发网络请求:两个回调都由宿主提供。缺少回调时,需要媒体解析的转换 会明确报错,而不是静默丢掉内容。

type MediaSource

type MediaSource struct {
	// URL 是图片来源地址,需要取回内容。
	URL string
	// Data 是内联的 base64 内容,不含 data URL 前缀。
	Data string
	// MimeType 是内联内容声明的类型,可能为空。
	MimeType string
}

MediaSource 是一次媒体解析请求的来源。

URL 与 Data 只会有一个非空:URL 表示内容要自己去取,Data 是内联的 base64。

func (MediaSource) Identifier

func (m MediaSource) Identifier() string

Identifier 返回可用于日志与报错的简短标识。

func (MediaSource) IsURL

func (m MediaSource) IsURL() bool

IsURL 报告内容是否需要自己取回。

type Options

type Options struct {
	// ToolLossPolicy 决定请求转换遇到工具语义损耗时是否报错。默认 allow:
	// 照常完成并把每条损耗写进诊断。响应与流式转换不受该策略影响。
	ToolLossPolicy LossPolicy
	// DefaultMaxTokens 返回源请求未带 max_tokens 时给 Claude 补的值。
	// 为 nil 时用 DefaultClaudeMaxTokens。
	DefaultMaxTokens func(model string) int
	// ThinkingAdapter 打开推理设置的渲染。模型名尾缀仍由 ParseModel 先行剥离。
	ThinkingAdapter bool
	// ModelSuffix 打开模型名尾缀识别。打开时 ParseModel 才会剥离
	// -thinking / -nothinking / -high 这类尾缀。
	ModelSuffix bool
}

Options 是内核的行为开关。零值可用,此时只做无附加适配的协议转换。

type Prepared

type Prepared struct {
	// Passthrough 为真时 Body 是客户端原始报文字节(可能只改过顶层 model 一个
	// 字段),未做 DTO 建模。
	Passthrough bool
	// Body 是发给上游的请求体。
	Body []byte
	// Stream 是客户端请求的流式意图。
	Stream bool
	// contains filtered or unexported fields
}

Prepared 是转换后的上游请求。

func (*Prepared) Diagnostics

func (p *Prepared) Diagnostics() []Diagnostic

Diagnostics 返回请求转换产生的诊断。Passthrough 为真时返回空。

func (*Prepared) Report

func (p *Prepared) Report() Report

Report 说明这次转换是怎么完成的。Passthrough 为真时返回零值。

type PreparedResponse

type PreparedResponse struct {
	// Passthrough 为真时 Body 是上游原始报文字节,未做解析。
	Passthrough bool
	// Body 是发给客户端的响应体。
	Body []byte
	// Usage 是归一后的用量,可能为 nil。
	//
	// 这个字段用的是 RelayKit 的类型,理由见 docs/relay.md 的
	// 「与 RelayKit 的关系」:镜像用量结构只会带来漂移。
	Usage *dto.Usage
	// contains filtered or unexported fields
}

PreparedResponse 是转换后的非流式响应。

func (*PreparedResponse) Diagnostics

func (p *PreparedResponse) Diagnostics() []Diagnostic

Diagnostics 返回响应转换产生的诊断。Passthrough 为真时返回空。

func (*PreparedResponse) Report

func (p *PreparedResponse) Report() Report

Report 说明这次转换是怎么完成的。Passthrough 为真时返回零值。

type Quality

type Quality string

Quality 是转换质量的等级。

const (
	// QualityGood 表示两种协议的核心结构较接近。
	QualityGood Quality = "good"
	// QualityFair 表示主要内容能转,协议独有字段以诊断形式报出。
	QualityFair Quality = "fair"
	// QualityDiscouraged 表示需要经过中间协议转换,语义损失风险更高。
	QualityDiscouraged Quality = "discouraged"
)

type Reasoning

type Reasoning struct {
	// Mode 是推理模式,例如 thinking 或 nothinking。
	Mode string
	// Effort 是推理强度,例如 low、medium、high。
	Effort string
	// BudgetTokens 是推理预算的 token 数。
	BudgetTokens *int
	// IncludeThoughts 表示是否要求把推理内容写进响应。
	IncludeThoughts *bool
}

Reasoning 是模型名尾缀解析出的推理设置。

type Report

type Report struct {
	// Converter 是所选转换器的标识。
	Converter string
	// Quality 是转换质量的等级。
	Quality Quality
	// Steps 是实际经过的转换跳;直接转换只有一跳。
	Steps []Step
	// From 与 To 是整个转换的源方言与目标方言。
	From dialect.Name
	To   dialect.Name
}

Report 说明一次转换实际是怎么完成的。

type Request

type Request struct {
	From          dialect.Name
	To            dialect.Name
	Body          []byte
	OriginModel   string
	UpstreamModel string
	Stream        bool
}

Request 描述一次待转换的请求。

UpstreamModel 是发往上游的模型名,由调用方从配置的路由规则算出;为空时沿用 OriginModel。OriginModel 是客户端请求的模型名,用于推理状态判断与诊断。

Stream 是调用方从请求行或路径得到的流式意图。Gemini 的流式只体现在路径上 (:streamGenerateContent),请求体里没有该字段,因此这个方言必须由调用方给出; 另外三方言以请求体为准,体里没写时才用本字段。

Body 会被完整读入内存后解析,调用方负责限制其大小。

type Response

type Response struct {
	From          dialect.Name
	To            dialect.Name
	Body          []byte
	OriginModel   string
	UpstreamModel string
}

Response 描述一次待转换的非流式响应。From 是渠道方言,To 是客户端方言。

type Severity

type Severity string

Severity 是诊断的级别。

const (
	// SeverityWarning 表示转换完成但丢了信息。
	SeverityWarning Severity = "warning"
	// SeverityError 表示转换丢了会影响执行语义的信息。
	SeverityError Severity = "error"
)

type Step

type Step struct {
	// Converter 是这一跳所用的转换器标识。
	Converter string
	// From 与 To 是这一跳的源方言与目标方言。
	From dialect.Name
	To   dialect.Name
}

Step 是一次转换跳。

type Stream

type Stream struct {
	// contains filtered or unexported fields
}

Stream 是一条上游流的转换会话。每条上游流对应一个实例,不可并发复用。

func (*Stream) Convert

func (s *Stream) Convert(ctx context.Context, data []byte) ([]dialect.StreamEvent, error)

Convert 转换一条上游流式事件。data 是 SSE 的 data 负载。返回空切片表示这条 事件不承载内容,调用方跳过即可。

meta.IsStream 在会话内固定为真,供上游为 Gemini 的转换路径判断目标请求是否 需要流式字段。

func (*Stream) Diagnostics

func (s *Stream) Diagnostics() []Diagnostic

Diagnostics 返回会话累计的转换损耗。

func (*Stream) Fail

func (s *Stream) Fail(code, message, param string) ([]dialect.StreamEvent, bool)

Fail 在流中途失败时补出错误事件。第二个返回值表示是否补出了事件。

func (*Stream) Finalize

func (s *Stream) Finalize(ctx context.Context) ([]dialect.StreamEvent, error)

Finalize 结束会话,补发终止事件与最终用量。上游流结束后必须调用一次, 否则部分转换路径不会补出终止帧。

func (*Stream) Report

func (s *Stream) Report() Report

Report 说明这次转换是怎么完成的。

func (*Stream) Usage

func (s *Stream) Usage() *dto.Usage

Usage 返回会话累计的用量,可能为 nil。

这个返回值的类型来自 RelayKit,理由见 docs/relay.md 的「与 RelayKit 的关系」。

type StreamOptions

type StreamOptions struct {
	// ID 是转发给客户端的响应 id 前缀。
	ID string
	// Model 是客户端请求的模型名,写进响应信封。
	Model string
	// Created 是响应创建时间(Unix 秒)。
	Created int64
	// IncludeUsage 要求上游在流末尾给出用量。
	IncludeUsage bool
	// EmitSequenceNumber 打开 OpenAI Responses 的 sequence_number 字段。
	EmitSequenceNumber bool
}

StreamOptions 是流式转换会话的创建参数,取自客户端请求里与响应信封相关的字段。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL