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 访问:

如需先安装 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。

  1. 命令行(先登录 Azure)

    在项目根目录执行(将 agnetdoc 换成你的 Function App 名称):

    az login
    func azure functionapp publish agnetdoc
    

    如需把本地的 local.settings.json 里的应用设置同步到 Azure(会覆盖远程同名设置):

    func azure functionapp publish agnetdoc --publish-local-settings
    
  2. VS Code 使用发布配置文件

    • 安装 Azure Functions 扩展。
    • 在 Azure 视图中找到你的 Function App(如 agnetdoc),右键 → Deploy to Function App using Publish Profile。
    • 选择已下载的 agnetdoc.PublishSettings 文件(例如在 Downloads 中)。
  3. 用脚本 + 发布配置文件发布(无需 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-RPC
  • GET /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)
S
Description
No description provided
Readme
89 KiB
Languages
Python 99.5%
Shell 0.5%