ci / vet-and-test (pull_request) Failing after 34s
Why: I2 increments 1-2 shipped the agent-intent ports (SemanticScorer, CommandGenerator); the backend still had no implementation, so the slow lane could not be enabled in the product. Evidence: go test ./... green; lint-boundaries ok; the two new runtime.intentSemantic / runtime.intentGenerator flags are registered with default false and the gate defaults to the I1 recognizer when both are off (TestIntentSlowLaneFlagsDefaultOff, TestGate*). Impact: no behavior change by default; enabling runtime.intentSemantic routes ambiguous rule matches through embedding cosine scoring, and runtime.intentGenerator lets the lightweight model propose commands on fallback with library-side fail-closed validation. Nested agent-intent pin moves to 343b1e6 (I2 increments 1-2). Refs: I2 increment 3
63 lines
1.8 KiB
Go
63 lines
1.8 KiB
Go
// Package intentsem 慢通道实现(I2 增量三):把 agent-intent 的
|
||
// SemanticScorer / CommandGenerator 端口接到宿主已有的向量与轻量模型
|
||
// 能力上。两个实现都是可插拔的——装配层默认不接线(设置开关关),
|
||
// 此时识别行为与 I1 完全一致。
|
||
package intentsem
|
||
|
||
import (
|
||
"context"
|
||
"math"
|
||
|
||
core "agent-system-core"
|
||
)
|
||
|
||
// EmbeddingScorer 用语义向量实现 agentintent.SemanticScorer:
|
||
// 对 input 与每个 example 取向量,返回最大余弦相似度。
|
||
// 任何错误都原样上抛——库侧约定 scorer 出错时识别保持 Ambiguous,
|
||
// 不会使 Recognize 失败(fail-open 到规则层结论)。
|
||
type EmbeddingScorer struct {
|
||
Provider core.EmbeddingProvider
|
||
}
|
||
|
||
// Score 返回 input 与 examples 的最高余弦相似度,取值 [0,1]。
|
||
func (s EmbeddingScorer) Score(ctx context.Context, input string, examples []string) (float64, error) {
|
||
if s.Provider == nil || len(examples) == 0 {
|
||
return 0, nil
|
||
}
|
||
texts := make([]string, 0, len(examples)+1)
|
||
texts = append(texts, input)
|
||
texts = append(texts, examples...)
|
||
vecs, err := s.Provider.Embed(ctx, texts)
|
||
if err != nil {
|
||
return 0, err
|
||
}
|
||
if len(vecs) != len(texts) || len(vecs[0]) == 0 {
|
||
return 0, nil
|
||
}
|
||
best := 0.0
|
||
for _, v := range vecs[1:] {
|
||
if sim := cosine(vecs[0], v); sim > best {
|
||
best = sim
|
||
}
|
||
}
|
||
return best, nil
|
||
}
|
||
|
||
// cosine 计算两个等长向量的余弦相似度;任一零向量或不等长返回 0。
|
||
func cosine(a, b []float32) float64 {
|
||
if len(a) == 0 || len(a) != len(b) {
|
||
return 0
|
||
}
|
||
var dot, na, nb float64
|
||
for i := range a {
|
||
fa, fb := float64(a[i]), float64(b[i])
|
||
dot += fa * fb
|
||
na += fa * fa
|
||
nb += fb * fb
|
||
}
|
||
if na == 0 || nb == 0 {
|
||
return 0
|
||
}
|
||
return dot / (math.Sqrt(na) * math.Sqrt(nb))
|
||
}
|