前一阵手头有个活儿要把一套私有知识问答系统整个放到本地一边是算能1684x 这颗边缘TPU上面跑 qwen3-vl 多模态大模型一边是腾讯开源的 weknora 知识库平台负责 RAG 检索和知识图谱最后再用编排服务把两边接起来让用户提问时能“先检索、后生成”。整套东西跑通之后机箱温度稳定功耗不到 40W回答质量甚至比一些云端 API 组合还稳。今天这篇就把整个过程拆开讲清楚——模型怎么转换、知识库怎么部署、两端怎么连踩过的坑也一并列出来。这篇内容适合三类人手里有 1684x 这类边缘推理设备、想在上面跑视觉语言模型的算法工程师正在评估 weknora 或者 Dify 这类本地知识库方案、需要私有化落地的后端开发以及被 RAG 召回质量反复折磨、想搞清楚“RAG 和知识图谱到底怎么分工”的落地实践者。我把每一步都写成可以直接抄作业的状态但也保留了一些需要你自己根据设备情况微调的参数毕竟边缘部署这种事每个环境脾气都不一样。1. 项目全貌边缘盒子、视觉大模型与知识库的三方组合1.1 算能1684x为什么要把大模型塞进一台边缘设备算能 1684x 是 SOPHON 的第三代边缘推理芯片INT8 算力 32 TOPSFP16/BF16 约 16 TFLOPS板载 16GB LPDDR4X 内存。单看数字它比不上数据中心里的 A100但在“一台设备、一块板卡、几十瓦功耗”的约束下这个规格已经是跑生成式模型的准入门槛量化后的 2B/4B 模型完全装得下推理速度也能做到每秒几 token 到十几 token用于知识库问答这种场景完全够用。选择边缘部署的核心原因就三个数据不出内网、时延可控、长期成本低。企业知识库里的合同、竞品分析、售后工单通常都敏感上云意味着先把数据送出去很多客户这一关就过不了。1684x 盒子放在机房里模型和数据都在本地权限和审计自己说了算。另外现在一张像样的数据中心GPU月租不便宜而一台二手 1684x 开发盒的价格往往只有其零头跑单路并发完全够用。我这次用的是 1684x 的 PCIe 形态搭配一台普通 x86 主机。实际部署时你也可以选整机盒子驱动和接口基本一致。需要提醒的是1684x 的驱动和编译工具链虽然开源但文档分散在好几个仓库里第一次接触的人很容易在环境上卡一两天后面我会把关键步骤和版本对应关系整理清楚。1.2 qwen3-vl给纯文本知识库加上“眼睛”qwen3-vl 是阿里推出的开源多模态大模型支持图片、文字混合输入。为什么知识库场景特别需要它因为企业内部文档远不止 PDF 和 Word——聊天截图、产品说明书里的结构图、表格截图、会议白板照片这些东西纯文本模型完全看不到。传统做法是先用 OCR 把图片转成文字再入库但 OCR 遇到复杂表格、页面版式乱的情况识别结果经常是灾难性的。qwen3-vl 的视觉理解能力可以让这条链路简化不少图片入库时模型直接生成图片的结构化描述或抽出关键信息用户带着截图提问时模型可以直接“看图回答”不再依赖那层脆弱的 OCR 中间件。官方发布了 2B、4B、32B 等多个规格还有 235B 的超大版本。我最终选的是 4B Instruct 版本在 1684x 上做 INT8 量化后权重约 4GB加上 KV Cache 和中间张量16GB 内存余量充足32B 即使量化也超过 20GB强行跑只能靠外部内存交换体验会很差。如果你只是做内部工具、对时延不敏感4B 绝对是甜点选择如果后续有更复杂的图表推理需求再考虑把视觉塔单独拆分到 GPU 上跑LLM 部分留在 1684x这种混合部署后面也会提到。1.3 WeKnora它不是普通 RAG而是“RAG 知识图谱”双引擎WeKnora 是腾讯开源的知识管理检索平台官方定位是把非结构化文档和结构化知识统一管理起来。它和我之前用过的那些向量数据库套壳产品最大的区别在于默认就把 RAG 和知识图谱放在同一套体系里。文档进来之后除了做切片、向量化、建立倒排索引还可以用 Ontology本体配置抽取出实体和关系形成知识图谱。查询时做混合检索——向量召回、BM25 关键字、图谱多跳查询同时跑再重排序。这个设计直击 RAG 的两个老毛病。第一纯向量检索对“断点式事实”和“需要常识推理的问题”召回很差比如“A公司的供应商里有哪些是通过B介绍的”文档里未必有现成句子但图谱里一跳就能查出来。第二RAG 在数字计算、多跳逻辑上经常翻车图谱侧的精确查询可以兜底。WeKnora 把这些能力封装成了标准 API前端带管理后台还支持 OIDC 企业登录对私有化部署非常友好。另外WeKnora 支持多模态数据入库。图片、音频、视频都可以作为知识对象存储图片会走 OCR 或视觉描述生成索引音视频可以走 ASR 转写。也就是说“RAG 知识库能存图片吗”这个问题的答案在 WeKnora 里是肯定的而且存的不仅是文件本身还有针对图片内容建立的检索索引。后面我会详细演示图片入库的实际效果。2. 部署前的整体架构设计与资源规划2.1 三层架构模型服务、知识库平台、编排层如何联动动手之前先把架构画清楚后面才不会乱。整个系统分三层模型服务层1684x 上跑 qwen3-vl 量化推理对外暴露 OpenAI 兼容的/v1/chat/completions接口处理文本和图片输入。知识库层WeKnora 负责文档解析、向量化、图谱构建和检索对外暴露检索 API、管理 API内部依赖 PostgreSQL、Milvus、MinIO、Redis 等组件。编排层一个轻量 Python 服务接收用户问题调用 WeKnora 检索出 top-k 片段组装成带上下文的 prompt再送给 qwen3-vl 生成答案。之所以不让 WeKnora 直接调外部大模型 API是因为我们要确保生成这个动作也发生在本地。WeKnora 本身支持配置 OpenAI 兼容的 LLM 地址所以最简单的接法是把模型服务层的地址直接填进 WeKnora 的 LLM 配置里这样 WeKnora 的问答页面就成了完整入口。但为了灵活处理“带图提问”和“多轮会话”我还是加了一层编排服务统一控制检索参数和 prompt 模板。2.2 硬件与系统准备清单我实际使用的硬件组合一块 1684x PCIe 卡16GB 版本插在一台双核四线程的旧工作站上宿主机 32GB 内存系统盘和知识库数据盘分开。注意WeKnora 的组件默认跑在 Docker 里宿主机内存如果只有 16GB同时跑 PostgreSQL、Milvus、MinIO 和多个 Python 服务会比较紧张建议至少 24GB 以上。软件栈分两套环境一套是编译环境负责把 qwen3-vl 转成 bmodel我直接用 x86 主机 Docker 里的 tpu-mlir 镜像另一套是运行环境负责加载 bmodel 做推理需要安装 libsophon 驱动和运行时。两套环境不要混着用因为 tpu-mlir 的编译环境和运行时库版本经常不完全同步我在这上面栽过跟头。系统层面用 Ubuntu 20.04 或 22.04 都行内核不用特调官方驱动包有预编译的 deb。Docker 环境单独装 docker-ceWeKnora 的 docker-compose 文件对版本有要求太老的 docker-compose 会遇到不兼容的参数。2.3 模型规格选择2B、4B、32B 怎么定这个问题很多人问我给的答案很直接1684x 上就用 4B。原因不只是内存还有 INT8 量化后的质量衰减。2B 模型量化后虽然更快但在中文长文档、复杂表格这类场景下幻觉率明显偏高经常一本正经地编造答案32B 就算能勉强塞进 16GBKV Cache 和并发吞吐也完全不可用。具体算一下账Qwen3-VL-4B 的 INT8 bmodel 大约 4GB给 KV Cache 留 4GB视觉塔的输出缓冲和推理中间张量留 4GB剩下的 4GB 给系统和其他进程。这是比较健康的分配。如果后续要加并发可以再把权重压到 INT4但 INT4 在视觉任务上的掉点会比纯文本更明显尤其是 OCR 场景字符容易出错我建议至少保留 INT8。选型确定之后还有一个隐藏决策视觉塔跑在哪里。qwen3-vl 由视觉编码器和 LLM 解码器两部分组成。1684x 上直接把整个模型转成一个 bmodel 不是不行但视觉塔是 CNN/Transformer 混合结构在 tpu-mlir 的算子覆盖上容易卡住。我的做法是LLM 部分用 TPU 跑视觉塔单独导出 ONNX在 CPU 上执行。虽然视觉编码每次要几十毫秒但相比 LLM 生成动辄几秒的总耗时这点开销完全可以接受而且换来的是转换过程的稳定和可调试性。3. qwen3-vl 在 1684x 上的部署转换、量化与 OpenAI 兼容服务3.1 跑通 1684x 的基础环境驱动与 tpu-mlir先装驱动和运行时。SOPHON 的 SDK 分几个包libsophon 里包含 PCIe 卡的驱动、BMRuntime 运行时以及 bmrt_test 这类工具tpu-mlir 是编译工具链负责把 PyTorch 模型转换成 bmodel。装驱动时要注意内核版本官方 deb 包对某些新内核的 open 驱动支持不好如果你用的内核太新安装后bm-smi查不到设备大概率就是驱动模块没加载成功。# 运行环境1684x 主机 sudo dpkg -i sophon-driver_*.deb libsophon_*.deb sudo apt-get install -f # 验证设备 bm-smi编译环境我建议直接用 Dockerdocker pull sophgo/tpuc_dev:latest docker run -v $(pwd):/workspace -it sophgo/tpuc_dev:latest模型权重从 ModelScope 或 HuggingFace 拉qwen3-vl-4b-instruct 下载下来约 8GB。下载后先确认 tokenizer 配置文件里的model_typetpu-mlir 对 Qwen 系列的支持比较成熟但如果版本太旧可能认不出 qwen3_vl 这个新类型这时候要么升级 tpu-mlir要么手动改配置前者优先。3.2 核心难点视觉语言模型怎么拆开转换这是我这次项目里最花时间的一步。 qwen3-vl 的结构可以理解成三块ViT 视觉编码器、连接视觉与文本的 patch 融合层、以及 LLM 解码器。如果试图一次转换tpu-mlir 大概率在 ViT 的某些算子上报错然后你要花一整天去逐层绕行。我试了两条路。第一条是完整转换失败在注意力机制的动态形状上第二条也就是最终采用的方案是把 LLM 部分当作一个纯文本模型转换视觉塔输出先算好作为 token 序列拼进 prompt。LLM 部分的转换命令大致如下model_transform.py \ --model_name qwen3_vl_llm \ --model_type qwen3_vl \ --input_path Qwen3-VL-4B-Instruct \ --mlir_path qwen3_vl_llm.mlir model_deploy.py \ --mlir_path qwen3_vl_llm.mlir \ --quantize INT8 \ --chip bm1684x \ --output qwen3_vl_llm_int8.bmodel如果你的 tpu-mlir 版本还没有 qwen3_vl 的模型类型支持就退一步用--model_type qwen2配合手工改好的 config 来转换但要注意词表尺寸和tie_word_embeddings这些配置项改错一个解码就崩。视觉塔这边用torch.onnx.export导出固定输入分辨率我用 448x448导出后把输出特征的维度和 LLM 的 embedding 维度对齐这一步决定了后面拼接是否顺利。3.3 写一个 OpenAI 兼容的推理服务把视觉和文本统一暴露出去转换完成后下一步是写一个 HTTP 服务把 bmodel 的加载和推理封装成标准接口。这里强烈建议做成 OpenAI 兼容格式理由很简单无论是 WeKnora、Dify 还是你后面想接的任何开源项目都认识/v1/chat/completions。下面是核心代码的骨架Sophon 运行时 API 我简化了重点是接口结构。from fastapi import FastAPI, HTTPException from pydantic import BaseModel import base64, io, requests from PIL import Image app FastAPI() class Message(BaseModel): role: str content: str class ChatRequest(BaseModel): model: str messages: list[Message] max_tokens: int 2048 temperature: float 0.7 def extract_text_and_image(messages): 从 messages 里解析纯文本和图片 base64返回 (文本, PIL.Image 或 None) text_parts, image [], None for msg in messages: if isinstance(msg.content, str): text_parts.append(msg.content) elif isinstance(msg.content, list): # OpenAI 多模态消息格式 for item in msg.content: if item.get(type) text: text_parts.append(item[text]) elif item.get(type) image_url: url item[image_url][url] if url.startswith(data:): _, b64 url.split(,, 1) image Image.open(io.BytesIO(base64.b64decode(b64))) return \n.join(text_parts), image app.post(/v1/chat/completions) async def chat(req: ChatRequest): text, image extract_text_and_image(req.messages) if image is None: raise HTTPException(400, 当前接口需要图片输入) # 1. 视觉塔CPU/ONNX预编码 image_feats vision_encoder(image) # shape: [num_patches, hidden_size] # 2. 组装输入 token ids image feats input_ids, img_position build_model_inputs(text, image_feats.shape[0]) # 3. 1684x 上执行 LLM 生成bmodel 推理 output_ids llm_generate(input_ids, image_feats, img_position, max_tokensreq.max_tokens) output_text tokenizer.decode(output_ids) return { id: chatcmpl-local, object: chat.completion, choices: [{ index: 0, message: {role: assistant, content: output_text}, finish_reason: stop }] }编码实现里最需要注意的是build_model_inputs。qwen3-vl 的图像 token 有固定数量位置 id 要和文本 token 区分开否则模型对齐位置信息会错乱表现就是回答内容与图片完全无关。我自己第一次跑通时忘记给图像 token 加独立的 position id结果模型把图片当成了一堆无意义文本输出乱码排查了很久。3.4 部署后的第一轮验证服务起来之后先用一张带文字的截图测 OCR 能力再用一张表格截图测结构理解。我实测 4B 模型在这两种任务上表现合格中文识别准确率能到 90% 以上但长文档里的生僻词偶尔会认错这是量化后的正常损耗。速度方面单请求场景下首 token 大约 1 秒左右后续每个 token 大约 100-200ms30 秒内能答完一段 200 字以内的长答案。这个速度拿来给人用没问题但如果准备做高并发就要考虑给服务加队列和超时控制了。FastAPI 的异步接口被多个请求同时打进来后1684x 上的 bmodel 是串行推理的多余的请求只会堆积在内存里。我加了一层简单的信号量限制并发数为 1并把超时时间设为 120 秒宁可让用户等待也不能让进程被拖死。4. WeKnora 本地部署Docker Compose 与初始化配置4.1 组件拆解PostgreSQL、Milvus、MinIO 和它背后的角色WeKnora 不是一个单体应用而是典型的微服务组合。我部署的版本里核心组件包括FastAPI 后端服务负责文档解析、检索、问答编排Vue 管理后台负责知识库和文档的可视化管理PostgreSQL存知识库元数据、文档索引、用户信息Milvus存文档切片的向量MinIO存原始文件和解析产物Redis做异步任务队列的 broker。这么多组件堆一起端口规划很关键。我把 PostgreSQL 和 Redis 的端口不暴露到宿主机只让容器内部访问Milvus 只暴露 19530 给 WeKnora 后端MinIO 的 9000 端口倒是要暴露因为后续要直接在浏览器里看原始文件。WeKnora 后端默认端口是 8091管理端我用 Nginx 做了反向代理统一走 443 对外避免直接暴露多个端口。4.2 docker-compose 启动与初始化直接贴我用的精简版 compose完整版本你以官方仓库为准但结构就是这样version: 3.8 services: postgres: image: postgres:16 environment: POSTGRES_USER: weknora POSTGRES_PASSWORD: weknora_pass POSTGRES_DB: weknora volumes: - pg_data:/var/lib/postgresql/data redis: image: redis:7-alpine minio: image: minio/minio:latest command: server /data --console-address :9001 environment: MINIO_ROOT_USER: weknora_admin MINIO_ROOT_PASSWORD: weknora_secret ports: - 9000:9000 milvus: image: milvusdb/milvus:v2.4 command: [milvus, run, standalone] ports: - 19530:19530 volumes: - milvus_data:/var/lib/milvus weknora: image: tencent/weknora:latest ports: - 8091:8091 environment: DB_HOST: postgres DB_PORT: 5432 REDIS_HOST: redis MILVUS_HOST: milvus MINIO_ENDPOINT: minio:9000 volumes: - weknora_data:/app/data depends_on: - postgres - redis - minio - milvus volumes: pg_data: milvus_data: weknora_data:启动后访问管理后台第一次会让你初始化管理员账号。初始化完成后先进“系统设置”检查三个东西Embedding 模型是否可用、LLM 地址是否已配置、对象存储连通性。WeKnora 支持内置的多家 Embedding API但在完全本地化的要求下我直接用 Docker 额外跑了一个 bge-small-zh 的 OpenAI 兼容 Embedding 服务地址填进 WeKnora三分钟就通了。4.3 把知识库建起来文档、网页、图片分别怎么入库WeKnora 的知识库创建很简单但有几个细节会直接影响检索效果。第一个是切片策略。我的经验是中文文档的 chunk_size 不要超过 500overlap 控制在 50 左右太长的 chunk 虽然能减少切片数但很容易把两个不相关的话题包在一起检索时召回一个四不像的片段。第二个是格式选择PDF 优先走内置的解析器Word 和 Markdown 走文本直读HTML 需要先清洗标签。WeKnora 对 PPT 和扫描版 PDF 的处理也比较完善扫描版会自动触发 OCR。图片入库这块我重点说一下。WeKnora 会把图片原文件存到 MinIO同时生成两个索引一个是 OCR 识别出的文字一个是视觉模型生成的图片描述。这样用户后面用“那张关于库存周转率的截图”这种自然语言也能搜到图。我实测下来针对流程截图和图表把图片描述生成作为入库的一部分召回质量提升非常明显。4.4 Embedding 与 LLM 的对接让 WeKnora 用上 1684x 上的 qwen3-vl这是整个系统“连接”的关键一步。在 WeKnora 的 LLM 配置里填上我们前面启动的推理服务地址https://你的1684x主机:8000/v1/chat/completions注意 WeKnora 只会把这个地址当一个普通 OpenAI 兼容接口来用所以之前那 120 秒超时设置在这里很关键——WeKnora 内部调 LLM 也有自己的超时如果两边超时都设置得太短长答案生成到一半就被掐断。我建议模型服务超时至少 120 秒WeKnora 侧的 LLM 超时也同步调大。Embedding 服务同理如果有多个知识库建议统一用同一个 Embedding 模型否则向量空间不一致跨库检索就是灾难。5. 连接两者的实际链路检索-增强-生成5.1 混合检索与 RAG 瓶颈的解决思路很多人都问过我RAG 系统最大的瓶颈是什么。我的回答是不在于用哪个向量数据库也不在于用多大的模型而在于“进库的内容质量”和“检索的取舍逻辑”。PDF 解析得稀碎再好的 embedding 也召回不到完整语义只做向量召回碰到“关键词精确匹配”的问题就抓瞎。WeKnora 缓解这个问题的办法是混合检索。它把向量召回、BM25 关键字召回、知识图谱多跳查询并列执行然后重排序。我实际调参时的经验是把向量召回和 BM25 的权重设为 6:4当用户问题是“什么是xxx”这类概念性描述向量召回效果好当用户问题是“订单号 OID1234 的状态”这种强标识词问题BM25 会更有用。知识图谱则专门兜底“谁和谁什么关系”这类多跳问题。三者结合之后整体检索命中率比单一向量检索提升非常明显。5.2 用 WeKnora 的检索 API 组装上下文WeKnora 后端自带 Swagger 文档检索接口可以直接用。我的编排服务里查询的构造大致是这样import requests WEKNORA_URL http://localhost:8091 KB_ID your_kb_id def retrieve(question: str, top_k: int 5) - list[dict]: resp requests.post( f{WEKNORA_URL}/api/v1/query/{KB_ID}, json{ query: question, topK: top_k, searchStrategy: hybrid, # 混合检索 enableKG: True, # 开启图谱查询 }, timeout30, ) resp.raise_for_status() results resp.json().get(results, []) return results检索结果里每一项包含原文内容、来源文件、页码、得分。我一般只取 top 5把内容按得分降序拼进 prompt并标注来源。这里有一个小技巧对检索结果先做一个简单的去重同一份文档里相邻片段经常内容重叠直接拼进 prompt 会占用大量上下文窗口导致模型输出偏离。5.3 编排服务文本与图片混合提问的处理流程编排服务是整个系统的“调度中心”它要做的事包括判断用户是否带图、调用检索、组装 prompt、调用模型服务、返回答案、带上引用来源。核心代码如下def ask(question: str, image_base64: str | None None) - dict: # 1. 搜索知识库纯文本问题才检索带图时也可以先检索图片描述 context_chunks retrieve(question, top_k5) if not image_base64 else [] # 2. 组装 prompt if context_chunks: context \n\n.join( f[{i1}] {c[content]} for i, c in enumerate(context_chunks) ) prompt ( 你是一个企业内部知识助手。请严格基于以下资料回答 不要编造资料中没有的信息。如果资料不充分请直接说明。\n\n f资料\n{context}\n\n问题{question}\n答案 ) else: prompt question # 3. 调用 1684x 上的 qwen3-vl messages [{role: user, content: prompt}] if image_base64: messages [{ role: user, content: [ {type: text, text: prompt}, {type: image_url, image_url: {url: fdata:image/jpeg;base64,{image_base64}}} ] }] llm_resp requests.post( f{LLM_URL}/v1/chat/completions, json{model: qwen3-vl-4b, messages: messages, max_tokens: 1024}, timeout120, ) answer llm_resp.json()[choices][0][message][content] return {answer: answer, sources: [c[source] for c in context_chunks]}我建议在返回答案的同时把命中的文档名称和页码也带回前端让用户能看到答案来源。这一点从产品角度看极其重要——用户对 AI 答案天然不信任有据可查才敢用。如果你接 Dify把 WeKnora 的检索接口封装成 Dify 的外部知识库插件再在 Dify 的画布上把模型节点指向 1684x 上的 qwen3-vl也能实现几乎一样的效果只是自由度不如自己写编排层。5.4 图片问答链路一张截图直接问文本问答跑通之后图片问答也不难。用户在对话里发一张聊天截图编排服务把图片和问题一起发给 qwen3-vl模型直接看图回答。这里有个取舍如果图片内容已经在知识库里是不是应该先检索我的经验是——先让模型看图如果模型明确说“图里的内容不够需要查资料”再触发检索链路。因为图片本身的视觉信息往往已经足够回答强行检索反而会把模型带到与图片无关的文档里。不过如果用户问的是“帮我看看这张合同的审批金额对不对”这就必须是“图 合同模板库检索”双通道输入了。这种场景下我会把合同模板里的金额规则抽成文本连同图片一起给模型让模型对照校验。实测下来qwen3-vl 4B 对简单的金额、日期、编号核对准确率不错但复杂的条款比对偶尔会漏细节生产环境建议加一道人工抽检。6. 踩坑记录、调优心得与扩展方向6.1 部署运维常见问题速查表我把这两周遇到的高频问题整理成了一张表基本覆盖了从模型转换到知识库检索的主要故障点现象可能原因排查与解法bm-smi 查不到设备驱动模块未加载或内核版本太新检查 lsmod模型转换报算子不支持tpu-mlir 版本过旧或模型类型未识别升级 tpu-mlir 到最新容器镜像检查 config 的 model_typeINT8 量化后中文乱码量化样本不足或 tokenizer 配置被改坏用 100 条以上中文样本做校准对照原始 config 逐项核对视觉塔输出拼接错误图像 patch 的 position id 没处理好检查输入序列的 position_ids确保图像 token 段与文本段不重叠生成到一半被掐断模型服务的 max_tokens 或请求超时设置过短调大 max_tokens 到 4096超时到 120 秒以上检索结果与该问题无关切片过大、embedding 模型与知识不匹配缩小 chunk_size换领域适配的 embedding 模型开启混合检索WeKnora OIDC 登录失败回调地址未配置或 JWT 算法不匹配检查 OIDC 客户端回调地址、Token Endpoint 配置统一签名算法Milvus 容器反复重启内存不足或磁盘权限问题检查/var/lib/milvus挂载权限给容器单独分配 4GB 以上内存6.2 检索质量调优的实操心得检索质量是这个项目里最值得花时间的部分。我的第一个心得是先用 20 个真实问题做成一个评估集每次调完参数就跑一遍记录命中率。不要凭感觉调参。第二个心得是如果某个领域问题总是召回不对优先排查切片而不是换模型——十有八九是切片把关键信息切成了两半。第三个心得是重排序的阈值不要设太死我一般保留置信度排序不做硬过滤让大模型在生成时自己判断效果比硬切更好。知识图谱这块WeKnora 的 Ontology 配置决定了实体抽取的上限。默认的通用本体在企业场景下抽取出的实体太宽泛比如“合同”“版本”“金额”这种都抽但检索时用不上。我建议按业务来定义本体比如“客户”“项目”“审批人”“截止日期”这几个实体以及它们之间的关系图谱才真正有价值。6.3 在 1684x 上继续往下走的三个方向这套系统跑通之后还可以往三个方向扩展。第一接入音频会议纪要WeKnora 支持 ASR 转写把会议录音入库之后用户就能直接问“上次周会我们确认了哪些事项”。第二做定时增量更新写一个定时任务把网盘新增的文档自动同步进 WeKnora知识库保持新鲜度。第三把视觉塔也从 CPU 挪到 1684x 上跑减少整机对宿主 CPU 的依赖解放出来给其他服务。最后分享一个我个人的体会这种边缘部署项目里真正难的不是把某个模型跑起来而是让整条链路在有限的算力下稳定、可用、可维护。我在整个项目里最受益的一个决定是把模型服务做成 OpenAI 兼容接口——之后无论是接 WeKnora、Dify 还是其他工具都是改 URL 的事再也不用为每个平台写一套对接代码。如果你也要做类似的私有知识问答建议从一开始就坚持这个标准后面能少走很多弯路。