内容
# touchdesigner-wiki-rag
在您的AI代理中搜索整个TouchDesigner文档,并附上实际引用。
该工具在官方TouchDesigner维基([docs.derivative.ca](https://docs.derivative.ca/),约2,270篇文章)上建立本地搜索索引,并通过[MCP](https://modelcontextprotocol.io/)(Claude Code、Claude Desktop、Cursor以及其他MCP客户端)将其暴露给AI代理。每个答案都附有可点击的URL的`页面 § 章节`引用,因此您可以验证代理告诉您的内容,而不是信任模型对TouchDesigner的记忆——这正是您最终得到虚构的参数名称的原因。
**您在自己的机器上,从实时维基构建索引。** 该存储库不包含任何文档内容——文档属于[Derivative](https://derivative.ca/),用户直接从docs.derivative.ca获取。构建需要约45分钟的无人值守获取(礼貌地限制速率)加上几分钟的索引,可以完全免费运行,无需API密钥。
## 为什么不直接让代理浏览维基?
有三个原因可以击败实时浏览:混合检索(精确术语BM25 +语义向量,融合和重新排序)可以找到关键词搜索遗漏的章节;索引知道TouchDesigner的操作符家族陷阱——**Noise TOP,Noise CHOP,Noise SOP和Noise POP是四个不同的操作符**,并且结果在存在同名兄弟时发出警告;答案基于检索的文本和引用,而不是模型记忆。
## 需求
- Python 3.12+ 和 [uv](https://docs.astral.sh/uv/)
- 约1.5 GB磁盘空间用于索引
- **默认完全本地设置无需API密钥**
- 可选(更好的检索):[OpenAI](https://platform.openai.com/)密钥用于更强的嵌入(约1-2美元一次性构建成本)和HyDE查询扩展;[Cohere](https://dashboard.cohere.com/)密钥用于更强的重新排序(约2美元每1000次搜索;免费试用密钥有效)
## 快速入门
```bash
git clone https://github.com/johnnyvincentvitale/touchdesigner-wiki-rag
cd touchdesigner-wiki-rag
uv sync
cp .env.example .env # 可选:添加API密钥;空值也有效
uv run python fetch.py # ~45分钟, 通过公共API获取维基
uv run python ingest.py --rebuild # 分块 + 嵌入 + 索引
# 在终端中试用
uv run python query.py "如何向纹理添加噪声"
```
嵌入后端在构建时选择——默认为本地[bge-base](https://huggingface.co/BAAI/bge-base-en-v1.5)(免费,无需账号),如果设置了`OPENAI_API_KEY`,则为OpenAI的`text-embedding-3-large`——并被记录到索引中,以便查询始终使用匹配的模型。有关详细信息,请参见`.env.example`。
### 已经有文档?跳过获取
TouchDesigner安装包中包含一个**离线帮助**镜像,镜像了维基。如果您有它,请导入它,而不是获取(几秒钟而不是约45分钟):
```bash
# Windows(默认安装位置):
uv run python fetch.py --offline-help "C:/Program Files/Derivative/TouchDesigner/Samples/Learn/OfflineHelp/https.docs.derivative.ca"
# 然后可选地拉取自上次镜像生成以来编辑的页面:
uv run python fetch.py --update
uv run python ingest.py --rebuild
```
注意:镜像在TouchDesigner发布日期时快照了维基——`--update`会从实时API更新它。最近的**macOS**版本将离线帮助文件夹置为空(一个已知的TouchDesigner问题),因此Mac用户应使用普通的API获取。
## 配置 — `.env`中有什么
**不需要任何内容。** 使用空的(或不存在的)`.env`,所有内容都可以在免费的本地模型上运行。密钥仅升级个别阶段:
| 变量 | 功能 | 没有它 |
|---|---|---|
| `OPENAI_API_KEY` | `text-embedding-3-large`嵌入(更强的密集检索)+ HyDE查询扩展 | 本地bge嵌入;HyDE禁用 |
| `COHERE_API_KEY` | Cohere Rerank评分 | 本地ms-marco交叉编码器重新排序 |
| `EMBED_BACKEND` | 强制使用`local`或`openai`嵌入 | 推断:如果设置了密钥,则为`openai`,否则为`local` |
| `EMBED_MODEL` | 不同的OpenAI嵌入模型(例如 `-3-small`,更便宜/更弱) | `text-embedding-3-large` |
| `COHERE_RERANK_MODEL` | 不同的Cohere重新排序模型 | `rerank-v3.5` |
| `HYDE_MODEL` | 不同的HyDE模型 | `gpt-4o-mini` |
| `OPENAI_BASE_URL` | 将OpenAI客户端调用路由到任何兼容的服务器(见下文) | api.openai.com |
两个值得注意的行为:嵌入后端在**构建时被记录到索引中**,查询会自动检测它,因此您不会意外地使用错误的模型查询——但是切换后端意味着重建(`ingest.py --rebuild`)。并且每个API阶段**都会明显降级,绝不会静默**:没有Cohere密钥会回落到本地重新排序器,不可达的嵌入API会将搜索降级为仅关键词并在响应中说明。
### 完全本地运行(包括HyDE)
默认无密钥设置已经是本地的,除了HyDE,它只是禁用了。要在本地模型上运行HyDE,请将OpenAI客户端指向任何OpenAI兼容的服务器——[Ollama](https://ollama.com/)或LM Studio:
```bash
# .env
OPENAI_API_KEY=任何非空值 # 满足客户端;从不发送到实际位置
OPENAI_BASE_URL=http://localhost:11434/v1
HYDE_MODEL=llama3.2 # 您已本地拉取的任何模型
EMBED_BACKEND=local # 保持嵌入在bge上 – 必需!
```
`EMBED_BACKEND=local`在这里至关重要:没有它,设置`OPENAI_API_KEY`会将嵌入切换到OpenAI后端,然后指向您的本地服务器,但期望一个它不提供的模型。小型本地HyDE模型比gpt-4o-mini粗糙,但HyDE仅在低评分搜索时触发,并且仅在评分更好时保留其结果——因此缺点是有限的。(本配方遵循OpenAI SDK的文档化的`OPENAI_BASE_URL`行为,但作者尚未在实时Ollama上测试过——欢迎问题报告。)
“本地”模型仍会在首次使用时从Hugging Face下载一次(无需帐户),之后会缓存;维基获取本身需要一次网络连接。索引构建后,无密钥设置会完全离线搜索。
## 将其连接到您的代理
**Claude 代码:**
```bash
claude mcp add --scope user touchdesigner-manual -- uv run --directory /ABSOLUTE/PATH/TO/touchdesigner-wiki-rag python server.py
```
**任何其他MCP客户端** — 标准输入/输出服务器配置:
```json
{
"mcpServers": {
"touchdesigner-manual": {
"command": "uv",
"args": ["run", "--directory", "/ABSOLUTE/PATH/TO/touchdesigner-wiki-rag", "python", "server.py"]
}
}
}
```
### 代理获取的内容
| 层级 | 工具 | 返回值 |
|---|---|---|
| L0 | `browse_manual(query, family, limit)` | 章节地图 — 廉价定位,发现维基自身的词汇 |
| L1 | `search_manual(query, family, limit)` | 带有`页面 § 章节` + URL引用的重新排序段落 |
| L2 | `read_page(title, section)` | 完整的markdown页面 |
附加资源:`manual://index`(语料库统计和新鲜度)和`manual://operators/{family}`(每个家族的操作符名册)。
`family`接受TOP、CHOP、SOP、DAT、MAT、COMP或POP,以将搜索范围限定在一个操作符家族中。
## 检索工作原理
1. **BM25**,基于SQLite FTS5,Porter词干提取 — 精确的操作符和参数名称
2. **密集向量搜索**,基于Chroma — 意译和概念问题
3. **互惠排名融合**,结合两个排名
4. **重新排序** — 如果配置了Cohere密钥,则使用Cohere Rerank,否则使用本地ms-marco交叉编码器(自动降级,离线可用)
5. **自适应HyDE** — 如果最高重新排序分数较低(可靠的“检索遗漏”信号),则LLM在维基词汇中编写假设答案,并对该答案重新运行检索。仅在需要时触发,仅在具有OpenAI密钥时触发,仅在评分更好时保留结果。
每条响应中都包含两个安全措施:**家族警告**,当结果的操作符在其他家族中有同名兄弟时;**低置信度警告**,当分数表明检索遗漏时 — 因此代理报告“未找到”而不是编造答案,并且从不因检索结果为空而得出某个功能不存在的结论。
## 保持索引新鲜
维基不断变化。响应会在自索引构建以来编辑页面时发出警告(针对维基的`recentchanges`源,每小时缓存,在离线时静默跳过)。要更新:
```bash
uv run python fetch.py --update # 重新获取自上次获取以来编辑的页面
uv run python ingest.py --rebuild # 重建索引
```
## 已知问题
- 每个操作符页面都带有相同的“常见操作符信息通道”样板章节;这些块可能会污染查询结果。
- `--offline-help`导入器针对合成的MediaWiki静态页面进行测试,但尚未针对真正的TouchDesigner安装镜像进行测试(作者的macOS版本为空)。如果导入器在您的安装中遗漏页面,请提交问题并附上示例HTML文件。
- 四个标题变体页面(例如`Palette:webRTC Ext`与`Palette:WebRTC Ext`)在大小写不敏感的文件系统上在页面缓存中发生冲突;它们的合作伙伴页面已编入索引,因此覆盖率影响可忽略不计。
- 重新排序/HyDE分数阈值已在小型保留查询集上校准;它们在`retrieval.py`中可调(`THRESHOLDS`)。
- `ingest.py`仅支持完全重建;使用OpenAI嵌入时,这会重新花费约1-2美元每次重建。本地后端免费重建。
## 内容所有权
所有文档内容归Derivative所有。本存储库不包含任何维基内容 — 仅包含通过公共API将内容获取到私有本地索引的代码,与浏览器或TouchDesigner的内置帮助程序相同。请保持`fetch.py`中的礼貌速率限制完整。
## 许可证
MIT — 参见[LICENSE](LICENSE)。仅适用于此存储库中的代码,不适用于TouchDesigner或其文档。