版本:v1.0 · 日期:2026-03-12
- 名称:TwinFlare — Your Digital Twin, Powered by Cloudflare
- 定位:面向开发者的 Cloudflare-native 个人 AI 分身平台,以 GitHub 仓库为知识源,通过 GitHub Actions 自动同步向量索引,通过 API 对外提供服务
- 核心价值:零服务器、知识文档 Git 版本管理、自动向量化流水线、隐私自主
主要用户:开发者 / 技术博主 / 个人知识工作者
使用场景:
- 将个人博客/笔记/简历以 Markdown 维护在 GitHub 仓库,push 后自动更新 AI 分身的知识库
- 在自己的网站/应用中嵌入聊天 Widget,调用 TwinFlare API
- 构建知识检索工具(文档语义搜索)
flowchart TD
subgraph github [GitHub]
Repo["GitHub Repo\ndocs/*.md\ntwinflare.config.json"]
Actions["GitHub Actions\non push to main"]
Secrets["GitHub Actions Secrets\n所有 secret 的单一来源"]
end
subgraph cf [Cloudflare]
Worker["Workers\nHono.js API\n含 Persona vars"]
Vectorize["Vectorize\n向量索引(唯一持久化)"]
WorkersAI["Workers AI\n嵌入模型 bge-base-en-v1.5(固定)"]
end
subgraph externalAI [外部 LLM Provider]
OpenAI["OpenAI\ngpt-4o 等"]
Anthropic["Anthropic\nClaude 系列"]
Google["Google\nGemini 系列"]
end
ExternalApp["第三方应用\nBearer Token"]
Repo --> Actions
Secrets -.->|"wrangler secret put"| Worker
Actions -->|"Job1: wrangler deploy"| Worker
Actions -->|"Job2: CF REST API"| Vectorize
Actions -->|"Job2: CF REST API"| WorkersAI
ExternalApp -->|"Bearer Token"| Worker
Worker --> Vectorize
Worker --> WorkersAI
WorkersAI -->|"生成 embeddings"| Vectorize
Worker -->|"provider=cloudflare\nenv.AI.run()"| WorkersAI
Worker -->|"Vercel AI SDK"| OpenAI
Worker -->|"Vercel AI SDK"| Anthropic
Worker -->|"Vercel AI SDK"| Google
| 资源 | 用途 | 备注 |
|---|---|---|
| Workers | API 层,所有业务逻辑(Hono.js) | Persona 配置烧入 [vars],读取零延迟 |
| Vectorize | 文档 chunk 向量索引 | 唯一持久化存储,按 filePath metadata 增量更新 |
| Workers AI | 嵌入模型 | 固定使用 @cf/baai/bge-m3,1024 维 |
R2 和 KV 均不需要。原始文档在 GitHub,Persona 配置在 Worker vars,向量在 Vectorize。
your-twinflare-repo/
├── docs/ # 知识文档(只处理此目录下的 .md 文件)
│ ├── about.md
│ ├── projects.md
│ └── blog/
│ └── post-1.md
├── twinflare.config.json # Persona 非敏感配置(随代码版本管理)
├── scripts/
│ ├── inject-config.js # CI 用:将 config 注入 wrangler.toml [vars]
│ └── sync.js # CI 用:git diff → CF REST API 直写 Vectorize
├── .github/
│ └── workflows/
│ └── deploy.yml # 部署 + 同步流水线
├── src/ # Cloudflare Worker 源码
└── wrangler.toml # Worker 配置([vars] 由 CI 注入,勿手动编辑)
{
"persona": {
"name": "My Digital Twin",
"systemPrompt": "你是 xxx 的数字分身,基于他的知识库回答问题...",
"provider": "anthropic",
"model": "claude-3-5-sonnet-20241022",
"topK": 5,
"temperature": 0.7
}
}支持的 provider:cloudflare(免费,无需额外 API Key)· openai · anthropic · google
单一来源:所有 secret 统一存储在 GitHub Actions Secrets,由 CI deploy job 通过 wrangler secret put 写入 Cloudflare Worker。开发者无需在本地执行任何 wrangler secret 命令。
GitHub Actions Secrets(单一来源)
│
│ deploy job: echo $SECRET | wrangler secret put SECRET_NAME
↓
Cloudflare Worker Runtime Secrets
│
│ env.ANTHROPIC_API_KEY 等
↓
Worker 运行时(LLM provider 初始化)
| Secret 名称 | 是否必填 | 用途 |
|---|---|---|
CLOUDFLARE_API_TOKEN |
必填 | wrangler 鉴权 + sync job 直调 CF REST API(Workers / Vectorize / AI 权限) |
CLOUDFLARE_ACCOUNT_ID |
必填 | Cloudflare 账户 ID(wrangler + sync job 共用) |
PUBLIC_API_TOKEN |
必填 | 公开 API Bearer Token,deploy job 写入 Worker |
OPENAI_API_KEY |
可选 | provider = openai 时填写 |
ANTHROPIC_API_KEY |
可选 | provider = anthropic 时填写 |
GOOGLE_API_KEY |
可选 | provider = google 时填写 |
触发条件:push 到 main 分支(任意文件变更均触发 deploy;仅 docs/** 或 twinflare.config.json 变更时触发 sync)
1. node scripts/inject-config.js
→ 读取 twinflare.config.json,将 persona 字段写入 wrangler.toml [vars]
2. wrangler vectorize create twinflare-vectorize-index --dimensions=1024 --metric=cosine
→ 幂等,已存在则跳过
3. wrangler deploy
→ 创建或更新 Worker(首次自动创建)
4. 写入所有 secrets:
echo $PUBLIC_API_TOKEN | wrangler secret put PUBLIC_API_TOKEN
echo $ANTHROPIC_API_KEY | wrangler secret put ANTHROPIC_API_KEY # 按需
...
1. git diff HEAD~1 HEAD -- docs/
→ 收集 upserted(新增/修改)+ deleted 文件列表
→ 首次提交(无 HEAD~1)则全量同步所有 docs/ 文件
2. 对每个 deleted 文件:
POST CF Vectorize REST API /get-by-ids → 取 manifest(含 chunkCount)
POST CF Vectorize REST API /delete-by-ids
3. 对每个 upserted 文件:
先执行删除(幂等)
chunkMarkdown(content) → chunks[]
POST CF Workers AI REST API (@cf/baai/bge-m3) → embeddings[]
POST CF Vectorize REST API /upsert(ndjson:manifest + chunk vectors)
4. 打印同步结果(processed / deleted / totalChunks)
首次使用只需配置好 GitHub Secrets,push 一次 commit 即完成从零到完整部署的全流程。
| Method | Path | 描述 |
|---|---|---|
POST |
/api/chat |
RAG 对话,SSE 流式返回 |
POST |
/api/search |
纯语义检索,返回匹配 chunks |
GET |
/api/persona |
获取 Persona 公开信息(name / provider / model) |
文档同步不经过 Worker HTTP 接口,由
scripts/sync.js直接调用 Cloudflare REST API 完成。
POST /api/chat { messages: [...] }
→ 取最后一条 user 消息,生成 embedding(Workers AI bge-base-en-v1.5)
→ Vectorize.query(embedding, { topK, filter: { type: "chunk" } })
→ 拼装 prompt:
[System]: {PERSONA_SYSTEM_PROMPT}
[Context]: {topK chunks 原文,按 score 排序}
[Messages]: {完整 messages 历史}
→ 路由到 LLM provider:
cloudflare → env.AI.run(model, { messages, stream: true })
openai → Vercel AI SDK streamText + @ai-sdk/openai
anthropic → Vercel AI SDK streamText + @ai-sdk/anthropic
google → Vercel AI SDK streamText + @ai-sdk/google
→ 流式返回(SSE / text stream)
sync.js 直接通过 Cloudflare REST API 读写 Vectorize,不依赖 Worker HTTP 接口。
对每个 deleted 文件:
1. POST /vectorize/v2/indexes/{name}/get-by-ids → 取 manifest(含 chunkCount)
2. POST /vectorize/v2/indexes/{name}/delete-by-ids(manifest + all chunks)
对每个 upserted 文件:
1. 先执行上述删除(幂等更新)
2. chunkMarkdown(content) → chunks[]
3. POST /ai/run/@cf/baai/bge-m3 → embeddings[](分批,每批 50 条)
4. POST /vectorize/v2/indexes/{name}/upsert(ndjson 格式)
manifest id = "m::{encodedPath}" metadata = { type, filePath, chunkCount, docTitle }
chunk id = "c::{encodedPath}::{i}" metadata = { type, filePath, chunkIndex, docTitle, text }
Manifest 模式(无 KV 的幂等删除方案):每个文件写入一个零向量 manifest,存储 chunkCount;删除时通过确定性 ID 精确清理,无需扫描。
| 变量名 | 示例值 |
|---|---|
PERSONA_NAME |
"Alex Chen" |
PERSONA_SYSTEM_PROMPT |
"你是 Alex 的数字分身..." |
PERSONA_PROVIDER |
"anthropic" |
PERSONA_MODEL |
"claude-3-5-sonnet-20241022" |
PERSONA_TOP_K |
"5" |
PERSONA_TEMPERATURE |
"0.7" |
| 字段 | 说明 |
|---|---|
type |
"manifest" 或 "chunk" |
filePath |
文件路径,如 docs/about.md |
chunkIndex |
chunk 序号(仅 chunk 类型) |
docTitle |
文档标题(取第一个 H1,降级为文件名) |
text |
chunk 原文,直接返回无需回查原文件(仅 chunk 类型) |
chunkCount |
该文件的 chunk 总数(仅 manifest 类型) |
| 层次 | 技术选型 |
|---|---|
| Web 框架 | Hono.js v4 |
| LLM 调用 | Vercel AI SDK v6(ai + @ai-sdk/*) |
| Embedding 模型 | Cloudflare Workers AI @cf/baai/bge-m3 |
| 向量数据库 | Cloudflare Vectorize |
| 语言 | TypeScript(严格模式) |
| 构建/部署 | Wrangler v4 |
| CI/CD | GitHub Actions |
- 部署方式:完全由 GitHub Actions 驱动,包括 Worker 首次创建、资源初始化、secrets 写入;用户无需本地 wrangler
- 幂等性:重复推送同一文件不产生重复向量(先删后写,manifest 记录 chunkCount)
- 向量容量:Vectorize 免费版 5 万向量(768 维/向量,约 65 个 chunks);付费版无限制
- 延迟目标:Chat API P90 < 3s,流式首 token < 1s
- 错误格式:统一
{ error: { code: string, message: string } } - CORS:默认
*,可在 Worker 代码中按需收窄
| Phase | 内容 | 状态 |
|---|---|---|
| Phase 1 — Core Worker | Hono.js 骨架、RAG Chat、/api/search、Bearer Token 鉴权 | ✅ 已完成 |
| Phase 2 — GitHub Actions | deploy.yml、inject-config.js、sync.js(直调 CF REST API)、增量 diff 逻辑 | ✅ 已完成 |
| Phase 3 — Polish | README 快速上手文档、mock docs 示例 | ✅ 已完成 |