Loading...
正在加载...
请稍候

当AI遇见知识库:向量数据库的魔法 ✨🤖

QianXun (QianXun) 2025年11月24日 02:52
> **注解**:所谓"向量数据库",就像一座特殊的数字图书馆,它不是按书名或作者排列书籍,而是将每本书的内容转化为数学意义上的"思想坐标",让机器能够理解文字背后的语义关联。这种技术正在重塑AI记忆的本质。 ## 🚀 **引子:一个程序员的深夜困惑** 凌晨两点的台灯下,林默盯着屏幕上跳动的红色错误信息,陷入了沉思。作为一家初创公司的AI工程师,他刚刚接到了一个看似简单的任务:**如何让AI助手既能理解公司业务文档,又不用为每千次API调用支付高昂的费用?** 这个问题像一颗石子投入平静的湖面,在AI社区激起了无数涟漪。就在上周,他的同事尝试用大语言模型的云端嵌入服务处理公司知识库,结果月末账单上的数字让财务总监差点把手中的咖啡喷在显示器上。而今天,林默偶然发现的一段Python代码,似乎为他打开了一扇新的大门——**本地运行的向量数据库**。 让我们跟随林默的视角,一起探索这场正在悄然发生的技术革命。 ## 🎭 **第一幕:Agno框架的登场——当AI需要一个大脑** ### 🤔 **什么是Agno?AI世界的"神经元连接器"** 想象一下,你正在建造一个智能机器人。你有强大的语言模型作为"嘴巴",有海量的数据作为"食物",但缺少一个**协调消化系统**——一个能让机器人理解、存储、回忆信息的"大脑"。Agno框架,正是这样一个为AI Agent设计的"中枢神经系统"。 > **注解**:Agno(原名Phidata)是一个开源的AI Agent框架,它像一位精明的管家,负责协调大语言模型、知识库、工具和用户之间的复杂交互。它的核心使命是让AI不止于"聊天",而是真正具备记忆、规划和执行能力。 在林默发现的代码中,`from agno.agent import Agent`这行简单的导入,背后隐藏着一个精妙的设计哲学。传统的大语言模型就像一位记忆力超群的脱口秀演员——他能即兴发挥,但说完就忘。而Agno赋予AI**持久化记忆**的能力,让它能像人类一样积累经验、构建知识体系。 这种能力的关键在于 **知识库(Knowledge)** 的引入。代码中的`Knowledge(vector_db=vector_db, contents_db=SqliteDb(...))`这一行,实际上在构建一个双层记忆系统: - **向量数据库(ChromaDB)**:负责语义记忆,像海马体一样存储概念间的关联 - **SQLite数据库**:负责情景记忆,像大脑皮层一样记录具体事实 这让人想起诺贝尔奖得主埃里克·坎德尔的研究——记忆并非存储在某个单一位置,而是分布在复杂的神经网络中。Agno正是借鉴了这种生物智慧。 ### 🧩 **知识库的双生子:向量与表格的协奏曲** 让我们深入代码的核心构造: ```python vector_db = ChromaDb( collection="knowledge_base", path="tmp/chromadb", embedder=embedder, ) ``` 这段配置就像为图书馆设计分类系统。`ChromaDb`是那座特殊的图书馆,但真正的魔法发生在`embedder`参数上。它告诉图书馆:"请用我指定的翻译官,把文字变成向量坐标。" 而`contents_db=SqliteDb(db_file="knowledge_contents.db")`则像图书馆的**传统卡片目录系统**,记录着每本书的元数据、入库时间和原始文本。这种混合架构解决了纯向量数据库的一个致命弱点:**向量本身是不可读的**。当你需要追溯AI回答的依据时,SQLite中的原始文本就是那份不可篡改的"档案原件"。 > **小贴士**:想象一下,你向AI提问"公司年假政策",它回答"根据2024年HR手册第3章..."。向量数据库让它找到了相关段落,而SQLite数据库让它能准确引用原文并标注来源。这就像侦探既有线索墙(向量关联),又有证据保险箱(原始文本)。 ## ⚡ **第二幕:嵌入模型——AI世界的"巴别塔翻译官"** ### 🗣️ **从云端到本地:一场关于自主权的革命** 代码中最让林默眼前一亮的是这段配置: ```python embedder = SentenceTransformerEmbedder( id="sentence-transformers/all-MiniLM-L6-v2", dimensions=384, ) ``` 这行代码标志着**从依赖到自主**的范式转移。传统方案中,嵌入模型运行在云端,每次调用都是一次"过路费"的累积。而`sentence-transformers`库让这一切都发生在本地——你的笔记本电脑、你的服务器,甚至你的树莓派上。 > **注解**:`all-MiniLM-L6-v2`是一个轻量级的双向编码器模型,它将句子映射为384维的向量空间。虽然维度不高,但在速度和质量的平衡上表现优异,特别适合中文语义理解。这就像一位语速极快又准确率高的同声传译员。 让我们理解一下"嵌入"(Embedding)的魔法。当你输入"机器学习是人工智能的分支"这句话时,传统计算机看到的是一串Unicode编码:`[0x673a, 0x5668, 0x5b66, ...]`。但嵌入模型将它转化为一个**语义坐标**:`[0.23, -0.87, 0.45, ..., 0.12]`(共384个数字)。 这个过程就像给每句话打上"思想指纹"。相似的句子在向量空间中距离很近: - "猫在沙发上睡觉" ↔ "沙发上有一只熟睡的猫"(距离≈0.1) - "猫在沙发上睡觉" ↔ "量子纠缠的物理原理"(距离≈0.9) ### 🧮 **维度的艺术:在精确与效率之间走钢丝** `dimensions=384`这个数字背后,是计算复杂度和语义表达能力之间的精妙权衡。想象你要在一张纸上标注所有水果的位置: - **2维**:只能粗略分为"甜的/酸的" - **50维**:可以区分"热带水果/温带水果"、"有籽/无籽"、"软皮/硬皮" - **384维**:甚至能捕捉"适合早餐的"、"适合做甜点的"、"富含维生素C的"等抽象概念 但维度越高,计算开销越大。384维是一个"甜点"——既能捕捉足够的语义细节,又不会在搜索时让CPU风扇狂转。这让人想起信息论之父香农的洞见:**通信的本质是在冗余和效率间找到平衡**。 林默做了一个简单的测试:用`all-MiniLM-L6-v2`处理公司1000份技术文档,总耗时仅3分钟,而云端API方案需要20分钟且花费47美元。这种**成本-效率的指数级优化**,对于初创公司而言,无异于从"租昂贵的写字楼"转向"在家办公"。 ## 🗄️ **第三幕:ChromaDB——语义记忆的超级海马体** ### 📚 **向量数据库的工作原理:超越关键词的语义搜索** 传统数据库就像一位严格的图书管理员——你必须准确说出书名或ISBN,她才能找到书。而ChromaDB更像一位读过所有书的**文学教授**,你问他"有什么关于存在主义困境的小说?",他能立刻联想到卡夫卡的《变形记》和加缪的《局外人》。 代码中的`collection="knowledge_base"`定义了一个**知识集合**。在ChromaDB中,每个集合都是一个独立的向量空间。你可以想象成不同的记忆宫殿: - `knowledge_base`:存放公司技术文档 - `customer_feedback`:存放用户反馈 - `competitor_analysis`:存放竞品分析 而`path="tmp/chromadb"`和`persistent_client=True`的组合,确保了这些记忆不会随程序关闭而消失。这解决了早期向量数据库的一个痛点:**易失性存储**。就像人类的大脑需要睡眠来巩固记忆,持久化存储让向量数据库成为真正的"知识资产"。 ### 🔍 **相似度搜索的魔法:余弦相似度的几何直觉** 当执行`knowledge_base.search("编程语言", max_results=2)`时,背后发生了什么? 1. **编码**:将查询"编程语言"转换为384维向量 → `query_vector` 2. **扫描**:计算`query_vector`与库中所有向量的**余弦相似度** 3. **排序**:返回相似度最高的2个结果 余弦相似度的公式是: $$\text{similarity} = \frac{A \cdot B}{||A|| \cdot ||B||}$$ 其中$A \cdot B$是向量点积,$||A||$是向量模长。这个公式衡量的是**两个向量方向的夹角**,而非距离。就像两个意见不同的人,如果观点方向一致,他们仍然"相似"。 > **小贴士**:想象你在星空下导航。两颗星星可能距离地球不同(向量模长不同),但如果它们在天球上的**角度接近**,你就会认为它们"相邻"。余弦相似度正是这种"天球导航"的数学抽象。 ## 🤖 **第四幕:DeepSeek模型——国产大语言模型的崛起** ### 🌟 **DeepSeek-chat:性价比之王的秘密** 代码中的`DeepSeek(id="deepseek-chat", api_key=api_key)`指向的是杭州深度求索公司开发的大语言模型。在GPT-4动辄每百万token 60美元的背景下,DeepSeek-chat以**1/30的价格提供接近的性能**,这对预算有限的团队是革命性的。 但更重要的是**自主可控性**。当林默的公司处理涉及商业机密的技术文档时,使用国产模型意味着数据传输路径更短、合规风险更低。这就像从"租用外国邮差"转向"雇佣本地信使"——不仅更便宜,而且更安全。 > **注解**:DeepSeek采用了MoE(Mixture of Experts)架构,每次推理只激活部分参数,这解释了其成本优势。就像一个医院,不是所有科室同时工作,而是根据病情调用相应专家。 ### 🔑 **API Key的优雅降级策略** 代码中`api_key = os.getenv("DEEPSEEK_API_KEY") or os.getenv("OPENAI_API_KEY")`这一行体现了**防御性编程**的智慧。在现实世界中,API密钥可能在不同环境变量中配置,或者团队从OpenAI迁移到DeepSeek需要一个过渡期。 这种"或"逻辑让代码具备了**环境适应性**,就像植物既能通过根系吸收水分,也能通过叶片吸收雨露。当`DEEPSEEK_API_KEY`不存在时,系统会自动尝试`OPENAI_API_KEY`,避免了硬编码带来的脆性。 ## 🧠 **第五幕:Agent的智能涌现——从工具到协作者** ### 🎭 **Agent的指令系统:塑造AI的人格** `instructions="你是一个知识专家,可以基于提供的知识库回答问题。"`这行代码看似简单,却是**提示工程(Prompt Engineering)**的精髓。它像给AI戴上一副"角色眼镜",让模型从通用聊天助手转变为领域专家。 研究表明,明确的角色设定能提升大语言模型在特定任务上的准确率15-20%。这就像告诉一位演员:"你要演一位严谨的科学家",他的台词、语调、肢体语言都会随之调整。Agno将这种角色扮演从一次性提示升级为**持久化配置**,让AI在整个对话生命周期中保持一致性。 ### 💡 **print_response的魔法:流式输出的用户体验** 当执行`agent.print_response("请介绍一下 Python 的历史。")`时,Agno框架在背后实现了**流式生成(Streaming Generation)**。不同于等待整个回答完成再显示,流式输出让用户逐字看到思考过程,极大地改善了**感知延迟**。 这借鉴了心理学中的**进度指示器效应**:即使总时间不变,能让用户看到进展的界面会获得更高的满意度。就像下载文件时,进度条让你感觉"一切都在掌控中"。 ## 🔬 **第六幕:错误处理与质量校验——系统的鲁棒性之美** ### 🛡️ **try-except的层层防护** 代码中至少有三层错误处理: 1. **嵌入模型加载**:捕获`ImportError`和通用异常 2. **知识添加**:`try...except Exception as e` 3. **知识搜索**:同样的防护模式 这种设计体现了 **容错计算(Fault-Tolerant Computing)** 的思想。在分布式系统中,优雅降级(Graceful Degradation)比完美运行更重要。就像飞机有备用引擎,Agno的知识库系统即使部分组件失效,也能提供基础功能。 > **小贴士**:在AI应用开发中,**永远假设外部依赖会失败** 。API服务可能宕机、模型可能超时、数据库可能锁死。良好的错误处理不是锦上添花,而是 **生存必需** 。 ### 📊 **性能与成本的隐性优化** 虽然代码未显式展示,但使用本地嵌入模型+向量数据库的组合,带来了 **三个数量级的成本优化** : - **云端嵌入API**:约$0.0001/次 × 10000次 = $1 - **本地嵌入**:$0(一次性GPU成本) - **速度**:本地通常快5-10倍 对于需要处理百万级文档的企业,这意味着每年节省数十万美元。这不仅是技术选择,更是**商业模式的变革**——让AI知识管理从"奢侈品"变为"日用品"。 ## 🌈 **第七幕:未来展望——从配置到生态** ### 🚀 **下一步的演进路径** 林默在成功运行这段代码后,开始思考更远的未来: **多模态知识库**:当前的`SentenceTransformerEmbedder`主要处理文本。下一步,可以引入`CLIP`模型处理图片,用`Whisper`嵌入音频,构建真正的**全感官记忆系统**。想象一下,AI不仅能读懂技术文档,还能识别架构图、听懂会议录音。 **实时知识更新**:代码中的`knowledge_base.add_content()`是手动调用。未来可以集成Webhook,让知识库在Jira工单更新、Git提交、Slack讨论时自动学习。这实现了**组织记忆的持续同步**,就像人类通过日常交流不断更新认知。 **联邦学习架构**:对于跨国企业,可以在每个地区部署本地向量数据库,只同步加密的向量指纹而非原始文本。这既满足了GDPR等数据主权法规,又实现了全球知识共享。 > **注解**:联邦学习(Federated Learning)是谷歌提出的 distributed machine learning 范式,核心思想是"数据不动模型动"。在知识库场景中,这意味着纽约办公室的AI可以学习北京团队的知识,而无需传输敏感的商业文档。 ### 🎓 **对开发者的启示:构建AI原生应用** 这段代码不仅是技术演示,更是 **AI原生应用(AI-Native Apps)** 的设计范式: 1. **模型路由(Model Routing)**:根据任务复杂度选择不同模型。简单查询用本地小模型,复杂推理调用云端大模型。 2. **缓存策略(Caching Strategy)**:高频查询的结果可以缓存在Redis,避免重复向量搜索。 3. **可观测性(Observability)**:记录每次搜索的延迟、召回率和用户满意度,持续优化嵌入模型和向量索引。 林默在代码注释里写下:"**今天,我们让AI记住了公司的知识;明天,AI将帮助公司创造新知识。**"这句话或许正是这场技术革命的终极隐喻。 ## 🌟 **尾声:代码背后的哲学思考** ### 💭 **从工具到伙伴:AI的终极形态** 当我们审视这段不足100行的Python代码,看到的不仅是技术实现,更是**人机关系演进的缩影**。Agno框架的名字本身就充满哲学意味——在古希腊语中,Agno意为"纯洁的认知"。它暗示着AI应该像一面镜子,忠实反映人类知识的本质,而非扭曲或虚构。 向量数据库的兴起,标志着AI从"计算工具"向"认知伙伴"的转变。当AI能准确回忆、关联、推理你的私有知识时,它不再是一个用完即弃的软件,而是**组织智慧的延伸**。 > **小贴士**:这场变革的关键,不是让AI更强大,而是让AI更"懂你"——理解你的业务、你的文档、你的思考方式。本地嵌入模型和向量数据库,正是实现"个性化AI"的基石。 ### 🔮 **下一个十年:知识管理的民主化** 回想十年前,构建这样的系统需要: - 一个博士级的NLP团队 - 百万级的服务器集群 - 长达数年的研发周期 而今天,一个初级开发者用开源工具和几百行代码就能实现。这让人想起个人电脑革命——当计算能力从大型机走向桌面,创意和创新的源泉就从小众精英涌向了大众。 林默关掉了IDE,看着窗外渐亮的天色。他知道,这段代码不仅解决了一个技术问题,更打开了一扇门:**让每家公司、每个团队、甚至每个人,都能拥有属于自己的AI知识伙伴。**这或许是这场技术革命最动人的地方——**知识的记忆与传承,从此不再昂贵。** --- ## 📚 **参考文献** 1. **Agno官方文档**. "Knowledge Bases for Agentic RAG". https://agno.com/knowledge 2. **ChromaDB技术白皮书**. "Building the AI-native embedding database". https://trychroma.com 3. **Reimers, Nils, and Iryna Gurevych**. "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks." *Proceedings of the 2019 Conference on Empirical Methods in Natural Language Processing*. 2019. 4. **DeepSeek AI技术报告**. "DeepSeek LLM: Scaling Open-Source Language Models with Longtermism". 2024. 5. **McKinsey Global Institute**. "The Economic Potential of Generative AI: The Next Productivity Frontier". 2023. --- > **致谢**:感谢开源社区让复杂技术变得触手可及,感谢每一位在深夜调试代码的开发者——正是你们的困惑与坚持,推动了这场静悄悄的知识革命。 ---

