Files
Agent-Intent/README.md
T
weichen c29cf6a283
ci / docker-checkout-hostgateway (pull_request) Successful in 1s
ci / vet-and-test (pull_request) Successful in 20s
Adopt credential safe CI and retire replaced source gitlinks
Why:
Make independent version consumption work from ordinary clones while retaining historical commits and existing branch workspaces.

Evidence:
SELF Dev task receipts record 24 CI boundary cases, all workflow syntax checks, readonly private-source prefetch in clean exports, provider tests and package installation without acquisition scripts. Platform CI remains pending.

Impact:
Remove only replaced index links, preserve old physical checkouts, and update dependency guidance. Library consumers retain their immutable versions until an explicit dependency update.

Refs:
Agent-System-Dev feature/dependency-workspace; approved versioned-dependency r1, U3-U7 and R15.
2026-10-13 17:11:44 +00:00

153 lines
9.3 KiB
Markdown
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.
# Agent-Intent
可定义、可配置、可扩展的通用意图识别基础库:把「输入文本 → 意图 + 槽位 + 分支裁决」做成纯内存、确定性的库能力,供宿主在 LLM 之前完成确定性分流——守卫拦截(安全红线、识别即拒绝)、系统功能命令识别、路由提示与多轮澄清入口。
本仓库是该模块的源码位置。Go 模块路径为 `git-ssh.u1680832.nyat.app/weichen/Agent-Intent.git`。不依赖 Agent-Native 或 Agent-Squad;文本处理依赖 `golang.org/x/text`,错误码与日志和 Error-Code-System / Logging-System 轻接入对齐(常量对齐 + 鸭子接口,核心包不依赖错误码库)。
设计目标与边界:
- **机制与内容分离**:本仓只提供识别流水线与定义框架,不内置任何业务意图;词表、正则、守卫内容一律由宿主以 Go 注册或 JSON 配置提供。
- **确定性**:同输入 + 同快照 → 同结果;识别路径纯内存、无 I/O、无时间与随机因素,「无匹配」(fallback)是正常结果而非错误。
- **fail-closed 配置**:spec 校验或配置加载失败时整批原子拒绝,保留上一生效快照并给出可定位到字段与来源的错误。
- **扩展点只留接口**:LLM 分类器、会话挂起预期、分句等由宿主实现并注入。
## 分层
| 包 | 职责 | 依赖边界 |
|---|---|---|
| intent | spec 定义与校验、注册表与不可变快照、JSON overlay 加载合并、四级漏斗识别器、槽位抽取、诊断 | 标准库 + 可选 logging-system |
| conformance | 消费方行为验收套件(Recognizer 公开契约正反例) | 只用公开 API |
| catalogcheck | 本仓错误常量与错误码库 `intent` 域的对齐断言 | 仅测试,import error-code-system |
| examples | 最小接入示例(embed 配置端到端) | 只用公开 API |
| cmd/intentctl | 配置 lint / 单条解释 / 评测集跑批的只读诊断 CLI | 组合根之一 |
## 识别流水线
```
Stage 0 Guard 守卫域规则(Options.GuardDomains;命中 → GuardHit,可表达"识别即拒绝")
Stage 1 Expectation 会话挂起预期(可选注入 ExpectationProvider;命中 → ExpectationHit)
Stage 2 Rules 规则计分:includes_any / includes_all / excludes_any / patterns
Stage 3 Adjudicate 置信度裁决:唯一过阈 → Matched;前两名分差 < AmbiguityMargin → Ambiguous;全不过 → Fallback
```
计分与裁决规则:
- 单 spec 得分 `score = base + (任一 pattern 命中 ? pattern_bonus : 0)`,上限 1.0,四位小数舍入;`score ≥ 该 spec 的 threshold` 才进入候选。
- 命中条件:`excludes_any` 全不命中 且 `includes_all` 全命中 且(`includes_any` 至少一词命中 或 任一 `pattern` 命中;仅配置 `includes_all` 时以全命中为准)。
- 候选排序:置信度降序 → `priority` 降序 → 合并注册序 → id 字典序,全程确定性。
- Ambiguous 分支可注入 `Classifier`(典型为宿主的 LLM 客户端适配器)重排;分类器失败保持 Ambiguous,不会使识别失败。
- 槽位:Top 候选才抽取槽位;必填槽位未命中不撤销匹配,记录在 `Top.MissingRequiredSlots`,由宿主决定澄清(配合挂起预期)。
## 快速开始
```go
b := intent.NewRegistryBuilder(intent.Options{
ProtectedDomains: []string{"guard"}, // overlay 不得覆盖/禁用
GuardDomains: []string{"guard"}, // Stage 0 演练的域
})
// 守卫内容宿主内置;业务意图走 JSON overlay(embed 或目录均可)。
if err := b.Register(guardSpecs...); err != nil { ... }
reg, err := b.BuildFS(ctx, specFS, "specs") // fs.FS + roots,root 为目录或单文件
if err != nil { ... } // fail-closed:配置坏则构建失败
rec := intent.NewRecognizer(intent.Options{}, nil, nil) // 可选挂起预期 / 分类器
res, err := rec.Recognize(ctx, "查询任务 42 的进度", reg.Snapshot())
// res.Branch == intent.BranchMatched
// res.Top.ID == "demo.run.status_query"; res.Top.Slots["run_id"] == "42"
// res.Top.Handler / Risk / RequiresConfirm / Metadata 由宿主解释
if err := reg.Reload(ctx); err != nil { ... } // 显式重读配置;失败保留旧快照
```
多意图输入用 `intent.NewRuleSegmenter().Segment(input)` 先分句再逐句识别。
## 意图定义(IntentSpec)
Go 与 JSON 共用同一结构;JSON overlay 文档形如:
```json
{
"intents": [
{
"id": "demo.run.status_query",
"domain": "demo",
"version": 1,
"description": "查询任务运行进度",
"matcher": {
"includes_any": ["进度", "状态"],
"includes_all": ["任务"],
"excludes_any": ["配置"],
"patterns": ["(?:查询|看).{0,6}(?:进度|状态)"],
"case_sensitive": false
},
"slots": [
{"key": "run_id", "required": false, "pattern": "(?:run|任务)[:# ]*([A-Za-z0-9-]+)", "group": 1}
],
"confidence": {"base": 0.8, "pattern_bonus": 0.2, "threshold": 0.7},
"priority": 100,
"risk": "low",
"requires_confirm": false,
"handler": "taskrun.query_status",
"metadata": {"channel": "dialogue"}
}
],
"disable": ["demo.run.restart"]
}
```
字段说明:
| 字段 | 说明 |
|---|---|
| `id` | 全局唯一;首段必须等于 `domain`,各段 `^[a-z][a-z0-9_-]{0,63}$`,可多级(`demo.run.status_query`) |
| `version` | ≥1;overlay 覆盖同 id 时必须递增 |
| `matcher` | 见上文计分规则;至少一个正向条件;`case_sensitive` 只作用于词表,pattern 用 `(?i)` |
| `slots` | `group` 默认 1;`required` 未捕获记录到 `MissingRequiredSlots`;`label`/`question` 供 HITL 提问与目录展示;`enum`/`format`/`normalize`(trim\|lower\|upper)/`validator`(`RegisterSlotValidator` 注册)构成确定性校验链,非法值进 `Top.InvalidSlots`(与"缺失"区分) |
| `confidence` | 缺省 `base=0.7 / pattern_bonus=0.2 / threshold=0.6` |
| `risk` / `requires_confirm` / `handler` / `metadata` | 模块不解释,透传给宿主做授权、确认与路由 |
| `disabled` | 定义但停用(灰度暂存) |
合并语义:Go 内置为基线;目录 root 内 `*.json` 按文件名字典序、roots 按给定顺序应用;同 id 覆盖需版本递增;`disable` 按 id 禁用(保护域整批失败);未知字段拒绝并定位到文件。数量上限见 `Options`(spec 总数、单 spec 正则/槽位数、输入长度),防止配置膨胀。
## 能力目录(Catalog)
`Snapshot.Catalog()/CatalogMarkdown()` 把启用的非守卫 spec 渲染为规划者/领导 Agent 可消费的声明式目录:有哪些可直接调用的能力、必填槽位与提问建议、风险与确认要求。用于"目录驱动的编排"——规划者据此把子任务短路给系统功能、按槽位 question 生成定向 HITL(Agent-Squad 已按此接入,见其 `squadintent` 与 `docs/records`)。
## 诊断(intentctl)
```bash
go run ./cmd/intentctl lint -root configs/intents # 校验 + 冲突提示
go run ./cmd/intentctl explain -root configs/intents "查询任务进度" # 分支/候选/槽位/裁决轨迹
go run ./cmd/intentctl eval -root configs/intents evals/corpus.json
go run ./cmd/intentctl catalog -root configs/intents # 能力目录(注入规划者提示词)
```
评测集格式见 `intent/testdata/corpus.json`(`name / input / expect_branch / expect_top / expect_slots / expect_missing_slots`)。评测集放在配置目录之外。注意:宿主以 Go 内置注册守卫时,守卫用例只能在宿主自己的测试(或 conformance.Run)中验证;intentctl 只加载 JSON 配置。
## 错误与日志
错误常量与 Error-Code-System 对齐(`intent.invalid_spec` / `intent.spec_protected` / `intent.load_failed`,调用方错误复用 `sys.invalid_argument`),`catalogcheck` 测试防双权威;映射表见 [Error-Code-System 的 agent-intent 映射](deps/error-code-system/docs/agent-intent-mapping.md)。错误类型实现 `ErrorCode()` / `ErrorFields()`,logsys 自动展开码与字段。日志为可选注入(`Options.Log`,nil→Nop),事件:`intent recognized`(branch/top/confidence/revision/duration)、`intent snapshot reloaded`、`intent config rejected`;原始输入不写入日志。
## 版本依赖与消费
消费方在已配置私有传输的环境中获取批准提交,由 Go 写入实际版本:
```bash
go get git-ssh.u1680832.nyat.app/weichen/Agent-Intent.git@<approved-commit>
GOWORK=off go test ./...
```
`go.mod` / `go.sum` 固定错误码与日志依赖,无源码目录 `replace`。正式构建使用 `GOWORK=off`;本地源码联调通过 Dev 的显式组件链接管理。接入后建议在消费方测试里用 `conformance.Run` 跑自己的用例集。
旧提交保留其 gitlinks 供历史组合和在途分支重建;本提交已移除已替代指针;本版本 Go 编译不消费这些目录,开发规范由 Dev components.lock.json 固定。在途分支显式迁移 import 与模块前缀,不改意图、命令或历史事件标识。
## 验证
```bash
GOWORK=off go vet ./... && GOWORK=off go test -count=1 ./...
GOWORK=off go test -count=1 -race ./...
GOWORK=off go list -m all # 核对固定版本与 MVS 解析结果
```
需要 Go 1.27。规则入口见 [AGENTS.md](AGENTS.md),项目事实见 [PROJECT.md](PROJECT.md),设计与验证记录见 `docs/records/`。