5.4 KiB
5.4 KiB
AI Search Agent
独立实现的 AI 搜索 Agent,不复用仓库里原有的 search_agent。
这个版本按“较完整的最佳实践骨架”组织,不是最小脚本:
- 用
s.jina.ai做网页搜索(不依赖 Bing DOM) - 用
r.jina.ai并发深读搜索结果正文 - 支持多轮搜索规划与反思(自动改写下一轮查询)
- 用可切换的 LLM 生成结构化回答
- 暴露 CLI、FastAPI 和 Azure Functions 三种入口
- 支持 SSE 流式事件输出
目录
ai_search_agent/
├── ai_search_agent/
│ ├── agent.py
│ ├── api.py
│ ├── config.py
│ ├── jina.py
│ ├── llm_client.py
│ ├── models.py
│ ├── parsers.py
│ ├── prompts.py
│ └── __init__.py
├── .env.example
├── tests/
│ └── test_parsers.py
├── main.py
├── README.md
├── serve.py
└── requirements.txt
环境变量
export JINA_API_KEY=your-jina-key
export LLM_API_KEY=your-llm-key
export LLM_API_STYLE=openai_chat
export LLM_ENDPOINT=https://dashscope-intl.aliyuncs.com/compatible-mode/v1
export MODEL_NAME=qwen3.5-flash
export SEARCH_PROVIDER=jina_search
export JINA_SEARCH_URL=https://s.jina.ai/
export TOP_K_PAGES=5
export MAX_PAGE_CHARS=5000
export MAX_CONCURRENCY=5
export MAX_SEARCH_ROUNDS=2
export SEARCH_TIMEOUT=20
export READER_TIMEOUT=25
export MODEL_TIMEOUT=90
export RETRY_ATTEMPTS=2
export AUDIT_LOG_PATH=logs/audit.jsonl
如果切回 xAI:
export JINA_API_KEY=your-jina-key
export LLM_API_KEY=your-xai-key
export LLM_API_STYLE=xai_responses
export MODEL_NAME=grok-4.20-multi-agent-0309
安装
cd ai_search_agent
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
运行
python main.py "PydanticAI 适合哪些场景?"
输出 JSON:
python main.py "PydanticAI 适合哪些场景?" --json
启动 API 服务
uvicorn serve:app --host 0.0.0.0 --port 8080
请求示例:
curl -X POST http://127.0.0.1:8080/search \
-H "Content-Type: application/json" \
-d '{"query":"PydanticAI 适合哪些场景?","top_k_pages":4}'
SSE 流式接口:
```bash
curl -N -X POST http://127.0.0.1:8080/search/stream \
-H "Content-Type: application/json" \
-d '{"query":"PydanticAI 适合哪些场景?","top_k_pages":4}'
事件类型示例:
round_startedround_finishedllm_startedresultaudit
Azure Functions 部署(aisousuo)
1. 准备 Azure Function App
az login
az account set --subscription "<your-subscription-id-or-name>"
# 若资源组不存在
az group create -n <resource-group> -l eastasia
# 创建 Linux Consumption Function App(Python)
az storage account create -n <storage-account> -g <resource-group> -l eastasia --sku Standard_LRS
az functionapp create \
-g <resource-group> \
-n aisousuo \
--storage-account <storage-account> \
--consumption-plan-location eastasia \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--os-type Linux
2. 配置应用设置
az functionapp config appsettings set \
-g <resource-group> \
-n aisousuo \
--settings \
JINA_API_KEY="<your-jina-key>" \
LLM_API_KEY="<your-llm-key>" \
LLM_API_STYLE="openai_chat" \
LLM_ENDPOINT="https://dashscope-intl.aliyuncs.com/compatible-mode/v1" \
MODEL_NAME="qwen3.5-flash" \
SEARCH_PROVIDER="jina_search" \
JINA_SEARCH_URL="https://s.jina.ai/" \
TOP_K_PAGES="5" \
MAX_PAGE_CHARS="5000" \
MAX_CONCURRENCY="5" \
MAX_SEARCH_ROUNDS="2" \
SEARCH_TIMEOUT="20" \
READER_TIMEOUT="25" \
MODEL_TIMEOUT="90" \
RETRY_ATTEMPTS="2" \
AUDIT_LOG_PATH="/tmp/audit.jsonl"
3. 发布
func azure functionapp publish aisousuo --python
4. 验证
curl https://aisousuo.azurewebsites.net/api/health
curl -X POST https://aisousuo.azurewebsites.net/api/search \
-H "Content-Type: application/json" \
-d '{"query":"PydanticAI 适合哪些场景?"}'
## 设计说明
- `SearchClient.search()` 固定走 `s.jina.ai`,通过 `X-Respond-With: no-content` 获取搜索结果文本
- `JinaClient.read_pages()` 负责通过 `r.jina.ai` 并发抓取页面内容,并带重试
- `AISearchAgent.run_stream()` 提供流式事件;`run()` 兼容一次性返回
- 支持多轮搜索规划和反思,证据不足时自动改写下一轮查询
- `LLMClient.answer()` 支持 `xai_responses` 和 `openai_chat` 两种模式
- 每次请求都会生成 `audit_id`,并把审计记录落到 `logs/audit.jsonl`
- 模型输出约束为 JSON 形状,解析失败时退化为纯文本答案
- `AISearchAgent.run()` 统一编排搜索、抓取、归纳和来源回填
- `create_app()` 复用同一套业务链路,不重复实现 API 逻辑
## 返回结构
```json
{
"query": "PydanticAI 适合哪些场景?",
"answer": {
"summary": "...",
"key_points": ["..."],
"caveats": ["..."],
"citations": [{"title": "...", "url": "https://..."}]
},
"search_rounds": [
{
"round_index": 1,
"query": "...",
"result_count": 10,
"fetched_page_count": 8,
"usable_page_count": 5,
"reflection": "..."
}
],
"search_results": [],
"pages": []
}
当前边界
- 目前多轮规划使用规则策略,不是独立 Planner 模型
- 流式接口是事件级流式(非 token 级模型流式)
- 大查询下“读取全部搜索结果”会增加耗时和成本