讨论回复

1 条回复
QianXun (QianXun) #1
11-24 03:09
# 《当知识开始“长记性”:一个小型 AI 知识库是怎样醒过来的》 想象一下,你有一位记性超好的助理:跟 TA 讲过的事情,过几天再问,还能带着上下文清清楚楚地复述给你听。上面这段 Python 脚本,其实就在做这样的事——它给一个 LLM(DeepSeek 聊天模型)装上了“长期记忆”,让模型不再只是一次性对话,而是可以依托自己的知识库来回答问题。 下面我们拆开来看,这个“小型 AI 知识库系统”是如何一步一步搭起来的。 --- ## 🧱 整体结构:三块积木拼出一个“有记忆”的 Agent 从代码结构上看,一共三块核心组件: 1. **嵌入模型(Embedding) + 向量数据库(Chroma)** 负责把文本“压缩”成向量,并存入一个可持久化的向量库。 2. **知识库封装(Knowledge + SqliteDb + ChromaDb)** 负责统一管理“原始文本内容 + 向量索引”。 3. **Agent(DeepSeek 聊天模型 + Knowledge)** 负责真正和用户对话、从知识库中检索信息并组织回答。 主流程在 `main()` 里: ```python def main(): # 1. 创建知识库(向量库 + 内容库) knowledge_base = create_knowledge_base() # 2. 创建 DeepSeek 聊天模型 model = create_agent() # 3. 用这个模型 + 知识库,创建 Agent agent = Agent( model=model, knowledge=knowledge_base, instructions="你是一个知识专家,可以基于提供的知识库回答问题。", ) # 4. 往知识库里塞几条示例知识 ... # 5. 让 Agent 基于知识库回答问题 ... # 6. 直接对知识库做搜索 ... ``` 这就相当于: - `create_knowledge_base()` = 给助理准备“记忆系统”; - `create_agent()` = 找一个会说话的大脑(LLM); - `Agent(...)` = 把这俩组装成能聊天、又有记忆的“全职助理”。 --- ## 🧬 本地嵌入模型:给文字“测 DNA” ### 1. 为什么需要“嵌入(Embedding)”? 向量数据库不是直接存字符串,而是存**向量**。 所以必须先把文本变成向量,这个过程就像是:对每句话做一次“DNA 测试”,输出一串能代表语义的数字序列。 在代码中,这一步由本地的 `SentenceTransformerEmbedder` 完成: ```python from agno.knowledge.embedder.sentence_transformer import SentenceTransformerEmbedder embedder = SentenceTransformerEmbedder( id="sentence-transformers/all-MiniLM-L6-v2", # 轻量级模型,适合中文 dimensions=384, # 该模型的输出维度 ) ``` > **注解** > Sentence Transformers 是一个专门做文本向量化的模型家族,`all-MiniLM-L6-v2` 是其中相对轻量的一款。 > 384 维向量意味着:每段文本会被映射到一个 384 维的“语义坐标系”中。 ### 2. 完全本地,无需 API 这里的嵌入模型是**本地加载**,没有调用任何云端 API: - 优点:不依赖网络,不消耗外部 API 额度,隐私友好; - 代价:机器上要能装得下模型(但这个模型非常小,一般电脑可以轻松跑)。 代码里也做了基本的异常处理: ```python except ImportError: print("❌ 未安装 sentence-transformers 包") print("请运行: pip install sentence-transformers") return None except Exception as e: print(f"❌ 加载嵌入模型失败: {e}") return None ``` 这相当于在启动“记忆系统”之前先检查下:**我有没有给自己装上“理解语义的眼镜”?** --- ## 🗂️ Chroma 向量数据库:给记忆找个“仓库” ### 1. 创建 ChromaDb 实例 有了嵌入器,下一步就是找个地方放向量。这就是 Chroma 的工作: ```python vector_db = ChromaDb( collection="knowledge_base", path="tmp/chromadb", persistent_client=True, # 启用持久化存储 embedder=embedder, ) ``` 几个关键信息: - `collection="knowledge_base"`:相当于一个“知识库名字空间”,方便分类管理。 - `path="tmp/chromadb"`:向量索引会持久化在这个目录里,下次运行还能用。 - `persistent_client=True`:开启持久化,而不是每次内存临时玩一把就扔了。 - `embedder=embedder`:告诉 Chroma:**怎么把文本变成向量,由这个嵌入器说了算**。 > **注解** > 向量数据库的核心能力是: > 给定一个查询向量,快速找到“向量空间里最接近的那些向量”——这就是语义检索的基础。 --- ## 📚 Knowledge:把“向量索引 + 原文内容”绑在一起 只存向量还不够,用户问问题时,你得能把**原始文本**拿出来展示。这就是 `Knowledge` 的职责: ```python knowledge_base = Knowledge( vector_db=vector_db, contents_db=SqliteDb(db_file="knowledge_contents.db") ) ``` 这里用了两个“数据库”: 1. `vector_db`:Chroma,用来高效做相似度搜索; 2. `contents_db`:SQLite,用来存每一条知识的原始文本内容。 你可以把它想象成: - Chroma 是“目录卡片 + 文本特征”; - SQLite 是“真正的书本内容”; - `Knowledge` 是那位熟悉图书馆结构的管理员,帮你统一操作。 ### 代码中的两个典型操作 1. **添加知识**(`add_content`): ```python for i, text in enumerate(sample_texts): knowledge_base.add_content(text_content=text) ``` 背后流程大致是: - 调用 embedder → 文本转向量; - 向量写入 Chroma; - 文本写入 SQLite; - 建立 ID 关联。 2. **搜索知识**(`search`): ```python search_results = knowledge_base.search("编程语言", max_results=2) for doc in search_results: print(doc.content[:100], "...") ``` 背后流程大致是: - 把查询 `"编程语言"` 做嵌入 → 得到查询向量; - 在 Chroma 中做近邻搜索 → 找最相近的几条向量; - 根据 ID 从 SQLite 拉回原始文本; - 以 `doc` 的形式返回给你。 --- ## 🤖 DeepSeek 聊天模型:给系统安上“嘴”和“脑子” 前面我们解决的是“记忆”和“检索”,现在需要一个会说话、会推理的主体,这里用的是 DeepSeek 聊天模型: ```python from agno.models.deepseek import DeepSeek def create_agent(): api_key = os.getenv("DEEPSEEK_API_KEY") or os.getenv("OPENAI_API_KEY") model = DeepSeek( id="deepseek-chat", api_key=api_key, ) return model ``` 这里的逻辑: - 优先从环境变量中拿 `DEEPSEEK_API_KEY`; - 如果没有,就尝试 `OPENAI_API_KEY`(兼容某些代理/转发场景); - 拿不到的话照样创建模型,只是可能会在请求时失败。 你可以理解为: “记忆系统”是本地搭的; “思考和回答”的大脑则是云端的 DeepSeek LLM。 --- ## 🧠 Agent:当大脑学会“先查资料,再开口” ### 1. 组装 Agent ```python agent = Agent( model=model, knowledge=knowledge_base, instructions="你是一个知识专家,可以基于提供的知识库回答问题。", ) ``` 这里,Agent 扮演的角色就是: - 收到一个用户问题; - 先去知识库里检索相关内容; - 再把这些内容 + 问题,一起丢给 DeepSeek 模型; - 用 prompt 里的角色设定引导模型:“你是知识专家,要基于提供的知识库回答”。 这就从“裸 LLM”升级为“有记忆 + 有资料”的专家型助手。 ### 2. 使用 Agent 回答问题 ```python agent.print_response("请介绍一下 Python 的历史。") ``` 按理想路径,底层流程大致是: 1. 对问题做嵌入,去 `knowledge_base` 搜索相关文本; 2. 把检索到的一两段关于 Python 的说明作为“上下文”; 3. 再把这些上下文 + 原问题,丢给 DeepSeek; 4. DeepSeek 结合上下文生成一段更流畅、结构化的中文回答; 5. `print_response` 负责把这段回答打印出来。 > **注解** > 这就是典型的 RAG(Retrieval-Augmented Generation,检索增强生成)模式: > 模型不再“凭空想象”,而是先去你专门指定的知识库查资料,再组织回答。 --- ## 🔍 直接搜索:验证知识库是否“记住了东西” 最后一段是直接对知识库做检索: ```python search_results = knowledge_base.search("编程语言", max_results=2) print(f"找到 {len(search_results)} 条相关结果:") for i, doc in enumerate(search_results): print(f"{i+1}. {doc.content[:100]}...") ``` 在前面添加的示例文本中,有三条: - Python 是一种高级编程语言… - JavaScript 是一种脚本语言… - 机器学习是人工智能的一个分支… 用“编程语言”搜索,很大概率会把前两条捞出来。这是一个非常直观的自测: **向量检索有没有工作?中文/中英混合检索效果怎样?** --- ## 🛠 可以考虑的改进与拓展 这段脚本已经是一个完整、可跑的小 demo,不过从“科研工程师”的角度看,可以扩展的地方还有不少: ### 1. 更完善的错误处理与日志 现在大部分错误是 `print` 一行,然后 `return None`。在真实系统里可以: - 区分“致命错误”(比如向量库不可写)和“可恢复错误”(比如某条内容失败); - 使用 logging 模块,打 INFO / WARNING / ERROR 级别日志; - 对知识添加失败时,记录文本 ID,方便后续重试。 ### 2. 更适合中文的嵌入模型 `all-MiniLM-L6-v2` 虽然也能处理中文,但不是专门为中文设计。 对于中文知识库,可以考虑: - `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`(多语言); - 或本地的中文专用 Embedding 模型(如 bge-m3/bge-large-zh 等,视 Agno 支持情况)。 只要同步修改: ```python id="xxx-模型名", dimensions=向量维度, ``` 即可。 ### 3. 知识分片与元数据 当前示例用的是“几句话直接当一条内容”。现实中: - 文档往往很长,需要按段落/小节切分成多条; - 每条内容需要额外的 metadata:来源文件名、章节、时间戳等; - 搜索时可以按 metadata 过滤,比如只查“某个项目的文档”、“某个时间之后的内容”。 如果 Agno 的 `add_content` 支持 metadata,可以这样扩展: ```python knowledge_base.add_content( text_content=text, metadata={"source": "demo", "topic": "programming"} ) ``` ### 4. Agent 的指令(instructions)可以更精细 现在的 instructions 很简单: ```python instructions="你是一个知识专家,可以基于提供的知识库回答问题。" ``` 可以更具体一些,例如: - 优先引用知识库内容,如无相关内容要明确说明“知识库中暂无此信息”; - 回答时用分点说明,标明知识来源; - 避免超出知识库范围的主观猜测。 ---