hot_video_analyse/base_line/prompt_manager.py

771 lines
37 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Manages the construction of prompts for different AI generation tasks.
"""
import os
import traceback
import logging # Add logging
import re # 添加正则表达式支持
import random # 添加随机模块支持
from .resource_loader import ResourceLoader # Use relative import within the same package
import json
class PromptManager:
"""Handles the loading and construction of prompts."""
def __init__(self,
topic_system_prompt_path: str,
topic_user_prompt_path: str,
content_system_prompt_path: str,
prompts_dir: str = None, # 兼容旧配置
prompts_config: list = None, # 新的配置方式
resource_dir_config: list = None,
topic_gen_num: int = 1, # Default values if needed
topic_gen_date: str = "",
content_judger_system_prompt_path: str = None # 添加内容审核系统提示词路径参数
):
self.topic_system_prompt_path = topic_system_prompt_path
self.topic_user_prompt_path = topic_user_prompt_path
self.content_system_prompt_path = content_system_prompt_path
self.content_judger_system_prompt_path = content_judger_system_prompt_path # 添加成员变量
self.prompts_dir = prompts_dir # 保留兼容旧配置
self.prompts_config = prompts_config or [] # 新的配置方式
self.resource_dir_config = resource_dir_config or []
self.topic_gen_num = topic_gen_num
self.topic_gen_date = topic_gen_date
# 缓存加载的文件内容
self._style_cache = {}
self._demand_cache = {}
self._refer_cache = {}
self._system_prompt_cache = {} # 新增:系统提示词缓存
self._user_prompt_cache = {} # 新增:用户提示词缓存
self._dateline_cache = None # 新增:日期线缓存
self._sample_rate = 0.1 # 提高随机抽样率
# 初始化时预加载配置的文件
self._preload_prompt_files()
def _preload_prompt_files(self):
"""预加载配置中的提示文件到缓存"""
# 预加载系统提示词和用户提示词文件
if self.topic_system_prompt_path and os.path.exists(self.topic_system_prompt_path):
content = ResourceLoader.load_file_content(self.topic_system_prompt_path)
if content:
self._system_prompt_cache["topic"] = content
logging.info(f"预加载系统提示词: {self.topic_system_prompt_path}")
if self.topic_user_prompt_path and os.path.exists(self.topic_user_prompt_path):
content = ResourceLoader.load_file_content(self.topic_user_prompt_path)
if content:
self._user_prompt_cache["topic"] = content
logging.info(f"预加载用户提示词: {self.topic_user_prompt_path}")
if self.content_system_prompt_path and os.path.exists(self.content_system_prompt_path):
content = ResourceLoader.load_file_content(self.content_system_prompt_path)
if content:
self._system_prompt_cache["content"] = content
logging.info(f"预加载内容系统提示词: {self.content_system_prompt_path}")
# 预加载内容审核系统提示词
if self.content_judger_system_prompt_path and os.path.exists(self.content_judger_system_prompt_path):
content = ResourceLoader.load_file_content(self.content_judger_system_prompt_path)
if content:
self._system_prompt_cache["judger_system_prompt"] = content
logging.info(f"预加载内容审核系统提示词: {self.content_judger_system_prompt_path}")
# 预加载日期线文件
if self.topic_user_prompt_path:
user_prompt_dir = os.path.dirname(self.topic_user_prompt_path)
dateline_path = os.path.join(user_prompt_dir, "2025各月节日宣传节点时间表.md")
if os.path.exists(dateline_path):
self._dateline_cache = ResourceLoader.load_file_content(dateline_path)
logging.info(f"预加载日期线文件: {dateline_path}")
# 加载prompts_config配置的文件
if not self.prompts_config:
return
for config_item in self.prompts_config:
prompt_type = config_item.get("type", "").lower()
file_paths = config_item.get("file_path", [])
if prompt_type == "style":
for path in file_paths:
if os.path.exists(path):
filename = os.path.basename(path)
content = ResourceLoader.load_file_content(path)
if content:
self._style_cache[filename] = content
name_without_ext = os.path.splitext(filename)[0]
self._style_cache[name_without_ext] = content # 同时缓存不带扩展名的版本
elif prompt_type == "demand":
for path in file_paths:
# print(path)
if os.path.exists(path):
filename = os.path.basename(path)
# print(filename)
content = ResourceLoader.load_file_content(path)
# print(content)
if content:
self._demand_cache[filename] = content
name_without_ext = os.path.splitext(filename)[0]
self._demand_cache[name_without_ext] = content # 同时缓存不带扩展名的版本
elif prompt_type == "refer":
for path in file_paths:
# print(path)
if os.path.exists(path):
filename = os.path.basename(path)
# print(filename)
# 检测是否为JSON文件
if filename.lower().endswith('.json'):
# 直接加载和解析JSON文件
try:
with open(path, 'r', encoding='utf-8') as f:
content = f.read()
# 移除可能的BOM头
if content.startswith('\ufeff'):
content = content[1:]
# 解析JSON
json_data = json.loads(content)
# 存储解析后的对象
self._refer_cache[filename] = json_data
logging.info(f"预加载并解析JSON参考文件: {filename}")
except Exception as e:
logging.error(f"预加载JSON文件{filename}失败: {str(e)}")
# 失败时尝试以普通文本加载
content = ResourceLoader.load_file_content(path)
if content:
self._refer_cache[filename] = content
else:
# 非JSON文件使用普通加载方式
content = ResourceLoader.load_all_refer_files(path, 1)
if content:
self._refer_cache[filename] = content
logging.info(f"预加载普通参考文件: {filename}")
def find_directory_fuzzy_match(self, name, directory=None, files=None):
"""
对文件名进行模糊匹配查找最匹配目标名称的文件
Args:
name: 目标名称
directory: 目录路径如果提供则从目录中读取文件列表
files: 文件名列表如果提供则直接使用
Returns:
tuple: (最佳匹配文件名, 匹配分数) 如果没有匹配则返回 (None, 0)
"""
logging.info(f"尝试对文件名进行模糊匹配: {name}")
try:
# 准备文件列表
all_files = []
if files:
all_files = files
elif directory and os.path.isdir(directory):
all_files = [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]
if not all_files:
logging.warning(f"没有可用于匹配的文件")
return None, 0
logging.info(f"找到 {len(all_files)} 个文件可用于模糊匹配")
# 从名称中提取关键词
# 通过常见分隔符分割(+、空格、_、-等)
parts = re.split(r'[+\s_\-]', name)
keywords = []
for part in parts:
# 只保留长度大于1的有意义关键词
if len(part) > 1:
keywords.append(part)
# 尝试匹配更短的语义单元例如中文的2-3个字的词语
for i in range(len(name) - 1):
keyword = name[i:i+2] # 提取2个字符
if len(keyword) == 2 and all('\u4e00' <= c <= '\u9fff' for c in keyword):
keywords.append(keyword)
logging.info(f"用于文件模糊匹配的关键词: {keywords}")
# 对每个文件进行评分
file_scores = {}
for filename in all_files:
score = 0
file_lower = filename.lower()
# 精确匹配,去掉扩展名比较
name_without_ext = os.path.splitext(name)[0].lower()
file_without_ext = os.path.splitext(filename)[0].lower()
if name_without_ext == file_without_ext:
# 精确匹配给高分
score += 10
else:
# 为每个匹配的关键词增加分数
for keyword in keywords:
if keyword.lower() in file_lower:
score += 1
# 如果得分大于0至少有匹配记录该文件
if score > 0:
file_scores[filename] = score
# 选择得分最高的文件
if file_scores:
best_match = max(file_scores.items(), key=lambda x: x[1])
found_file = best_match[0]
score = best_match[1]
logging.info(f"模糊匹配成功!匹配文件: {found_file},匹配分数: {score}")
return found_file, score
else:
logging.warning(f"模糊匹配未找到任何包含关键词的文件")
return None, 0
except Exception as e:
logging.exception(f"文件模糊匹配过程中出错: {e}")
return None, 0
def _get_style_content(self, style_name):
"""获取Style文件内容优先从缓存获取如果不存在则尝试从目录加载"""
# 首先检查缓存
if style_name in self._style_cache:
return self._style_cache[style_name]
# 确保有扩展名
if not style_name.lower().endswith('.txt'):
style_file = f"{style_name}.txt"
else:
style_file = style_name
style_name = os.path.splitext(style_name)[0] # 移除扩展名
# 尝试模糊匹配缓存中的文件名
cache_files = list(self._style_cache.keys())
matched_key, score = self.find_directory_fuzzy_match(style_name, files=cache_files)
if matched_key and score > 0:
return self._style_cache[matched_key]
# 如果没有在缓存中找到模糊匹配尝试从prompts_dir加载
if self.prompts_dir:
style_dir = os.path.join(self.prompts_dir, "Style")
style_path = os.path.join(style_dir, style_file)
# 精确路径匹配
if os.path.exists(style_path):
content = ResourceLoader.load_file_content(style_path)
if content:
# 保存到缓存
self._style_cache[style_name] = content
self._style_cache[style_file] = content
return content
# 如果精确匹配失败,尝试目录中的模糊匹配
if os.path.isdir(style_dir):
matched_file, score = self.find_directory_fuzzy_match(style_name, directory=style_dir)
if matched_file and score > 0:
matched_path = os.path.join(style_dir, matched_file)
content = ResourceLoader.load_file_content(matched_path)
if content:
# 保存到缓存
self._style_cache[style_name] = content
self._style_cache[matched_file] = content
file_without_ext = os.path.splitext(matched_file)[0]
self._style_cache[file_without_ext] = content # 同时缓存不带扩展名的版本
return content
logging.warning(f"未能找到Style文件: '{style_name}',尝试过以下位置: 缓存, {self.prompts_dir}/Style/")
return None
def _get_demand_content(self, demand_name):
"""获取Demand文件内容优先从缓存获取如果不存在则尝试从目录加载"""
# 首先检查缓存
if demand_name in self._demand_cache:
return self._demand_cache[demand_name]
# 确保有扩展名
if not demand_name.lower().endswith('.txt'):
demand_file = f"{demand_name}.txt"
else:
demand_file = demand_name
demand_name = os.path.splitext(demand_name)[0] # 移除扩展名
# 尝试模糊匹配缓存中的文件名
cache_files = list(self._demand_cache.keys())
matched_key, score = self.find_directory_fuzzy_match(demand_name, files=cache_files)
if matched_key and score > 0:
return self._demand_cache[matched_key]
# 如果没有在缓存中找到模糊匹配尝试从prompts_dir加载向后兼容
if self.prompts_dir:
demand_dir = os.path.join(self.prompts_dir, "Demand")
demand_path = os.path.join(demand_dir, demand_file)
# 精确路径匹配
if os.path.exists(demand_path):
content = ResourceLoader.load_file_content(demand_path)
if content:
# 保存到缓存
self._demand_cache[demand_name] = content
self._demand_cache[demand_file] = content
return content
# 如果精确匹配失败,尝试目录中的模糊匹配
if os.path.isdir(demand_dir):
matched_file, score = self.find_directory_fuzzy_match(demand_name, directory=demand_dir)
if matched_file and score > 0:
matched_path = os.path.join(demand_dir, matched_file)
content = ResourceLoader.load_file_content(matched_path)
if content:
# 保存到缓存
self._demand_cache[demand_name] = content
self._demand_cache[matched_file] = content
file_without_ext = os.path.splitext(matched_file)[0]
self._demand_cache[file_without_ext] = content # 同时缓存不带扩展名的版本
return content
# 如果所有尝试都失败
logging.warning(f"未能找到Demand文件: '{demand_name}',尝试过以下位置: 缓存, {self.prompts_dir}/Demand/")
return None
def _get_refer_content(self, refer_dir):
"""从Refer目录加载JSON和文本参考文件
Args:
refer_dir: Refer目录路径
Returns:
dict: 文件名到内容的映射
"""
results = {}
if not os.path.isdir(refer_dir):
return results
# 列出所有文件
refer_files = [f for f in os.listdir(refer_dir) if os.path.isfile(os.path.join(refer_dir, f))]
for refer_file in refer_files:
refer_path = os.path.join(refer_dir, refer_file)
content = None
# 对JSON文件特殊处理
if refer_file.lower().endswith('.json'):
try:
with open(refer_path, 'r', encoding='utf-8') as f:
content = f.read()
# 移除可能的BOM头
if content.startswith('\ufeff'):
content = content[1:]
# 验证是否为有效的JSON
try:
json.loads(content) # 只验证,不存储结果
logging.info(f"成功验证JSON文件: {refer_file}")
except json.JSONDecodeError as e:
logging.warning(f"文件{refer_file}内容不是有效的JSON: {str(e)}")
except Exception as e:
logging.error(f"读取JSON文件{refer_file}时出错: {str(e)}")
content = None
else:
# 使用ResourceLoader加载非JSON文件
content = ResourceLoader.load_file_content(refer_path)
if content:
results[refer_file] = content
return results
def _load_and_parse_json(self, file_path):
"""安全地加载和解析JSON文件
Args:
file_path: JSON文件路径
Returns:
dict or None: 解析后的JSON对象解析失败则返回None
"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 移除可能的BOM头
if content.startswith('\ufeff'):
content = content[1:]
return json.loads(content)
except Exception as e:
logging.error(f"加载和解析JSON文件{file_path}时出错: {str(e)}")
return None
def _get_all_refer_contents(self, random_sample=True):
"""获取所有Refer文件内容可选择随机抽样文件内容
Args:
random_sample: 是否对文件内容进行随机抽样默认为True
Returns:
str: 组合后的refer内容
"""
import json
# 初始化结果字符串
refer_content_all = ""
# 如果缓存为空,尝试加载文件
if not self._refer_cache and self.prompts_dir:
refer_dir = os.path.join(self.prompts_dir, "Refer")
if os.path.isdir(refer_dir):
refer_files = [f for f in os.listdir(refer_dir) if os.path.isfile(os.path.join(refer_dir, f))]
for refer_file in refer_files:
file_path = os.path.join(refer_dir, refer_file)
# 对JSON文件特殊处理
if refer_file.lower().endswith('.json'):
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 移除可能的BOM头
if content.startswith('\ufeff'):
content = content[1:]
# 解析并存储JSON对象
json_data = json.loads(content)
self._refer_cache[refer_file] = json_data
logging.info(f"加载并解析JSON参考文件: {refer_file}")
except Exception as e:
logging.error(f"加载JSON文件{refer_file}失败: {str(e)}")
# 失败时尝试以普通文本加载
content = ResourceLoader.load_file_content(file_path)
if content:
self._refer_cache[refer_file] = content
else:
# 非JSON文件使用普通加载方式
content = ResourceLoader.load_file_content(file_path)
if content:
self._refer_cache[refer_file] = content
if not self._refer_cache:
logging.warning("没有找到任何Refer文件")
return refer_content_all
logging.info(f"找到{len(self._refer_cache)}个Refer文件")
# 处理所有文件
for filename, content in self._refer_cache.items():
# 添加文件头部信息
refer_content_all += f"--- Refer File: {filename} ---\n"
# 检查内容类型
if isinstance(content, dict) and 'title' in content and 'examples' in content:
# 已解析的JSON对象
title = content.get("title", "未命名参考资料")
description = content.get("description", "")
examples = content.get("examples", [])
refer_content_all += f"标题: {title}\n"
refer_content_all += f"描述: {description}\n\n"
if examples:
# 处理examples数组
if random_sample and len(examples) > 10:
# 对examples进行随机抽样
sample_size = max(10, int(len(examples) * self._sample_rate))
sampled_examples = random.sample(examples, sample_size)
logging.info(f"从文件{filename}的JSON中随机抽样了{sample_size}/{len(examples)}个示例")
refer_content_all += "示例:\n"
for idx, example in enumerate(sampled_examples, 1):
content_text = example.get("content", "")
refer_content_all += f"{idx}. {content_text}\n"
else:
# 不进行抽样或examples数量较少使用全部
refer_content_all += "示例:\n"
for idx, example in enumerate(examples, 1):
content_text = example.get("content", "")
refer_content_all += f"{idx}. {content_text}\n"
elif isinstance(content, str):
# 文本内容
if random_sample:
lines = content.split('\n')
if len(lines) > 10: # 只对较长的内容进行抽样
sample_size = max(10, int(len(lines) * self._sample_rate))
sampled_lines = random.sample(lines, sample_size)
# 保持原有顺序
sampled_lines.sort(key=lambda line: lines.index(line))
sampled_content = '\n'.join(sampled_lines)
logging.info(f"从文件{filename}中随机抽样了{sample_size}/{len(lines)}行内容")
refer_content_all += f"{sampled_content}\n"
else:
# 内容较短,不进行抽样
refer_content_all += f"{content}\n"
else:
# 不进行抽样
refer_content_all += f"{content}\n"
else:
# 内容是其他类型
refer_content_all += f"未知内容类型: {type(content)}\n"
# 添加文件之间的分隔
refer_content_all += "\n"
return refer_content_all
def get_topic_prompts(self):
"""Constructs the system and user prompts for topic generation."""
logging.info("Constructing prompts for topic generation...")
try:
# --- System Prompt ---
system_prompt = self._system_prompt_cache.get("topic")
if not system_prompt:
if not self.topic_system_prompt_path:
logging.error("Topic system prompt path not provided during PromptManager initialization.")
return None, None
system_prompt = ResourceLoader.load_file_content(self.topic_system_prompt_path)
if system_prompt:
self._system_prompt_cache["topic"] = system_prompt
else:
logging.error(f"Failed to load topic system prompt from '{self.topic_system_prompt_path}'.")
return None, None
# --- User Prompt ---
base_user_prompt = self._user_prompt_cache.get("topic")
if not base_user_prompt:
if not self.topic_user_prompt_path:
logging.error("Topic user prompt path not provided during PromptManager initialization.")
return None, None
base_user_prompt = ResourceLoader.load_file_content(self.topic_user_prompt_path)
if base_user_prompt:
self._user_prompt_cache["topic"] = base_user_prompt
else:
logging.error(f"Failed to load base topic user prompt from '{self.topic_user_prompt_path}'.")
return None, None
# --- Build the dynamic part of the user prompt ---
user_prompt_dynamic = "你拥有的创作资料如下:\n"
# 添加prompts_config配置的文件信息
if self.prompts_config:
for config_item in self.prompts_config:
prompt_type = config_item.get("type", "").lower()
file_paths = config_item.get("file_path", [])
if file_paths:
user_prompt_dynamic += f"{prompt_type.capitalize()}文件列表:\n"
for path in file_paths:
filename = os.path.basename(path)
user_prompt_dynamic += f"- {filename}\n"
user_prompt_dynamic += "\n"
# 兼容旧配置Add genPrompts directory structure
elif self.prompts_dir and os.path.isdir(self.prompts_dir):
try:
gen_prompts_list = os.listdir(self.prompts_dir)
for gen_prompt_folder in gen_prompts_list:
folder_path = os.path.join(self.prompts_dir, gen_prompt_folder)
if os.path.isdir(folder_path):
try:
# List files, filter out subdirs if needed
gen_prompts_files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
user_prompt_dynamic += f"{gen_prompt_folder}\n{gen_prompts_files}\n"
except OSError as e:
logging.warning(f"Could not list directory {folder_path}: {e}")
except OSError as e:
logging.warning(f"Could not list base prompts directory {self.prompts_dir}: {e}")
else:
logging.warning(f"Neither prompts_config nor prompts_dir provided or valid.")
# Add resource directory contents
for dir_info in self.resource_dir_config:
source_type = dir_info.get("type", "UnknownType")
source_file_paths = dir_info.get("file_path", [])
for file_path in source_file_paths:
# Use ResourceLoader's static method
file_content = ResourceLoader.load_file_content(file_path)
if file_content:
user_prompt_dynamic += f"{source_type}信息:\n{os.path.basename(file_path)}\n{file_content}\n\n"
else:
logging.warning(f"Could not load resource file {file_path}")
# Add dateline information (optional)
if self._dateline_cache:
user_prompt_dynamic += f"\n{self._dateline_cache}"
else:
user_prompt_dir = os.path.dirname(self.topic_user_prompt_path)
dateline_path = os.path.join(user_prompt_dir, "2025各月节日宣传节点时间表.md") # Consider making this configurable
if os.path.exists(dateline_path):
dateline_content = ResourceLoader.load_file_content(dateline_path)
if dateline_content:
self._dateline_cache = dateline_content
user_prompt_dynamic += f"\n{dateline_content}"
# Combine dynamic part, base template, and final parameters
user_prompt = user_prompt_dynamic + base_user_prompt
user_prompt += f"\n选题数量:{self.topic_gen_num}\n选题日期:{self.topic_gen_date}\n"
logging.info(f"Topic prompts constructed. System: {len(system_prompt)} chars, User: {len(user_prompt)} chars.")
return system_prompt, user_prompt
except Exception as e:
logging.exception("Error constructing topic prompts:")
return None, None
def get_content_prompts(self, topic_item):
"""Constructs the system and user prompts for content generation."""
logging.info("Constructing prompts for content generation...")
try:
# --- System Prompt ---
system_prompt = self._system_prompt_cache.get("content")
if not system_prompt:
if not self.content_system_prompt_path:
logging.error("Content system prompt path not provided.")
return None, None
system_prompt = ResourceLoader.load_file_content(self.content_system_prompt_path)
if system_prompt:
self._system_prompt_cache["content"] = system_prompt
else:
logging.error(f"Failed to load content system prompt from '{self.content_system_prompt_path}'.")
return None, None
# --- User Prompt ---
style = ""
demand = ""
refers = ""
object_info = ""
# Extract style from topic
if "style" in topic_item and topic_item["style"]:
style_name = topic_item["style"]
style_content = self._get_style_content(style_name)
if style_content:
style = f"Style: {style_name}\n{style_content}\n\n"
else:
logging.warning(f"Style content for '{style_name}' not found.")
# Extract demand from topic
if "target_audience" in topic_item and topic_item["target_audience"]:
demand_name = topic_item["target_audience"]
demand_content = self._get_demand_content(demand_name)
if demand_content:
demand = f"Demand: {demand_name}\n{demand_content}\n\n"
else:
logging.warning(f"Demand content for '{demand_name}' not found.")
# Add refer contents - 现在使用随机抽样
refers_content = self._get_all_refer_contents(random_sample=True)
if refers_content:
refers = f"Reference:\n{refers_content}\n\n"
# Get object information
object_name = topic_item.get("object", "")
if object_name:
# 优化遍历resource_dir_config查找对象描述
found_object_info = False
# 1. 搜集所有可能的资源文件
all_description_files = []
for dir_info in self.resource_dir_config:
if dir_info.get("type") in ["Object", "Description"]:
all_description_files.extend(dir_info.get("file_path", []))
# 2. 尝试精确匹配
for file_path in all_description_files:
if object_name in os.path.basename(file_path):
info = ResourceLoader.load_file_content(file_path)
if info:
object_info = f"Object: {object_name}\n{info}\n\n"
logging.info(f"找到对象'{object_name}'的精确匹配资源文件: {file_path}")
found_object_info = True
break
# 3. 如果精确匹配失败,尝试模糊匹配
if not found_object_info and all_description_files:
logging.info(f"尝试模糊匹配对象'{object_name}'的资源文件")
# 提取所有文件名
file_names = [os.path.basename(f) for f in all_description_files]
# 模糊匹配
matched_filename, score = self.find_directory_fuzzy_match(object_name, files=file_names)
if matched_filename and score > 0:
# 找到匹配的完整路径
for file_path in all_description_files:
if os.path.basename(file_path) == matched_filename:
info = ResourceLoader.load_file_content(file_path)
if info:
object_info = f"Object: {object_name}\n{info}\n\n"
logging.info(f"模糊匹配找到对象'{object_name}'的资源文件: {file_path},匹配分数: {score}")
found_object_info = True
break
if not found_object_info:
logging.warning(f"未找到对象'{object_name}'的任何匹配资源文件")
# Get product information if any
product_name = topic_item.get("product", "")
if product_name:
product_info = ""
# 优化遍历resource_dir_config查找产品描述
found_product_info = False
# 搜集所有可能的产品资源文件
all_product_files = []
for dir_info in self.resource_dir_config:
if dir_info.get("type") == "Product":
all_product_files.extend(dir_info.get("file_path", []))
# 尝试精确匹配
for file_path in all_product_files:
if product_name in os.path.basename(file_path):
info = ResourceLoader.load_file_content(file_path)
if info:
product_info = f"Product: {product_name}\n{info}\n\n"
logging.info(f"找到产品'{product_name}'的精确匹配资源文件: {file_path}")
found_product_info = True
break
# 如果精确匹配失败,尝试模糊匹配
if not found_product_info and all_product_files:
logging.info(f"尝试模糊匹配产品'{product_name}'的资源文件")
# 提取所有文件名
file_names = [os.path.basename(f) for f in all_product_files]
# 模糊匹配
matched_filename, score = self.find_directory_fuzzy_match(product_name, files=file_names)
if matched_filename and score > 0:
# 找到匹配的完整路径
for file_path in all_product_files:
if os.path.basename(file_path) == matched_filename:
info = ResourceLoader.load_file_content(file_path)
if info:
product_info = f"Product: {product_name}\n{info}\n\n"
logging.info(f"模糊匹配找到产品'{product_name}'的资源文件: {file_path},匹配分数: {score}")
found_product_info = True
break
if not found_product_info:
logging.warning(f"未找到产品'{product_name}'的任何匹配资源文件")
# 添加产品信息到对象信息中
if product_info:
object_info += product_info
# Construct final user prompt
user_prompt = f"""请为我创建一个旅游文案。
{style}{demand}{refers}{object_info}
请考虑以上所有信息创作一篇{topic_item.get('target_audience','')}文旅内容"""
return system_prompt, user_prompt
except Exception as e:
traceback.print_exc()
logging.error(f"Error creating content prompts: {str(e)}")
return None, None