外观
AI 框架封装
概述
模块路径:backend/app/api/v1/module_ai/framework 定位:AI 大模型应用的底层能力层,对 LangChain、LangGraph、LlamaIndex、OpenAI/兼容协议、联网搜索、异步任务等做统一抽象,供「模型管理 / 知识库 / 智能对话 / 智能写作」等上层业务直接复用。
设计目标
为了让上层业务从具体的 AI 基础设施实现中解耦,框架层做了三件事:
- 统一抽象:用一套工厂 + 单例封装 LlamaIndex 各原生组件(Embedding、VectorStore、Retriever、NodeParser、Postprocessor),上层只关心「要做什么」,不关心「背后是哪个引擎」。
- 多后端可插拔:向量库支持 Chroma / Milvus / Qdrant / PGVector,Embedding 支持 Ollama / Xinference / OpenAI 兼容,重排支持 Xinference / SiliconFlow,联网搜索支持 Bing / 智谱——切换后端只改配置或一行参数。
- 生产可用性:内置客户端/实例缓存、配置变更重建、模型可达性预检、异常兜底(联网搜索失败不阻断对话)、异步任务队列(文档解析异步化)。
约定:RAG能力基于 LlamaIndex 封装,不重复造轮子。
整体结构
framework/
├── settings.py # 框架配置(向量库/联网搜索)
├── llm/ # 大模型对话封装(OpenAI 兼容协议)
│ ├── base.py # ChatMessage / ChatRequest / ChatStreamChunk / ChatClient
│ └── factory.py # AiModelFactory 单例
├── embedding/ # 向量化(Embedding)封装
│ └── factory.py # LlamaEmbeddingFactory 单例
├── vector/ # 向量存储封装
│ └── factory.py # LlamaVectorStoreFactory 单例
├── loader/ # 文档加载(多格式解析)
│ ├── core.py # load / read_url / download_bytes
│ └── reader.py # HtmlContentReader
├── splitter/ # 文本切分封装
│ └── factory.py # SplitterFactory 单例
├── retriever/ # 检索器 + 检索管道
│ ├── factory.py # get_retriever 工厂方法
│ └── pipeline.py # RetrievalPipeline 两阶段召回
├── postprocessor/ # 节点后处理 / 重排
│ ├── factory.py # get_postprocessor 工厂方法
│ └── rerank.py # resolve_rerank_postprocessor
├── websearch/ # 联网搜索
│ ├── base.py # WebSearchBase 抽象基类
│ ├── factory.py # WebSearchFactory 单例
│ ├── provider_bing.py # BingSearch
│ └── provider_zhipu.py # ZhipuSearch
└── task_queue/ # 异步任务 Worker(arq)
└── worker.py # WorkerSettings组件说明
大模型对话 llm/
基于 AsyncOpenAI 对 OpenAI 兼容协议做封装,兼容任意 OpenAI 协议的大模型(OpenAI、DeepSeek、Ollama、Xinference、智谱等)。
base.py定义请求/响应数据类与ChatClient:ChatMessage:对话消息,content支持str(纯文本)或list[dict](多模态 content parts,如图片 URL)。ChatRequest:统一请求(messages / model / temperature / max_tokens / stream / extra等),extra透传厂商特有参数(如推理参数)。ChatClient:提供chat_completion(一次性返回)与chat_completion_stream(流式,ChatStreamChunk把正文content与推理过程reasoning_content分离产出)。
factory.py的AiModelFactory是单例:按平台:模型缓存并复用AsyncOpenAI客户端,密钥或base_url变更时自动重建;resolve_key解析密钥(优先api_key表)与base_url(模型自定义 > 密钥自定义)。
前端对应:对话交互在
apps/web-ele/src/views/ai/chat/,流式对话由chat/index/composables/use-chat-stream.ts驱动;消息渲染拆分为message/parts/下的text-part(正文)、reasoning-part(推理过程)、knowledge-part(知识库引用)、web-search-part(联网搜索),与后端ChatStreamChunk的字段一一对应。
向量模型 embedding/
LlamaEmbeddingFactory 单例,按 provider 返回 LlamaIndex 原生 BaseEmbedding:
| provider | 实现 | 说明 |
|---|---|---|
openai / openaicompat | OpenAIEmbedding | 兼容 OpenAI 协议(含 SiliconFlow、DeepSeek 等) |
ollama | OllamaEmbedding | 本地部署 |
xinference | XinferenceEmbedding | Xinference 自托管 |
工厂按 provider:model 缓存实例,构造后做轻量预检(Ollama 校验 GET /api/tags 模型是否已下载;OpenAI 兼容校验 GET /v1/models),不可达或模型缺失时抛面向用户的 CustomException。
前端对应:向量化模型的「平台 / 模型名 / 服务地址 / 密钥」在
apps/web-ele/src/views/ai/model/下的apiKey(密钥)与model(模型,含 EMBEDDING 类型)页面配置,配置即决定get_embedding的入参。
向量存储 vector/
LlamaVectorStoreFactory 单例,支持四种后端,按 backend:collection 缓存:
| backend | 实现 | 必需配置 |
|---|---|---|
chroma | ChromaVectorStore | 本地持久化目录(默认 ./static/chroma_data) |
milvus | MilvusVectorStore | 连接地址 + 向量维度(dim) |
qdrant | QdrantVectorStore | 连接地址 + API Key |
pgvector | PGVectorStore | PostgreSQL 连接信息 + 向量维度 |
显式入参 > 框架配置(ModuleAiSettings)> 内置默认值。额外提供 update_node_metadata 用于合并更新已入库节点元数据(当前支持 Chroma / Milvus)。
前端对应:向量后端类型与连接信息由后端环境变量配置(见「配置」);知识库对应的集合/向量维度在
apps/web-ele/src/views/ai/knowledge/knowledge/manage/(知识库管理表单)中设置,入库时驱动get_store与update_node_metadata。
文档加载 loader/
core.py 的 load(content, filename) 把文件字节解析为 LlamaIndex Document:
- 通过
SimpleDirectoryReader+FILE_EXTRACTOR分发多格式 Reader(PDF / DOCX / PPTX / XLSX / CSV / RTF / HTML 等)。 _sniff_real_ext按二进制魔数嗅探真实格式(如 docx 被改名为 md),避免二进制当纯文本解码乱码。HtmlContentReader(自定义)用 BeautifulSoup 清洗网页,移除script/style等噪声。read_url/download_bytes支持从 URL 下载并解析;is_image_url用于识别多模态图片附件。
前端对应:文档上传与解析在
apps/web-ele/src/views/ai/knowledge/document/,上传步骤document/form/modules/upload-step.vue把文件交给后端loader解析入库;解析状态由task_queue(见下)异步推进并在文档列表页实时展示。
文本切分 splitter/
SplitterFactory 单例,按策略返回 LlamaIndex 原生 NodeParser,按 strategy:chunk_size:chunk_overlap:kwargs 缓存:
AUTO:按扩展名自动选择(md→Markdown、html→HTML、json→JSON、代码→Code、其它→Sentence)。SENTENCE/TOKEN/MARKDOWN/CODE/HTML/JSON/SEMANTIC(语义切分需embed_model)/SENTENCE_WINDOW/PARENT_CHILD(父子分块)。
前端对应:分段设置在
apps/web-ele/src/views/ai/knowledge/document/form/modules/split-step.vue,可选「分块策略 / 分块大小 / 重叠大小」,其splitStrategy取值与后端SplitStrategyEnum完全对齐(默认auto),并可调用后端接口实时预览分段效果。
检索器与检索管道 retriever/
factory.py的get_retriever工厂方法,按RetrieverName枚举装配 LlamaIndex 原生检索器:向量检索、BM25 关键词、查询融合(混合)、自动合并、递归、路由、向量自动检索。BM25针对中英混合做了 token 规则与停用词优化。pipeline.py的RetrievalPipeline编排两阶段召回:- 检索器粗召回(按
RECALL_MULTIPLIER=5放大候选量,可按recallK覆盖); - Rerank 重排(可选)→ 相似度阈值过滤 → 截断
top_k。
管道只负责编排顺序,Embedding / VectorStore / Rerank 实例由调用方解析后传入;
knowledge_id用于向量库元数据过滤,避免跨知识库串库。- 检索器粗召回(按
前端对应:召回效果验证在
apps/web-ele/src/views/ai/knowledge/knowledge/retrieval/index.vue(文档召回测试),可输入查询文本并设置topK与「相似度阈值」,实时查看各分段 score 与内容,对应RetrievalPipeline的入参与输出。
后处理与重排 postprocessor/
factory.py的get_postprocessor工厂方法,按PostprocessorName装配 LlamaIndex 原生后处理器(相似度过滤、关键词过滤、LLM 重排、SentenceTransformer 重排、长上下文重排、时间加权等)。rerank.py的resolve_rerank_postprocessor面向「重排模型」配置:按平台返回XinferenceRerank(私有化)或SiliconFlowRerank(云端),要求配置服务地址与密钥。
前端对应:重排模型作为
model的一种类型(RERANK)在apps/web-ele/src/views/ai/model/model/配置,知识库启用重排后即驱动resolve_rerank_postprocessor接入检索管道。
联网搜索 websearch/
基于抽象基类 WebSearchBase,统一返回 AiWebSearchPageSchema(title / url / snippet):
WebSearchFactory单例按配置WEB_SEARCH_PROVIDER构建客户端。BingSearch:解析 Bing 搜索结果页,免密钥(锁定中文市场、忽略系统代理防国际版)。ZhipuSearch:调用智谱 Web Search API,返回结构化结果(含来源/发布时间),需 API Key。search方法带异常兜底:失败时返回空列表,不阻断主对话链路。
前端对应:搜索提供方由后端环境变量配置;对话中命中的联网结果由
apps/web-ele/src/views/ai/chat/index/message/parts/web-search-part.vue以可展开列表 + 详情抽屉渲染(标题 / 摘要 / 来源 / 原文链接),与AiWebSearchPageSchema字段对应。
异步任务队列 task_queue/
基于 arq(Redis 后端)的异步 Worker,用于文档解析等耗时任务异步化、可水平扩展:
bash
uv run arq app.api.v1.module_ai.framework.task_queue.worker.WorkerSettingsWorkerSettings 复用 task_queue_settings(队列名、Redis、并发、超时、重试),队列名须与投递端一致。
前端对应:文档入库后的解析、向量化等耗时步骤投递到该队列异步执行;前端
apps/web-ele/src/views/ai/knowledge/document/通过轮询/状态展示解析进度,避免阻塞用户操作。