news 2026/9/17 22:00:49

ag-ui-rag-agent:基于 Pydantic AI 与 PostgreSQL PGVector 构建语义 + 混合搜索的 RAG 智能体

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ag-ui-rag-agent:基于 Pydantic AI 与 PostgreSQL PGVector 构建语义 + 混合搜索的 RAG 智能体

ag-ui-rag-agent:基于 Pydantic AI 与 PostgreSQL PGVector 构建语义 + 混合搜索的 RAG 智能体

【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents

本文以 ag-ui-rag-agent/agent/README.md 中定义的 Semantic Search Agent 为核心,完整讲解如何用 Pydantic AI 与 PostgreSQL(PGVector 扩展)搭建一个具备语义搜索与混合搜索双策略、可自动选择检索方式并总结结果的知识库问答智能体。读完后,你可以掌握从建库、配置环境变量、文档摄取到 CLI 交互与 AG-UI 前端状态同步的完整实战链路。

一、这个智能体解决了什么问题

该智能体是一个"智能知识库搜索系统",官方定位为:powered by Pydantic AI and PostgreSQL with PGVector。它提供两种检索能力,并由 Agent 自动选择策略、对检索结果做总结:

  • Semantic Search(语义搜索):纯向量相似度检索,基于 embedding;
  • Hybrid Search(混合搜索):语义向量与关键词匹配结合,适合精确命中;
  • Intelligent Strategy Selection:Agent 根据查询类型自动选择检索方式;
  • Result Summarization:从检索到的分块生成连贯的洞察性回答;
  • Interactive CLI:基于 Rich 的交互式命令行,支持实时流式输出;
  • Multi-Provider Support:兼容任意 OpenAI 协议 API(OpenAI、Gemini、Ollama 等)。

从源码结构看,该目录实际上处于两条形态的叠加状态:README.md 描述的是独立的 Semantic Search Agent 形态,而 agent.py 已升级为 AG-UI(Agent User Interaction Protocol)支持版本——检索结果会写入共享状态RAGState并通过状态快照事件推送给前端,这一点本文会在第六节结合源码展开。

二、前置条件与安装步骤

README 给出的运行前提:

  • Python 3.10+;
  • 带 PGVector 扩展的 PostgreSQL;
  • 一个 LLM API Key(OpenAI、Gemini、Ollama、Groq 或任意 OpenAI 兼容服务);
  • 已建好、且包含 documents 与 chunks 数据的数据库(仓库提供 schema)。

安装流程(对应 README.md 的 Installation 一节):

  1. 进入 agent 目录;
  2. 安装依赖:
pip install -r requirements.txt
  1. 初始化数据库 schema。仓库提供了现成的建库脚本 sql/schema.sql,README 给出两种执行方式:在 Supabase/Postgres 平台里直接执行 SQL,或用 psql:
psql -d your_database -f sql/schema.sql
  1. 配置环境变量文件.env(README 建议从.env.example复制后编辑;该目录当前未包含此示例文件,可参照下文配置项自行创建);
  2. 摄取文档。README 明确说明这一步必须先于运行 Agent 完成
python -m ingestion.ingest --documents documents/

仓库的 requirements.txt 也印证了技术栈:核心为pydantic-ai[agui]ag-uiopenai;数据库层为asyncpgpsycopg2-binarypgvector;Web 层为fastapiuvicornpython-multipart;数据与文档处理依赖pandasnumpyscikit-learntiktokenpypdfpython-docxbeautifulsoup4等;开发工具为pytestpytest-asyncioblackruffmypy

三、配置体系:环境变量与默认值

README 列出的必需环境变量如下:

变量说明
DATABASE_URL带 PGVector 的 PostgreSQL 连接串
LLM_PROVIDER提供商名称(openai、anthropic、ollama 等)
LLM_API_KEYLLM 提供商 API Key
LLM_MODEL使用的模型(如 gpt-4.1-mini、gemini-2.5-flash)
LLM_BASE_URLAPI 基础地址(默认https://api.openai.com/v1
EMBEDDING_MODEL向量模型(如 text-embedding-3-small、text-embedding-3-large)

这些变量在 settings.py 中通过pydantic_settings.BaseSettings统一解析,load_settings()在缺少DATABASE_URL或 API Key 时会抛出带明确提示的错误。结合源码,完整的配置项与默认值如下(Settings类,settings.py):

配置项默认值含义
database_url必填PostgreSQL 连接 URL
llm_provideropenaiLLM 提供商名称
llm_api_key必填LLM API Key
llm_modelgpt-4o-mini检索与总结使用的对话模型
llm_base_urlhttps://api.openai.com/v1OpenAI 兼容服务的 Base URL
default_match_count10搜索默认返回条数
max_match_count50允许的最大返回条数
default_text_weight0.3混合搜索中关键词匹配权重(0–1)
db_pool_min_size10连接池最小连接数
db_pool_max_size20连接池最大连接数
embedding_modeltext-embedding-3-small向量模型
embedding_dimension1536向量维度

多提供商支持的关键在于 providers.py:get_llm_model()用配置里的base_urlapi_key构造OpenAIProvider,再包一层OpenAIModel——因此只要把LLM_BASE_URL指向 Ollama、Groq 等 OpenAI 兼容端点即可切换模型;get_model_info()则供info命令展示当前配置。

四、数据库 Schema 与两个核心搜索函数

README 的 Database Setup 一节概括了 schema 的四要素:documents表(存全文与元数据)、chunks表(存分块与向量)、match_chunks()(语义搜索函数)、hybrid_search()(混合搜索函数)。sql/schema.sql 给出了完整实现:

4.1 表结构与索引

  • documentsid UUID主键、titlesourcecontentmetadata JSONB、时间戳字段,并对metadata建 GIN 索引、对created_at建降序索引;
  • chunksid UUID主键、外键document_id(级联删除)、contentembedding vector(1536)chunk_indexmetadata JSONBtoken_count
  • 关键索引包括idx_chunks_embedding(IVFFlat 余弦索引,WITH (lists = 1))、idx_chunks_document_id、以及供关键词路径使用的idx_chunks_content_trgmgin_trgm_ops三元组 GIN 索引)。

schema 同时启用vectoruuid-ossppg_trgm三个扩展,并附有一个自动更新documents.updated_at的触发器update_documents_updated_at

4.2 match_chunks:纯语义搜索

函数签名match_chunks(query_embedding vector(1536), match_count INT DEFAULT 10),实现逻辑(schema.sql):

SELECT c.id AS chunk_id, c.document_id, c.content, 1 - (c.embedding <=> query_embedding) AS similarity, -- 余弦距离转相似度 c.metadata, d.title AS document_title, d.source AS document_source FROM chunks c JOIN documents d ON c.document_id = d.id WHERE c.embedding IS NOT NULL ORDER BY c.embedding <=> query_embedding LIMIT match_count;

要点:用 PGVector 的<=>(余弦距离)操作符排序,并把相似度表达为1 - 距离,因此返回值范围在 -1 到 1 之间、越接近 1 越相似。

4.3 hybrid_search:混合搜索

函数签名hybrid_search(query_embedding vector(1536), query_text TEXT, match_count INT DEFAULT 10, text_weight FLOAT DEFAULT 0.3)。它用两个 CTE 分别产出向量路径结果(vector_results,同上按余弦距离取全部候选)与文本路径结果(text_results,基于to_tsvector('english', ...)plainto_tsquery做全文匹配、以ts_rank_cd计算文本分),再做FULL OUTER JOIN,合并公式为(schema.sql):

(COALESCE(v.vector_sim, 0) * (1 - text_weight) + COALESCE(t.text_sim, 0) * text_weight)::float8 AS combined_score

