380 lines
12 KiB
Markdown
380 lines
12 KiB
Markdown
# GEO 系统与 AgentKit 联通指南
|
||
|
||
## 一、AgentKit 是什么
|
||
|
||
AgentKit 是一个**统一 Agent 开发框架**,核心能力:
|
||
|
||
| 能力 | 说明 |
|
||
|------|------|
|
||
| **ReAct 推理引擎** | Think → Act → Observe 循环,LLM 自主选择工具、决定何时输出 |
|
||
| **LLM Gateway** | 统一 LLM 调用入口,管理 API Key、模型路由、降级策略、用量统计 |
|
||
| **Skill 系统** | YAML 配置定义技能(Prompt + Tool + 质量门禁),无需写代码 |
|
||
| **意图路由** | 关键词匹配(零成本)+ LLM 分类(兜底),自动路由到最佳 Skill |
|
||
| **产出质量管理** | 必填字段、最低字数、Schema 校验、自定义验证器,不通过自动重试 |
|
||
| **标准化输出** | Schema 验证 + 类型归一化 + 元数据附加,所有 Skill 产出格式统一 |
|
||
| **记忆系统** | 语义记忆(pgvector)+ 情景记忆(Redis)+ 工作记忆 |
|
||
| **MCP 协议** | 支持 Model Context Protocol,可连接外部工具服务器 |
|
||
| **CLI 工具** | `agentkit` 命令行,支持 init/serve/task/skill/pair/doctor/usage |
|
||
| **独立部署** | FastAPI Server + Docker,业务系统通过 HTTP API 调用 |
|
||
|
||
**一句话总结**:AgentKit 让你从写 150 行 Agent 代码降为 10-20 行 YAML 配置。
|
||
|
||
---
|
||
|
||
## 二、架构关系
|
||
|
||
```
|
||
┌──────────────────────┐ HTTP API ┌──────────────────────────┐
|
||
│ GEO Backend │ ───────────────→ │ AgentKit Server │
|
||
│ (FastAPI :8000) │ │ (FastAPI :8001) │
|
||
│ │ POST /tasks │ │
|
||
│ 不再 import │ GET /tasks/{id} │ Intent Router │
|
||
│ agentkit 内部类 │ GET /skills │ ReAct Engine │
|
||
│ │ GET /llm/usage │ LLM Gateway │
|
||
│ 只用 AgentKitClient │ │ Quality Gate │
|
||
│ │ ←── callback ─── │ Output Standardizer │
|
||
│ /internal/* API │ (custom_handler) │ AgentPool + SkillRegistry│
|
||
└──────────────────────┘ └──────────────────────────┘
|
||
│
|
||
┌─────┴─────┐
|
||
│ LLM APIs │
|
||
│ (DeepSeek │
|
||
│ OpenAI…) │
|
||
└───────────┘
|
||
```
|
||
|
||
**关键原则**:
|
||
- GEO Backend **不 import agentkit 内部类**,只通过 HTTP API 调用
|
||
- AgentKit Server **不直接访问 GEO 数据库**,需要 DB 时回调 GEO 的内部 API
|
||
- LLM API Key **只在 AgentKit Server 中配置**,GEO 不需要
|
||
|
||
---
|
||
|
||
## 三、联通步骤
|
||
|
||
### Step 1:部署 AgentKit Server
|
||
|
||
```bash
|
||
cd fischer-agentkit
|
||
|
||
# 初始化配置
|
||
agentkit init
|
||
|
||
# 编辑 .env,填入 LLM API Key
|
||
cp .env.example .env
|
||
# DEEPSEEK_API_KEY=sk-xxx
|
||
# OPENAI_API_KEY=sk-xxx
|
||
|
||
# 配对 GEO 业务系统
|
||
agentkit pair --name geo-backend --skills-dir ./configs/skills
|
||
# 输出: API Key = ak_live_xxxxxxxxxxxx
|
||
|
||
# 启动 Server
|
||
agentkit serve --host 0.0.0.0 --port 8001
|
||
|
||
# 验证
|
||
agentkit doctor
|
||
```
|
||
|
||
### Step 2:GEO Backend 配置环境变量
|
||
|
||
在 GEO 的 `.env` 中添加:
|
||
|
||
```bash
|
||
# AgentKit Server 连接
|
||
AGENTKIT_SERVER_URL=http://localhost:8001
|
||
AGENTKIT_API_KEY=ak_live_xxxxxxxxxxxx # Step 1 中 pair 生成的 key
|
||
```
|
||
|
||
### Step 3:改造 GEO 的 agent_framework 适配层
|
||
|
||
将 `app/agent_framework/adapter.py` 从 import 模式改为 HTTP API 模式:
|
||
|
||
```python
|
||
# app/agent_framework/adapter.py — Mode A 版本
|
||
import os
|
||
import logging
|
||
from agentkit.server.client import AgentKitClient
|
||
|
||
logger = logging.getLogger(__name__)
|
||
_CLIENT: AgentKitClient | None = None
|
||
|
||
def get_agentkit_client() -> AgentKitClient:
|
||
"""获取 AgentKit Server HTTP 客户端"""
|
||
global _CLIENT
|
||
if _CLIENT is None:
|
||
base_url = os.getenv("AGENTKIT_SERVER_URL", "http://localhost:8001")
|
||
api_key = os.getenv("AGENTKIT_API_KEY")
|
||
_CLIENT = AgentKitClient(base_url=base_url, api_key=api_key)
|
||
return _CLIENT
|
||
|
||
async def submit_task(input_data: dict, skill_name: str | None = None) -> dict:
|
||
"""提交任务到 AgentKit Server"""
|
||
client = get_agentkit_client()
|
||
return await client.submit_task(input_data=input_data, skill_name=skill_name)
|
||
|
||
async def get_task_status(task_id: str) -> dict:
|
||
"""查询任务状态"""
|
||
client = get_agentkit_client()
|
||
return await client.get_task_status(task_id)
|
||
|
||
async def get_llm_usage(agent_name: str | None = None) -> dict:
|
||
"""查询 LLM 用量"""
|
||
client = get_agentkit_client()
|
||
return await client.get_usage(agent_name=agent_name)
|
||
```
|
||
|
||
### Step 4:改造业务调用
|
||
|
||
**内容生成**(原来 3 次 dispatch → 1 次 submit_task):
|
||
|
||
```python
|
||
# 改造前
|
||
from app.agent_framework.dispatcher import TaskDispatcher
|
||
dispatcher = TaskDispatcher(settings.REDIS_URL)
|
||
task = TaskMessage(agent_name="content_generator", ...)
|
||
result = await dispatcher.dispatch(task, ...)
|
||
|
||
# 改造后
|
||
from app.agent_framework.adapter import submit_task
|
||
result = await submit_task(
|
||
input_data={"target_keyword": keyword, "brand_name": brand, ...},
|
||
skill_name="content_generator",
|
||
)
|
||
content = result["data"]["content"]
|
||
```
|
||
|
||
**引用检测**:
|
||
|
||
```python
|
||
# 改造前
|
||
from app.agent_framework.agents import CitationDetectorAgent
|
||
agent = CitationDetectorAgent()
|
||
result = await agent.execute(task)
|
||
|
||
# 改造后
|
||
from app.agent_framework.adapter import submit_task
|
||
result = await submit_task(
|
||
input_data={"keyword": keyword, "platform": platform, ...},
|
||
skill_name="citation_detector",
|
||
)
|
||
```
|
||
|
||
### Step 5:新增内部 API(供 AgentKit Server 回调)
|
||
|
||
custom_handler 需要 DB 访问时,AgentKit Server 通过 HTTP 回调 GEO:
|
||
|
||
```python
|
||
# app/api/internal.py
|
||
from fastapi import APIRouter, Depends
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from app.database import get_db
|
||
|
||
router = APIRouter(prefix="/internal", tags=["internal"])
|
||
|
||
@router.post("/citation/detect")
|
||
async def citation_detect(input_data: dict, db: AsyncSession = Depends(get_db)):
|
||
"""供 AgentKit Server 的 citation_handler 回调"""
|
||
from app.services.citation.citation import CitationService
|
||
service = CitationService()
|
||
return await service.detect_full(input_data, db=db)
|
||
|
||
@router.post("/knowledge/search")
|
||
async def knowledge_search(input_data: dict, db: AsyncSession = Depends(get_db)):
|
||
"""供 AgentKit Server 的 retrieve_knowledge Tool 回调"""
|
||
from app.services.knowledge.rag_service import RAGService
|
||
service = RAGService()
|
||
results = await service.search(session=db, query=input_data["query"])
|
||
return {"results": results}
|
||
```
|
||
|
||
### Step 6:Docker Compose 联合部署
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
version: "3.8"
|
||
services:
|
||
geo-backend:
|
||
build: ./geo/backend
|
||
ports: ["8000:8000"]
|
||
environment:
|
||
- AGENTKIT_SERVER_URL=http://agentkit-server:8001
|
||
- AGENTKIT_API_KEY=${AGENTKIT_API_KEY}
|
||
depends_on:
|
||
- agentkit-server
|
||
|
||
agentkit-server:
|
||
build: ./fischer-agentkit
|
||
command: serve --host 0.0.0.0 --port 8001
|
||
ports: ["8001:8001"]
|
||
env_file: ./fischer-agentkit/.env
|
||
environment:
|
||
- GEO_BACKEND_URL=http://geo-backend:8000
|
||
depends_on:
|
||
- redis
|
||
- postgres
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
|
||
postgres:
|
||
image: pgvector/pgvector:pg15
|
||
environment:
|
||
POSTGRES_USER: agentkit
|
||
POSTGRES_PASSWORD: agentkit
|
||
POSTGRES_DB: agentkit
|
||
```
|
||
|
||
---
|
||
|
||
## 四、GEO 当前 8 个 Skill 映射
|
||
|
||
| 原 Agent 名 | Skill 名 | 模式 | 改造要点 |
|
||
|-------------|---------|------|---------|
|
||
| citation_detector | citation_detector | custom | handler 回调 GEO `/internal/citation/detect` |
|
||
| monitor | monitor | custom | handler 回调 GEO `/internal/monitor/check` |
|
||
| schema_advisor | schema_advisor | custom | handler 回调 GEO `/internal/schema/advise` |
|
||
| content_generator | content_generator | llm_generate | 直接迁移 YAML,添加 intent + quality_gate |
|
||
| deai_agent | deai_agent | llm_generate | 直接迁移 YAML |
|
||
| geo_optimizer | geo_optimizer | llm_generate | 直接迁移 YAML |
|
||
| competitor_analyzer | competitor_analyzer | tool_call | Tool 迁移到 AgentKit Server |
|
||
| trend_agent | trend_agent | tool_call | Tool 迁移到 AgentKit Server |
|
||
|
||
**YAML 零修改**:现有 8 个 YAML 配置无需修改即可被 AgentKit 加载(SkillConfig 向后兼容 AgentConfig)。建议为 llm_generate 模式的 Skill 添加 `intent` 和 `quality_gate` 字段以启用新能力。
|
||
|
||
---
|
||
|
||
## 五、API 参考
|
||
|
||
### AgentKit Server REST API
|
||
|
||
| 路径 | 方法 | 说明 |
|
||
|------|------|------|
|
||
| `POST /api/v1/tasks` | POST | 提交任务(支持意图路由自动匹配 Skill) |
|
||
| `GET /api/v1/tasks/{id}` | GET | 查询任务状态和结果 |
|
||
| `GET /api/v1/tasks` | GET | 列出任务 |
|
||
| `DELETE /api/v1/tasks/{id}` | DELETE | 取消任务 |
|
||
| `POST /api/v1/agents` | POST | 创建 Agent 实例 |
|
||
| `GET /api/v1/agents` | GET | 列出 Agent 实例 |
|
||
| `POST /api/v1/skills` | POST | 注册 Skill |
|
||
| `GET /api/v1/skills` | GET | 列出已注册 Skill |
|
||
| `GET /api/v1/llm/usage` | GET | 查询 LLM 用量统计 |
|
||
| `GET /api/v1/health` | GET | 健康检查 |
|
||
|
||
### 认证
|
||
|
||
所有 API 请求需携带 Header:
|
||
|
||
```
|
||
X-API-Key: ak_live_xxxxxxxxxxxx
|
||
```
|
||
|
||
### 提交任务示例
|
||
|
||
```bash
|
||
# 指定 Skill
|
||
curl -X POST http://localhost:8001/api/v1/tasks \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: ak_live_xxxxxxxxxxxx" \
|
||
-d '{
|
||
"skill_name": "content_generator",
|
||
"input_data": {"target_keyword": "AI", "brand_name": "BrandX"}
|
||
}'
|
||
|
||
# 意图路由自动匹配
|
||
curl -X POST http://localhost:8001/api/v1/tasks \
|
||
-H "Content-Type: application/json" \
|
||
-H "X-API-Key: ak_live_xxxxxxxxxxxx" \
|
||
-d '{
|
||
"input_data": {"query": "帮我生成一篇关于AI的文章"}
|
||
}'
|
||
```
|
||
|
||
### Python SDK
|
||
|
||
```python
|
||
from agentkit.server.client import AgentKitClient
|
||
|
||
client = AgentKitClient(
|
||
base_url="http://localhost:8001",
|
||
api_key="ak_live_xxxxxxxxxxxx",
|
||
)
|
||
|
||
# 提交任务
|
||
result = await client.submit_task(
|
||
skill_name="content_generator",
|
||
input_data={"target_keyword": "AI", "brand_name": "BrandX"},
|
||
)
|
||
|
||
# 查询用量
|
||
usage = await client.get_usage()
|
||
```
|
||
|
||
---
|
||
|
||
## 六、CLI 速查
|
||
|
||
```bash
|
||
agentkit init # 初始化项目配置
|
||
agentkit serve --port 8001 # 启动 Server
|
||
agentkit doctor # 诊断健康状态
|
||
agentkit version # 查看版本
|
||
|
||
agentkit pair --name geo-backend # 配对业务系统,生成 API Key
|
||
agentkit pair --list # 查看已配对客户端
|
||
agentkit pair --revoke geo-backend # 撤销配对
|
||
|
||
agentkit task submit --skill content_generator --input '{"topic":"AI"}' --server-url http://localhost:8001
|
||
agentkit task status <task_id> --server-url http://localhost:8001
|
||
agentkit task list --server-url http://localhost:8001
|
||
|
||
agentkit skill list --server-url http://localhost:8001
|
||
agentkit skill load ./my_skill.yaml
|
||
agentkit skill info content_generator --server-url http://localhost:8001
|
||
|
||
agentkit usage --server-url http://localhost:8001
|
||
```
|
||
|
||
---
|
||
|
||
## 七、迁移检查清单
|
||
|
||
### Phase 1:AgentKit Server 部署
|
||
- [ ] `agentkit init` 生成配置
|
||
- [ ] `.env` 填入 LLM API Key
|
||
- [ ] `agentkit pair --name geo-backend` 生成 API Key
|
||
- [ ] 8 个 YAML 配置复制到 `configs/skills/`
|
||
- [ ] 14 个 FunctionTool 迁移到 `configs/geo_tools.py`
|
||
- [ ] 3 个 custom_handler 迁移到 `configs/geo_handlers.py`
|
||
- [ ] `agentkit serve` 启动成功
|
||
- [ ] `agentkit doctor` 健康检查通过
|
||
|
||
### Phase 2:GEO Backend 改造
|
||
- [ ] `.env` 添加 `AGENTKIT_SERVER_URL` + `AGENTKIT_API_KEY`
|
||
- [ ] `adapter.py` 改为 HTTP API 模式
|
||
- [ ] `content_generation_service.py` 改用 `submit_task()`
|
||
- [ ] `citation.py` 改用 `submit_task()`
|
||
- [ ] `scheduler.py` 改用 `submit_task()`
|
||
- [ ] 新增 `/internal/*` API 路由
|
||
- [ ] 端到端测试通过
|
||
|
||
### Phase 3:清理
|
||
- [ ] 删除旧框架文件(base.py, dispatcher.py, registry.py 等)
|
||
- [ ] 删除旧 Agent 类
|
||
- [ ] 更新 `__init__.py` 导出
|
||
- [ ] 全量回归测试
|
||
|
||
---
|
||
|
||
## 八、配置优先级
|
||
|
||
```
|
||
客户端自定义配置(pair 时 --skills-dir 指定)
|
||
↓ 覆盖
|
||
init 默认配置(agentkit.yaml)
|
||
↓ 覆盖
|
||
硬编码默认值
|
||
```
|
||
|
||
业务系统可以通过 `agentkit pair --name geo-backend --skills-dir ./custom_skills` 指定自己的 Skill 目录,优先级高于 AgentKit Server 的默认配置。
|