This commit is contained in:
LuiKlee
2025-12-16 16:18:59 +08:00
parent c2a1d7b00b
commit 0feb878830
20 changed files with 251 additions and 261 deletions

View File

@@ -6,8 +6,8 @@ from pathlib import Path
project_root = Path(__file__).parent.parent
sys.path.insert(0, str(project_root))
from src.memory_graph.manager_singleton import get_unified_memory_manager
from src.common.logger import get_logger
from src.memory_graph.manager_singleton import get_unified_memory_manager
logger = get_logger("memory_transfer_check")
@@ -32,8 +32,8 @@ async def check_short_term_status():
print(f"📊 当前记忆数量: {stats['total_memories']}/{stats['max_memories']}")
# 计算占用率
if stats['max_memories'] > 0:
occupancy = stats['total_memories'] / stats['max_memories']
if stats["max_memories"] > 0:
occupancy = stats["total_memories"] / stats["max_memories"]
print(f"📈 容量占用率: {occupancy:.1%}")
# 根据占用率给出建议
@@ -103,7 +103,7 @@ async def check_auto_transfer_task():
manager = get_unified_memory_manager()
# 检查任务是否存在
if not hasattr(manager, '_auto_transfer_task') or manager._auto_transfer_task is None:
if not hasattr(manager, "_auto_transfer_task") or manager._auto_transfer_task is None:
print("❌ 自动转移任务未创建!")
print("\n建议:调用 manager.initialize() 初始化系统")
return False
@@ -125,12 +125,12 @@ async def check_auto_transfer_task():
print("✅ 自动转移任务正在运行")
# 检查转移缓存
if hasattr(manager, '_transfer_cache'):
if hasattr(manager, "_transfer_cache"):
cache_size = len(manager._transfer_cache) if manager._transfer_cache else 0
print(f"📦 转移缓存: {cache_size} 条记忆")
# 检查上次转移时间
if hasattr(manager, '_last_transfer_time'):
if hasattr(manager, "_last_transfer_time"):
from datetime import datetime
last_time = manager._last_transfer_time
if last_time:
@@ -169,7 +169,7 @@ async def manual_transfer_test():
print("这将把当前符合条件的短期记忆转移到长期记忆")
response = input("\n是否继续? (y/n): ").strip().lower()
if response != 'y':
if response != "y":
print("❌ 已取消手动转移")
return None
@@ -180,15 +180,15 @@ async def manual_transfer_test():
result = await manager.manual_transfer()
print("\n✅ 转移完成!")
print(f"\n转移结果:")
print("\n转移结果:")
print(f" 已处理: {result.get('processed_count', 0)}")
print(f" 成功转移: {len(result.get('transferred_memory_ids', []))}")
print(f" 失败: {result.get('failed_count', 0)}")
print(f" 跳过: {result.get('skipped_count', 0)}")
if result.get('errors'):
print(f"\n错误信息:")
for error in result['errors'][:3]: # 只显示前3个错误
if result.get("errors"):
print("\n错误信息:")
for error in result["errors"][:3]: # 只显示前3个错误
print(f" - {error}")
return result

View File

@@ -17,8 +17,8 @@ from pathlib import Path
PROJECT_ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(PROJECT_ROOT))
from src.config.config import global_config # noqa: E402
from src.memory_graph.short_term_manager import ShortTermMemoryManager # noqa: E402
from src.config.config import global_config
from src.memory_graph.short_term_manager import ShortTermMemoryManager
def resolve_data_dir() -> Path:

View File

@@ -12,17 +12,16 @@ from typing import Any, Optional, cast
import json_repair
from PIL import Image
from rich.traceback import install
from sqlalchemy import select
from src.chat.emoji_system.emoji_constants import EMOJI_DIR, EMOJI_REGISTERED_DIR, MAX_EMOJI_FOR_PROMPT
from src.chat.emoji_system.emoji_entities import MaiEmoji
from src.chat.emoji_system.emoji_utils import (
_emoji_objects_to_readable_list,
_to_emoji_objects,
_ensure_emoji_dir,
clear_temp_emoji,
_to_emoji_objects,
clean_unused_emojis,
clear_temp_emoji,
list_image_files,
)
from src.chat.utils.utils_image import get_image_manager, image_path_to_base64

View File

