智能体服务封装

import asyncio

import logging

from typing import Dict, List, Optional, Any, AsyncIterator, Union

from third.TranssionAgentClient import agent_client_instance

from constants.conversation_constants import AgentConstants

logger = logging.getLogger(name)

class AgentService:

"""智能体服务封装类"""

复制代码
def __init__(self):
    self.client = agent_client_instance

async def chat(self, messages: List[Dict[str, str]], 
               options: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
    """
    智能体普通对话
    
    Args:
        messages: 消息列表,格式: [{"role": "user", "content": "消息内容"}]
        options: 可选参数,支持:
            - dellE3Size: 如果用的是dellE3,生成图片的尺寸大小,必须是 1792x1024、1024x1024 或 1024x1792
            - userId: 如果是传神云文档问答需要在智库授权,并需要传用户工号
    
    Returns:
        Dict包含以下字段:
        - code: 响应码
        - data: 原始模型返回的结构体
        - dataContent: 返回的消息内容(且加工后的)
        - message: 响应消息
        - success: 是否成功
    
    Example:
        result = await agent_service.chat(
            [{"role": "user", "content": "你好"}]
        )
        content = result.get("dataContent", "")
    """
    try:
        if not self.client.is_configured():
            raise ValueError("智能体客户端未正确配置,请检查 AGENT_APP_ID、AGENT_APP_SECRET 和 AGENT_ASSISTANT_CODE")
        
        # 验证消息格式
        if not messages or not isinstance(messages, list):
            raise ValueError("messages 参数必须是非空列表")
        
        for msg in messages:
            if not isinstance(msg, dict) or "role" not in msg or "content" not in msg:
                raise ValueError("消息格式错误,每个消息必须包含 role 和 content 字段")
            if msg["role"] not in ["user", "assistant"]:
                raise ValueError("消息角色必须是 'user' 或 'assistant'")
        
        logger.info(f"[AgentService.chat] 调用智能体普通对话")
        result = await self.client.chat(messages, options)
        
        # 统一响应格式处理
        if result.get(AgentConstants.FIELD_CODE) == AgentConstants.HTTP_SUCCESS and result.get(AgentConstants.FIELD_SUCCESS):
            logger.info(f"[AgentService.chat] 调用成功,响应内容长度: {len(result.get('dataContent', ''))}")
        else:
            logger.warning(f"[AgentService.chat] 调用失败,错误信息: {result.get(AgentConstants.FIELD_MESSAGE, '未知错误')}")
        
        return result
        
    except Exception as e:
        logger.error(f"[AgentService.chat] 智能体对话失败: {str(e)}")
        return {
            AgentConstants.FIELD_CODE: AgentConstants.HTTP_SERVER_ERROR,
            AgentConstants.FIELD_MESSAGE: f"智能体调用失败: {str(e)}",
            AgentConstants.FIELD_DATA: None,
            "dataContent": "",
            AgentConstants.FIELD_SUCCESS: False
        }

async def stream_chat(self, messages: List[Dict[str, str]], 
                     options: Optional[Dict[str, Any]] = None) -> AsyncIterator[Dict[str, Any]]:
    """
    智能体流式对话
    
    Args:
        messages: 消息列表
        options: 可选参数
    
    Yields:
        Dict包含以下字段:
        - data: 当前的状态
        - dataContent: 返回的消息内容(且加工后的)
        - dataObject: 原始的gpt返回对象
        - errorMsg: 错误异常消息
        - errorCode: 错误码
    
    Example:
        async for chunk in agent_service.stream_chat(
            [{"role": "user", "content": "写一篇文章"}]
        ):
            content = chunk.get("dataContent", "")
            if content:
                print(content, end="", flush=True)
    """
    try:
        if not self.client.is_configured():
            yield {
                "data": "error",
                "dataContent": "",
                "dataObject": None,
                "errorMsg": "智能体客户端未正确配置,请检查 AGENT_APP_ID、AGENT_APP_SECRET 和 AGENT_ASSISTANT_CODE",
                "errorCode": 500
            }
            return
        
        # 验证消息格式
        if not messages or not isinstance(messages, list):
            yield {
                "data": "error", 
                "dataContent": "",
                "dataObject": None,
                "errorMsg": "messages 参数必须是非空列表",
                "errorCode": 400
            }
            return
        
        for msg in messages:
            if not isinstance(msg, dict) or "role" not in msg or "content" not in msg:
                yield {
                    "data": "error",
                    "dataContent": "",
                    "dataObject": None,
                    "errorMsg": "消息格式错误,每个消息必须包含 role 和 content 字段",
                    "errorCode": 400
                }
                return
            if msg["role"] not in ["user", "assistant"]:
                yield {
                    "data": "error",
                    "dataContent": "",
                    "dataObject": None,
                    "errorMsg": "消息角色必须是 'user' 或 'assistant'",
                    "errorCode": 400
                }
                return
        
        logger.info(f"[AgentService.stream_chat] 调用智能体流式对话")
        
        async for chunk in self.client.stream_chat(messages, options):
            yield chunk
            
    except Exception as e:
        logger.error(f"[AgentService.stream_chat] 智能体流式对话失败: {str(e)}")
        yield {
            "data": "error",
            "dataContent": "",
            "dataObject": None,
            "errorMsg": f"智能体流式调用失败: {str(e)}",
            "errorCode": 500
        }


async def close(self):
    """关闭服务连接"""
    await self.client.close()

def is_available(self) -> bool:
    """检查服务是否可用"""
    return self.client.is_configured()

创建全局服务实例

agent_service = AgentService()

相关推荐
weixin_4462608535 分钟前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
我的xiaodoujiao1 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
人邮异步社区1 小时前
怎么把C语言学到精通?
c语言·开发语言
qetfw1 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具
心平气和量大福大2 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai2 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
用户8356290780512 小时前
Python 实现 Excel 页面布局与打印设置自动化
后端·python
এ慕ོ冬℘゜2 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa2 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio
一次旅行2 小时前
Python+大模型端到端自动化日报系统
开发语言·python·自动化