You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

287 lines
9.6 KiB

"""智能体管理模块路由。
提供 AI 智能体的配置管理、对话交互和聊天历史记录查询功能。
支持多种智能体类型(员工/管理者/任务/文档)的动态创建和对话。
"""
import uuid
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_db
from models import User, ChatSession, ChatMessage, AgentConfig
from schemas import AgentConfigCreate, AgentConfigUpdate, AgentConfigOut
from agentscope_integration.factory import AgentFactory
router = APIRouter(prefix="/api/agent", tags=["agent"])
@router.post("/chat/{agent_type}")
async def agent_chat(
agent_type: str,
request: Request,
payload: dict,
db: AsyncSession = Depends(get_db),
):
"""与指定类型的 AI 智能体进行对话。
根据用户身份创建或获取对应的智能体实例,处理用户消息并返回 AI 回复。
同时会自动创建或复用聊天会话,并保存对话消息到数据库。
Args:
agent_type: 智能体类型(employee/manager/task/document)。
request: HTTP 请求对象,用于获取当前用户信息。
payload: 请求体,包含 message 和可选的 session_id。
db: 异步数据库会话。
Returns:
dict: 包含 session_id、reply 和 role 的响应数据。
"""
user_ctx = request.state.user
user_id = uuid.UUID(user_ctx["id"])
msg_content = payload.get("message", "") # 用户消息内容
session_id = payload.get("session_id", f"session_{uuid.uuid4().hex[:12]}") # 会话 ID,未提供则自动生成
# 查询当前用户信息
result = await db.execute(select(User).where(User.id == user_id))
user = result.scalar_one_or_none()
if not user:
raise HTTPException(404, "用户不存在")
# 查询或创建聊天会话
session_result = await db.execute(
select(ChatSession).where(ChatSession.session_id == session_id)
)
session = session_result.scalar_one_or_none()
if not session:
session = ChatSession(
user_id=user.id, agent_type=agent_type,
session_id=session_id,
)
db.add(session)
await db.flush()
# 保存用户消息到数据库
user_msg = ChatMessage(
session_id=session.id, user_id=user.id,
role="user", content=msg_content,
)
db.add(user_msg)
await db.flush()
# 创建对应类型的 AI 智能体
agent = await AgentFactory.create_agent(
agent_type=agent_type,
user_id=str(user.id),
user_name=user.display_name,
department_id=str(user.department_id) if user.department_id else None,
)
# 构造消息并调用智能体回复
from agentscope.message import Msg
input_msg = Msg(name="user", content=msg_content, role="user")
response = await agent.reply(input_msg)
reply_text = response.get_text_content() if hasattr(response, 'get_text_content') else str(response)
# 保存 AI 回复消息到数据库
ai_msg = ChatMessage(
session_id=session.id, user_id=user.id,
role="assistant", content=reply_text,
)
db.add(ai_msg)
await db.flush()
return {
"code": 200,
"data": {
"session_id": session_id,
"reply": reply_text,
"role": "assistant",
},
}
@router.get("/list")
async def get_agent_list(request: Request, db: AsyncSession = Depends(get_db)):
"""获取所有处于活跃状态的智能体配置列表。
Returns:
dict: 包含智能体配置列表的响应数据。
"""
result = await db.execute(
select(AgentConfig).where(AgentConfig.status == "active").order_by(AgentConfig.updated_at.desc())
)
agents = result.scalars().all()
return {
"code": 200,
"data": [{
"id": str(a.id),
"name": a.name,
"description": a.description,
"system_prompt": a.system_prompt,
"model": a.model,
"temperature": a.temperature if isinstance(a.temperature, float) else float(a.temperature) / 10.0,
"tools": a.tools or [],
"status": a.status,
} for a in agents],
}
@router.post("/", response_model=AgentConfigOut)
async def create_agent(req: AgentConfigCreate, request: Request, db: AsyncSession = Depends(get_db)):
"""创建新的智能体配置。
Args:
req: 智能体配置创建请求体。
request: HTTP 请求对象。
db: 异步数据库会话。
Returns:
AgentConfigOut: 创建后的智能体配置响应。
"""
user_ctx = request.state.user
agent = AgentConfig(
name=req.name,
description=req.description,
system_prompt=req.system_prompt,
model=req.model,
temperature=req.temperature,
tools=req.tools,
creator_id=uuid.UUID(user_ctx["id"]),
)
db.add(agent)
await db.flush()
return AgentConfigOut(
id=agent.id, name=agent.name, description=agent.description,
system_prompt=agent.system_prompt, model=agent.model,
temperature=agent.temperature if isinstance(agent.temperature, float) else float(agent.temperature) / 10.0,
tools=agent.tools or [], status=agent.status,
creator_id=agent.creator_id,
created_at=agent.created_at, updated_at=agent.updated_at,
)
@router.get("/{agent_id}", response_model=AgentConfigOut)
async def get_agent(agent_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)):
"""获取指定智能体的配置详情。
Args:
agent_id: 智能体唯一标识 ID。
request: HTTP 请求对象。
db: 异步数据库会话。
Returns:
AgentConfigOut: 智能体配置响应。
"""
result = await db.execute(select(AgentConfig).where(AgentConfig.id == agent_id))
agent = result.scalar_one_or_none()
if not agent:
raise HTTPException(404, "Agent不存在")
return AgentConfigOut(
id=agent.id, name=agent.name, description=agent.description,
system_prompt=agent.system_prompt, model=agent.model,
temperature=agent.temperature if isinstance(agent.temperature, float) else float(agent.temperature) / 10.0,
tools=agent.tools or [], status=agent.status,
creator_id=agent.creator_id,
created_at=agent.created_at, updated_at=agent.updated_at,
)
@router.put("/{agent_id}", response_model=AgentConfigOut)
async def update_agent(agent_id: uuid.UUID, req: AgentConfigUpdate, request: Request, db: AsyncSession = Depends(get_db)):
"""更新指定智能体的配置。
Args:
agent_id: 智能体唯一标识 ID。
req: 智能体配置更新请求体。
request: HTTP 请求对象。
db: 异步数据库会话。
Returns:
AgentConfigOut: 更新后的智能体配置响应。
"""
result = await db.execute(select(AgentConfig).where(AgentConfig.id == agent_id))
agent = result.scalar_one_or_none()
if not agent:
raise HTTPException(404, "Agent不存在")
if req.name is not None:
agent.name = req.name
if req.description is not None:
agent.description = req.description
if req.system_prompt is not None:
agent.system_prompt = req.system_prompt
if req.model is not None:
agent.model = req.model
if req.temperature is not None:
agent.temperature = req.temperature
if req.tools is not None:
agent.tools = req.tools
if req.status is not None:
agent.status = req.status
await db.flush()
return AgentConfigOut(
id=agent.id, name=agent.name, description=agent.description,
system_prompt=agent.system_prompt, model=agent.model,
temperature=agent.temperature if isinstance(agent.temperature, float) else float(agent.temperature) / 10.0,
tools=agent.tools or [], status=agent.status,
creator_id=agent.creator_id,
created_at=agent.created_at, updated_at=agent.updated_at,
)
@router.delete("/{agent_id}")
async def delete_agent(agent_id: uuid.UUID, request: Request, db: AsyncSession = Depends(get_db)):
"""删除指定的智能体配置。
Args:
agent_id: 智能体唯一标识 ID。
request: HTTP 请求对象。
db: 异步数据库会话。
Returns:
dict: 操作结果响应。
"""
result = await db.execute(select(AgentConfig).where(AgentConfig.id == agent_id))
agent = result.scalar_one_or_none()
if not agent:
raise HTTPException(404, "Agent不存在")
await db.delete(agent)
return {"code": 200, "message": "已删除"}
@router.get("/history/{session_id}")
async def get_chat_history(
session_id: str,
request: Request,
db: AsyncSession = Depends(get_db),
):
"""获取指定会话的完整聊天历史记录。
Args:
session_id: 会话唯一标识。
request: HTTP 请求对象。
db: 异步数据库会话。
Returns:
dict: 包含消息列表的响应数据,按时间顺序排列。
"""
session_result = await db.execute(
select(ChatSession).where(ChatSession.session_id == session_id)
)
session = session_result.scalar_one_or_none()
if not session:
raise HTTPException(404, "会话不存在")
msg_result = await db.execute(
select(ChatMessage).where(ChatMessage.session_id == session.id).order_by(ChatMessage.created_at)
)
messages = msg_result.scalars().all()
return {
"code": 200,
"data": [{
"role": m.role,
"content": m.content,
"created_at": str(m.created_at),
} for m in messages],
}