一个面向知识资产问答场景的轻量 Web App。项目实现了知识资产列表、新增资产、基础检索、Agent 问答、引用来源和可审计的 Agent Trace。
- React + TypeScript + Vite
- CSS Grid / Flexbox / CSS Variables
- localStorage 作为本地持久化
- Vitest 覆盖核心检索与问答逻辑
- lucide-react 提供操作图标
npm install
npm run dev本地开发服务默认由 Vite 启动,通常是 http://localhost:5173。
生产构建:
npm run build测试:
npm test- 展示知识资产列表,每条资产包含
id、title、content、tags、createdAt。 - 内置 3 条初始知识资产:AIOS 平台介绍、数字资产知识库、Agent 工作流。
- 支持新增知识资产,提交后立即进入列表,并持久化到 localStorage。
- 支持编辑、删除、重置、导入和导出知识资产。
- 支持按标题、正文或标签筛选资产,资产多时也能快速定位。
- 支持基于关键词、标签、标题、正文和中文字符覆盖率的 Top 3 检索。
- 支持用户向 Agent 提问。
- 提供示例问题入口,评审打开页面后可以一键体验典型问答链路。
- Agent 基于检索结果生成本地可解释回答,并展示引用来源。
- 提供“本地问答”和“模型接入预览”两种模式。模型接入预览会生成可发送给真实模型的提示词,但本地仍保持零配置可运行。
- 展示中文化 Agent Trace,包括模式、用户问题、命中资产、相关度分数、提示词预览和最终回答。
- 覆盖 Loading、Empty、Error 状态。
- 页面采用响应式布局,桌面端为三栏工作台,窄屏下自动堆叠。
- 增加领域逻辑测试和 UI 交互测试,覆盖新增、编辑、删除和模型接入预览模式。
type KnowledgeAsset = {
id: string;
title: string;
content: string;
tags: string[];
createdAt: string;
};
type SearchResult = {
assetId: string;
title: string;
snippet: string;
score: number;
};设计思路:
KnowledgeAsset保持足够简单,适合前端内存、JSON 文件、SQLite 或后端数据库之间迁移。tags使用数组而不是字符串,方便检索、筛选和未来做权限/分类。createdAt使用 ISO 字符串,方便排序、跨端传输和持久化。SearchResult不直接复制完整正文,只暴露snippet,避免检索结果区过载。
当前实现位于 src/domain/knowledge.ts。
检索流程:
- 将用户问题分词并去重。
- 对每条知识资产计算相关度分数。
- 标题命中权重最高,标签次之,正文命中再次之。
- 对较长中文 query 增加字符覆盖率评分,但排除高频停用字,避免无关中文问题误召回。
- 过滤零分资产,按分数降序返回 Top 3。
这个方案没有依赖真实向量数据库,优点是稳定、可解释、无外部服务成本,适合笔试范围内展示检索链路和产品判断。
- 为每条
KnowledgeAsset增加embeddingId、tenantId、updatedAt、sourceType等字段。 - 新增 ingestion 流程:资产新增或更新后切分 chunk,生成 embedding,写入向量库。
- 检索从当前本地 scoring 改成 hybrid search:关键词过滤 + 向量召回 + rerank。
SearchResult保留assetId、snippet、score,但 score 来源改为向量相似度和 rerank 综合分。- Agent Trace 继续保留 Query、Retrieved Assets、Scores 和 Final Answer,便于排查召回质量。
当前项目已经在 Trace 中生成提示词预览,这是接入真实 LLM 的边界。
实际接入时我会这样改:
- 新增后端 API Route,例如
POST /api/agent/answer,前端只传用户问题和检索结果 ID。 - 服务端读取模型密钥,避免把 API Key 暴露到浏览器。
- 将提示词预览作为服务端 prompt builder 的输入模板,加入引用约束和输出 JSON schema。
- 模型返回后仍保留 sources 和 trace,避免答案变成黑盒。
- 增加超时、重试、限流、内容安全过滤和成本统计。
- 如果模型失败,回退到当前本地检索式回答,让产品仍可用。
KnowledgeAsset增加tenantId、ownerId、visibility、acl。- 所有查询必须带
tenantId,服务端强制隔离,不能只依赖前端过滤。 - 向量库索引按租户隔离,或至少将
tenantId作为强过滤 metadata。 - localStorage 替换为后端数据库,并增加鉴权、审计日志和权限校验。
- Trace 中保留权限过滤结果,方便解释为什么某些资产没有被召回。
我最担心的是权限与可信度,而不是单纯的回答效果。
- 权限:企业知识通常包含客户资料、销售策略、合同、内部流程。如果检索层没有严格租户隔离和 ACL,Agent 很容易越权引用。
- 可信度:Agent 必须展示引用来源和检索过程,否则用户很难判断答案是否来自真实知识资产。
- 数据新鲜度:知识资产更新后,索引、缓存和向量库需要一致,否则会出现旧答案。
- 可观测性:需要记录 query、召回资产、分数、最终回答和用户反馈,才能持续优化。
- 成本与延迟:真实 LLM 和 embedding API 成本不可忽视,需要缓存、限流和异步索引。
- 选择 localStorage:笔试要求允许内存、localStorage、JSON 或 SQLite。这里选择 localStorage,可以直接体验新增资产后的持久化。
- 没接真实 LLM:题目允许本地模拟回答。当前答案明确基于检索结果生成,并展示引用和 Trace。
- 增加模型接入预览模式:它展示真实接入所需的提示词和 Trace 边界,但不要求评审配置密钥。
- 没引入 UI 框架:为了控制视觉细节和代码体积,使用原生 CSS 实现三栏工作台。
- 检索不用向量库:当前重点是产品判断、工程结构和可解释链路;向量库接入方案已在上文说明。
- 未接入真实后端、真实 LLM、真实 embedding 或向量数据库。
- 未实现登录、租户权限。
- 未实现服务端审计日志。
这些能力属于下一阶段工程化建设,不影响当前笔试要求中的本地可运行知识资产问答工作台。