combined_score = 向量相似度 × (1 − text_weight) + 文本相似度 × text_weight,按combined_score DESC取前match_count条,并同时返回vector_similaritytext_similarity两个子分,方便上层解释排序原因。默认text_weight = 0.3意味着混合检索以语义为主、关键词为辅;查专有名词时调高该权重可以让精确词命中占更大比重。

此外 schema 还提供了get_document_chunks(doc_id)函数,按chunk_index顺序返回某文档的全部分块,用于"从分块回溯全文结构"的场景。

五、两种搜索策略:适用场景与工具层实现

README 对策略选择给出了清晰的经验法则:

语义搜索(Semantic Search)

适合概念性、主题性查询,例如:

  • "concepts similar to machine learning"
  • "ideas about artificial intelligence"
  • "related to neural networks"

混合搜索(Hybrid Search)

适合特定事实与技术术语,例如:

  • "OpenAI GPT-4 specifications"
  • "NASDAQ:NVDA stock price"
  • "specific quote from Sam Altman"

README 说明:Agent 会根据查询自动选择合适的策略,也可以在 prompt 中显式指定检索类型。

工具层实现在 tools.py。semantic_search()hybrid_search()两个协程的关键行为(均以RunContext[AgentDependencies]注入依赖):

  1. 参数兜底与钳制match_count缺省时取settings.default_match_count(10),并统一min(match_count, max_match_count)(上限 50);text_weight缺省时优先读会话级user_preferences['text_weight'],再落到settings.default_text_weight(0.3),且被钳制在[0.0, 1.0]
  2. 查询向量化:通过deps.get_embedding(query)生成查询向量——dependencies.py 中该函数调用 OpenAI 兼容 API 的embeddings.create(model=embedding_model, input=text)并返回浮点列表;
  3. 向量字符串格式:Python 侧手工拼成 PGVector 接受的'[0.1,0.2,...]'(逗号后无空格)格式再执行SELECT * FROM match_chunks($1::vector, $2)/SELECT * FROM hybrid_search($1::vector, $2, $3, $4)
  4. 结果模型semantic_search返回SearchResult列表(chunk_id、document_id、content、similarity、metadata、document_title、document_source);hybrid_search返回附带combined_scorevector_similaritytext_similarity的字典列表;
  5. 错误处理:数据库异常时打印并返回空列表,保证 Agent 不会因检索失败而崩溃。

tests/test_tools.py 用 mock 数据库验证了这些行为:自定义match_count是否正确下传(test_semantic_search_with_custom_count断言第 3 个参数为 5)、超过上限时被钳制到max_match_count(50)、embedding 生成参数正确、空结果与异常路径等。

六、AG-UI 形态:共享状态与工具事件(源码级补充)

在 agent.py 中,Agent 已升级为 AG-UI 支持版本,这是理解本目录名的关键:

  • 共享状态RAGState(agent.py):包含retrieved_chunksRetrievedChunk列表,含 chunk_id、content、similarity、document_title、highlight 等字段)、current_querysearch_history(只保留最近 10 条)、selected_chunk_idtotal_chunks_in_kbknowledge_base_status
  • Agent 定义rag_agent = Agent(get_llm_model(), deps_type=StateDeps[RAGState], system_prompt=MAIN_SYSTEM_PROMPT)
  • 工具集
    • search_knowledge_base(query, match_count, search_type):执行语义或混合检索,把结果写入state.retrieved_chunks并返回StateSnapshotEvent(前端据此刷新列表);出错时清空 chunks 并把knowledge_base_status置为error: ...
    • clear_search_results():清空当前结果与选中项;
    • select_chunk(chunk_id):高亮指定分块;
    • get_knowledge_base_stats():执行SELECT COUNT(*) FROM chunks更新知识库统计;
    • display_search_results():发出名为DisplaySearchResultsCustomEvent,携带 chunks、query、total_results 触发 UI 展示;
  • 动态指令@rag_agent.instructions装饰的rag_instructions每次运行时根据状态拼装系统指令——有检索结果时会把 Top 5 分块的得分、来源与前 200 字符摘要注入 prompt,让模型基于真实检索内容作答;
  • 应用导出:文件末尾app = rag_agent.to_ag_ui(deps=StateDeps(RAGState()))__main__下用uvicorn0.0.0.0:8000启动(agent.py)。仓库上层还有一个 Next.js/CopilotKit 前端(见 README_AGUI_SETUP.md 与 src/app/api/copilotkit/route.ts)与之对接。

