Files
Agent-System-Backend/internal/intentsem/scorer.go
T
weichen 45b011af9f
ci / vet-and-test (pull_request) Failing after 34s
Wire the intent slow lane behind settings flags (I2 WP3)
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
2026-10-07 11:20:41 +00:00

63 lines
1.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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))
}