diff --git a/bot.py b/bot.py index 98b5f1c25..884f39161 100644 --- a/bot.py +++ b/bot.py @@ -1,18 +1,21 @@ import asyncio import hashlib import os +from dotenv import load_dotenv +if os.path.exists(".env"): + load_dotenv(".env", override=True) + print("成功加载环境变量配置") +else: + print("未找到.env文件,请确保程序所需的环境变量被正确设置") import sys import time import platform import traceback from pathlib import Path -from dotenv import load_dotenv from rich.traceback import install - # maim_message imports for console input from maim_message import Seg, UserInfo, BaseMessageInfo, MessageBase from src.chat.message_receive.bot import chat_bot - # 最早期初始化日志系统,确保所有后续模块都使用正确的日志格式 from src.common.logger import initialize_logging, get_logger, shutdown_logging from src.main import MainSystem @@ -22,12 +25,7 @@ initialize_logging() logger = get_logger("main") -# 直接加载生产环境变量配置 -if os.path.exists(".env"): - load_dotenv(".env", override=True) - logger.info("成功加载环境变量配置") -else: - logger.warning("未找到.env文件,请确保程序所需的环境变量被正确设置") + install(extra_lines=3) diff --git a/src/chat/express/expression_selector.py b/src/chat/express/expression_selector.py new file mode 100644 index 000000000..6f30698c3 --- /dev/null +++ b/src/chat/express/expression_selector.py @@ -0,0 +1,243 @@ +from .exprssion_learner import get_expression_learner +import random +from typing import List, Dict, Tuple +from json_repair import repair_json +import json +import os +import time +from src.llm_models.utils_model import LLMRequest +from src.config.config import global_config +from src.common.logger import get_logger +from src.chat.utils.prompt_builder import Prompt, global_prompt_manager + +logger = get_logger("expression_selector") + +def init_prompt(): + expression_evaluation_prompt = """ +你的名字是{bot_name} + +以下是正在进行的聊天内容: +{chat_observe_info} + +以下是可选的表达情境: +{all_situations} + +请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的5-10个情境。 +考虑因素包括: +1. 聊天的情绪氛围(轻松、严肃、幽默等) +2. 话题类型(日常、技术、游戏、情感等) +3. 情境与当前语境的匹配度 + +请以JSON格式输出,只需要输出选中的情境编号: +例如: +{{ + "selected_situations": [2, 3, 5, 7, 9, 12, 15, 18, 21, 25] +}} +例如: +{{ + "selected_situations": [1, 4, 7, 9, 13, 18, 24] +}} + +请严格按照JSON格式输出,不要包含其他内容: +""" + Prompt(expression_evaluation_prompt, "expression_evaluation_prompt") + +def weighted_sample(population: List[Dict], weights: List[float], k: int) -> List[Dict]: + """按权重随机抽样""" + if not population or not weights or k <= 0: + return [] + + if len(population) <= k: + return population.copy() + + # 使用累积权重的方法进行加权抽样 + selected = [] + population_copy = population.copy() + weights_copy = weights.copy() + + for _ in range(k): + if not population_copy: + break + + # 选择一个元素 + chosen_idx = random.choices(range(len(population_copy)), weights=weights_copy)[0] + selected.append(population_copy.pop(chosen_idx)) + weights_copy.pop(chosen_idx) + + return selected + +class ExpressionSelector: + def __init__(self): + self.expression_learner = get_expression_learner() + # TODO: API-Adapter修改标记 + self.llm_model = LLMRequest( + model=global_config.model.utils_small, + request_type="expression.selector", + ) + + def get_random_expressions(self, chat_id: str, style_num: int, grammar_num: int, personality_num: int) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]: + ( + learnt_style_expressions, + learnt_grammar_expressions, + personality_expressions, + ) = self.expression_learner.get_expression_by_chat_id(chat_id) + + # 按权重抽样(使用count作为权重) + if learnt_style_expressions: + style_weights = [expr.get("count", 1) for expr in learnt_style_expressions] + selected_style = weighted_sample(learnt_style_expressions, style_weights, style_num) + else: + selected_style = [] + + if learnt_grammar_expressions: + grammar_weights = [expr.get("count", 1) for expr in learnt_grammar_expressions] + selected_grammar = weighted_sample(learnt_grammar_expressions, grammar_weights, grammar_num) + else: + selected_grammar = [] + + if personality_expressions: + personality_weights = [expr.get("count", 1) for expr in personality_expressions] + selected_personality = weighted_sample(personality_expressions, personality_weights, personality_num) + else: + selected_personality = [] + + return selected_style, selected_grammar, selected_personality + + def update_expression_count(self, chat_id: str, expression: Dict[str, str], multiplier: float = 1.5): + """更新表达方式的count值""" + if expression.get("type") == "style_personality": + # personality表达方式存储在全局文件中 + file_path = os.path.join("data", "expression", "personality", "expressions.json") + else: + # style和grammar表达方式存储在对应chat_id目录中 + expr_type = expression.get("type", "style") + if expr_type == "style": + file_path = os.path.join("data", "expression", "learnt_style", str(chat_id), "expressions.json") + elif expr_type == "grammar": + file_path = os.path.join("data", "expression", "learnt_grammar", str(chat_id), "expressions.json") + else: + return + + if not os.path.exists(file_path): + return + + try: + with open(file_path, "r", encoding="utf-8") as f: + expressions = json.load(f) + + # 找到匹配的表达方式并更新count + for expr in expressions: + if (expr.get("situation") == expression.get("situation") and + expr.get("style") == expression.get("style")): + expr["count"] = expr.get("count", 1) * multiplier + expr["last_active_time"] = time.time() + break + + # 保存更新后的文件 + with open(file_path, "w", encoding="utf-8") as f: + json.dump(expressions, f, ensure_ascii=False, indent=2) + + except Exception as e: + logger.error(f"更新表达方式count失败: {e}") + + async def select_suitable_expressions_llm(self, chat_id: str, chat_info: str) -> List[Dict[str, str]]: + """使用LLM选择适合的表达方式""" + + # 1. 获取35个随机表达方式(现在按权重抽取) + style_exprs, grammar_exprs, personality_exprs = self.get_random_expressions(chat_id, 25, 25, 10) + + # 2. 构建所有表达方式的索引和情境列表 + all_expressions = [] + all_situations = [] + + # 添加style表达方式 + for expr in style_exprs: + if isinstance(expr, dict) and "situation" in expr and "style" in expr: + expr_with_type = expr.copy() + expr_with_type["type"] = "style" + all_expressions.append(expr_with_type) + all_situations.append(f"{len(all_expressions)}.{expr['situation']}") + + # 添加grammar表达方式 + for expr in grammar_exprs: + if isinstance(expr, dict) and "situation" in expr and "style" in expr: + expr_with_type = expr.copy() + expr_with_type["type"] = "grammar" + all_expressions.append(expr_with_type) + all_situations.append(f"{len(all_expressions)}.{expr['situation']}") + + # 添加personality表达方式 + for expr in personality_exprs: + if isinstance(expr, dict) and "situation" in expr and "style" in expr: + expr_with_type = expr.copy() + expr_with_type["type"] = "style_personality" + all_expressions.append(expr_with_type) + all_situations.append(f"{len(all_expressions)}.{expr['situation']}") + + if not all_expressions: + logger.warning("没有找到可用的表达方式") + return [] + + all_situations_str = "\n".join(all_situations) + + # 3. 构建prompt(只包含情境,不包含完整的表达方式) + prompt = (await global_prompt_manager.get_prompt_async("expression_evaluation_prompt")).format( + bot_name=global_config.bot.nickname, + chat_observe_info=chat_info, + all_situations=all_situations_str, + ) + + print(prompt) + + # 4. 调用LLM + try: + content, (_, _) = await self.llm_model.generate_response_async(prompt=prompt) + + # logger.info(f"{self.log_prefix} LLM返回结果: {content}") + + if not content: + logger.warning("LLM返回空结果") + return [] + + # 5. 解析结果 + result = repair_json(content) + if isinstance(result, str): + result = json.loads(result) + + if not isinstance(result, dict) or "selected_situations" not in result: + logger.error("LLM返回格式错误") + return [] + + selected_indices = result["selected_situations"] + + # 根据索引获取完整的表达方式 + valid_expressions = [] + for idx in selected_indices: + if isinstance(idx, int) and 1 <= idx <= len(all_expressions): + expression = all_expressions[idx - 1] # 索引从1开始 + valid_expressions.append(expression) + + # 对选中的表达方式count数*1.5 + self.update_expression_count(chat_id, expression, 1.5) + + # logger.info(f"LLM从{len(all_expressions)}个情境中选择了{len(valid_expressions)}个") + return valid_expressions + + except Exception as e: + logger.error(f"LLM处理表达方式选择时出错: {e}") + return [] + + +init_prompt() + +try: + expression_selector = ExpressionSelector() +except Exception as e: + print(f"ExpressionSelector初始化失败: {e}") + + + + + + + diff --git a/src/chat/express/exprssion_learner.py b/src/chat/express/exprssion_learner.py index 479c886af..bbe7680cd 100644 --- a/src/chat/express/exprssion_learner.py +++ b/src/chat/express/exprssion_learner.py @@ -29,7 +29,7 @@ def init_prompt() -> None: 4. 思考有没有特殊的梗,一并总结成语言风格 5. 例子仅供参考,请严格根据群聊内容总结!!! 注意:总结成如下格式的规律,总结的内容要详细,但具有概括性: -当"xxxxxx"时,可以"xxxxxx", xxxxxx不超过20个字 +当"xxxxxx"时,可以"xxxxxx", xxxxxx不超过20个字,为特定句式或表达 例如: 当"对某件事表示十分惊叹,有些意外"时,使用"我嘞个xxxx" @@ -73,7 +73,7 @@ class ExpressionLearner: request_type="expressor.learner", ) - async def get_expression_by_chat_id(self, chat_id: str) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]: + def get_expression_by_chat_id(self, chat_id: str) -> Tuple[List[Dict[str, str]], List[Dict[str, str]]]: """ 读取/data/expression/learnt/{chat_id}/expressions.json和/data/expression/personality/expressions.json 返回(learnt_expressions, personality_expressions) diff --git a/src/chat/focus_chat/info_processors/expression_selector_processor.py b/src/chat/focus_chat/info_processors/expression_selector_processor.py index ed0a8c7c1..9bce1b49b 100644 --- a/src/chat/focus_chat/info_processors/expression_selector_processor.py +++ b/src/chat/focus_chat/info_processors/expression_selector_processor.py @@ -1,98 +1,18 @@ import time import random -from typing import List, Dict +from typing import List from src.chat.heart_flow.observation.chatting_observation import ChattingObservation from src.chat.heart_flow.observation.observation import Observation -from src.llm_models.utils_model import LLMRequest -from src.config.config import global_config from src.common.logger import get_logger -from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.message_receive.chat_stream import get_chat_manager from .base_processor import BaseProcessor from src.chat.focus_chat.info.info_base import InfoBase from src.chat.focus_chat.info.expression_selection_info import ExpressionSelectionInfo -from src.chat.express.exprssion_learner import get_expression_learner -from json_repair import repair_json -import json +from src.chat.express.expression_selector import expression_selector logger = get_logger("processor") -def weighted_sample_no_replacement(items, weights, k) -> list: - """ - 加权随机抽样,不允许重复 - - Args: - items: 待抽样的项目列表 - weights: 对应项目的权重列表 - k: 抽样数量 - - Returns: - 抽样结果列表 - """ - if not items or k <= 0: - return [] - - k = min(k, len(items)) - selected = [] - remaining_items = list(items) - remaining_weights = list(weights) - - for _ in range(k): - if not remaining_items: - break - - # 计算累积权重 - total_weight = sum(remaining_weights) - if total_weight <= 0: - # 如果权重都为0或负数,则随机选择 - selected_index = random.randint(0, len(remaining_items) - 1) - else: - # 加权随机选择 - rand_val = random.uniform(0, total_weight) - cumulative_weight = 0 - selected_index = 0 - for i, weight in enumerate(remaining_weights): - cumulative_weight += weight - if rand_val <= cumulative_weight: - selected_index = i - break - - # 添加选中的项目 - selected.append(remaining_items[selected_index]) - # 移除已选中的项目 - remaining_items.pop(selected_index) - remaining_weights.pop(selected_index) - - return selected - - -def init_prompt(): - expression_evaluation_prompt = """ -你的名字是{bot_name} - -以下是正在进行的聊天内容: -{chat_observe_info} - -以下是可选的表达情境: -{all_situations} - -请你分析聊天内容的语境、情绪、话题类型,从上述情境中选择最适合当前聊天情境的10个情境。 -考虑因素包括: -1. 聊天的情绪氛围(轻松、严肃、幽默等) -2. 话题类型(日常、技术、游戏、情感等) -3. 情境与当前语境的匹配度 - -请以JSON格式输出,只需要输出选中的情境编号: -{{ - "selected_situations": [1, 3, 5, 7, 9, 12, 15, 18, 21, 25] -}} - -请严格按照JSON格式输出,不要包含其他内容: -""" - Prompt(expression_evaluation_prompt, "expression_evaluation_prompt") - - class ExpressionSelectorProcessor(BaseProcessor): log_prefix = "表达选择器" @@ -101,16 +21,9 @@ class ExpressionSelectorProcessor(BaseProcessor): self.subheartflow_id = subheartflow_id self.last_selection_time = 0 - self.selection_interval = 40 # 1分钟间隔 + self.selection_interval = 10 # 40秒间隔 self.cached_expressions = [] # 缓存上一次选择的表达方式 - # 表达方式选择模式 - self.selection_mode = getattr(global_config.expression, "selection_mode", "llm") # "llm" 或 "random" - - self.llm_model = LLMRequest( - model=global_config.model.utils_small, - request_type="focus.processor.expression_selector", - ) name = get_chat_manager().get_stream_name(self.subheartflow_id) self.log_prefix = f"[{name}] 表达选择器" @@ -158,26 +71,20 @@ class ExpressionSelectorProcessor(BaseProcessor): return [] try: - # 根据模式选择表达方式 - # LLM模式:调用LLM选择15个,然后随机选5个 - selected_expressions = await self._select_suitable_expressions_llm(chat_info) + # LLM模式:调用LLM选择5-10个,然后随机选5个 + selected_expressions = await expression_selector.select_suitable_expressions_llm(self.subheartflow_id, chat_info) cache_size = len(selected_expressions) if selected_expressions else 0 mode_desc = f"LLM模式(已缓存{cache_size}个)" if selected_expressions: - # 缓存选择的表达方式 self.cached_expressions = selected_expressions - # 更新最后选择时间 self.last_selection_time = current_time - # 从选择的表达方式中随机选5个 - final_expressions = random.sample(selected_expressions, min(4, len(selected_expressions))) - # 创建表达选择信息 expression_info = ExpressionSelectionInfo() - expression_info.set_selected_expressions(final_expressions) + expression_info.set_selected_expressions(selected_expressions) - logger.info(f"{self.log_prefix} 为当前聊天选择了{len(final_expressions)}个表达方式({mode_desc})") + logger.info(f"{self.log_prefix} 为当前聊天选择了{len(selected_expressions)}个表达方式({mode_desc})") return [expression_info] else: logger.debug(f"{self.log_prefix} 未选择任何表达方式") @@ -187,104 +94,3 @@ class ExpressionSelectorProcessor(BaseProcessor): logger.error(f"{self.log_prefix} 处理表达方式选择时出错: {e}") return [] - async def _get_random_expressions(self) -> tuple[List[Dict], List[Dict], List[Dict]]: - """随机获取表达方式:20个style,20个grammar,20个personality""" - expression_learner = get_expression_learner() - - # 获取所有表达方式 - ( - learnt_style_expressions, - learnt_grammar_expressions, - personality_expressions, - ) = await expression_learner.get_expression_by_chat_id(self.subheartflow_id) - - # 随机选择 - selected_style = random.sample(learnt_style_expressions, min(15, len(learnt_style_expressions))) - selected_grammar = random.sample(learnt_grammar_expressions, min(15, len(learnt_grammar_expressions))) - selected_personality = random.sample(personality_expressions, min(5, len(personality_expressions))) - - return selected_style, selected_grammar, selected_personality - - async def _select_suitable_expressions_llm(self, chat_info: str) -> List[Dict[str, str]]: - """使用LLM选择适合的表达方式""" - - # 1. 获取35个随机表达方式 - style_exprs, grammar_exprs, personality_exprs = await self._get_random_expressions() - - # 2. 构建所有表达方式的索引和情境列表 - all_expressions = [] - all_situations = [] - - # 添加style表达方式 - for expr in style_exprs: - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - expr_with_type = expr.copy() - expr_with_type["type"] = "style" - all_expressions.append(expr_with_type) - all_situations.append(f"{len(all_expressions)}. [语言风格] {expr['situation']}") - - # 添加grammar表达方式 - for expr in grammar_exprs: - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - expr_with_type = expr.copy() - expr_with_type["type"] = "grammar" - all_expressions.append(expr_with_type) - all_situations.append(f"{len(all_expressions)}. [句法语法] {expr['situation']}") - - # 添加personality表达方式 - for expr in personality_exprs: - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - expr_with_type = expr.copy() - expr_with_type["type"] = "personality" - all_expressions.append(expr_with_type) - all_situations.append(f"{len(all_expressions)}. [个性表达] {expr['situation']}") - - if not all_expressions: - logger.warning(f"{self.log_prefix} 没有找到可用的表达方式") - return [] - - all_situations_str = "\n".join(all_situations) - - # 3. 构建prompt(只包含情境,不包含完整的表达方式) - prompt = (await global_prompt_manager.get_prompt_async("expression_evaluation_prompt")).format( - bot_name=global_config.bot.nickname, - chat_observe_info=chat_info, - all_situations=all_situations_str, - ) - - # 4. 调用LLM - try: - content, _ = await self.llm_model.generate_response_async(prompt=prompt) - - # logger.info(f"{self.log_prefix} LLM返回结果: {content}") - - if not content: - logger.warning(f"{self.log_prefix} LLM返回空结果") - return [] - - # 5. 解析结果 - result = repair_json(content) - if isinstance(result, str): - result = json.loads(result) - - if not isinstance(result, dict) or "selected_situations" not in result: - logger.error(f"{self.log_prefix} LLM返回格式错误") - return [] - - selected_indices = result["selected_situations"] - - # 根据索引获取完整的表达方式 - valid_expressions = [] - for idx in selected_indices: - if isinstance(idx, int) and 1 <= idx <= len(all_expressions): - valid_expressions.append(all_expressions[idx - 1]) # 索引从1开始 - - logger.info(f"{self.log_prefix} LLM从{len(all_expressions)}个情境中选择了{len(valid_expressions)}个") - return valid_expressions - - except Exception as e: - logger.error(f"{self.log_prefix} LLM处理表达方式选择时出错: {e}") - return [] - - -init_prompt() diff --git a/src/chat/focus_chat/replyer/default_generator.py b/src/chat/focus_chat/replyer/default_generator.py index a3de152ef..1acc48b20 100644 --- a/src/chat/focus_chat/replyer/default_generator.py +++ b/src/chat/focus_chat/replyer/default_generator.py @@ -490,7 +490,7 @@ class DefaultReplyer: learnt_style_expressions, learnt_grammar_expressions, personality_expressions, - ) = await expression_learner.get_expression_by_chat_id(chat_stream.stream_id) + ) = expression_learner.get_expression_by_chat_id(chat_stream.stream_id) style_habbits = [] grammar_habbits = [] diff --git a/src/chat/normal_chat/normal_prompt.py b/src/chat/normal_chat/normal_prompt.py index e0971a919..2cf2bcf87 100644 --- a/src/chat/normal_chat/normal_prompt.py +++ b/src/chat/normal_chat/normal_prompt.py @@ -1,7 +1,5 @@ -from src.chat.express.exprssion_learner import get_expression_learner from src.config.config import global_config from src.common.logger import get_logger -from src.individuality.individuality import get_individuality from src.chat.utils.prompt_builder import Prompt, global_prompt_manager from src.chat.utils.chat_message_builder import build_readable_messages, get_raw_msg_before_timestamp_with_chat import time @@ -10,6 +8,8 @@ from src.manager.mood_manager import mood_manager from src.chat.memory_system.Hippocampus import hippocampus_manager from src.chat.knowledge.knowledge_lib import qa_manager import random +from src.person_info.person_info import get_person_info_manager +from src.chat.express.expression_selector import expression_selector import re from src.person_info.relationship_manager import get_relationship_manager @@ -27,7 +27,7 @@ def init_prompt(): """ 你可以参考以下的语言习惯,如果情景合适就使用,不要盲目使用,不要生硬使用,而是结合到表达中: {style_habbits} -请你根据情景使用以下句法,不要盲目使用,不要生硬使用,而是结合到表达中: +请你根据情景使用以下,不要盲目使用,不要生硬使用,而是结合到表达中: {grammar_habbits} {memory_prompt} @@ -91,7 +91,14 @@ class PromptBuilder: enable_planner: bool = False, available_actions=None, ) -> str: - prompt_personality = get_individuality().get_prompt(x_person=2, level=2) + core_personality = global_config.personality.personality_core + person_info_manager = get_person_info_manager() + bot_person_id = person_info_manager.get_person_id("system", "bot_id") + short_impression = await person_info_manager.get_value(bot_person_id, "short_impression") + prompt_personality = core_personality + if short_impression: + prompt_personality += short_impression + is_group_chat = bool(chat_stream.group_info) who_chat_in_group = [] @@ -113,40 +120,8 @@ class PromptBuilder: relation_prompt += await relationship_manager.build_relationship_info(person) mood_prompt = mood_manager.get_mood_prompt() - expression_learner = get_expression_learner() - ( - learnt_style_expressions, - learnt_grammar_expressions, - personality_expressions, - ) = await expression_learner.get_expression_by_chat_id(chat_stream.stream_id) - - style_habbits = [] - grammar_habbits = [] - # 1. learnt_expressions加权随机选2条 - if learnt_style_expressions: - weights = [expr["count"] for expr in learnt_style_expressions] - selected_learnt = weighted_sample_no_replacement(learnt_style_expressions, weights, 2) - for expr in selected_learnt: - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}") - # 2. learnt_grammar_expressions加权随机选2条 - if learnt_grammar_expressions: - weights = [expr["count"] for expr in learnt_grammar_expressions] - selected_learnt = weighted_sample_no_replacement(learnt_grammar_expressions, weights, 2) - for expr in selected_learnt: - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - grammar_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}") - # 3. personality_expressions随机选1条 - if personality_expressions: - expr = random.choice(personality_expressions) - if isinstance(expr, dict) and "situation" in expr and "style" in expr: - style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}") - - style_habbits_str = "\n".join(style_habbits) - grammar_habbits_str = "\n".join(grammar_habbits) memory_prompt = "" - if global_config.memory.enable_memory: related_memory = await hippocampus_manager.get_memory_from_text( text=message_txt, max_memory_num=2, max_memory_length=2, max_depth=3, fast_retrieval=False @@ -173,6 +148,37 @@ class PromptBuilder: read_mark=0.0, show_actions=True, ) + + message_list_before_now_half = get_raw_msg_before_timestamp_with_chat( + chat_id=chat_stream.stream_id, + timestamp=time.time(), + limit=global_config.focus_chat.observation_context_size * 0.5, + ) + chat_talking_prompt_half = build_readable_messages( + message_list_before_now_half, + replace_bot_name=True, + merge_messages=False, + timestamp_mode="relative", + read_mark=0.0, + show_actions=True, + ) + + expressions = expression_selector.select_suitable_expressions_llm(chat_stream.stream_id, chat_talking_prompt_half) + style_habbits = [] + grammar_habbits = [] + if expressions: + for expr in expressions: + if isinstance(expr, dict) and "situation" in expr and "style" in expr: + expr_type = expr.get("type", "style") + if expr_type == "grammar": + grammar_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}") + else: + style_habbits.append(f"当{expr['situation']}时,使用 {expr['style']}") + else: + logger.debug("没有从处理器获得表达方式,将使用空的表达方式") + + style_habbits_str = "\n".join(style_habbits) + grammar_habbits_str = "\n".join(grammar_habbits) # 关键词检测与反应 keywords_reaction_prompt = "" diff --git a/src/chat/utils/chat_message_builder.py b/src/chat/utils/chat_message_builder.py index ed69c7558..84593bcff 100644 --- a/src/chat/utils/chat_message_builder.py +++ b/src/chat/utils/chat_message_builder.py @@ -599,7 +599,6 @@ def build_readable_messages( copy_messages.sort(key=lambda x: x.get("time", 0)) if read_mark <= 0: - print(f"read_mark: {read_mark}") # 没有有效的 read_mark,直接格式化所有消息 formatted_string, _, pic_id_mapping, _ = _build_readable_messages_internal( copy_messages, replace_bot_name, merge_messages, timestamp_mode, truncate diff --git a/src/individuality/individuality.py b/src/individuality/individuality.py index eda883efe..2937703e4 100644 --- a/src/individuality/individuality.py +++ b/src/individuality/individuality.py @@ -1,5 +1,7 @@ from typing import Optional import asyncio + +from src.llm_models.utils_model import LLMRequest from .personality import Personality from .identity import Identity from .expression_style import PersonalityExpression @@ -10,6 +12,7 @@ import hashlib from rich.traceback import install from src.common.logger import get_logger from src.person_info.person_info import get_person_info_manager +from src.config.config import global_config install(extra_lines=3) @@ -28,6 +31,11 @@ class Individuality: self.name = "" self.bot_person_id = "" self.meta_info_file_path = "data/personality/meta.json" + + self.model = LLMRequest( + model=global_config.model.utils, + request_type="individuality.compress", + ) async def initialize( self, @@ -90,6 +98,11 @@ class Individuality: ) logger.info("已将完整人设更新到bot的impression中") + # 创建压缩版本的short_impression + asyncio.create_task(self._create_compressed_impression( + personality_core, personality_sides, identity_detail + )) + asyncio.create_task(self.express_style.extract_and_store_personality_expressions()) def to_dict(self) -> dict: @@ -357,6 +370,71 @@ class Individuality: logger.error(f"解析info_list失败: {info_list_json}") return keywords + async def _create_compressed_impression( + self, personality_core: str, personality_sides: list, identity_detail: list + ) -> str: + """使用LLM创建压缩版本的impression + + Args: + personality_core: 核心人格 + personality_sides: 人格侧面列表 + identity_detail: 身份细节列表 + + Returns: + str: 压缩后的impression文本 + """ + # 核心人格保持不变 + compressed_parts = [] + if personality_core: + compressed_parts.append(f"{personality_core}") + + # 准备需要压缩的内容 + content_to_compress = [] + if personality_sides: + content_to_compress.append(f"人格特质: {'、'.join(personality_sides)}") + if identity_detail: + content_to_compress.append(f"身份背景: {'、'.join(identity_detail)}") + + if not content_to_compress: + # 如果没有需要压缩的内容,直接返回核心人格 + result = "。".join(compressed_parts) + return result + "。" if result else "" + + # 使用LLM压缩其他内容 + try: + compress_content = "、".join(content_to_compress) + + prompt = f"""请将以下人设信息进行简洁压缩,保留主要内容,用简练的中文表达: + +{compress_content} + +要求: +1. 保持原意不变,尽量使用原文 +2. 尽量简洁,不超过30字 +3. 直接输出压缩后的内容,不要解释""" + + response,(_,_) = await self.model.generate_response_async( + prompt=prompt, + ) + + if response.strip(): + compressed_parts.append(response.strip()) + logger.info(f"精简人格侧面: {response.strip()}") + else: + logger.error(f"使用LLM压缩人设时出错: {response}") + except Exception as e: + logger.error(f"使用LLM压缩人设时出错: {e}") + + result = "。".join(compressed_parts) + + # 更新short_impression字段 + if result: + person_info_manager = get_person_info_manager() + await person_info_manager.update_one_field( + self.bot_person_id, "short_impression", result + ) + logger.info("已将压缩人设更新到bot的short_impression中") + individuality = None diff --git a/src/llm_models/utils_model.py b/src/llm_models/utils_model.py index 377fd3813..f38dfa480 100644 --- a/src/llm_models/utils_model.py +++ b/src/llm_models/utils_model.py @@ -109,6 +109,7 @@ class LLMRequest: def __init__(self, model: dict, **kwargs): # 将大写的配置键转换为小写并从config中获取实际值 try: + # print(f"model['provider']: {model['provider']}") self.api_key = os.environ[f"{model['provider']}_KEY"] self.base_url = os.environ[f"{model['provider']}_BASE_URL"] except AttributeError as e: