<think>
我们正在处理一个大型AI系统的代码修复问题,根据提供的多个文件和日志,我们需要修复的主要问题包括:
1. 模型加载失败(路径问题)
2. 模块加载失败(抽象方法未实现、消息总线未初始化)
3. 路径格式不一致(混合使用正斜杠和反斜杠)
我已经提供了关键修复代码片段,但用户要求提供完整文件以便直接替换。因此,我将提供以下文件的完整修复版本:
- environment_interface.py
- model_manager.py
- cognitive_architecture.py
- path_utils.py(新增)
- 配置文件调整建议
注意:由于代码量较大,我会尽量保持代码完整,但省略部分非关键代码(用注释标注)。同时,我会在关键修改处添加注释说明。
由于用户要求不要省略,因此我将提供完整的文件内容,但为了阅读清晰,我会在每个文件开头标注关键修改点。
开始修复:
</think>
### 完整修复代码(直接复制使用)
#### 1. 环境接口模块 (environment_interface.py)
```python
# E:\AI_System\agent\environment_interface.py
import logging
import time
import queue
import threading
import json
from typing import Any, Optional, Dict, List
from agent.base_module import UnifiedCognitiveModule
from core.message import Message, MessageType
class EnvironmentInterface(UnifiedCognitiveModule):
"""环境交互接口 - 完整实现"""
def __init__(
self,
name: str = "EnvironmentInterface",
coordinator: Optional[Any] = None,
config: Optional[Dict] = None
):
super().__init__(name=name, coordinator=coordinator, config=config)
# 配置参数
config = config or {}
self.max_workers = config.get("max_workers", 4)
self.response_timeout = config.get("response_timeout", 30.0)
self.log_level = config.get("log_level", "INFO")
# 日志配置
self.logger = logging.getLogger(name)
log_level = getattr(logging, self.log_level.upper(), logging.INFO)
self.logger.setLevel(log_level)
# 输入输出队列
self.input_queue = queue.Queue()
self.output_queue = queue.Queue()
# 线程控制
self.running = True
self.message_thread = threading.Thread(target=self._process_messages, daemon=True)
self.message_thread.start()
def shutdown(self) -> bool:
"""关闭环境接口"""
try:
self.running = False
if self.message_thread.is_alive():
self.message_thread.join(timeout=2.0)
super().shutdown()
self.logger.info("🛑 环境接口已关闭")
return True
except Exception as e:
self.logger.error(f"❌ 关闭失败: {str(e)}")
return False
def process(self, input_data: Any) -> dict:
"""处理输入数据"""
if isinstance(input_data, dict):
self.add_input(input_data)
return {"status": "queued"}
elif isinstance(input_data, str):
self.add_input({"command": input_data})
return {"status": "queued"}
else:
return {"error": "不支持的输入类型"}
def _process_messages(self):
"""处理消息的后台线程"""
while self.running:
try:
# 获取用户输入
user_input = self.get_input(timeout=0.5)
if user_input:
# 发送到认知系统
message = Message(
msg_type=MessageType.EVENT,
sender=self.name,
content=user_input,
target="CognitiveSystem"
)
self.send_message(message)
self.logger.debug(f"📤 发送用户输入: {user_input['command'][:20]}...")
# 处理输出队列
if not self.output_queue.empty():
output = self.output_queue.get_nowait()
self._display_output(output)
except Exception as e:
self.logger.error(f"消息处理出错: {str(e)}")
time.sleep(0.1)
def handle_message(self, message: Message):
"""处理接收到的消息"""
if message.target and message.target != self.name:
return
self.logger.debug(f"📩 收到消息 [{message.sender}]: {message.msg_type.name}")
# 根据消息类型处理
if message.msg_type == MessageType.DATA:
self.output(message.content)
elif message.msg_type == MessageType.RESPONSE:
self.output(message.content)
elif message.msg_type == MessageType.STATUS:
self.logger.info(f"系统状态更新: {message.content}")
def get_input(self, timeout: float = 0.5) -> Optional[Dict]:
"""获取输入"""
try:
return self.input_queue.get(timeout=timeout)
except queue.Empty:
return None
def output(self, response: Any):
"""添加响应"""
self.output_queue.put(response)
def _display_output(self, response: Any):
"""格式化并显示输出"""
try:
# 处理不同类型的响应
if isinstance(response, dict):
response.setdefault("timestamp", time.time())
response.setdefault("source", "system")
response_str = json.dumps(response, ensure_ascii=False, indent=2)
print(f"<< {response_str}")
if "message" in response:
self.logger.info(f"💬 系统响应: {response['message']}")
else:
self.logger.info("💬 系统响应: 无内容")
elif isinstance(response, str):
print(f"<< {response}")
self.logger.info(f"💬 系统响应: {response}")
elif isinstance(response, Message):
print(f"<< [Message from {response.sender}]: {response.content[:50]}...")
self.logger.info(f"💬 收到消息响应: {response.content[:50]}...")
else:
response_str = str(response)
print(f"<< {response_str}")
self.logger.info(f"💬 系统响应: {response_str}")
except Exception as e:
self.logger.error(f"输出响应失败: {str(e)}")
def add_input(self, input_data: dict):
"""添加新输入"""
if not isinstance(input_data, dict):
self.logger.error("输入数据格式错误,必须是字典")
return
input_data.setdefault("timestamp", time.time())
input_data.setdefault("source", "user")
self.input_queue.put(input_data)
self.logger.debug(f"手动添加输入: {input_data['command'][:20]}...")
def get_health_status(self) -> dict:
"""返回模块健康状态"""
return {
"status": "running" if self.running else "stopped",
"module": self.name,
"queue_size": self.input_queue.qsize(),
"last_activity": time.time(),
"output_queue_size": self.output_queue.qsize()
}
```
#### 2. 模型管理器 (model_manager.py)
```python
# E:\AI_System\agent\model_manager.py
import os
import sys
import logging
import json
import hashlib
import gc
import time
from pathlib import Path
from typing import Dict, Any, Optional, Tuple, List
from utils.path_utils import normalize_path, is_valid_hf_id
class ModelManager:
"""AI模型管理器 - 完整修复版"""
MODEL_REGISTRY_FILE = "model_registry.json"
DEFAULT_MODEL_PATHS = {
"TEXT_BASE": "local_models/text_base",
"TEXT_CHAT": "local_models/text_chat",
"IMAGE_MODEL": "local_models/image_model"
}
def __init__(self, config: Dict[str, Any] = None,
cache_dir: str = "model_cache",
use_gpu: bool = True,
max_models_in_memory: int = 3):
# 配置日志
self.logger = logging.getLogger("ModelManager")
self.logger.setLevel(logging.INFO)
if not self.logger.handlers:
handler = logging.StreamHandler()
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
handler.setFormatter(formatter)
self.logger.addHandler(handler)
self.logger.info("🚀 初始化模型管理器...")
# 初始化参数
self.config = config or {}
self.cache_dir = normalize_path(cache_dir) # 使用路径规范化
self.use_gpu = use_gpu
self.max_models_in_memory = max_models_in_memory
# 确保缓存目录存在
os.makedirs(self.cache_dir, exist_ok=True)
# 加载或创建注册表
self._persistent_registry = self._load_or_create_registry()
# 已加载的模型
self.loaded_models: Dict[str, Any] = {}
# 自动注册默认模型
self._register_default_models()
self.logger.info(f"✅ 模型管理器初始化完成 (GPU: {'启用' if use_gpu else '禁用'})")
self.logger.info(f"已注册模型: {list(self._persistent_registry.keys())}")
def _load_or_create_registry(self) -> Dict[str, dict]:
"""加载或创建模型注册表"""
try:
registry_path = Path(normalize_path(self.MODEL_REGISTRY_FILE)) # 路径规范化
if registry_path.exists():
with open(registry_path, 'r', encoding='utf-8') as f:
registry = json.load(f)
self.logger.info(f"📋 成功加载模型注册表: {registry_path}")
return registry
self.logger.warning(f"⚠️ 模型注册表不存在,创建新文件: {registry_path}")
with open(registry_path, 'w', encoding='utf-8') as f:
json.dump({}, f, indent=2)
return {}
except Exception as e:
self.logger.error(f"❌ 处理模型注册表失败: {str(e)}")
return {}
def _register_default_models(self):
"""注册配置文件中的默认模型"""
model_settings = self.config.get("model_settings", {})
# 合并默认路径和配置路径
default_paths = {**self.DEFAULT_MODEL_PATHS, **{
name: info.get("path", self.DEFAULT_MODEL_PATHS.get(name, ""))
for name, info in model_settings.items()
}}
# 注册模型
for model_name, model_path in default_paths.items():
if model_name not in self._persistent_registry:
abs_path = normalize_path(model_path) # 路径规范化
model_type = model_settings.get(model_name, {}).get("type", "text")
self.register_model(model_name, abs_path, model_type)
def _save_registry(self):
"""保存模型注册表"""
try:
registry_path = normalize_path(self.MODEL_REGISTRY_FILE) # 路径规范化
with open(registry_path, 'w', encoding='utf-8') as f:
json.dump(self._persistent_registry, f, indent=2, ensure_ascii=False)
self.logger.info(f"💾 模型注册表已保存: {registry_path}")
return True
except Exception as e:
self.logger.error(f"❌ 保存模型注册表失败: {str(e)}")
return False
def register_model(self, model_name: str, model_path: str, model_type: str = "text",
adapter_config: Optional[dict] = None) -> bool:
"""
注册新模型
"""
# 检查模型是否存在
exists, is_local = self._check_model_exists(model_path)
if not exists:
self.logger.error(f"❌ 模型路径不可访问: {model_path}")
return False
# 计算校验和
checksum = "unknown"
if is_local:
try:
checksum = self._calculate_checksum(model_path)
except Exception as e:
self.logger.warning(f"⚠️ 无法计算校验和: {str(e)}")
checksum = "error"
# 添加到注册表
self._persistent_registry[model_name] = {
"path": model_path,
"type": model_type,
"status": "unloaded",
"checksum": checksum,
"last_accessed": time.time(),
"adapter": adapter_config,
"is_local": is_local
}
self.logger.info(f"✅ 模型注册成功: {model_name} ({model_type})")
self._save_registry()
return True
def _check_model_exists(self, model_path: str) -> Tuple[bool, bool]:
"""检查模型路径是否有效"""
# 如果是HuggingFace模型ID
if is_valid_hf_id(model_path): # 使用路径工具验证
self.logger.info(f"🔍 检测到HuggingFace模型ID: {model_path}")
return True, False
# 检查本地路径
abs_path = normalize_path(model_path) # 路径规范化
if os.path.exists(abs_path):
return True, True
# 尝试相对路径
if os.path.exists(model_path):
return True, True
return False, False
def _calculate_checksum(self, model_path: str) -> str:
"""计算模型校验和"""
abs_path = normalize_path(model_path) # 路径规范化
if os.path.isdir(abs_path):
sha256 = hashlib.sha256()
key_files = ["pytorch_model.bin", "model.safetensors", "config.json"]
for root, _, files in os.walk(abs_path):
for file in files:
if file in key_files:
file_path = os.path.join(root, file)
with open(file_path, 'rb') as f:
while chunk := f.read(8192):
sha256.update(chunk)
return sha256.hexdigest()
# 单个模型文件
with open(abs_path, 'rb') as f:
return hashlib.sha256(f.read()).hexdigest()
def load_model(self, model_name: str, force_reload: bool = False) -> Tuple[bool, Any]:
"""
加载模型到内存
"""
if model_name not in self._persistent_registry:
self.logger.error(f"❌ 模型未注册: {model_name}")
return False, None
model_info = self._persistent_registry[model_name]
model_path = model_info["path"]
abs_path = normalize_path(model_path) if model_info.get("is_local", True) else model_path # 路径规范化
# 如果模型已加载且不需要强制重载
if model_name in self.loaded_models and not force_reload:
self.logger.info(f"📦 模型已在内存中: {model_name}")
model_info["last_accessed"] = time.time()
return True, self.loaded_models[model_name]
# 检查内存占用
if len(self.loaded_models) >= self.max_models_in_memory:
self._unload_least_recently_used()
# 实际加载模型
try:
self.logger.info(f"🔄 加载模型: {model_name} ({model_info['type']})")
model_type = model_info["type"]
if model_type == "text":
model = self._load_text_model(model_info, abs_path)
elif model_type == "image":
model = self._load_image_model(model_info, abs_path)
elif model_type == "audio":
model = self._load_audio_model(model_info, abs_path)
else:
self.logger.error(f"❌ 不支持的模型类型: {model_type}")
return False, None
# 更新状态
self.loaded_models[model_name] = model
model_info["status"] = "loaded"
model_info["last_accessed"] = time.time()
self._save_registry()
self.logger.info(f"✅ 模型加载成功: {model_name}")
return True, model
except ImportError as e:
self.logger.error(f"❌ 缺失依赖库: {str(e)}")
return False, None
except Exception as e:
self.logger.error(f"❌ 模型加载失败: {model_name}, 路径: {abs_path}, 错误: {str(e)}")
model_info["status"] = "error"
return False, None
def _load_text_model(self, model_info: dict, model_path: str) -> Any:
"""加载文本模型"""
try:
from transformers import AutoModelForCausalLM, AutoTokenizer
except ImportError:
self.logger.error("❌ transformers库未安装")
raise RuntimeError("transformers not installed")
self.logger.debug(f"🔧 加载文本模型: {model_path}")
device = "cuda" if self.use_gpu else "cpu"
try:
tokenizer = AutoTokenizer.from_pretrained(model_path, cache_dir=self.cache_dir)
model = AutoModelForCausalLM.from_pretrained(
model_path,
cache_dir=self.cache_dir,
device_map=device if self.use_gpu else None
)
return {
"model": model,
"tokenizer": tokenizer,
"info": model_info
}
except OSError as e:
self.logger.error(f"❌ 加载失败: 请检查路径 '{model_path}' 是否正确")
fallback_path = self._try_find_model_path(model_path)
if fallback_path:
self.logger.warning(f"⚠️ 尝试备用路径: {fallback_path}")
return self._load_text_model(model_info, fallback_path)
raise
except Exception as e:
self.logger.error(f"❌ 加载过程中发生意外错误: {str(e)}")
raise
def _try_find_model_path(self, original_path: str) -> Optional[str]:
"""尝试找到备用模型路径"""
# 1. 检查项目内的模型目录
project_models = os.path.join(os.getcwd(), "local_models", os.path.basename(original_path))
if os.path.exists(project_models):
return project_models
# 2. 检查缓存目录
cache_path = os.path.join(self.cache_dir, "models", os.path.basename(original_path))
if os.path.exists(cache_path):
return cache_path
# 3. 尝试父目录
parent_path = os.path.join(os.path.dirname(os.getcwd()), os.path.basename(original_path))
if os.path.exists(parent_path):
return parent_path
return None
def unload_model(self, model_name: str = None) -> bool:
"""卸载模型"""
if model_name is None:
self.logger.info("卸载所有模型")
for name in list(self.loaded_models.keys()):
if not self._unload_single_model(name