How ItzCrazyKns/Perplexica Works
Perplexica 定位为开源、可自托管的 Perplexity AI 替代品。与 Perplexity AI 等商业云服务相比,其核心竞争优势在于 **隐私保护** 和 **高度可定制性**。用户可以将应用完全部署在自己的硬件上,掌控所有数据和模型交互,实现真正的私有化。它通过支持本地(Ollama)和多种云端(OpenAI, Anthropic 等)LLM 供应商,并集成隐私元搜索引擎 SearxNG,为技术爱好者和注重数据主权的企业提供了一个灵活、透明且功能强大的对话式搜索解决方案。它并非简单克隆,而是在技术上选择了更开放和模块化的架构。
Overview
Perplexica 定位为开源、可自托管的 Perplexity AI 替代品。与 Perplexity AI 等商业云服务相比,其核心竞争优势在于 **隐私保护** 和 **高度可定制性**。用户可以将应用完全部署在自己的硬件上,掌控所有数据和模型交互,实现真正的私有化。它通过支持本地(Ollama)和多种云端(OpenAI, Anthropic 等)LLM 供应商,并集成隐私元搜索引擎 SearxNG,为技术爱好者和注重数据主权的企业提供了一个灵活、透明且功能强大的对话式搜索解决方案。它并非简单克隆,而是在技术上选择了更开放和模块化的架构。
Perplexica 是一个以隐私为核心、可被私有化部署的 AI 问答引擎,它通过整合互联网信息、本地及云端大语言模型,为用户提供带有引用来源的、精准的答案。
How It Works: End-to-End Flows
AI 问答核心流程
这是用户与 Perplexica 交互最核心的场景。用户输入一个问题,系统首先对问题意图进行智能分类,判断是否需要联网搜索以及需要启用哪些专业信息源(如学术、论坛)。随后,系统会并行启动研究任务和小组件(如天气、计算器)。在研究阶段,AI 代理会根据用户选择的模式(速度/均衡/质量)进行多轮迭代的信息搜集,并将每一步进展实时地流式传输给前端。研究完成后,系统整合所有信息,指示一个“写作”AI 生成一份带有精确来源引用的、结构化的答案,并同样以流式方式逐字呈现在用户面前。整个过程旨在为用户提供一个透明、高效且可信的问答体验。
- 用户输入问题并发送
- 系统对查询进行意图分类,决定搜索策略
- 系统并行执行研究任务和小组件,并流式更新研究进展
- 研究完成后,系统整合信息并生成带引用的答案
- 系统流式输出最终答案,并在结束后提供后续问题建议
- 系统将完整的对话(包括所有中间步骤)持久化存储
构建与查询个人知识库
当用户需要基于私有文档进行问答时,会触发此流程。用户首先通过界面上传一个或多个文件(如 PDF、Word 文档)。系统接收到文件后,会自动在后台启动一条处理流水线:提取文本、进行语义切块、生成向量嵌入,并将结果存储在本地。此后,当用户在对话中提出与文档内容相关的问题时,系统的意图分类器会识别出“个人搜索”意图,并激活文档检索工具。该工具通过语义相似度匹配,在用户上传的文档中快速定位最相关的内容片段,并将其作为上下文提供给 AI,最终生成一个完全基于用户私有数据的精准回答。这为用户处理个人或企业内部知识提供了强大的隐私保障。
- 用户上传一个或多个文档文件
- 系统自动提取文本、切块、生成向量并持久化存储
- 用户在对话中提出与文档内容相关的问题
- 系统执行语义检索,从文档中找到最相关的内容片段
- 系统基于检索到的文档内容,生成并流式输出答案
首次安装与系统配置
此流程主要面向首次部署 Perplexica 的用户。用户通过 Docker 或源码方式启动应用后,会被引导至一个设置页面。在这里,用户可以配置核心系统依赖,最关键的是添加至少一个大语言模型供应商(如本地的 Ollama 或云端的 OpenAI)并填入凭证。系统提供了对多种主流供应商的“即插即用”支持。配置可以通过界面操作,也可以通过注入环境变量来完成,后者更适合自动化的容器部署。完成基础配置后,系统便具备了完整的问答能力,用户可以开始正常使用。这个流程的设计旨在简化自托管应用的初始设置门槛。
- 用户通过 Docker 或源码启动应用
- 系统通过环境变量或配置文件加载初始设置
- 用户在设置页面添加或修改模型供应商配置
- 系统连接供应商并获取可用模型列表
- 用户为聊天和嵌入功能选择具体模型,完成设置
浏览与管理历史对话
当用户想要回顾过去的交流时,可以进入“聊天记录库”。系统会通过 API 获取所有历史对话的列表,并按时间倒序展示。用户可以点击任意一场对话,系统将加载该对话的全部消息记录,并通过“响应块”数据,完整地重建出当初的交互界面,包括所有的研究步骤、引用和最终答案。此外,用户也可以在此处选择并删除不再需要的对话,系统会一并清理相关的消息数据。这个流程为用户的知识沉淀和信息管理提供了基础支持。
- 用户进入“聊天记录库”界面
- 系统加载并展示所有历史对话的列表
- 用户点击某场对话,系统加载其完整消息记录并重建界面
- 用户选择并删除一场对话
Key Features
AI 搜索代理核心
这是产品的“大脑”,负责端到端地协调整个问答流程。它首先通过意图分类来理解用户查询,然后并行启动信息搜集(研究与小组件)任务,最后将所有信息整合,生成一个带有精确引用的、流式输出的最终答案。该模块的核心设计策略是“先规划,后执行,再总结”,通过多阶段处理和并行计算,在保证答案质量的同时优化用户感知速度。
- 查询意图分类 — 【设计策略】为了避免对所有查询都进行昂贵且缓慢的网页搜索,并确保复杂问题能被导向最合适的信息源,系统在执行任何操作前会先对用户意图进行精准分类。\n\n【业务逻辑】\n- Step 1: 在启动研究前,系统将用户的当前问题、对话历史、以及用户启用的数据源配置,一同发送给一个分类大模型。\n- Step 2: 模型被要求以结构化的 JSON 格式返回分析结果,包含一系列决策标志:\n - `是否跳过搜索`: 判断问题是否能基于模型的内部知识直接回答(例如,简单的数学计算或常识)。\n - `特定搜索标志`: 决定是否启用学术搜索、论坛讨论搜索或个人文档搜索。\n - `小组件触发标志`: 判断是否需要展示天气、股票、计算器等即时信息小组件。\n- Step 3: 分类器还会生成一个优化后的、无上下文依赖的独立查询,用于后续的搜索引擎输入。\n- Step 4: 整个问答流程的后续步骤将根据这些分类标志动态调整,例如,如果“跳过搜索”为真,则直接进入答案生成阶段。
- 答案生成与引用注入 — 【设计策略】为确保答案的可信度和可追溯性,系统采用了一套严格的引用生成机制,强制要求模型的输出内容必须扎根于搜集到的信息源。\n\n【业务逻辑】\n- Step 1: 在研究任务完成后,系统将所有搜集到的信息(网页、文档、论文等)格式化为带有编号和标题的上下文片段。\n- Step 2: 将格式化后的上下文、小组件的结果以及用户原始问题一起注入到一个“写作”提示词中。\n- Step 3: 提示词中包含严格的指令,要求大模型在生成答案时,必须在每个关键信息点后通过 `[编号]` 的格式插入对应的来源引用。\n- Step 4: 如果在搜索结果中没有找到与问题相关的信息,模型被指示需明确告知用户“未能找到相关信息”,并建议用户尝试其他问法。\n- Step 5: 当用户选择“质量模式”时,提示词会额外增加一条指令,要求生成的答案不少于2000字,并以研究报告的格式呈现,以满足深度研究的需求。
多源信息研究引擎
这是 AI 代理的“感官系统”,负责从互联网上搜集信息。它包含一组可动态启用的“研究工具”,能根据用户需求和查询类型,从通用网页、学术论文库、社交论坛等不同来源获取情报。该模块的设计核心是“工具化”和“策略化”,通过为不同信息源设计专用工具,并根据用户选择的模式(速度、均衡、质量)调整研究深度,实现成本、速度和质量的平衡。
- 动态研究工具集 — 【设计策略】为了让 AI 代理能像人类一样灵活地选择信息来源,系统将不同的搜索能力封装成独立的“研究工具”,并根据上下文动态启用。\n\n【业务逻辑】\n- Step 1: 系统维护一个工具注册表,包含通用网页搜索、学术搜索、社交媒体搜索、文档内容提取等多种工具。\n- Step 2: 在研究开始前,系统会根据“查询意图分类”的结果和用户在设置中启用的数据源(如“学术”、“论坛”),来决定本次任务可以使用的工具集。\n- Step 3: 例如,只有当用户启用了“学术”数据源且意图分类器识别出学术意图时,“学术搜索”工具才会被激活。\n- Step 4: 最终可用的工具列表及其功能描述会被注入到模型的提示词中,引导模型在后续的研究循环中选择最合适的工具。
- 模式驱动的研究循环 — 【设计策略】为了平衡搜索的深度、速度和成本,系统提供了三种研究模式,每种模式对应不同的研究迭代次数和策略。\n\n【业务逻辑】\n- Step 1: 用户可以在“速度”、“均衡”、“质量”三种模式中选择。\n- Step 2: 系统会根据所选模式设定一个最大研究迭代次数上限:\n - **速度模式**: 最多 2 次迭代,旨在快速返回答案。\n - **均衡模式**: 最多 6 次迭代,适用于日常搜索。\n - **质量模式**: 最多 25 次迭代,用于深入、全面的研究。\n- Step 3: 在每次迭代中,大模型会调用一个或多个研究工具。当模型认为已收集到足够信息时,会调用一个特殊的“完成”工具来提前结束研究循环。\n- Step 4: 如果在达到最大迭代次数前没有调用“完成”工具,研究循环也会自动终止,以防止无限循环和失控的成本。
- 专用信息源搜索 — 【设计策略】为了提高在特定领域查询的准确性,系统集成了针对学术和社交领域的专用搜索引擎。\n\n【业务逻辑】\n- **学术搜索**: 当“学术搜索”工具被激活时,系统会向元搜索引擎 SearxNG 发出请求,并明确指定只查询 `arXiv`、`Google Scholar` 和 `PubMed` 这三个学术数据库。\n- **社交媒体搜索**: 当“社交讨论搜索”工具被激活时,系统会指定只查询 `Reddit`,以获取来自社区的观点、经验和讨论。\n- **网页内容提取**: 提供一个通用工具,可以接收一个或多个网址,然后抓取这些页面的完整内容并转换为干净的文本格式,用于对特定来源的深度分析。
个人知识库(RAG)
该模块为用户提供了一个私有的、基于个人文档的问答能力(Retrieval-Augmented Generation)。用户可以上传自己的文件(PDF, DOCX, TXT),系统会自动处理这些文件并建立索引。在对话中,AI 代理能够理解与文档内容相关的问题,并从中检索信息来生成答案。这相当于为每个用户构建了一个专属的、与外部互联网隔离的知识库,极大地增强了应用的个性化和隐私性。
- 文档处理与索引流水线 — 【设计策略】为了让非结构化的文档能被 AI 理解和检索,系统设计了一条自动化的文档处理流水线,将文档内容转化为可供机器学习的格式。\n\n【业务逻辑】\n- Step 1: 用户通过界面上传文件,系统支持 PDF、DOCX、TXT 等常见格式。\n- Step 2: 系统根据文件类型,使用相应的解析库提取出全部文本内容。\n- Step 3: 为了适应模型处理的长度限制,提取出的长文本会被切割成固定大小(如 512 个 token)的文本块,并且块与块之间保留一部分重叠内容(如 128 个 token)以保证上下文的连续性。\n- Step 4: 系统调用用户配置的嵌入模型(Embedding Model),将每个文本块转换成一个高维向量。\n- Step 5: 最终,文本块及其对应的向量被作为一个整体,存储在服务器本地的 JSON 文件中,完成文档的索引过程。
- 基于语义的文档内容检索 — 【设计策略】采用向量相似度搜索技术,使系统能够理解用户问题的“语义”而非仅仅是“关键词”,从而在个人文档中找到最相关的内容片段。\n\n【业务逻辑】\n- Step 1: 当 AI 代理决定在用户文档中搜索时(通常由意图分类器的 `personalSearch` 标志触发),它会将用户的查询也转换成一个向量。\n- Step 2: 系统计算用户问题向量与文档中所有文本块向量之间的余弦相似度。\n- Step 3: 所有文本块根据相似度得分进行排序,得分最高的块被认为是与问题最相关的内容。\n- Step 4: 如果模型一次性生成了多个查询,系统会将多轮查询的结果进行加权合并和去重,以提供更多样化和全面的信息。\n- Step 5: 最终,排名靠前的若干个文本块及其内容,会作为上下文信息,被送入答案生成模块,用于生成基于个人文档的回答。
用户互动与发现
此模块旨在提升用户粘性和探索体验。它包含一个“发现”页面,让用户可以浏览不同主题的热点新闻和文章;同时提供“后续问题建议”功能,在用户每次提问后,智能生成相关的追问建议,引导对话向纵深发展。这些功能降低了用户发现新信息和深入研究的门槛。
- “发现”内容流 — 【设计策略】通过聚合特定领域知名网站的内容,为用户提供一个无需主动搜索即可发现新知的信息流。\n\n【业务逻辑】\n- Step 1: 系统预定义了多个主题,如科技、财经、艺术等。每个主题下都配置了一组相关的权威网站域名和一组搜索关键词。\n- Step 2: 当用户选择一个主题时,系统会组合这些域名和关键词,向元搜索引擎发起多次定向搜索(例如,在 techcrunch.com 中搜索“AI”)。\n- Step 3: 系统收集所有搜索结果,去除重复的链接,并进行随机排序。\n- Step 4: 最终,筛选出带有缩略图的文章,以卡片流的形式展示给用户。用户点击卡片会直接在应用内对该文章发起一个“总结”请求,无缝衔接核心问答流程。
- 智能后续问题建议 — 【设计策略】利用大模型分析当前对话上下文,生成富有启发性的追问建议,帮助用户拓宽思路,减少思考下一问的认知负担。\n\n【业务逻辑】\n- Step 1: 在一次问答交流结束后,系统会将完整的对话历史发送给一个专门负责生成建议的大模型。\n- Step 2: 提示词会要求模型根据上下文,生成 4-5 个相关的、具有探索性的后续问题。\n- Step 3: 为了保证输出的可靠性,模型被要求必须以指定的 JSON 格式(一个包含字符串的数组)返回建议列表。\n- Step 4: 系统收到建议列表后,将其以可点击按钮的形式展示在答案下方,用户点击即可发起新的提问。
系统配置与模型管理
这是实现产品自托管和高度可定制性的基石。它允许用户通过一个统一的设置界面或环境变量,来管理所有的大语言模型(LLM)供应商、嵌入模型(Embedding Model)以及搜索引擎等核心依赖。用户可以动态地添加、删除和切换不同的模型,使产品能适应各种硬件环境和成本预算。
- 多供应商模型接入与管理 — 【设计策略】通过抽象的“供应商”层和动态的注册机制,实现对不同 LLM 服务的“即插即用”支持。\n\n【业务逻辑】\n- Step 1: 系统定义了一个标准的供应商接口,所有支持的 LLM 服务(如 OpenAI, Ollama, Anthropic, Groq)都实现了这个接口。\n- Step 2: 用户可以在设置界面选择供应商类型,并填入相应的凭证(如 API 密钥和基础 URL)。\n- Step 3: 添加后,系统会自动连接该供应商,获取其所支持的聊天模型和嵌入模型列表,并展示给用户。\n- Step 4: 用户可以在不同供应商提供的模型中,分别为“聊天”和“文档嵌入”功能指定使用的模型。\n- Step 5: 所有配置(包括敏感的 API 密钥)都以明文 JSON 的形式保存在服务器本地的 `config.json` 文件中。\n【权衡】将配置存储在本地明文 JSON 文件中,简化了部署和修改,但牺牲了安全性。在生产环境中,需要文件系统级别的权限控制来保护凭证安全。
- 环境变量与文件双轨配置 — 【设计策略】提供两种配置方式——环境变量和配置文件,以适应不同的部署场景,特别是 Docker 等容器化环境。\n\n【业务逻辑】\n- Step 1: 在应用启动时,系统首先会加载本地 `config.json` 文件中的配置。\n- Step 2: 随后,系统会检查预设的环境变量(如 `OPENAI_API_KEY`, `SEARXNG_API_URL`)。\n- Step 3: 如果某个环境变量存在,其值会覆盖 `config.json` 中对应的配置项。\n- Step 4: 这种“环境变量优先”的策略,使得用户可以通过 Docker-compose 或 Kubernetes 的 secret/configmap 来注入敏感凭证,而无需直接修改配置文件,更符合云原生部署的最佳实践。
对话历史与持久化
为了让用户的交流可以跨会话持续,该模块负责将所有的对话和研究步骤完整地持久化存储。系统使用 SQLite 数据库记录每一次的提问和 AI 的完整响应过程,并提供 API 对历史对话进行增删查改,构成了“聊天记录”功能的基础。
- 对话与消息持久化 — 【设计策略】采用两张表(`chats` 和 `messages`)的结构来存储对话数据,确保了对话元信息和具体消息内容的有效分离和管理。\n\n【业务逻辑】\n- Step 1: `chats` 表用于存储每一场对话的元数据,包括对话ID、标题(默认为首个问题)、创建时间、以及该对话中使用的全局配置(如数据源、文件等)。\n- Step 2: `messages` 表则记录了对话中的每一次具体交互,包括消息ID、用户查询内容、以及 AI 响应的完整结构化数据(称为“响应块”)。\n- Step 3: 所谓的“响应块”是一个 JSON 数组,它完整记录了 AI 生成此条回答的所有中间步骤和最终结果,包括小组件、研究步骤、引用来源、建议和最终的文本答案。\n- Step 4: 所有数据被存储在服务器本地的 `db.sqlite` 文件中,通过 Drizzle ORM 进行操作。
- 对话历史管理 — 【设计策略】提供一套完整的 RESTful API 用于管理用户的对话历史,支撑前端的“聊天记录”界面功能。\n\n【业务逻辑】\n- **列表**: 提供一个 `GET /api/chats` 接口,按时间倒序返回所有对话的元数据列表,用于在聊天记录库中展示。\n- **详情**: 提供一个 `GET /api/chats/[id]` 接口,返回特定对话的元数据及其包含的所有消息(及完整的“响应块”),用于恢复和展示一场完整的历史对话。\n- **删除**: 提供一个 `DELETE /api/chats/[id]` 接口,在删除一场对话的元数据时,会一并删除该对话下的所有消息记录。\n【权衡】当前列表接口不包含分页功能,如果用户有大量历史对话,一次性加载所有对话可能会导致性能问题。
- 重试与幂等性处理 — 【设计策略】为应对网络不稳定等异常情况,消息创建过程被设计为幂等的,即重复提交相同的请求不会产生副作用。\n\n【业务逻辑】\n- Step 1: 客户端在每次发送消息时,会生成一个唯一的消息ID。\n- Step 2: 服务器在收到请求后,会先根据(对话ID, 消息ID)检查该消息是否已存在。\n- Step 3: 如果消息已存在(例如,因客户端超时重试),服务器不会创建新记录,而是会重置该消息的状态为“正在应答”,并清理掉可能存在的旧的、不完整的响应数据,然后继续处理。\n- Step 4: 如果消息不存在,则正常创建新记录。这一机制确保了即使在网络不佳的情况下,也不会产生重复的消息记录。
实时流式前端
这是用户与 Perplexica 交互的主界面,基于 React/Next.js 构建。其核心特性是能够实时、增量地展示 AI 的“思考过程”。通过与后端建立长连接,前端可以接收并渲染一系列事件,如研究步骤的更新、小组件的出现、以及最终答案的逐字生成,为用户提供了极具动态感和透明度的交互体验。
- 基于事件的流式通信 — 【设计策略】采用服务器发送事件(Server-Sent Events, SSE)技术,在客户端和服务器之间建立一个单向的长连接,以实现高效的实时数据推送。\n\n【业务逻辑】\n- Step 1: 当用户发送消息后,前端会向 `/api/chat` 接口发起请求,该请求的响应是一个 `text/event-stream` 类型的流。\n- Step 2: 服务器在处理请求的过程中,会不断向这个流中写入 JSON 格式的事件对象,每个事件由换行符分隔。\n- Step 3: 事件类型包括:创建新界面块(`block`)、更新现有块(`updateBlock`)、研究完成(`researchComplete`)、消息结束(`messageEnd`)和错误(`error`)。\n- Step 4: 前端持续监听这个流,每当接收到一个完整的事件 JSON,就立即解析并更新界面状态。
- 增量界面更新(JSON Patch) — 【用户价值】在展示流式生成的长文本时,避免了每次都传输全部内容的浪费,极大地提升了效率和响应速度。\n\n【设计策略】对于更新操作,服务器不发送完整的界面块数据,而是发送一个描述“如何从旧状态变为新状态”的指令集(JSON Patch)。\n\n【业务逻辑】\n- Step 1: 当 AI 的答案逐字生成时,服务器会为第一个字词创建一个新的“文本块”并发送给前端。\n- Step 2: 对于后续生成的每个字词,服务器不再发送完整的文本内容,而是生成一个遵循 RFC6902 标准的 JSON Patch 对象。例如:`{ "op": "replace", "path": "/data", "value": "更新后的完整文本" }`。\n- Step 3: 服务器将这个极小的 Patch 对象作为 `updateBlock` 事件发送给前端。\n- Step 4: 前端接收到该事件后,使用一个专门的库将这个 Patch 应用到本地存储的“文本块”对象上,从而实现对界面文本的增量更新。这个机制同样适用于更新研究步骤等复杂结构。
- 会话重连与事件重放 — 【设计策略】为应对网络波动导致的连接中断,系统提供了一套会话重连和事件重放机制,确保用户不会丢失正在进行的流式响应。\n\n【业务逻辑】\n- Step 1: 服务器为每个正在进行的问答会话维护一个临时的、有时效性(30分钟)的事件缓冲区,记录下所有已发送给客户端的事件。\n- Step 2: 如果客户端因网络问题断开连接,它可以向 `/api/reconnect/[session_id]` 接口发起请求,尝试重连。\n- Step 3: 服务器收到重连请求后,会找到对应的会话。首先,它会将缓冲区中记录的所有历史事件一次性地“重放”给客户端,使其恢复到断连前的状态。\n- Step 4: 重放完成后,再继续实时推送新的事件,从而实现无缝的流式体验续接。\n【权衡】会话状态完全存储在服务器内存中,无法在多个服务器实例间共享。这要求在多节点部署时必须使用“粘性会话”(Sticky Session)来确保用户的重连请求能命中同一个服务器实例。
Core Technical Capabilities
实时增量界面更新架构
Problem: 如何在不重复发送大量数据的前提下,实时、流畅地向用户展示一个复杂的多阶段 AI 响应过程(包含研究步骤、小组件、流式文本等)?如果每次状态变更都发送完整数据,将导致网络拥堵和前端卡顿。
Solution: Step 1: 后端为每个问答会话维护一个内存中的UI“块”状态,并通过服务器发送事件(SSE)与前端建立一个持久的单向连接。\nStep 2: 当一个全新的UI块(如一个天气小组件)生成时,后端通过SSE发送一个“创建块”事件,其中包含该块的完整数据。\nStep 3: 当一个已有的块需要更新时(如流式答案中新增一个字),后端会计算新旧状态的差异,并生成一个标准的JSON Patch指令。\nStep 4: 后端仅将这个体积微小的Patch指令作为“更新块”事件发送给前端。前端接收后,在本地应用此Patch,从而增量更新UI。\n这个方案的核心价值在于将全量更新变为增量更新,大幅减少了网络传输量,实现了高效、低延迟的实时交互体验。
Technologies: Server-Sent Events (SSE), JSON Patch (RFC6902), ReadableStream
Boundaries & Risks: 该方案下的会话状态完全存储在服务器的内存中,且没有跨节点同步机制。这使得它在多服务器实例部署时,必须依赖负载均衡的“粘性会话”策略,否则用户的请求可能会路由到没有其会话数据的实例上,导致连接失败。同时,内存中的会话有30分钟的过期时间,可能无法支撑超过此时长的超长研究任务。
可插拔的多供应商模型架构
Problem: 如何让一个自托管应用能够灵活地接入不同来源、不同成本的大语言模型(本地、闭源API、开源模型等),以适应不同的硬件和预算限制?硬编码特定供应商会使系统僵化且难以扩展。
Solution: Step 1: 定义一个统一的“模型供应商”抽象基类,规范了所有供应商必须实现的核心方法,如获取模型列表、加载聊天模型、加载嵌入模型等。\nStep 2: 为每个具体的服务商(如OpenAI、Ollama、Groq)创建一个实现该基类的子类,将各自独特的API调用逻辑封装在内部。\nStep 3: 创建一个“模型注册表”作为中心协调者。它在应用启动时,根据用户的配置文件,动态地实例化所需的供应商子类。\nStep 4: 当应用需要使用模型时,它不直接与任何具体供应商交互,而是向“模型注册表”请求一个模型实例。注册表会根据当前配置,返回一个符合统一接口的模型对象。\n这一设计模式(通常称为策略模式或工厂模式)实现了模型使用的“控制反转”,使得添加或切换模型供应商无需修改核心代码,只需增加一个新的子类实现,具有极高的扩展性和灵活性。
Technologies: 抽象基类, 工厂模式, 依赖注入
Boundaries & Risks: 虽然架构上支持热插拔,但所有供应商配置(包括API密钥)都以明文形式存储在本地JSON文件中,存在安全风险。此外,系统在更新供应商配置时,内存中的实例管理存在缺陷,可能导致旧的配置实例未被完全清理,存在潜在的内存泄漏和配置不一致问题。
基于工具调用的迭代式研究循环
Problem: 如何让AI像人类研究员一样,能够根据问题制定计划、选择工具、迭代搜集信息,并最终在信息充足时停止?传统的单次搜索无法应对复杂问题的研究需求。
Solution: Step 1: 将信息搜集能力(如网页搜索、学术搜索)封装成独立的、可被大模型调用的“工具”。\nStep 2: 构建一个研究循环,循环的次数上限由用户选择的模式(速度/均衡/质量)决定。\nStep 3: 在每次循环中,系统向大模型发起请求,并提供可用的工具列表。模型根据当前研究进展和目标,决定调用一个或多个工具。\nStep 4: 系统执行模型指定的工具调用,并将结果返回给模型,作为下一次循环的输入。\nStep 5: 模型被赋予一个特殊的“完成”工具。当模型判断已收集到足够信息时,它会主动调用“完成”工具来终止研究循环。如果达到最大迭代次数,循环也会强制结束。\n这种机制赋予了AI规划和自主决策的能力,使其能够动态调整研究深度和广度,以适应不同问题的复杂性。
Technologies: LLM Tool Calling, 有限状态机, 异步流程控制
Boundaries & Risks: 该循环的效率和效果高度依赖于大模型的工具调用能力和“何时完成”的判断力。如果模型决策不佳,可能导致研究不充分或执行不必要的操作,从而影响答案质量和成本。循环的终止条件较为简单,缺乏更复杂的启发式规则。
基于文件系统的本地化 RAG 解决方案
Problem: 如何在不依赖外部向量数据库或付费服务的情况下,为用户提供一个功能完整的、基于私有文档的问答(RAG)能力?
Solution: Step 1: 文档上传后,系统在服务器本地文件系统上为每个文件创建一个文件夹,并将原始文件存入。\nStep 2: 系统提取文件文本,进行分块和向量化后,将文本块和对应的向量一起存储在一个与原始文件配对的 `.content.json` 文件中。\nStep 3: 所有的文件元数据被记录在另一个顶级的 `uploaded_files.json` 文件中,作为文件索引。\nStep 4: 当需要进行语义检索时,系统直接从文件系统中读取相应的 `.content.json` 文件,将所有文本块及其向量加载到内存中。\nStep 5: 在内存中完成用户查询向量与所有文本块向量的相似度计算,并返回最相关的结果。\n该方案用本地文件系统模拟了向量数据库的核心功能,为自托管应用提供了一个零依赖、零成本的RAG实现,完美契合了项目的隐私和易部署特性。
Technologies: 文本分块算法, 向量嵌入, 本地文件存储 (JSON), 余弦相似度计算
Boundaries & Risks: 所有向量和文本块在查询时都会被加载到内存中,对于拥有大量或非常大的文档的用户,可能会导致显著的内存占用和性能瓶颈。该方案不适合需要管理海量文档的企业级场景。同时,文件存储没有用户隔离,在多租户环境下存在数据泄露风险。
