Toadied's picture
1
f99e86e verified
Raw
History Blame Contribute Delete
10.3 kB
import os
import sys
import logging
from contextlib import asynccontextmanager
from dotenv import load_dotenv
load_dotenv()
# 配置日志(增强企业级日志格式)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[logging.StreamHandler(sys.stdout)]
)
logger = logging.getLogger(__name__)
# 路径配置
BACKEND_APP_DIR = os.path.dirname(os.path.abspath(__file__))
# 将 backend_app 加入 Python 搜索路径最前端(优先识别)
if BACKEND_APP_DIR not in sys.path:
sys.path.insert(0, BACKEND_APP_DIR)
logger.info(f"✅ 已将 backend_app 加入搜索路径: {BACKEND_APP_DIR}")
# FastAPI 核心导入
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse
from helloAgents.tools.registry import global_registry
from helloAgents.tools.builtin.rag_tool import RAGTool # RAG工具类
from helloAgents.tools.builtin.memory_tool import MemoryTool # 记忆工具类
from helloAgents.tools.builtin.terminal_tool import TerminalTool # 命令行工具类
from helloAgents.tools.builtin.search_tool import SearchTool # 搜索工具类
from helloAgents.tools.builtin.calculator import CalculatorTool # 计算器工具类
from helloAgents.tools.builtin.note_tool import NoteTool # 笔记工具类
from helloAgents.tools.builtin.protocol_tools import MCPTool, A2ATool, ANPTool # 协议工具类
from helloAgents.core.exceptions import (
HelloAgentsException,
http_exception_handler,
hello_agents_exception_handler,
general_exception_handler
)
import logging
# 关闭 pdfminer 烦人的警告
logging.getLogger("pdfminer").setLevel(logging.ERROR)
logging.getLogger("pdfminer.pdffont").setLevel(logging.ERROR)
import torch
print(torch.cuda.is_available()) # True = 有GPU可用
print(torch.cuda.device_count()) # GPU数量
# ---------------------- 工具注册函数 ----------------------
def register_all_core_tools():
"""注册所有核心工具到全局注册表"""
tools_registered = []
try:
# 1. RAG工具
logger.info("🔄 初始化RAG工具...")
rag_tool = RAGTool()
if not rag_tool.initialized:
raise RuntimeError(f"RAG工具初始化失败: {getattr(rag_tool, 'init_error', '未知错误')}")
global_registry.register_tool(rag_tool)
tools_registered.append(("rag", "✅"))
logger.info("✅ RAG工具已注册")
except Exception as e:
logger.error(f"❌ RAG工具注册失败: {e}")
tools_registered.append(("rag", "❌"))
try:
# 2. 记忆工具
logger.info("🔄 初始化记忆工具...")
memory_tool = MemoryTool()
global_registry.register_tool(memory_tool)
tools_registered.append(("memory", "✅"))
logger.info("✅ 记忆工具已注册")
except Exception as e:
logger.error(f"❌ 记忆工具注册失败: {e}")
tools_registered.append(("memory", "❌"))
# try:
# # 3. 命令行工具
# logger.info("🔄 初始化命令行工具...")
# terminal_tool = TerminalTool(workspace="./workspace")
# global_registry.register_tool(terminal_tool)
# tools_registered.append(("terminal", "✅"))
# logger.info("✅ 命令行工具已注册")
# except Exception as e:
# logger.error(f"❌ 命令行工具注册失败: {e}")
# tools_registered.append(("terminal", "❌"))
# try:
# # 4. 搜索工具
# logger.info("🔄 初始化搜索工具...")
# search_tool = SearchTool(backend="hybrid")
# global_registry.register_tool(search_tool)
# tools_registered.append(("search", "✅"))
# logger.info("✅ 搜索工具已注册")
# except Exception as e:
# logger.error(f"❌ 搜索工具注册失败: {e}")
# tools_registered.append(("search", "❌"))
# try:
# # 5. 计算器工具
# logger.info("🔄 初始化计算器工具...")
# calculator_tool = CalculatorTool()
# global_registry.register_tool(calculator_tool)
# tools_registered.append(("calculator", "✅"))
# logger.info("✅ 计算器工具已注册")
# except Exception as e:
# logger.error(f"❌ 计算器工具注册失败: {e}")
# tools_registered.append(("calculator", "❌"))
# try:
# # 6. 笔记工具
# logger.info("🔄 初始化笔记工具...")
# note_tool = NoteTool()
# global_registry.register_tool(note_tool)
# tools_registered.append(("note", "✅"))
# logger.info("✅ 笔记工具已注册")
# except Exception as e:
# logger.error(f"❌ 笔记工具注册失败: {e}")
# tools_registered.append(("note", "❌"))
try:
# 7. MCP协议工具
logger.info("🔄 初始化MCP协议工具...")
# 7.1 基础MCP工具(内置演示服务器)
server_script = os.path.join(os.path.dirname(__file__), "helloAgents", "protocols", "mcp", "mcpServer", "sendEmailServer.py")
send_qq_email_mcp_tool = MCPTool(
name="send_qq_email",
description="发送qq邮件",
# server_command=["python", server_script], # 启动MCP服务器的命令
server="http://127.0.0.1:8081/mcp",
auto_expand=True
)
global_registry.register_tool(send_qq_email_mcp_tool)
tools_registered.append(("send_qq_email_mcp_tool", "✅"))
logger.info("✅ 基础MCP工具已注册")
except Exception as e:
logger.error(f"❌ MCP工具注册失败: {e}")
tools_registered.append(("send_qq_email_mcp_tool", "❌"))
# # 7.3 A2A工具(需要a2a-sdk)
# try:
# a2a_tool = A2ATool(
# name="a2a",
# agent_url="http://localhost:5000", # 默认URL,实际使用时需要配置
# description="连接到A2A Agent,支持提问和获取信息。需要安装官方a2a-sdk库。"
# )
# global_registry.register_tool(a2a_tool)
# tools_registered.append(("a2a", "✅"))
# logger.info("✅ A2A工具已注册")
# except Exception as e:
# logger.warning(f"⚠️ A2A工具注册失败(可能需要安装a2a-sdk): {e}")
# tools_registered.append(("a2a", "⚠️"))
# # 7.4 ANP工具(概念性实现)
# try:
# anp_tool = ANPTool(
# name="anp",
# description="智能体网络管理工具,支持服务发现、节点管理和消息路由。概念性实现。"
# )
# global_registry.register_tool(anp_tool)
# tools_registered.append(("anp", "✅"))
# logger.info("✅ ANP工具已注册")
# except Exception as e:
# logger.error(f"❌ ANP工具注册失败: {e}")
# tools_registered.append(("anp", "❌"))
# except Exception as e:
# logger.error(f"❌ MCP协议工具注册失败: {e}")
# tools_registered.append(("mcp_protocols", "❌"))
# 总结注册结果
logger.info("📋 核心工具注册完成:")
for tool_name, status in tools_registered:
logger.info(f" {status} {tool_name}")
# 列出所有可用工具
all_tools = global_registry.list_tools()
return all_tools
# ---------------------- 应用生命周期管理 ----------------------
@asynccontextmanager
async def lifespan(app: FastAPI):
# 启动阶段:初始化并注册所有核心工具
logger.info("🚀 应用启动中...")
try:
# 注册所有核心工具
register_all_core_tools()
logger.info("✅ 所有核心工具已成功注册到全局注册表")
except Exception as e:
logger.critical(f"❌ 工具初始化失败,应用启动终止: {e}")
raise # 核心工具初始化失败,终止应用启动
yield # 应用运行阶段
# 关闭阶段:清理资源
logger.info("🔌 应用关闭中...")
try:
# 可选:清理工具资源
rag_tool = global_registry.get_tool("rag")
if rag_tool:
# 示例:清空过期命名空间/关闭数据库连接
# rag_tool.clear_all_namespaces()
logger.info("✅ RAG工具资源已清理")
# 清理其他工具资源(如有需要)
logger.info("✅ 所有工具资源已清理")
except Exception as e:
logger.error(f"⚠️ 清理工具资源时发生警告: {e}")
# ---------------------- 创建 FastAPI 应用实例 ----------------------
app = FastAPI(
title="Llama3.2 RAG 服务",
description="集成RAGTool的检索增强生成服务",
version="1.0.0",
lifespan=lifespan, # 绑定生命周期钩子
reload=False # 开发模式自动重载
)
# ---------------------- 导入并注册已有路由 ----------------------
# 你的上传/查询接口都在这个路由中,保持原有逻辑不变
try:
from api.api_router import api_router
app.include_router(router=api_router, prefix='/api/v1')
logger.info("✅ 已注册API路由: /api/v1")
except ImportError as e:
logger.error(f"❌ 导入API路由失败: {e}")
raise
# ---------------------- 注册全局异常处理器 ----------------------
# 统一处理HTTP异常、业务异常和未知异常
app.add_exception_handler(HTTPException, http_exception_handler)
app.add_exception_handler(HelloAgentsException, hello_agents_exception_handler)
app.add_exception_handler(Exception, general_exception_handler)
logger.info("✅ 全局异常处理器已注册")
# ---------------------- 辅助接口:工具管理 ----------------------
@app.get("/")
async def root():
"""根路由:健康检查"""
# 获取RAG工具状态
rag_tool = global_registry.get_tool("rag")
rag_status = "✅ 已初始化" if getattr(rag_tool, "initialized", False) else "❌ 未初始化"
return JSONResponse(
content={
"message": "Llama3.2 服务启动成功!",
"rag_tool_status": rag_status,
"registered_tools": global_registry.list_tools(),
"api_prefix": "/api/v1"
}
)