@@ -578,8 +578,7 @@ class ExpressionLearner:
logger.info(f"相同情景覆盖:'{same_situation_expr.situation}' 的表达从 '{same_situation_expr.style}' 更新为 '{style_val}'")
# 更新映射
old_key = (same_situation_expr.situation, same_situation_expr.style)
if old_key in exact_match_map:
del exact_match_map[old_key]
exact_match_map.pop(old_key, None)
same_situation_expr.style = style_val
same_situation_expr.count = same_situation_expr.count + 1
same_situation_expr.last_active_time = current_time
@@ -591,8 +590,7 @@ class ExpressionLearner:
logger.info(f"相同表达覆盖:'{same_style_expr.style}' 的情景从 '{same_style_expr.situation}' 更新为 '{situation}'")
# 更新映射
old_key = (same_style_expr.situation, same_style_expr.style)
if old_key in exact_match_map:
del exact_match_map[old_key]
exact_match_map.pop(old_key, None)
same_style_expr.situation = situation
same_style_expr.count = same_style_expr.count + 1
same_style_expr.last_active_time = current_time
@@ -627,8 +625,7 @@ class ExpressionLearner:
await session.delete(expr)
# 从映射中移除
key = (expr.situation, expr.style)
if key in exact_match_map:
del exact_match_map[key]
exact_match_map.pop(key, None)
logger.debug(f"已删除 {len(all_current_exprs) - MAX_EXPRESSION_COUNT} 个低频表达方式")
# 提交数据库更改

View File

@@ -1,4 +1,3 @@
# ruff: noqa: G004, BLE001
# pylint: disable=logging-fstring-interpolation,broad-except,unused-argument
# pyright: reportOptionalMemberAccess=false
"""

View File

@@ -3,7 +3,6 @@ MaiZone麦麦空间- 重构版
"""
import asyncio
from pathlib import Path
from src.common.logger import get_logger
from src.plugin_system import BasePlugin, ComponentInfo, register_plugin

View File

@@ -258,7 +258,7 @@ class ContentService:
- 运动风:"masterpiece, best quality, 1girl, sportswear, running in park, energetic, morning light, trees background, dynamic pose, healthy lifestyle"
- 咖啡馆:"masterpiece, best quality, 1girl, sitting in cozy cafe, holding coffee cup, warm lighting, wooden table, books beside, peaceful atmosphere"
"""
output_format = '''{"text": "说说正文内容", "image": {"prompt": "详细的英文提示词(包含画质+主体+场景+氛围+光线+色彩)", "negative_prompt": "负面词", "include_character": true/false, "aspect_ratio": "方图/横图/竖图"}}'''
output_format = """{"text": "说说正文内容", "image": {"prompt": "详细的英文提示词(包含画质+主体+场景+氛围+光线+色彩)", "negative_prompt": "负面词", "include_character": true/false, "aspect_ratio": "方图/横图/竖图"}}"""
elif ai_image_enabled and provider == "siliconflow":
novelai_guide = """
**配图说明:**
@@ -277,7 +277,7 @@ class ContentService:
- "sunset over the calm ocean, golden hour, orange and purple sky, gentle waves, peaceful and serene mood, wide angle view"
- "cherry blossoms in spring, soft pink petals falling, blue sky, sunlight filtering through branches, peaceful park scene, gentle breeze"
"""
output_format = '''{"text": "说说正文内容", "image": {"prompt": "详细的英文描述(主体+场景+氛围+光线+细节)"}}'''
output_format = """{"text": "说说正文内容", "image": {"prompt": "详细的英文描述(主体+场景+氛围+光线+细节)"}}"""
prompt = f"""
{personality_desc}

View File