系统提示词基础版在 prompts.py:要求"仅在用户明确需要知识库信息时才搜索"、问候语直接回复不触发检索、优先小match_count(5–10)聚焦结果,并给出了text_weight的调节建议;get_dynamic_prompt()还会把会话 ID、用户偏好(search_typetext_weightresult_count)与最近 3 次搜索历史拼入上下文。

七、文档摄取管道(Ingestion Pipeline)

README 中"必须先摄取文档"一步的实现在 ingestion/ingest.py。完整支持的命令行参数(argparse定义见 ingest.py):

python -m ingestion.ingest \ --documents documents/ \ --chunk-size 1000 \ --chunk-overlap 200 \ --no-semantic \ --clean \ --verbose
参数默认值说明
--documents/-ddocuments文档目录(递归查找*.md*.markdown*.txt
--chunk-size1000目标分块字符数
--chunk-overlap200分块重叠字符数
--no-semantic关闭禁用语义分块,改用纯规则分块
--clean/-c关闭摄取前清空chunksdocuments
--verbose/-v关闭日志级别提升至 DEBUG

管道DocumentIngestionPipeline处理单个文档的流程:读取文件(UTF-8 失败回退 latin-1)→ 从 Markdown 首行#提取标题(否则用文件名)→ 抽取元数据(文件路径、大小、行数、词数,若文档带 YAML frontmatter 则一并解析合并)→ 分块 → 生成 embedding → 在单个事务中先插documents再逐条插chunks(embedding 同样拼为[...]字符串写入vector列)。结束后输出总结:处理文档数、总分块数、错误数与总耗时。

分块策略在 ingestion/chunker.py:ChunkingConfig默认chunk_size=1000chunk_overlap=200max_chunk_size=2000min_chunk_size=100,并校验 overlap 必须小于 chunk size。SemanticChunker先按 Markdown 结构边界(标题、段落、列表、代码块、表格)切段,再把段聚合到chunk_size以内;超长段落会调用 LLM(通过 Pydantic AI 临时 Agent,以---CHUNK---分隔)做语义切分,失败时回退到句界优先的规则切分(_simple_split在目标位置附近回溯.!?\n作为切点)。SimpleChunker则完全按段落做规则分块、支持 overlap。仓库的 documents/ 目录自带 21 篇大科技 AI 行业 Markdown 样本(如 doc1_openai_funding.md),可直接用于端到端验证——这也解释了 README 中 "NASDAQ:NVDA"、"Sam Altman" 等示例查询的出处。

八、交互式 CLI 使用

README 给出的运行命令:

python -m cli

CLI 提供的能力与命令表(README.md 与 cli.py 的display_help一致):

命令作用
help显示可用命令
info展示系统配置(LLM Provider/Model、Embedding Model、默认 match count 与 text weight)
clear清屏并重新显示欢迎面板
set <key>=<value>设置会话偏好,如set text_weight=0.5(自动尝试 int/float 转换)
exit/quit/q退出

从 cli.py 源码看,会话流程为:main()初始化AgentDependencies(建立 asyncpg 连接池、创建会话 UUID)→ 循环读取输入 → 将最近 6 轮对话拼成 "Previous conversation" 上下文 → 通过search_agent.iter(prompt, deps=deps)流式执行,逐节点处理:模型请求节点中把PartDeltaEventcontent_delta实时打印为 Assistant 输出,工具调用节点打印 "🔹 Calling tool: ..." 及参数预览(长值截断)、工具结果打印 "✅ Tool result: ..."(截断至 100 字符)。set命令写入的user_preferences会被hybrid_search在计算text_weight时优先读取,实现"会话内在线调参"。需注意:当前 agent.py 导出的 Agent 实例名为rag_agent(AG-UI 形态),而 cli.py 与测试仍从模块导入search_agent,从源码结构看,CLI 入口与 Agent 模块之间尚存在命名未完全对齐的情况,实际以仓库当前版本为准。

九、测试与开发

README 的 Development 一节给出的命令:

pytest tests/ black . ruff check .

仓库 tests/ 目录包含test_agent.pytest_cli.pytest_dependencies.pytest_tools.pytest_integration.pytest_requirements.py等测试文件与共享 fixture 的conftest.py,以及一份 VALIDATION_REPORT.md。以 test_tools.py 为例,测试用AsyncMock模拟 asyncpg 连接,覆盖基础检索、自定义条数、上限钳制、embedding 调用参数、数据库异常与空结果等路径,是验证第五节所述工具行为的直接证据。

README 描述的目录结构与实际文件一一对应:

semantic_search_agent/ ├── agent.py # 主 Agent 实现 ├── cli.py # 命令行界面 ├── dependencies.py # Agent 依赖 ├── providers.py # 模型提供商 ├── prompts.py # 系统提示词 ├── settings.py # 配置 ├── tools.py # 搜索工具 ├── ingestion/ # 文档摄取管道 ├── sql/ # 数据库 schema └── documents/ # 示例文档

对应本仓库路径为 ag-ui-rag-agent/agent/,其中ingestion/下另有embedder.py(embedding 客户端工厂)、utils/下另有db_utils.pymodels.pyIngestionConfigIngestionResult等数据模型)、providers.py

十、小结

这套 Semantic Search Agent 的完整闭环是:schema.sql用 PGVector 的余弦距离与 Postgres 全文检索实现match_chunks/hybrid_search两个数据库函数;settings.py+.env统一管理与 OpenAI 兼容端点的连接;ingestion/管道负责把 Markdown 文档切成带 embedding 的分块入库;tools.py把两个 SQL 函数包装为带参数钳制的 Pydantic AI 工具;agent.py再将其扩展为 AG-UI 共享状态 Agent,检索结果以状态快照事件驱动前端展示。配置时重点关注LLM_BASE_URL(切换提供商)、EMBEDDING_MODEL(须与库内 1536 维向量匹配)、default_text_weight(混合检索的关键词占比)三个参数,即可在不同知识库场景下快速调整检索行为。

【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 21:59:32

企业训考一体化工具推荐:支持在线考试的培训系统汇总

数字化转型背景下&#xff0c;企业内部员工培训、技能考核、岗前测评的需求持续升级&#xff0c;传统线下集中培训、纸质考试模式效率低下、数据难以留存&#xff0c;无法适配现代企业常态化人才培养需求。训考一体化系统凭借线上培训、智能出题、自动考核、数据复盘的全链路能…

作者头像 李华
网站建设 2026/9/17 21:59:13

Excel工作表保护密码破解:VBA脚本与XML清理法详解

简介&#xff1a;这是一份面向办公人员与数据处理初学者的Excel工作表保护破解实操文档&#xff0c;解决因忘记密码或他人设置锁定而无法编辑、查看工作表内容的常见问题。文档首先讲解工作表保护的标准设置方法&#xff0c;包括锁定单元格与保护工作表的操作路径&#xff1b;随…

作者头像 李华
网站建设 2026/9/17 21:57:58

Flink 1.13集成Hadoop 3.x:版本冲突解决与源码编译实战

这些年在公司做实时数仓&#xff0c;经常要面对的一个问题就是 Flink 和 Hadoop 的版本配套关系。Flink 1.13 这个版本用得人不少&#xff0c;但当你拿着官方下载的 Flink 1.13 包去对接一个 Hadoop 3.x 集群时&#xff0c;十有八九会碰一鼻子灰&#xff0c;报错信息千奇百怪&a…

作者头像 李华