[add ] handoffs service and test

This commit is contained in:
Mark
2026-01-07 14:58:23 +08:00
parent 957f8f83ff
commit ba2220d7c8
2 changed files with 635 additions and 25 deletions

View File

@@ -1,23 +1,22 @@
from fastapi import APIRouter, Depends, status, Query, HTTPException
from langchain_core.messages import HumanMessage, SystemMessage
from fastapi import APIRouter, Depends, status, HTTPException, Body, Path
from fastapi.responses import StreamingResponse
from langchain_core.prompts import ChatPromptTemplate
from sqlalchemy.orm import Session
from typing import List, Optional
import uuid
from app.core.models import RedBearLLM, RedBearRerank
from app.core.models.base import RedBearModelConfig
from app.core.models.embedding import RedBearEmbeddings
from app.db import get_db
from app.dependencies import get_current_user
from app.models.models_model import ModelApiKey, ModelProvider, ModelType
from app.models.user_model import User
from app.schemas import model_schema
from app.models.models_model import ModelApiKey
from app.core.response_utils import success
from app.schemas.response_schema import ApiResponse, PageData
from app.services.model_service import ModelConfigService, ModelApiKeyService
from app.schemas.response_schema import ApiResponse
from app.schemas.app_schema import AppChatRequest
from app.services.model_service import ModelConfigService
from app.services.handoffs_service import get_handoffs_service, reset_default_service
from app.services.conversation_service import ConversationService
from app.core.logging_config import get_api_logger
from app.dependencies import get_current_user
# 获取API专用日志器
api_logger = get_api_logger()
@@ -28,6 +27,8 @@ router = APIRouter(
)
# ==================== 原有测试接口 ====================
@router.get("/llm/{model_id}", response_model=ApiResponse)
def test_llm(
model_id: uuid.UUID,
@@ -50,7 +51,6 @@ def test_llm(
template = """Question: {question}
Answer: Let's think step by step."""
# ChatPromptTemplate
prompt = ChatPromptTemplate.from_template(template)
chain = prompt | llm
answer = chain.invoke({"question": "What is LangChain?"})
@@ -80,13 +80,13 @@ def test_embedding(
base_url=apiConfig.api_base
))
data = [
"最近哪家咖啡店评价最好?",
"附近有没有推荐的咖啡厅?",
"明天天气预报说会下雨。",
"北京是中国的首都。",
"我想找一个适合学习的地方。"
]
data = [
"最近哪家咖啡店评价最好?",
"附近有没有推荐的咖啡厅?",
"明天天气预报说会下雨。",
"北京是中国的首都。",
"我想找一个适合学习的地方。"
]
embeddings = model.embed_documents(data)
print(embeddings)
query = "我想找一个适合学习的地方。"
@@ -114,13 +114,109 @@ def test_rerank(
base_url=apiConfig.api_base
))
query = "最近哪家咖啡店评价最好?"
data = [
"最近哪家咖啡店评价最好?",
"附近有没有推荐的咖啡厅?",
"明天天气预报说会下雨。",
"北京是中国的首都。",
"我想找一个适合学习的地方。"
]
data = [
"最近哪家咖啡店评价最好?",
"附近有没有推荐的咖啡厅?",
"明天天气预报说会下雨。",
"北京是中国的首都。",
"我想找一个适合学习的地方。"
]
scores = model.rerank(query=query, documents=data, top_n=3)
print(scores)
return success(msg="测试Rerank成功", data={"query": query, "documents": data, "scores": scores})
# ==================== Handoffs 测试接口 ====================
@router.post("/handoffs/{app_id}")
async def test_handoffs(
app_id: uuid.UUID = Path(..., description="应用 ID"),
request: AppChatRequest = Body(...),
current_user=Depends(get_current_user),
db: Session = Depends(get_db)
):
"""测试 Agent Handoffs 功能
演示 LangGraph 实现的多 Agent 协作和动态切换
- 默认从 sales_agent 开始
- 根据用户问题自动切换到合适的 Agent
- 使用 conversation_id 保持会话状态
- 通过 stream 参数控制是否流式输出
事件类型(流式):
- start: 开始执行
- agent: 当前 Agent 信息
- message: 流式消息内容
- handoff: Agent 切换事件
- end: 执行结束
- error: 错误信息
"""
try:
workspace_id = current_user.current_workspace_id
# 获取或创建会话
conversation_service = ConversationService(db)
if request.conversation_id:
# 验证会话存在
conversation = conversation_service.get_conversation(uuid.UUID(request.conversation_id))
if not conversation:
raise HTTPException(status_code=404, detail="会话不存在")
conversation_id = str(conversation.id)
else:
# 创建新会话
conversation = conversation_service.create_or_get_conversation(
app_id=app_id,
workspace_id=workspace_id,
user_id=request.user_id,
is_draft=True
)
conversation_id = str(conversation.id)
# 根据 stream 参数决定返回方式
if request.stream:
# 流式返回
service = get_handoffs_service(streaming=True)
return StreamingResponse(
service.chat_stream(
message=request.message,
conversation_id=conversation_id
),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"X-Accel-Buffering": "no"
}
)
else:
# 非流式返回
service = get_handoffs_service(streaming=False)
result = await service.chat(
message=request.message,
conversation_id=conversation_id
)
return success(data=result, msg="Handoffs 测试成功")
except HTTPException:
raise
except Exception as e:
api_logger.error(f"Handoffs 测试失败: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/handoffs/agents", response_model=ApiResponse)
def get_handoff_agents():
"""获取可用的 Handoff Agent 列表"""
service = get_handoffs_service()
agents = service.get_agents()
return success(data={"agents": agents}, msg="获取 Agent 列表成功")
@router.delete("/handoffs/reset")
def reset_handoff_service():
"""重置 Handoff 服务(清除所有会话状态)"""
reset_default_service()
return success(msg="Handoff 服务已重置")