feat: Agent 监控与编排、仪表盘/配置页及文档更新
- agent_runtime: orchestrator、core/memory/schemas 调整 - agent_monitoring API、service、agent_llm_log 模型与 database 注册 - 前端 AgentDashboard、AgentConfig、Agents/MainLayout/路由与 AgentChat - 文档:(红头)项目核心文档汇总、自主AI Agent改造完成情况、AI agent改造计划 Made-with: Cursor
This commit is contained in:
@@ -8,20 +8,24 @@ POST /api/v1/agent-chat/bare
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any, Dict, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.core.database import get_db
|
||||
from sqlalchemy.orm import Session
|
||||
from app.api.auth import get_current_user
|
||||
from app.models.user import User
|
||||
from app.models.agent import Agent
|
||||
from app.models.agent_llm_log import AgentLLMLog
|
||||
from app.agent_runtime import (
|
||||
AgentRuntime,
|
||||
AgentConfig,
|
||||
AgentLLMConfig,
|
||||
AgentToolConfig,
|
||||
AgentStep,
|
||||
AgentOrchestrator,
|
||||
OrchestratorAgentConfig,
|
||||
)
|
||||
from app.core.config import settings
|
||||
|
||||
@@ -29,6 +33,37 @@ logger = logging.getLogger(__name__)
|
||||
router = APIRouter(prefix="/api/v1/agent-chat", tags=["agent-chat"])
|
||||
|
||||
|
||||
def _make_llm_logger(
|
||||
db: Session,
|
||||
agent_id: Optional[str] = None,
|
||||
user_id: Optional[str] = None,
|
||||
):
|
||||
"""创建 LLM 调用日志回调,写入 AgentLLMLog 表。"""
|
||||
def _log(metrics: dict):
|
||||
try:
|
||||
log = AgentLLMLog(
|
||||
agent_id=agent_id,
|
||||
session_id=metrics.get("session_id"),
|
||||
user_id=user_id,
|
||||
model=metrics.get("model", ""),
|
||||
provider=metrics.get("provider"),
|
||||
prompt_tokens=metrics.get("prompt_tokens", 0),
|
||||
completion_tokens=metrics.get("completion_tokens", 0),
|
||||
total_tokens=metrics.get("total_tokens", 0),
|
||||
latency_ms=metrics.get("latency_ms", 0),
|
||||
iteration_number=metrics.get("iteration_number", 0),
|
||||
step_type=metrics.get("step_type"),
|
||||
tool_name=metrics.get("tool_name"),
|
||||
status=metrics.get("status", "success"),
|
||||
error_message=metrics.get("error_message"),
|
||||
)
|
||||
db.add(log)
|
||||
db.commit()
|
||||
except Exception as e:
|
||||
logger.warning("写入 AgentLLMLog 失败: %s", e)
|
||||
return _log
|
||||
|
||||
|
||||
class ChatRequest(BaseModel):
|
||||
message: str
|
||||
session_id: Optional[str] = None
|
||||
@@ -44,12 +79,103 @@ class ChatResponse(BaseModel):
|
||||
truncated: bool
|
||||
session_id: str
|
||||
agent_id: Optional[str] = None
|
||||
steps: List[AgentStep] = Field(default_factory=list, description="执行追踪步骤")
|
||||
|
||||
|
||||
class OrchestrateAgentItem(BaseModel):
|
||||
"""编排中单个 Agent 的定义"""
|
||||
id: str
|
||||
name: str = "Agent"
|
||||
system_prompt: str = "你是一个有用的AI助手。"
|
||||
model: str = "deepseek-v4-flash"
|
||||
provider: str = "deepseek"
|
||||
temperature: float = 0.7
|
||||
max_iterations: int = 10
|
||||
tools: List[str] = Field(default_factory=list)
|
||||
description: str = ""
|
||||
|
||||
|
||||
class OrchestrateRequest(BaseModel):
|
||||
"""多 Agent 编排请求"""
|
||||
message: str
|
||||
mode: str = "debate"
|
||||
agents: List[OrchestrateAgentItem] = Field(..., min_length=1)
|
||||
model: Optional[str] = None
|
||||
|
||||
|
||||
class OrchestrateStepItem(BaseModel):
|
||||
"""编排步骤"""
|
||||
agent_id: str
|
||||
agent_name: str
|
||||
input: str = ""
|
||||
output: str = ""
|
||||
iterations_used: int = 0
|
||||
tool_calls_made: int = 0
|
||||
error: Optional[str] = None
|
||||
|
||||
|
||||
class OrchestrateResponse(BaseModel):
|
||||
"""多 Agent 编排响应"""
|
||||
mode: str
|
||||
final_answer: str
|
||||
steps: List[OrchestrateStepItem] = Field(default_factory=list)
|
||||
agent_results: List[Dict[str, Any]] = Field(default_factory=list)
|
||||
|
||||
|
||||
@router.post("/orchestrate", response_model=OrchestrateResponse)
|
||||
async def orchestrate_agents(
|
||||
req: OrchestrateRequest,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""多 Agent 编排:支持 route / sequential / debate 三种模式。"""
|
||||
agents = [
|
||||
OrchestratorAgentConfig(
|
||||
id=a.id, name=a.name,
|
||||
system_prompt=a.system_prompt,
|
||||
model=req.model or a.model,
|
||||
provider=a.provider,
|
||||
temperature=a.temperature,
|
||||
max_iterations=a.max_iterations,
|
||||
tools=a.tools,
|
||||
description=a.description,
|
||||
)
|
||||
for a in req.agents
|
||||
]
|
||||
|
||||
on_llm_call = _make_llm_logger(db, agent_id=None, user_id=current_user.id)
|
||||
orchestrator = AgentOrchestrator(
|
||||
default_llm_config=AgentLLMConfig(
|
||||
model=req.model or "deepseek-v4-flash",
|
||||
temperature=0.3,
|
||||
),
|
||||
)
|
||||
result = await orchestrator.run(req.mode, req.message, agents, on_llm_call=on_llm_call)
|
||||
|
||||
return OrchestrateResponse(
|
||||
mode=result.mode,
|
||||
final_answer=result.final_answer,
|
||||
steps=[
|
||||
OrchestrateStepItem(
|
||||
agent_id=s.agent_id,
|
||||
agent_name=s.agent_name,
|
||||
input=s.input,
|
||||
output=s.output,
|
||||
iterations_used=s.iterations_used,
|
||||
tool_calls_made=s.tool_calls_made,
|
||||
error=s.error,
|
||||
)
|
||||
for s in result.steps
|
||||
],
|
||||
agent_results=result.agent_results,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/bare", response_model=ChatResponse)
|
||||
async def chat_bare(
|
||||
req: ChatRequest,
|
||||
current_user: User = Depends(get_current_user),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""无需 Agent 配置,使用默认设置直接对话。"""
|
||||
config = AgentConfig(
|
||||
@@ -65,7 +191,8 @@ async def chat_bare(
|
||||
),
|
||||
user_id=current_user.id,
|
||||
)
|
||||
runtime = AgentRuntime(config=config)
|
||||
on_llm_call = _make_llm_logger(db, agent_id=None, user_id=current_user.id)
|
||||
runtime = AgentRuntime(config=config, on_llm_call=on_llm_call)
|
||||
result = await runtime.run(req.message)
|
||||
|
||||
return ChatResponse(
|
||||
@@ -74,6 +201,7 @@ async def chat_bare(
|
||||
tool_calls_made=result.tool_calls_made,
|
||||
truncated=result.truncated,
|
||||
session_id=runtime.context.session_id,
|
||||
steps=result.steps,
|
||||
)
|
||||
|
||||
|
||||
@@ -113,7 +241,8 @@ async def chat_with_agent(
|
||||
user_id=current_user.id,
|
||||
)
|
||||
|
||||
runtime = AgentRuntime(config=config)
|
||||
on_llm_call = _make_llm_logger(db, agent_id=agent_id, user_id=current_user.id)
|
||||
runtime = AgentRuntime(config=config, on_llm_call=on_llm_call)
|
||||
result = await runtime.run(req.message)
|
||||
|
||||
return ChatResponse(
|
||||
@@ -123,6 +252,7 @@ async def chat_with_agent(
|
||||
truncated=result.truncated,
|
||||
session_id=runtime.context.session_id,
|
||||
agent_id=agent_id,
|
||||
steps=result.steps,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user