hot_video_analyse/base_line/prompt_manager.py

771 lines
37 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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