From e200b5b58117b984e64216e0fd295640b07f2c5a Mon Sep 17 00:00:00 2001 From: UnCLAS-Prommer Date: Mon, 2 Mar 2026 17:18:13 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=99Expression=E7=B3=BB=E7=BB=9F=E7=9A=84?= =?UTF-8?q?=E4=B8=80=E4=BA=9B=E5=87=86=E5=A4=87=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- prompts/expression_evaluation.prompt | 29 +++++------- prompts/expression_select.prompt | 22 ++++++++++ pytests/message_test/session_message_test.py | 2 +- src/bw_learner/expression_selector.py | 2 +- .../data_models/expression_data_model.py | 12 ++--- .../message_component_data_model.py | 44 +++++++++++++------ src/common/database/database_model.py | 2 +- 7 files changed, 73 insertions(+), 40 deletions(-) create mode 100644 prompts/expression_select.prompt diff --git a/prompts/expression_evaluation.prompt b/prompts/expression_evaluation.prompt index 69fa1dc5..abb5b5aa 100644 --- a/prompts/expression_evaluation.prompt +++ b/prompts/expression_evaluation.prompt @@ -1,22 +1,15 @@ -{chat_observe_info} +请评估以下表达方式或语言风格以及使用条件或使用情景是否合适: +使用条件或使用情景:{situation} +表达方式或言语风格:{style} -你的名字是{bot_name}{target_message} -{reply_reason_block} +请从以下方面进行评估: +{criteria_list} -以下是可选的表达情境: -{all_situations} - -请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的,最多{max_num}个情境。 -考虑因素包括: -1.聊天的情绪氛围(轻松、严肃、幽默等) -2.话题类型(日常、技术、游戏、情感等) -3.情境与当前语境的匹配度 -{target_message_extra_block} - -请以JSON格式输出,只需要输出选中的情境编号: -例如: +请以JSON格式输出评估结果: {{ - "selected_situations": [2, 3, 5, 7, 19] -}} + "suitable": true/false, + "reason": "评估理由(如果不合适,请说明原因)" -请严格按照JSON格式输出,不要包含其他内容: \ No newline at end of file +}} +如果合适,suitable设为true;如果不合适,suitable设为false,并在reason中说明原因。 +请严格按照JSON格式输出,不要包含其他内容。 \ No newline at end of file diff --git a/prompts/expression_select.prompt b/prompts/expression_select.prompt new file mode 100644 index 00000000..69fa1dc5 --- /dev/null +++ b/prompts/expression_select.prompt @@ -0,0 +1,22 @@ +{chat_observe_info} + +你的名字是{bot_name}{target_message} +{reply_reason_block} + +以下是可选的表达情境: +{all_situations} + +请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的,最多{max_num}个情境。 +考虑因素包括: +1.聊天的情绪氛围(轻松、严肃、幽默等) +2.话题类型(日常、技术、游戏、情感等) +3.情境与当前语境的匹配度 +{target_message_extra_block} + +请以JSON格式输出,只需要输出选中的情境编号: +例如: +{{ + "selected_situations": [2, 3, 5, 7, 19] +}} + +请严格按照JSON格式输出,不要包含其他内容: \ No newline at end of file diff --git a/pytests/message_test/session_message_test.py b/pytests/message_test/session_message_test.py index a48a3f8b..aab8971a 100644 --- a/pytests/message_test/session_message_test.py +++ b/pytests/message_test/session_message_test.py @@ -121,7 +121,7 @@ def setup_mocks(monkeypatch): db_mod = _stub_module("src.common.database.database") db_mod.get_db_session = get_db_session db_mod.get_manual_db_session = get_manual_db_session - + db_model_mod = _stub_module("src.common.database.database_model") db_model_mod.Messages = None # 可以根据需要添加更多的属性或方法 diff --git a/src/bw_learner/expression_selector.py b/src/bw_learner/expression_selector.py index 4f77ad74..863481a3 100644 --- a/src/bw_learner/expression_selector.py +++ b/src/bw_learner/expression_selector.py @@ -378,7 +378,7 @@ class ExpressionSelector: reply_reason_block = "" # 3. 构建prompt(只包含情境,不包含完整的表达方式) - prompt_template = prompt_manager.get_prompt("expression_evaluation") + prompt_template = prompt_manager.get_prompt("expression_select") prompt_template.add_context("bot_name", global_config.bot.nickname) prompt_template.add_context("chat_observe_info", chat_context) prompt_template.add_context("all_situations", all_situations_str) diff --git a/src/common/data_models/expression_data_model.py b/src/common/data_models/expression_data_model.py index 8b8a9e28..8015b985 100644 --- a/src/common/data_models/expression_data_model.py +++ b/src/common/data_models/expression_data_model.py @@ -14,7 +14,7 @@ class MaiExpression(BaseDatabaseDataModel[Expression]): item_id: int, situation: str, style: str, - context: str, + # context: str, # up_content: str, content: List[str], count: int, @@ -31,8 +31,8 @@ class MaiExpression(BaseDatabaseDataModel[Expression]): """表达方式使用情景""" self.style = style """表达方式风格""" - self.context = context - """表达方式上下文""" + # self.context = context + # """表达方式上下文""" # self.up_content = up_content self.content: List[str] = content """内容列表""" @@ -40,7 +40,7 @@ class MaiExpression(BaseDatabaseDataModel[Expression]): self.last_active_time: datetime = last_active_time or datetime.now() self.create_time: datetime = create_time or datetime.now() self.session_id: Optional[str] = session_id - + self.checked: bool = checked """是否已经被检查过""" self.rejected: bool = rejected @@ -58,7 +58,7 @@ class MaiExpression(BaseDatabaseDataModel[Expression]): item_id=db_record.id, # type: ignore situation=db_record.situation, style=db_record.style, - context=db_record.context, + # context=db_record.context, content=content_list, count=db_record.count, last_active_time=db_record.last_active_time, @@ -77,7 +77,7 @@ class MaiExpression(BaseDatabaseDataModel[Expression]): id=self.item_id, situation=self.situation, style=self.style, - context=self.context, + # context=self.context, content_list=json.dumps(self.content), count=self.count, last_active_time=self.last_active_time, diff --git a/src/common/data_models/message_component_data_model.py b/src/common/data_models/message_component_data_model.py index 3b511eab..3149db57 100644 --- a/src/common/data_models/message_component_data_model.py +++ b/src/common/data_models/message_component_data_model.py @@ -1,6 +1,8 @@ from abc import ABC, abstractmethod from copy import deepcopy from maim_message import Seg, UserInfo, MessageBase, BaseMessageInfo +from pathlib import Path +from sqlmodel import select from typing import Optional, List, Union, Dict, Any import asyncio @@ -61,8 +63,21 @@ class ImageComponent(BaseMessageComponentModel, ByteComponent): return "image" async def load_image_binary(self): - if not self.binary_data: - raise NotImplementedError + if self.binary_data: + return + from src.common.database.database import get_db_session + from src.common.database.database_model import Images, ImageType + + try: + with get_db_session() as db: + statement = select(Images).filter_by(image_hash=self.binary_hash, image_type=ImageType.IMAGE).limit(1) + if image_record := db.exec(statement).first(): + image_path = Path(image_record.full_path) + else: + raise ValueError(f"无法通过 image_hash 加载图片二进制数据: {self.binary_hash}") + self.binary_data = await asyncio.to_thread(image_path.read_bytes) + except Exception as e: + raise ValueError(f"通过 image_hash 加载图片二进制数据时发生错误: {e}") from e async def to_seg(self) -> Seg: if not self.binary_data: @@ -85,18 +100,21 @@ class EmojiComponent(BaseMessageComponentModel, ByteComponent): ValueError: 如果 binary_data 为空且缺少 emoji_hash ValueError: 如果无法通过 emoji_hash 加载表情二进制数据 """ - if not self.binary_data: - from src.chat.emoji_system.emoji_manager import emoji_manager + if self.binary_data: + return + from src.common.database.database import get_db_session + from src.common.database.database_model import Images, ImageType - if not ( - emoji := emoji_manager.get_emoji_by_hash(self.binary_hash) - or emoji_manager.get_emoji_by_hash_from_db(self.binary_hash) - ): - raise ValueError(f"无法通过 emoji_hash 加载表情二进制数据: {self.binary_hash}") - try: - self.binary_data = await asyncio.to_thread(emoji.full_path.read_bytes) - except Exception as e: - raise ValueError(f"通过 emoji_hash 加载表情二进制数据时发生错误: {e}") from e + try: + with get_db_session() as db: + statement = select(Images).filter_by(image_hash=self.binary_hash, image_type=ImageType.EMOJI).limit(1) + if image_record := db.exec(statement).first(): + image_path = Path(image_record.full_path) + else: + raise ValueError(f"无法通过 emoji_hash 加载表情二进制数据: {self.binary_hash}") + self.binary_data = await asyncio.to_thread(image_path.read_bytes) + except Exception as e: + raise ValueError(f"通过 emoji_hash 加载表情二进制数据时发生错误: {e}") from e async def to_seg(self) -> Seg: if not self.binary_data: diff --git a/src/common/database/database_model.py b/src/common/database/database_model.py index 112ce2bd..dbda3cdd 100644 --- a/src/common/database/database_model.py +++ b/src/common/database/database_model.py @@ -170,7 +170,7 @@ class Expression(SQLModel, table=True): situation: str = Field(index=True, max_length=255, primary_key=True) # 情景 style: str = Field(index=True, max_length=255, primary_key=True) # 风格 - context: str # 上下文 + # context: str # 上下文 # up_content: str content_list: str # 内容列表,JSON格式存储