@@ -2,14 +2,11 @@
NovelAI图片生成服务 - 空间插件专用
独立实现,不依赖其他插件
"""
import asyncio
import base64
import io
import random
import uuid
import zipfile
import io
from pathlib import Path
from typing import Optional
import aiohttp
from PIL import Image
@@ -60,11 +57,11 @@ class MaiZoneNovelAIService:
async def generate_image_from_prompt_data(
self,
prompt: str,
negative_prompt: Optional[str] = None,
negative_prompt: str | None = None,
include_character: bool = False,
width: int = 1024,
height: int = 1024
) -> tuple[bool, Optional[Path], str]:
) -> tuple[bool, Path | None, str]:
"""根据提示词生成图片
Args:
@@ -85,7 +82,7 @@ class MaiZoneNovelAIService:
final_prompt = prompt
if include_character and self.character_prompt:
final_prompt = f"{self.character_prompt}, {prompt}"
logger.info(f"包含角色形象,添加角色提示词")
logger.info("包含角色形象,添加角色提示词")
# 合并负面提示词
final_negative = self.base_negative_prompt
@@ -95,7 +92,7 @@ class MaiZoneNovelAIService:
else:
final_negative = negative_prompt
logger.info(f"🎨 开始生成图片...")
logger.info("🎨 开始生成图片...")
logger.info(f" 尺寸: {width}x{height}")
logger.info(f" 正面提示词: {final_prompt[:100]}...")
logger.info(f" 负面提示词: {final_negative[:100]}...")
@@ -118,7 +115,7 @@ class MaiZoneNovelAIService:
except Exception as e:
logger.error(f"生成图片时出错: {e}", exc_info=True)
return False, None, f"生成失败: {str(e)}"
return False, None, f"生成失败: {e!s}"
def _build_payload(self, prompt: str, negative_prompt: str, width: int, height: int) -> dict:
"""构建NovelAI API请求payload"""
@@ -197,7 +194,7 @@ class MaiZoneNovelAIService:
return payload
async def _call_novelai_api(self, payload: dict) -> Optional[bytes]:
async def _call_novelai_api(self, payload: dict) -> bytes | None:
"""调用NovelAI API"""
headers = {
"Authorization": f"Bearer {self.api_key}",
@@ -228,10 +225,10 @@ class MaiZoneNovelAIService:
logger.info(f"收到响应数据: {len(img_data)} bytes")
# 检查是否是ZIP文件
if img_data[:4] == b'PK\x03\x04':
if img_data[:4] == b"PK\x03\x04":
logger.info("检测到ZIP格式解压中...")
return self._extract_from_zip(img_data)
elif img_data[:4] == b'\x89PNG':
elif img_data[:4] == b"\x89PNG":
logger.info("检测到PNG格式")
return img_data
else:
@@ -242,12 +239,12 @@ class MaiZoneNovelAIService:
logger.error(f"API调用失败: {e}", exc_info=True)
return None
def _extract_from_zip(self, zip_data: bytes) -> Optional[bytes]:
def _extract_from_zip(self, zip_data: bytes) -> bytes | None:
"""从ZIP中提取PNG"""
try:
with zipfile.ZipFile(io.BytesIO(zip_data)) as zf:
for filename in zf.namelist():
if filename.lower().endswith('.png'):
if filename.lower().endswith(".png"):
img_data = zf.read(filename)
logger.info(f"从ZIP提取: {filename} ({len(img_data)} bytes)")
return img_data
@@ -257,7 +254,7 @@ class MaiZoneNovelAIService:
logger.error(f"解压ZIP失败: {e}")
return None
async def _save_image(self, image_data: bytes) -> Optional[Path]:
async def _save_image(self, image_data: bytes) -> Path | None:
"""保存图片到本地"""
try:
filename = f"novelai_{uuid.uuid4().hex[:12]}.png"

View File

@@ -5,7 +5,6 @@ QQ空间服务模块
import asyncio
import base64
import os
import random
import time
from collections.abc import Callable
@@ -114,7 +113,7 @@ class QZoneService:
}
width, height = size_map.get(aspect_ratio, (1024, 1024))
logger.info(f"🎨 开始生成NovelAI配图...")
logger.info("🎨 开始生成NovelAI配图...")
success, img_path, msg = await novelai_service.generate_image_from_prompt_data(
prompt=image_info.get("prompt", ""),
negative_prompt=image_info.get("negative_prompt"),
@@ -125,7 +124,7 @@ class QZoneService:
if success and img_path:
image_path = img_path
logger.info(f"✅ NovelAI配图生成成功")
logger.info("✅ NovelAI配图生成成功")
else:
logger.warning(f"⚠️ NovelAI配图生成失败: {msg}")
else:
@@ -143,9 +142,9 @@ class QZoneService:
)
if success and img_path:
image_path = img_path
logger.info(f"✅ 硅基流动配图生成成功")
logger.info("✅ 硅基流动配图生成成功")
else:
logger.warning(f"⚠️ 硅基流动配图生成失败")
logger.warning("⚠️ 硅基流动配图生成失败")
except Exception as e:
logger.error(f"硅基流动配图生成出错: {e}", exc_info=True)
else:
@@ -167,7 +166,7 @@ class QZoneService:
try:
with open(image_path, "rb") as f:
images_bytes.append(f.read())
logger.info(f"添加AI配图到说说")
logger.info("添加AI配图到说说")
except Exception as e:
logger.error(f"读取AI配图失败: {e}")