快速开始
下面的步骤把 RAG 服务跑起来——后端 + 官方前端,串通后即可在 UI 里创建知识库、上传文档、做检索。1
配置并启动 RAG 服务
给 其中与 RAG 相关的
create_app 传入与 RAG 相关的几个组件即可开启 /knowledge_bases 全部端点。下面的最小示例分别演示本地 blob 存储与 S3 blob 存储两种配置——前提是 Redis、Qdrant 已经在本地(或可访问的地址上)准备好:create_app 参数如下;不传 knowledge_base_manager 时整组知识库端点不会被注册。KnowledgeBaseManagerBase | None
默认值:"None"
知识库生命周期的拥有者,绑定一个向量库实例(其连接生命周期由 manager 代理)。内置实现
CollectionPerKbManager 采用「每个知识库一个 collection」的隔离策略,允许各知识库自由选择嵌入维度。list[ParserBase] | dict[str, ParserBase] | None
默认值:"[TextParser()]"
注册到上传链路的 parser 列表,按各 parser 声明的
supported_media_types 路由上传文件。list 形式下,后注册的同类型 parser 覆盖前者(覆盖会打 warning);dict 形式 media_type → parser 表示显式路由(适合同一 parser 绑定多个类型或自定义别名)。ChunkerBase | None
默认值:"ApproxTokenChunker()"
全部知识库共用的切块策略。生产场景按嵌入模型上下文窗口调整
chunk_size 与 overlap。BlobStoreBase | None
默认值:"LocalBlobStore('./blobs')"
上传文件落地的二进制存储。本地存储适合单机;分布式部署请用 S3 或自实现的共享后端,因为 worker 必须与 API 共享同一份文件源。
bool
默认值:"True"
True 时 API 进程内同时跑解析 / 切块 / 嵌入(单进程模式);False 时 API 只接收上传与入队任务,索引交给独立 worker(分布式模式),详见下文「部署形态」。2
启动官方前端
AgentScope 仓库的 打开 dev server 输出的 URL(通常是
examples/web_ui 目录提供与上面后端配套的 React 前端,直接拉起即可:http://localhost:5173),前端会自动连接到 8000 端口的服务。3
在前端操作
打开前端后,可以在 UI 里完成新建知识库、上传文档、查看处理进度、做检索测试等全套操作。
部署形态
上一节的快速开始把 API 与索引跑在同一个进程里,对本地开发和小流量场景足够用;但生产环境里,解析 / 切块 / 嵌入是 CPU 与 IO 双重密集的链路,跟 HTTP 请求挤在同一个进程会出现两个问题:- 资源相互挤占:一份大 PDF 进来,事件循环被解析卡住,同进程内其他 API 请求一起变慢;
- 扩容颗粒度过粗:唯一的横向扩缩单位是「API 副本」,但真正吃资源的只有索引链路,整体扩等于在浪费资源。
单进程部署
create_app 的 enable_index_worker 默认为 True,API 进程在 lifespan 里自动起一个内置的 worker 协程,无需额外配置——这就是「快速开始」演示的形态。如果之前显式关掉过,传回 True 即可:
分布式部署
API 进程关掉内置 worker,只负责接收上传、入队任务、跑兜底自愈;一个或多个 worker 进程独立启动,订阅同一条消息总线通道并拉取任务。 API 端:- CLI 方式:通过
python -m agentscope.app.rag.index_worker,配合环境变量AGENTSCOPE_WORKER_BOOTSTRAP=module:callable指向一个返回后端字典的工厂。运维直接拷贝同一份 systemd / k8s 单元即可批量扩容; - 库方式:在自己的入口脚本里调用
agentscope.app.rag.index_worker.run_worker(...)(也可直接from agentscope.app.rag import run_worker导入),与create_app拼出来的后端共享同一组实例。
run_worker(...) 调用拆成「构造 kwargs」和「调用」两步——把要传给 run_worker 的关键字参数作为 dict 返回即可:
向量库本身的高可用 / 多副本由所选向量库后端负责;服务层只持有连接句柄。把 Qdrant 指向集群、把 S3 指向跨区桶,即可在不动应用代码的前提下完成存储侧扩展。
运行原理
服务层的核心设计是用消息总线(event bus)把「上传」与「索引」彻底解耦——前者是同步链路、追求毫秒级返回,后者是异步链路、可重、可分布式。两条链路只通过 bus 上的一条index_tasks 通道通信,因此同一份代码既能在「快速开始」里跑成单进程,也能在「分布式部署」里跨多机扩容,业务逻辑完全相同。
围绕这条 bus 的几个角色:
下图展示一份文档从上传到可检索的完整路径,所有跨进程通信都经过 bus,因此把 worker 抽出来部署不需要改任何配线:
链路要点:
- 上传链路(API 进程):路由把请求交给知识库服务,后者把文件流式写进 blob 存储、落一条
pending记录,然后向 bus 推一条索引任务;HTTP 立刻返回,不在请求体里跑解析 / 嵌入。 - 索引链路(worker 进程,可内置在 API 中也可独立部署):索引消费者订阅 bus 信号、批量拉取任务、转交给索引 worker 跑「抢 lease → 解析 → 切块 → 嵌入 → 入库 → 标记 ready」全流程。索引内部统一通过
KnowledgeBaseManagerBase.get_knowledge(...)拿到一个KnowledgeBase运行时句柄,再调用insert_document(...)完成嵌入 + 入库,与 library 模式跑的是同一条逻辑。 - 自愈链路(始终在 API 进程):索引兜底周期性发现超时 lease 或长时间未被处理的
pending记录,重新向 bus 入队;worker 侧的 CAS lease 保证不会重复处理。
文档状态机
文档记录的status 字段在生命周期内严格按以下顺序流转,前端可以根据它渲染进度条或失败提示:
容错与自愈
服务层围绕 bus + lease 做了几项让长跑更省心的设计:- lease + CAS 防重入:worker 接到任务后先用 storage 层的 CAS 抢 lease,重复入队或多 worker 抢同一文档都只会执行一次;
- lease 自动续约:lease 默认 90 秒,worker 内置心跳每 45 秒续一次,长文档解析不会超时;
- race 检测:worker 同时跑流水线与心跳;心跳一旦发现 lease 被夺(sweeper 误判 / 网络抖动),立即取消流水线,避免和接管 worker 同时写入向量库;
- 兜底重派:lease 过期(worker 崩溃)或
pending超过宽限期(API 推送失败)的文档会被周期性重新入队; - 错误隔离到记录上:任意阶段抛异常都会被写到记录的
error字段,前端可见,blob 与记录不会自动清理,便于排查后重传; - 删除链路幂等:先删向量库、再删记录、最后删 blob,任意中途失败重试都不会留下状态不一致。
REST API 概览
服务层在/knowledge_bases 前缀下暴露完整的 CRUD + 上传 + 检索端点。下表按职责分组,请求 / 响应的字段细节由 OpenAPI 文档给出:
延伸阅读
RAG
了解 parser / chunker / vector store / middleware 的原子接口与 library 模式用法。
架构
create_app 的全局参数、lifespan、依赖注入与 ASGI 中间件层。中间件
RAGMiddleware 借助哪些钩子注入检索结果。嵌入模型
嵌入模型卡 / 维度约束,决定知识库可选哪些模型。