615 lines
23 KiB
Markdown
615 lines
23 KiB
Markdown
# GEO 项目迁移至 AgentKit v2 Mode A 方案
|
||
|
||
## 1. 目标
|
||
|
||
将 GEO 项目从当前的**旧框架 + import 混合模式**迁移至 **AgentKit v2 Mode A(HTTP API 模式)**。
|
||
|
||
迁移完成后:
|
||
- AgentKit Server 独立部署,GEO 通过 HTTP API 调用
|
||
- LLM 调用统一由 AgentKit Server 的 LLM Gateway 管理
|
||
- 意图识别、ReAct 循环、质量检查、标准化输出全部在 AgentKit Server 内完成
|
||
- GEO 项目不再直接 import agentkit 内部类
|
||
|
||
## 2. 当前架构 vs 目标架构
|
||
|
||
### 当前架构(3 条调用链并存)
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────┐
|
||
│ GEO Backend │
|
||
│ │
|
||
│ Chain A: API Route → TaskDispatcher → Redis → BaseAgent │
|
||
│ Chain B: Service → 直接实例化 Agent → 直接调用 execute() │
|
||
│ Chain C: Adapter → ConfigDrivenAgent → custom_handler │
|
||
│ │
|
||
│ ┌─────────────────────────────────────────────────────┐ │
|
||
│ │ GEO 内部的旧框架(BaseAgent + Redis Queue + DB) │ │
|
||
│ │ + agentkit import(ConfigDrivenAgent + ToolRegistry)│ │
|
||
│ │ + LLMFactory(GEO 自己的 LLM 封装) │ │
|
||
│ └─────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
### 目标架构(Mode A)
|
||
|
||
```
|
||
┌──────────────────────┐ HTTP API ┌──────────────────────────┐
|
||
│ GEO Backend │ ───────────────→ │ AgentKit Server │
|
||
│ │ │ │
|
||
│ API Routes │ POST /tasks │ Intent Router │
|
||
│ Services │ GET /tasks/{id} │ ReAct Engine │
|
||
│ Workers │ GET /llm/usage │ LLM Gateway │
|
||
│ │ │ Quality Gate │
|
||
│ 不再 import │ │ Output Standardizer │
|
||
│ agentkit 内部类 │ │ AgentPool │
|
||
│ │ │ SkillRegistry │
|
||
│ 只用 AgentKitClient │ │ ToolRegistry │
|
||
│ │ │ MCP Bridge │
|
||
└──────────────────────┘ └──────────────────────────┘
|
||
│
|
||
┌─────┴─────┐
|
||
│ LLM APIs │
|
||
└───────────┘
|
||
```
|
||
|
||
## 3. 需要改动的文件清单
|
||
|
||
### 3.1 必须改动(核心迁移)
|
||
|
||
| 文件 | 当前用法 | 改动内容 |
|
||
|------|---------|---------|
|
||
| `app/agent_framework/adapter.py` | import agentkit 内部类 | 改为只提供 `get_agentkit_client()` 和 `submit_task_via_api()` |
|
||
| `app/agent_framework/__init__.py` | 导出大量 agentkit 类 | 精简导出,只暴露 `AgentKitClient` 相关 |
|
||
| `app/api/agents.py` | 用旧 `TaskDispatcher` + `TaskMessage` | 改为调用 `AgentKitClient.submit_task()` |
|
||
| `app/services/content/content_generation_service.py` | 用旧 `TaskDispatcher` + 轮询 | 改为调用 `AgentKitClient.submit_task()` |
|
||
| `app/services/citation/citation.py` | 直接实例化 `CitationDetectorAgent` | 改为调用 `AgentKitClient.submit_task()` |
|
||
| `app/workers/scheduler.py` | 直接实例化 `CitationDetectorAgent` | 改为调用 `AgentKitClient.submit_task()` |
|
||
|
||
### 3.2 需要迁移到 AgentKit Server 的代码
|
||
|
||
| 当前位置 | 功能 | 迁移目标 |
|
||
|---------|------|---------|
|
||
| `app/agent_framework/agents/custom_handlers/citation_handler.py` | 引用检测业务逻辑 | AgentKit Server 的 Tool 或 custom_handler |
|
||
| `app/agent_framework/agents/custom_handlers/monitor_handler.py` | 监控业务逻辑 | AgentKit Server 的 Tool 或 custom_handler |
|
||
| `app/agent_framework/agents/custom_handlers/schema_handler.py` | Schema 建议业务逻辑 | AgentKit Server 的 Tool 或 custom_handler |
|
||
| `app/agent_framework/tools/*.py`(14 个 FunctionTool) | 业务 Tool 定义 | AgentKit Server 的 ToolRegistry |
|
||
| `app/agent_framework/agents/configs/*.yaml`(8 个) | Agent 配置 | AgentKit Server 的 SkillLoader 加载目录 |
|
||
|
||
### 3.3 可删除(迁移完成后)
|
||
|
||
| 文件/目录 | 原因 |
|
||
|----------|------|
|
||
| `app/agent_framework/base.py` | 旧 BaseAgent,被 AgentKit Server 取代 |
|
||
| `app/agent_framework/dispatcher.py` | 旧 TaskDispatcher,被 AgentKit Server 取代 |
|
||
| `app/agent_framework/registry.py` | 旧 AgentRegistry,被 AgentKit Server 取代 |
|
||
| `app/agent_framework/protocol.py` | 旧协议类,被 agentkit.core.protocol 取代 |
|
||
| `app/agent_framework/exceptions.py` | 旧异常类,被 agentkit.core.exceptions 取代 |
|
||
| `app/agent_framework/config_manager.py` | 旧配置管理,被 SkillConfig 取代 |
|
||
| `app/agent_framework/standalone.py` | 旧运行器,被 AgentKit Server 取代 |
|
||
| `app/agent_framework/pipeline/` | 旧 Pipeline,被 AgentKit Server 编排取代 |
|
||
| `app/agent_framework/agents/` 下的旧 Agent 类 | 被 YAML 配置 + Skill 取代 |
|
||
|
||
## 4. 分步迁移方案
|
||
|
||
### Phase 1:部署 AgentKit Server + 配置迁移
|
||
|
||
**目标**:AgentKit Server 能独立运行,加载 GEO 的 8 个 Skill 配置和 14 个 Tool。
|
||
|
||
#### 4.1.1 创建 AgentKit Server 启动配置
|
||
|
||
在 `fischer-agentkit/` 项目中创建:
|
||
|
||
```yaml
|
||
# configs/llm_config.yaml — LLM Provider 配置
|
||
providers:
|
||
deepseek:
|
||
api_key: "${DEEPSEEK_API_KEY}"
|
||
base_url: "https://api.deepseek.com/v1"
|
||
models:
|
||
deepseek-chat:
|
||
max_tokens: 64000
|
||
cost_per_1k_input: 0.00014
|
||
cost_per_1k_output: 0.00028
|
||
|
||
model_aliases:
|
||
default: "deepseek-chat"
|
||
fast: "deepseek-chat"
|
||
powerful: "deepseek-chat"
|
||
|
||
fallbacks:
|
||
deepseek-chat: []
|
||
```
|
||
|
||
#### 4.1.2 迁移 YAML 配置为 SkillConfig
|
||
|
||
现有 8 个 YAML 无需修改即可加载(SkillConfig 向后兼容 AgentConfig)。
|
||
但建议为需要意图识别的 Skill 添加 `intent` 字段:
|
||
|
||
```yaml
|
||
# content_generator.yaml — 增加的 v2 字段
|
||
intent:
|
||
keywords: ["生成内容", "写文章", "选题", "generate", "content"]
|
||
description: "用户需要生成SEO/GEO优化内容、推荐选题或撰写文章"
|
||
examples:
|
||
- "帮我写一篇关于AI的文章"
|
||
- "推荐一些选题"
|
||
|
||
execution_mode: react # 使用 ReAct 引擎
|
||
max_steps: 5
|
||
|
||
quality_gate:
|
||
required_fields: ["content"]
|
||
min_word_count: 500
|
||
max_retries: 1
|
||
```
|
||
|
||
#### 4.1.3 迁移 14 个 FunctionTool 到 AgentKit Server
|
||
|
||
将 GEO 的 Tool 注册代码迁移为 AgentKit Server 的 Tool 插件。
|
||
|
||
**方式 A(推荐)**:在 AgentKit Server 启动时注册 Tool
|
||
|
||
```python
|
||
# fischer-agentkit/configs/geo_tools.py
|
||
"""GEO 项目的 Tool 注册 — 供 AgentKit Server 使用"""
|
||
|
||
from agentkit.tools.function_tool import FunctionTool
|
||
from agentkit.tools.registry import ToolRegistry
|
||
|
||
|
||
def register_geo_tools(registry: ToolRegistry) -> None:
|
||
"""注册 GEO 项目的所有 Tool"""
|
||
|
||
# --- Citation Tools ---
|
||
async def execute_single_platform(keyword: str, platform: str,
|
||
target_brand: str, brand_aliases: list[str] = None):
|
||
"""在单个 AI 平台执行引用检测"""
|
||
# 调用 GEO 的业务服务(通过 HTTP 调用 GEO Backend API)
|
||
from agentkit.tools.function_tool import FunctionTool
|
||
# ... 实现 ...
|
||
|
||
registry.register(FunctionTool(
|
||
name="execute_single_platform",
|
||
description="在单个AI平台执行引用检测",
|
||
func=execute_single_platform,
|
||
input_schema={...},
|
||
tags=["citation", "detection"],
|
||
))
|
||
# ... 注册其他 13 个 Tool ...
|
||
```
|
||
|
||
**方式 B**:custom_handler 保持为 custom 模式
|
||
|
||
3 个 custom_handler(citation/monitor/schema)因为涉及复杂的 DB 操作和多服务编排,
|
||
可以保持 `execution_mode: custom`,在 AgentKit Server 中注册为 custom_handler。
|
||
|
||
```python
|
||
# fischer-agentkit/configs/geo_handlers.py
|
||
"""GEO 项目的 Custom Handler — 供 AgentKit Server 使用"""
|
||
|
||
async def handle_citation_task(task):
|
||
"""引用检测 handler — 通过 HTTP 调用 GEO Backend 的业务 API"""
|
||
import httpx
|
||
async with httpx.AsyncClient() as client:
|
||
if task.task_type == "citation_detect":
|
||
resp = await client.post(
|
||
"http://geo-backend:8000/internal/citation/detect",
|
||
json=task.input_data,
|
||
)
|
||
return resp.json()
|
||
elif task.task_type == "citation_detect_single":
|
||
resp = await client.post(
|
||
"http://geo-backend:8000/internal/citation/detect-single",
|
||
json=task.input_data,
|
||
)
|
||
return resp.json()
|
||
```
|
||
|
||
> **关键决策**:custom_handler 需要 DB 访问。有两种方案:
|
||
> - **方案 1(推荐)**:AgentKit Server 通过 HTTP 回调 GEO Backend 的内部 API 访问 DB
|
||
> - **方案 2**:AgentKit Server 直接连接 GEO 的数据库(耦合度高,不推荐)
|
||
|
||
#### 4.1.4 创建 AgentKit Server 启动脚本
|
||
|
||
```python
|
||
# fischer-agentkit/configs/geo_server.py
|
||
"""GEO 专用 AgentKit Server 启动配置"""
|
||
|
||
from agentkit.server.app import create_app
|
||
from agentkit.llm.gateway import LLMGateway
|
||
from agentkit.llm.config import LLMConfig
|
||
from agentkit.skills.loader import SkillLoader
|
||
from agentkit.skills.registry import SkillRegistry
|
||
from agentkit.tools.registry import ToolRegistry
|
||
|
||
from configs.geo_tools import register_geo_tools
|
||
from configs.geo_handlers import handle_citation_task, handle_monitor_task, handle_schema_task
|
||
|
||
|
||
def create_geo_app():
|
||
# 1. 初始化 LLM Gateway
|
||
llm_config = LLMConfig.from_yaml("configs/llm_config.yaml")
|
||
llm_gateway = LLMGateway(config=llm_config)
|
||
|
||
# 2. 初始化 Tool Registry
|
||
tool_registry = ToolRegistry()
|
||
register_geo_tools(tool_registry)
|
||
|
||
# 3. 初始化 Skill Registry
|
||
skill_registry = SkillRegistry()
|
||
loader = SkillLoader(skill_registry=skill_registry, tool_registry=tool_registry)
|
||
loader.load_from_directory("configs/skills") # 8 个 YAML
|
||
|
||
# 4. 创建 FastAPI App
|
||
app = create_app(
|
||
llm_gateway=llm_gateway,
|
||
skill_registry=skill_registry,
|
||
tool_registry=tool_registry,
|
||
)
|
||
|
||
return app
|
||
|
||
|
||
# 启动命令:
|
||
# uvicorn configs.geo_server:create_geo_app --factory --host 0.0.0.0 --port 8000
|
||
```
|
||
|
||
### Phase 2:GEO Backend 改造
|
||
|
||
**目标**:GEO Backend 不再直接使用 agentkit 内部类,全部通过 `AgentKitClient` 调用。
|
||
|
||
#### 4.2.1 改造 adapter.py
|
||
|
||
```python
|
||
# app/agent_framework/adapter.py — Mode A 版本
|
||
"""GEO Agent 适配层 — Mode A(HTTP API)
|
||
|
||
所有 Agent 操作通过 AgentKit Server 的 HTTP API 完成。
|
||
GEO Backend 不再 import agentkit 内部类。
|
||
"""
|
||
|
||
import logging
|
||
import os
|
||
|
||
from agentkit.server.client import AgentKitClient
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
_AGENTKIT_CLIENT: AgentKitClient | None = None
|
||
|
||
|
||
def get_agentkit_client() -> AgentKitClient:
|
||
"""获取 AgentKit Server HTTP 客户端
|
||
|
||
环境变量:
|
||
AGENTKIT_SERVER_URL: AgentKit Server 地址,默认 http://localhost:8000
|
||
"""
|
||
global _AGENTKIT_CLIENT
|
||
if _AGENTKIT_CLIENT is None:
|
||
base_url = os.getenv("AGENTKIT_SERVER_URL", "http://localhost:8000")
|
||
_AGENTKIT_CLIENT = AgentKitClient(base_url=base_url)
|
||
logger.info(f"AgentKitClient initialized: {base_url}")
|
||
return _AGENTKIT_CLIENT
|
||
|
||
|
||
async def submit_task(
|
||
input_data: dict,
|
||
skill_name: str | None = None,
|
||
agent_name: str | None = None,
|
||
) -> dict:
|
||
"""提交任务到 AgentKit Server
|
||
|
||
Args:
|
||
input_data: 任务输入数据
|
||
skill_name: 指定 Skill 名称(可选,不指定则自动路由)
|
||
agent_name: 指定 Agent 名称(可选)
|
||
|
||
Returns:
|
||
标准化输出结果,包含 skill_name, data, metadata
|
||
"""
|
||
client = get_agentkit_client()
|
||
result = await client.submit_task(
|
||
input_data=input_data,
|
||
skill_name=skill_name,
|
||
agent_name=agent_name,
|
||
)
|
||
return result
|
||
|
||
|
||
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)
|
||
```
|
||
|
||
#### 4.2.2 改造 API 路由(app/api/agents.py)
|
||
|
||
```python
|
||
# 改造前:
|
||
from app.agent_framework.dispatcher import TaskDispatcher
|
||
from app.agent_framework.protocol import TaskMessage, TaskStatus
|
||
|
||
task = TaskMessage(...)
|
||
dispatcher = TaskDispatcher(settings.REDIS_URL)
|
||
await dispatcher.dispatch(task, ...)
|
||
|
||
# 改造后:
|
||
from app.agent_framework.adapter import submit_task, get_task_status, get_llm_usage
|
||
|
||
result = await submit_task(
|
||
input_data=body.input_data,
|
||
skill_name=body.agent_name, # agent_name 映射为 skill_name
|
||
)
|
||
```
|
||
|
||
#### 4.2.3 改造 ContentGenerationService
|
||
|
||
```python
|
||
# 改造前(三阶段轮询):
|
||
from app.agent_framework.dispatcher import TaskDispatcher
|
||
from app.agent_framework.protocol import TaskMessage
|
||
|
||
dispatcher = TaskDispatcher(settings.REDIS_URL)
|
||
task = TaskMessage(agent_name="content_generator", ...)
|
||
dispatched_id = await dispatcher.dispatch(task, ...)
|
||
result = await self._poll_task_result(dispatcher, dispatched_id, timeout=300)
|
||
|
||
# 改造后(单次调用,AgentKit Server 内部编排):
|
||
from app.agent_framework.adapter import submit_task
|
||
|
||
result = await submit_task(
|
||
input_data={
|
||
"target_keyword": keyword,
|
||
"brand_name": brand_name,
|
||
"target_platform": platform,
|
||
"word_count": word_count,
|
||
"content_style": content_style,
|
||
"run_deai": run_deai,
|
||
"run_geo": run_geo,
|
||
},
|
||
skill_name="content_generator",
|
||
)
|
||
content = result["data"]["content"]
|
||
```
|
||
|
||
> **注意**:当前 content_generation_service 的三阶段(generate → de-AI → GEO optimize)
|
||
> 是通过 3 次独立的 TaskDispatcher.dispatch 实现的。
|
||
> 迁移到 Mode A 后,有两种方案:
|
||
>
|
||
> **方案 1(推荐)**:在 AgentKit Server 中创建一个 `content_production` Pipeline Skill,
|
||
> 内部编排 3 个子 Skill 的执行顺序。GEO 只需一次 `submit_task` 调用。
|
||
>
|
||
> **方案 2(简单)**:GEO 仍然调用 3 次 `submit_task`,每次指定不同的 skill_name。
|
||
> 改动最小,但调用方仍需编排逻辑。
|
||
|
||
#### 4.2.4 改造 Citation 和 Scheduler
|
||
|
||
```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",
|
||
)
|
||
```
|
||
|
||
### Phase 3:GEO Backend 内部 API(供 AgentKit Server 回调)
|
||
|
||
custom_handler 需要 DB 访问,AgentKit Server 通过 HTTP 回调 GEO Backend。
|
||
|
||
#### 4.3.1 新增内部 API 路由
|
||
|
||
```python
|
||
# app/api/internal.py — 仅供 AgentKit Server 内部调用
|
||
"""内部 API — 供 AgentKit Server 回调访问 GEO 业务逻辑"""
|
||
|
||
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("/citation/detect-single")
|
||
async def citation_detect_single(input_data: dict, db: AsyncSession = Depends(get_db)):
|
||
"""单平台引用检测 — 供 AgentKit Server 回调"""
|
||
from app.services.citation.citation import CitationService
|
||
service = CitationService()
|
||
return await service.detect_single(input_data, db=db)
|
||
|
||
|
||
@router.post("/monitor/check")
|
||
async def monitor_check(input_data: dict, db: AsyncSession = Depends(get_db)):
|
||
"""品牌监控检查 — 供 AgentKit Server 的 monitor_handler 回调"""
|
||
from app.services.monitor.monitor_service import MonitorService
|
||
service = MonitorService()
|
||
return await service.check_and_compare(input_data, db=db)
|
||
|
||
|
||
@router.post("/schema/advise")
|
||
async def schema_advise(input_data: dict, db: AsyncSession = Depends(get_db)):
|
||
"""Schema 建议 — 供 AgentKit Server 的 schema_handler 回调"""
|
||
from app.services.schema.schema_service import SchemaService
|
||
service = SchemaService()
|
||
return await service.advise(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"],
|
||
knowledge_base_ids=input_data.get("knowledge_base_ids", []),
|
||
top_k=input_data.get("top_k", 3),
|
||
)
|
||
return {"results": results}
|
||
```
|
||
|
||
> **安全**:内部 API 应限制只允许 AgentKit Server 的 IP 访问,或使用内部认证 Token。
|
||
|
||
### Phase 4:清理旧代码
|
||
|
||
迁移完成并验证后,删除以下文件/目录:
|
||
|
||
```
|
||
app/agent_framework/
|
||
├── base.py # 删除
|
||
├── dispatcher.py # 删除
|
||
├── registry.py # 删除
|
||
├── protocol.py # 删除
|
||
├── exceptions.py # 删除
|
||
├── config_manager.py # 删除
|
||
├── standalone.py # 删除
|
||
├── pipeline/ # 删除
|
||
└── agents/
|
||
├── __init__.py # 删除(旧 Agent 类导出)
|
||
├── base_agent.py # 删除
|
||
├── citation_detector.py # 删除
|
||
├── ...其他旧 Agent 类 # 删除
|
||
└── configs/ # 保留(已迁移到 AgentKit Server)
|
||
```
|
||
|
||
保留的文件:
|
||
```
|
||
app/agent_framework/
|
||
├── __init__.py # 精简,只导出 AgentKitClient 相关
|
||
├── adapter.py # Mode A 版本
|
||
└── tools/ # 保留(Tool 定义已迁移到 AgentKit Server,但可作为参考)
|
||
```
|
||
|
||
## 5. 部署架构
|
||
|
||
### 5.1 docker-compose 配置
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
version: "3.8"
|
||
|
||
services:
|
||
# GEO Backend
|
||
geo-backend:
|
||
build: ./geo/backend
|
||
ports:
|
||
- "8000:8000"
|
||
environment:
|
||
- AGENTKIT_SERVER_URL=http://agentkit-server:8001
|
||
- DATABASE_URL=postgresql+asyncpg://...
|
||
- REDIS_URL=redis://redis:6379/0
|
||
depends_on:
|
||
- agentkit-server
|
||
- postgres
|
||
- redis
|
||
|
||
# AgentKit Server
|
||
agentkit-server:
|
||
build: ./fischer-agentkit
|
||
command: uvicorn configs.geo_server:create_geo_app --factory --host 0.0.0.0 --port 8001
|
||
ports:
|
||
- "8001:8001"
|
||
environment:
|
||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY}
|
||
- OPENAI_API_KEY=${OPENAI_API_KEY}
|
||
- GEO_BACKEND_URL=http://geo-backend:8000
|
||
volumes:
|
||
- ./fischer-agentkit/configs:/app/configs
|
||
depends_on:
|
||
- postgres
|
||
- redis
|
||
|
||
postgres:
|
||
image: pgvector/pg15:latest
|
||
ports:
|
||
- "5432:5432"
|
||
|
||
redis:
|
||
image: redis:7-alpine
|
||
ports:
|
||
- "6379:6379"
|
||
```
|
||
|
||
### 5.2 网络拓扑
|
||
|
||
```
|
||
┌──────────────┐
|
||
│ Frontend │
|
||
└──────┬───────┘
|
||
│
|
||
┌──────▼───────┐
|
||
│ GEO Backend │ :8000
|
||
│ (FastAPI) │
|
||
└──────┬───────┘
|
||
│ HTTP
|
||
┌──────▼───────┐
|
||
│ AgentKit Svr │ :8001
|
||
│ (FastAPI) │
|
||
└──────┬───────┘
|
||
┌────┼────┐
|
||
│ │ │
|
||
┌────▼┐ ┌▼───┐ ┌▼────┐
|
||
│Redis│ │ PG │ │ LLM │
|
||
└─────┘ └────┘ └─────┘
|
||
|
||
AgentKit Server ←→ GEO Backend:内部 API 回调(custom_handler 访问 DB)
|
||
GEO Backend ←→ AgentKit Server:HTTP API(submit_task / get_usage)
|
||
```
|
||
|
||
## 6. 迁移检查清单
|
||
|
||
### Phase 1:AgentKit Server 部署
|
||
- [ ] 创建 `configs/llm_config.yaml`
|
||
- [ ] 将 8 个 YAML 配置复制到 `configs/skills/` 目录
|
||
- [ ] 为需要意图识别的 Skill 添加 `intent` 字段
|
||
- [ ] 迁移 14 个 FunctionTool 到 `configs/geo_tools.py`
|
||
- [ ] 迁移 3 个 custom_handler 到 `configs/geo_handlers.py`
|
||
- [ ] 创建 `configs/geo_server.py` 启动配置
|
||
- [ ] 验证 AgentKit Server 能独立启动并加载所有 Skill/Tool
|
||
- [ ] 验证 `POST /api/v1/health` 返回 ok
|
||
|
||
### Phase 2:GEO Backend 改造
|
||
- [ ] 改造 `adapter.py` 为 Mode A 版本
|
||
- [ ] 改造 `app/api/agents.py` 使用 `submit_task()`
|
||
- [ ] 改造 `content_generation_service.py` 使用 `submit_task()`
|
||
- [ ] 改造 `citation.py` 和 `scheduler.py` 使用 `submit_task()`
|
||
- [ ] 新增 `app/api/internal.py` 内部 API
|
||
- [ ] 配置 `AGENTKIT_SERVER_URL` 环境变量
|
||
- [ ] 端到端测试:提交任务 → AgentKit 处理 → 返回结果
|
||
|
||
### Phase 3:清理
|
||
- [ ] 删除旧框架文件(base.py, dispatcher.py, registry.py 等)
|
||
- [ ] 删除旧 Agent 类文件
|
||
- [ ] 更新 `__init__.py` 导出
|
||
- [ ] 全量回归测试
|
||
|
||
## 7. 风险与缓解
|
||
|
||
| 风险 | 影响 | 缓解 |
|
||
|------|------|------|
|
||
| custom_handler 需要回调 GEO Backend | 增加网络延迟和故障点 | 内部 API 加超时+重试;AgentKit Server 和 GEO Backend 部署在同一网络 |
|
||
| 三阶段内容生成编排 | 调用方式变化 | 推荐 Pipeline Skill 方案,一次调用完成三阶段 |
|
||
| 旧代码删除导致其他模块 break | 运行时错误 | 逐文件删除,每次删除后跑全量测试 |
|
||
| AgentKit Server 单点故障 | 所有 Agent 功能不可用 | 部署多实例 + 负载均衡 |
|
||
| LLM API Key 安全 | 泄露风险 | AgentKit Server 环境变量注入,不写入代码或配置文件 |
|