Made-with: Cursor
Azure AI Search Agent
基于 Pydantic AI 的 Azure AI Search 资源库管理 Agent,作为 OpenClaw 的外部资源库。
采用 混合搜索(关键词 BM25 + 向量语义),支持项目文档的上传、下载、修改、搜索和删除。 调用方可以是 OpenClaw 也可以是人类用户。
搜索模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
hybrid(默认) |
关键词 + 向量融合排序 | 通用场景,推荐 |
keyword |
纯 BM25 关键词匹配 | 精确搜索术语/ID |
vector |
纯语义向量搜索 | 自然语言提问,找语义相关文档 |
- 上传文档时自动通过 LiteLLM 生成 embedding 向量(
taiji/text-embedding-3-small,1536 维) - 更新
title或content时自动重新生成向量 - 搜索时关键词和向量结果由 Azure AI Search 自动融合排序(RRF)
功能
| 工具 | 说明 |
|---|---|
create_index |
创建混合搜索索引(含向量字段) |
list_indexes |
列出所有索引 |
upload_documents |
上传文档(自动生成向量,支持批量) |
search_documents |
混合/关键词/向量搜索,支持筛选、排序 |
get_document |
根据 ID 获取单个文档 |
update_document |
更新文档部分字段(自动重新生成向量) |
delete_documents |
删除文档 |
smart_query |
AI 智能问答(混合搜索 + LLM 总结) |
文档 Schema
| 字段 | 类型 | 说明 |
|---|---|---|
id |
String (Key) | 文档唯一 ID |
title |
String (Searchable) | 标题 |
content |
String (Searchable) | 正文内容 |
content_vector |
Collection(Single) | 内容向量(1536 维,自动生成) |
project |
String (Filterable) | 项目名称 |
category |
String (Facetable) | 分类 |
tags |
String (Filterable) | 标签,逗号分隔 |
source |
String (Filterable) | 来源(openclaw / human) |
author |
String (Filterable) | 作者 |
created_at |
DateTimeOffset | 创建时间 |
updated_at |
DateTimeOffset | 更新时间 |
metadata |
String (Searchable) | 额外元数据 JSON |
如何运行(标准 Azure 函数)
重要:func start 会使用当前 shell 的 Python 环境加载你的代码。必须先在本项目目录下创建并激活虚拟环境、安装依赖,再启动,否则会报 ModuleNotFoundError: No module named 'fastapi'。
在项目根目录 azure_search_agent/ 下按顺序执行:
# 1. 进入项目目录
cd /path/to/azure_search_agent
# 2. 创建虚拟环境(若尚未创建)
python3 -m venv .venv
# 3. 激活虚拟环境(必做,否则 func 找不到依赖)
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# 4. 安装依赖
pip install -r requirements.txt
# 5. 确认已有 local.settings.json,再启动
func start
一行命令(在项目目录下,且已存在 .venv):
source .venv/bin/activate && func start
启动成功后终端会显示:
Functions:
http_app: [GET,POST,DELETE,HEAD,PATCH,PUT,OPTIONS] http://localhost:7071/{*route}
在浏览器或 curl 访问:
- 根路径:http://localhost:7071/
- 健康检查:http://localhost:7071/health
- 搜索 API:
curl -X POST http://localhost:7071/api/v1/search -H "Content-Type: application/json" -H "api-key: sk-xxx" -d '{"query":"test","top":5}'
如需先安装 Azure Functions Core Tools(尚未安装时):
# Windows (npm)
npm i -g azure-functions-core-tools@4
# macOS
brew tap azure/functions && brew install azure-functions-core-tools@4
# Linux (Ubuntu/Debian)
curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list'
sudo apt-get update && sudo apt-get install azure-functions-core-tools-4
快速开始
1. 配置环境变量
export AZURE_SEARCH_ENDPOINT="https://your-search-service.search.windows.net"
export AZURE_SEARCH_API_KEY="your-admin-key"
export AZURE_SEARCH_INDEX_NAME="openclaw-resources"
# LiteLLM(用于 embedding 和 smart_query)
export OPENAI_BASE_URL="https://litellm.example.com/v1"
export OPENAI_API_KEY="sk-your-key"
export EMBEDDING_MODEL="taiji/text-embedding-3-small"
2. 本地测试
pip install -r requirements.txt
python run_api_server.py
部署到 Azure Function App
本 Agent 支持直接部署到 Azure 函数应用(无需 AKS)。
1. 安装 Azure Functions Core Tools
# Windows (npm)
npm i -g azure-functions-core-tools@4
# macOS (Homebrew)
brew tap azure/functions && brew install azure-functions-core-tools@4
# Linux 见: https://learn.microsoft.com/azure/azure-functions/functions-run-local
2. 本地配置
cp local.settings.json.example local.settings.json
# 编辑 local.settings.json,填入 AZURE_SEARCH_*、OPENAI_* 等
注意:local.settings.json 含密钥,不要提交到 Git(已在 .gitignore 中忽略)。
3. 本地运行(模拟 Function App)
pip install -r requirements.txt
func start
默认地址:http://localhost:7071。例如健康检查:http://localhost:7071/health。
4. 部署到 Azure
方式 A:Azure CLI
# 登录
az login
# 创建资源组与存储(若尚未创建)
az group create --name rg-azure-search-agent --location eastasia
az storage account create --name styouragent --resource-group rg-azure-search-agent --sku Standard_LRS
# 创建 Function App(Linux + Python 3.11)
az functionapp create \
--resource-group rg-azure-search-agent \
--consumption-plan-location eastasia \
--runtime python \
--runtime-version 3.11 \
--functions-version 4 \
--name func-azure-search-agent \
--storage-account styouragent \
--os-type Linux
# 配置应用设置(与 local.settings.json 中的 Values 对应)
az functionapp config appsettings set --name func-azure-search-agent --resource-group rg-azure-search-agent --settings \
AZURE_SEARCH_ENDPOINT="https://aiagnet.search.windows.net" \
AZURE_SEARCH_API_KEY="<你的密钥>" \
AZURE_SEARCH_INDEX_NAME="openclaw-resources" \
OPENAI_BASE_URL="https://litellm.graystone-fb459c5d.southeastasia.azurecontainerapps.io/v1" \
OPENAI_API_KEY="<你的密钥>" \
EMBEDDING_MODEL="taiji/text-embedding-3-small"
# 部署代码(在项目根目录执行)
func azure functionapp publish func-azure-search-agent
方式 B:VS Code
安装 Azure Functions 扩展,右键项目 → “Deploy to Function App” → 选择或新建 Function App。
方式 C:使用发布配置文件 (agnetdoc.PublishSettings)
若已从 Azure 门户下载了发布配置文件(如 agnetdoc.PublishSettings),可按以下任一方式发布到 Function App agnetdoc。
-
命令行(先登录 Azure)
在项目根目录执行(将
agnetdoc换成你的 Function App 名称):az login func azure functionapp publish agnetdoc如需把本地的
local.settings.json里的应用设置同步到 Azure(会覆盖远程同名设置):func azure functionapp publish agnetdoc --publish-local-settings -
VS Code 使用发布配置文件
- 安装 Azure Functions 扩展。
- 在 Azure 视图中找到你的 Function App(如 agnetdoc),右键 → Deploy to Function App using Publish Profile。
- 选择已下载的
agnetdoc.PublishSettings文件(例如在Downloads中)。
-
用脚本 + 发布配置文件发布(无需 az login)
项目内提供
publish_with_profile.py,读取.PublishSettings后通过 Kudu 做 zip 部署:# Windows(发布配置文件在下载目录) .venv\Scripts\python publish_with_profile.py "C:\Users\gjgon\Downloads\agnetdoc.PublishSettings" # Linux/macOS .venv/bin/python publish_with_profile.py /path/to/agnetdoc.PublishSettings
5. 部署后访问
- 根路径:
https://<your-function-app>.azurewebsites.net/ - 健康检查:
https://<your-function-app>.azurewebsites.net/health - REST API:
https://<your-function-app>.azurewebsites.net/api/v1/search等
业务接口仍通过请求头 api-key 或 Authorization: Bearer <key> 鉴权,与本地/uvicorn 行为一致。
6. 说明
- host.json 中
routePrefix: ""必须保留,否则 FastAPI 路由会多一层前缀。 - AzureWebJobsStorage 与本地 Unhealthy:
local.settings.json里若为UseDevelopmentStorage=true,需本机运行 Azurite 才会通过存储检查;否则 func 会一直报azure.functions.webjobs.storage: Unhealthy,但 HTTP 接口仍可用。若不想跑 Azurite,可把AzureWebJobsStorage改为真实的 Azure 存储连接串,Unhealthy 即会消失。 - 如需生产级鉴权,可在 Azure 门户将 HTTP 触发器改为
FUNCTION级别,或在前端加 APIM/网关。 - 消费计划(Consumption)有冷启动与超时限制;长时间运行或高并发可考虑 Premium 或 Dedicated 计划。
API 接口
MCP 端点
POST /mcp— MCP JSON-RPCGET /mcp/sse— MCP SSE 连接POST /mcp/sse— MCP SSE 请求
REST API
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /api/v1/indexes |
创建索引 |
| GET | /api/v1/indexes |
列出索引 |
| POST | /api/v1/upload |
上传文档 |
| POST | /api/v1/search |
搜索文档 |
| GET | /api/v1/documents/{id} |
获取文档 |
| PATCH | /api/v1/documents/{id} |
更新文档 |
| DELETE | /api/v1/documents/{id} |
删除文档 |
| POST | /api/v1/smart-query |
AI 智能问答 |
使用示例
上传文档:
curl -X POST http://localhost:8000/api/v1/upload \
-H "api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"documents": [
{
"id": "doc-001",
"title": "项目架构设计文档",
"content": "本项目采用微服务架构...",
"project": "my-project",
"category": "设计文档",
"source": "human",
"author": "张三"
}
]
}'
混合搜索(默认):
curl -X POST http://localhost:8000/api/v1/search \
-H "api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "系统用了什么技术栈", "top": 5}'
纯关键词搜索:
curl -X POST http://localhost:8000/api/v1/search \
-H "api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "微服务", "search_mode": "keyword"}'
AI 智能问答:
curl -X POST http://localhost:8000/api/v1/smart-query \
-H "api-key: YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"question": "怎么开发新的 Agent?", "project": "openclaw"}'
环境变量
| 变量 | 必需 | 说明 |
|---|---|---|
| AZURE_SEARCH_ENDPOINT | 是 | Azure AI Search 服务端点 URL |
| AZURE_SEARCH_API_KEY | 是 | Azure AI Search 管理密钥 |
| AZURE_SEARCH_INDEX_NAME | 否 | 默认索引名称,默认 openclaw-resources |
| OPENAI_BASE_URL | 否 | LiteLLM Gateway URL(embedding + 智能问答) |
| OPENAI_API_KEY | 否 | LiteLLM API Key |
| EMBEDDING_MODEL | 否 | Embedding 模型名称,默认 taiji/text-embedding-3-small |
| EMBEDDING_DIMENSIONS | 否 | 向量维度,默认 1536 |
| LITELLM_MODEL | 否 | LLM 模型名称,默认 taiji/gpt-4o-mini |
| API_PORT | 否 | 端口,默认 8000 |
项目结构
azure_search_agent/
├── README.md
├── requirements.txt
├── run_api_server.py # 本地 uvicorn 启动(非 Function App)
├── function_app.py # Azure Function App 入口(ASGI 挂载 FastAPI)
├── host.json # Function 主机配置(routePrefix 为空)
├── local.settings.json.example
├── local.settings.json # 本地配置(勿提交,复制 example 后填写)
└── src/
├── __init__.py
└── server/
├── __init__.py
├── api_server.py # FastAPI + MCP HTTP + REST API
└── mcp_server.py # MCP 工具定义(混合搜索 + embedding)