feat(capability): 转码能力装配进组合根(工具真进注册表、日志带 source)+ design/25 非bit-exact 留痕更正
This commit is contained in:
1 parent
f91a83ff81
commit
c6f5c3fea0
4 files changed
+87
-3
No files matched your search
+8
-3
@@ -11,6 +11,7 @@ import (
|
|||||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/mcp"
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/mcp"
|
||||||
pluginmgr "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/plugin"
|
pluginmgr "git.yeij.top/AskaEth/Cyrene_v2/internal/capability/plugin"
|
||||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
|
||||||
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/transcode"
|
||||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/session"
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/channel/session"
|
||||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/config"
|
||||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/db"
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/db"
|
||||||
@@ -62,9 +63,13 @@ type app struct {
|
|||||||
llm *model.RuntimeLLM
|
llm *model.RuntimeLLM
|
||||||
personas *personareg.Registry
|
personas *personareg.Registry
|
||||||
caps *registry.Registry
|
caps *registry.Registry
|
||||||
dispatcher *tool.Dispatcher
|
// transcoder 是本地转码引擎(design/25):进程内、同步、纯本地,供渠道与其它
|
||||||
memStore *memory.Store
|
// 模块经依赖注入调用;同一个引擎也以 `transcode` 工具注册进 caps。装配只告警、
|
||||||
retriever *memory.Retriever
|
// 绝不阻塞启动,见 wire_transcode.go。
|
||||||
|
transcoder transcode.Transcoder
|
||||||
|
dispatcher *tool.Dispatcher
|
||||||
|
memStore *memory.Store
|
||||||
|
retriever *memory.Retriever
|
||||||
// embedder 与 memoryTidy 属于记忆整理(design/23):整理只在 embedder
|
// embedder 与 memoryTidy 属于记忆整理(design/23):整理只在 embedder
|
||||||
// 上算召回相似度,绝不接触会话/历史读数。
|
// 上算召回相似度,绝不接触会话/历史读数。
|
||||||
embedder embedding.Embedder
|
embedder embedding.Embedder
|
||||||
|
|||||||
@@ -165,6 +165,7 @@ func (a *app) wireRuntime() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
a.wireVision()
|
a.wireVision()
|
||||||
|
a.wireTranscode()
|
||||||
|
|
||||||
// 上下文溢出压缩:预算按模型窗口推导(CONTEXT_MAX_TOKENS 未设置时;
|
// 上下文溢出压缩:预算按模型窗口推导(CONTEXT_MAX_TOKENS 未设置时;
|
||||||
// 显式 >0 = 覆盖、0/负 = 关闭),推导与「窗口未声明」的 WARN 都在
|
// 显式 >0 = 覆盖、0/负 = 关闭),推导与「窗口未声明」的 WARN 都在
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/transcode"
|
||||||
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// transcodeLogSource 是转码能力的日志来源(design/25 §5.3)。引擎自身不带前缀,
|
||||||
|
// 前缀由组合根在这里用 logger.WithSource 接上 —— 漏接则日志无来源,撞
|
||||||
|
// AGENTS §10 红线。
|
||||||
|
const transcodeLogSource = "capability/transcode"
|
||||||
|
|
||||||
|
// wireTranscode 构造本地转码引擎,并把它暴露成能力注册表里的 `transcode` 工具
|
||||||
|
// (design/25 §1.3.2 第二层注册;与 wireVision 同族)。
|
||||||
|
//
|
||||||
|
// 两道失败都**只告警、绝不阻塞启动**:编解码器注册不全(RegistrationError)时引擎
|
||||||
|
// 仍可用已注册的路,工具注册失败(重名等)时能力面缺席、进程内 DI 路径照常。
|
||||||
|
// 转码是可选能力,缺了它其余子系统不受影响,因此这一步没有错误返回值。
|
||||||
|
func (a *app) wireTranscode() {
|
||||||
|
log := logger.WithSource(a.log, transcodeLogSource)
|
||||||
|
tr := transcode.NewEngine(
|
||||||
|
transcode.DefaultLimits(),
|
||||||
|
transcode.WithCodecs(transcode.DefaultCodecs()...),
|
||||||
|
transcode.WithLogger(log),
|
||||||
|
)
|
||||||
|
if err := tr.RegistrationError(); err != nil {
|
||||||
|
log.Warn("transcode codec registration incomplete", "error", err)
|
||||||
|
}
|
||||||
|
a.transcoder = tr
|
||||||
|
if err := transcode.RegisterTool(a.caps, tr); err != nil {
|
||||||
|
log.Warn("transcode tool register skipped", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Info("transcode tool registered", "formats", formatNames(tr.Formats()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// formatNames 把已注册的格式转成可读字符串,供启动日志列出这条路支持什么。
|
||||||
|
func formatNames(formats []transcode.Format) []string {
|
||||||
|
names := make([]string, 0, len(formats))
|
||||||
|
for _, f := range formats {
|
||||||
|
names = append(names, transcode.FormatName(f))
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/registry"
|
||||||
|
"git.yeij.top/AskaEth/Cyrene_v2/internal/capability/transcode"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestWireTranscodeRegistersTool 断言 wireTranscode 真的把转码装配起来了:引擎挂到
|
||||||
|
// app 上、`transcode` 工具进了能力注册表、且默认的 amr→wav 路可用。它是「组合根漏接
|
||||||
|
// 转码」这一整类回归的哨兵(design/25 §1.3.2)。
|
||||||
|
func TestWireTranscodeRegistersTool(t *testing.T) {
|
||||||
|
a := &app{log: testLog(), caps: registry.New()}
|
||||||
|
|
||||||
|
a.wireTranscode()
|
||||||
|
|
||||||
|
if a.transcoder == nil {
|
||||||
|
t.Fatal("wireTranscode 之后 a.transcoder 仍为 nil(引擎没被装配)")
|
||||||
|
}
|
||||||
|
cap, err := a.caps.Get(transcode.ToolName)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("transcode 工具没进能力注册表: %v", err)
|
||||||
|
}
|
||||||
|
if cap.Kind != registry.KindTool {
|
||||||
|
t.Fatalf("能力类型 = %q, want %q", cap.Kind, registry.KindTool)
|
||||||
|
}
|
||||||
|
if _, ok := cap.Value.(*transcode.Tool); !ok {
|
||||||
|
t.Fatalf("能力值类型 = %T, want *transcode.Tool", cap.Value)
|
||||||
|
}
|
||||||
|
if !a.transcoder.Supports(transcode.FormatAMR, transcode.FormatWAV) {
|
||||||
|
t.Fatal("装配后 amr->wav 这条路不可用(默认编解码器没进引擎)")
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user