优化了提示词选题逻辑
This commit is contained in:
parent
0c9e7f90ae
commit
52492d0c6d
22
main.py
22
main.py
@ -13,6 +13,7 @@ import core.posterGen as posterGen
|
|||||||
import core.simple_collage as simple_collage
|
import core.simple_collage as simple_collage
|
||||||
from utils.resource_loader import ResourceLoader
|
from utils.resource_loader import ResourceLoader
|
||||||
from utils.tweet_generator import generate_single_content, run_topic_generation_pipeline # Import the new pipeline function
|
from utils.tweet_generator import generate_single_content, run_topic_generation_pipeline # Import the new pipeline function
|
||||||
|
from utils.prompt_manager import PromptManager # Import PromptManager
|
||||||
import random
|
import random
|
||||||
|
|
||||||
TEXT_POSBILITY = 0.3 # Consider moving this to config if it varies
|
TEXT_POSBILITY = 0.3 # Consider moving this to config if it varies
|
||||||
@ -56,6 +57,14 @@ def generate_content_and_posters_step(config, run_id, tweet_topic_record):
|
|||||||
output_dir = os.path.join(base_output_dir, run_id) # Directory for this specific run
|
output_dir = os.path.join(base_output_dir, run_id) # Directory for this specific run
|
||||||
|
|
||||||
# --- Pre-load resources and initialize shared objects ---
|
# --- Pre-load resources and initialize shared objects ---
|
||||||
|
# Initialize PromptManager once for this phase
|
||||||
|
try:
|
||||||
|
prompt_manager = PromptManager(config)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error initializing PromptManager: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return
|
||||||
|
|
||||||
# Load content generation system prompt once
|
# Load content generation system prompt once
|
||||||
content_system_prompt = ResourceLoader.load_system_prompt(config["content_system_prompt"])
|
content_system_prompt = ResourceLoader.load_system_prompt(config["content_system_prompt"])
|
||||||
if not content_system_prompt:
|
if not content_system_prompt:
|
||||||
@ -95,12 +104,19 @@ def generate_content_and_posters_step(config, run_id, tweet_topic_record):
|
|||||||
for j in range(config["variants"]):
|
for j in range(config["variants"]):
|
||||||
variant_index = j + 1
|
variant_index = j + 1
|
||||||
print(f" Generating Variant {variant_index}/{config['variants']}...")
|
print(f" Generating Variant {variant_index}/{config['variants']}...")
|
||||||
|
|
||||||
|
# Get prompts for this specific topic item using PromptManager
|
||||||
|
content_system_prompt, content_user_prompt = prompt_manager.get_content_prompts(topic)
|
||||||
|
|
||||||
|
if not content_system_prompt or not content_user_prompt:
|
||||||
|
print(f" Skipping Variant {variant_index} due to missing content prompts.")
|
||||||
|
continue # Skip this variant if prompts failed
|
||||||
|
|
||||||
time.sleep(random.random() * 0.5) # Slightly reduced delay
|
time.sleep(random.random() * 0.5) # Slightly reduced delay
|
||||||
try:
|
try:
|
||||||
# Use the pre-initialized AI Agent
|
# Use the pre-initialized AI Agent and pass the specific prompts
|
||||||
tweet_content, gen_result = generate_single_content(
|
tweet_content, gen_result = generate_single_content(
|
||||||
ai_agent, content_system_prompt, topic,
|
ai_agent, content_system_prompt, content_user_prompt, topic,
|
||||||
config["prompts_dir"], config["resource_dir"],
|
|
||||||
output_dir, run_id, topic_index, variant_index, config.get("content_temperature", 0.3)
|
output_dir, run_id, topic_index, variant_index, config.get("content_temperature", 0.3)
|
||||||
)
|
)
|
||||||
if tweet_content:
|
if tweet_content:
|
||||||
|
|||||||
249
utils/prompt_manager.py
Normal file
249
utils/prompt_manager.py
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Manages the construction of prompts for different AI generation tasks.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import traceback
|
||||||
|
from .resource_loader import ResourceLoader # Use relative import within the same package
|
||||||
|
|
||||||
|
class PromptManager:
|
||||||
|
"""Handles the loading and construction of prompts."""
|
||||||
|
|
||||||
|
def __init__(self, config):
|
||||||
|
"""Initializes the PromptManager with the global configuration."""
|
||||||
|
self.config = config
|
||||||
|
# Instantiate ResourceLoader once, assuming it's mostly static methods or stateless
|
||||||
|
self.resource_loader = ResourceLoader()
|
||||||
|
|
||||||
|
def get_topic_prompts(self):
|
||||||
|
"""Constructs the system and user prompts for topic generation."""
|
||||||
|
print("Constructing prompts for topic generation...")
|
||||||
|
try:
|
||||||
|
# --- System Prompt ---
|
||||||
|
system_prompt_path = self.config.get("topic_system_prompt")
|
||||||
|
if not system_prompt_path:
|
||||||
|
print("Error: topic_system_prompt path not specified in config.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
# Use ResourceLoader's static method directly
|
||||||
|
system_prompt = ResourceLoader.load_file_content(system_prompt_path)
|
||||||
|
if not system_prompt:
|
||||||
|
print(f"Error: Failed to load topic system prompt from '{system_prompt_path}'.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
# --- User Prompt ---
|
||||||
|
user_prompt_path = self.config.get("topic_user_prompt")
|
||||||
|
if not user_prompt_path:
|
||||||
|
print("Error: topic_user_prompt path not specified in config.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
base_user_prompt = ResourceLoader.load_file_content(user_prompt_path)
|
||||||
|
if base_user_prompt is None: # Check for None explicitly
|
||||||
|
print(f"Error: Failed to load base topic user prompt from '{user_prompt_path}'.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
# --- Build the dynamic part of the user prompt (Logic moved from prepare_topic_generation) ---
|
||||||
|
user_prompt_dynamic = "你拥有的创作资料如下:\n"
|
||||||
|
|
||||||
|
# Add genPrompts directory structure
|
||||||
|
gen_prompts_path = self.config.get("prompts_dir")
|
||||||
|
if gen_prompts_path and os.path.isdir(gen_prompts_path):
|
||||||
|
try:
|
||||||
|
gen_prompts_list = os.listdir(gen_prompts_path)
|
||||||
|
for gen_prompt_folder in gen_prompts_list:
|
||||||
|
folder_path = os.path.join(gen_prompts_path, 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:
|
||||||
|
print(f"Warning: Could not list directory {folder_path}: {e}")
|
||||||
|
except OSError as e:
|
||||||
|
print(f"Warning: Could not list base prompts directory {gen_prompts_path}: {e}")
|
||||||
|
else:
|
||||||
|
print(f"Warning: Prompts directory '{gen_prompts_path}' not found or invalid.")
|
||||||
|
|
||||||
|
# Add resource directory contents
|
||||||
|
resource_dir_config = self.config.get("resource_dir", [])
|
||||||
|
for dir_info in 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:
|
||||||
|
print(f"Warning: Could not load resource file {file_path}")
|
||||||
|
|
||||||
|
# Add dateline information (optional)
|
||||||
|
user_prompt_dir = os.path.dirname(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:
|
||||||
|
user_prompt_dynamic += f"\n{dateline_content}"
|
||||||
|
|
||||||
|
# Combine dynamic part, base template, and final parameters
|
||||||
|
user_prompt = user_prompt_dynamic + base_user_prompt
|
||||||
|
|
||||||
|
select_num = self.config.get("num", 1) # Default to 1 if not specified
|
||||||
|
select_date = self.config.get("date", "")
|
||||||
|
user_prompt += f"\n选题数量:{select_num}\n选题日期:{select_date}\n"
|
||||||
|
# --- End of moved logic ---
|
||||||
|
|
||||||
|
print(f"Topic prompts constructed. System: {len(system_prompt)} chars, User: {len(user_prompt)} chars.")
|
||||||
|
return system_prompt, user_prompt
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error constructing topic prompts: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
def get_content_prompts(self, topic_item):
|
||||||
|
"""Constructs the system and user prompts for content generation based on a topic item."""
|
||||||
|
print(f"Constructing content prompts for topic: {topic_item.get('object', 'N/A')}...")
|
||||||
|
try:
|
||||||
|
# --- System Prompt ---
|
||||||
|
system_prompt_path = self.config.get("content_system_prompt")
|
||||||
|
if not system_prompt_path:
|
||||||
|
print("Error: content_system_prompt path not specified in config.")
|
||||||
|
return None, None
|
||||||
|
# Use ResourceLoader's static method. load_system_prompt was just load_file_content.
|
||||||
|
system_prompt = ResourceLoader.load_file_content(system_prompt_path)
|
||||||
|
if not system_prompt:
|
||||||
|
print(f"Error: Failed to load content system prompt from '{system_prompt_path}'.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
# --- User Prompt (Logic moved from ResourceLoader.build_user_prompt) ---
|
||||||
|
user_prompt = ""
|
||||||
|
prompts_dir = self.config.get("prompts_dir")
|
||||||
|
resource_dir_config = self.config.get("resource_dir", [])
|
||||||
|
|
||||||
|
if not prompts_dir or not os.path.isdir(prompts_dir):
|
||||||
|
print(f"Warning: Prompts directory '{prompts_dir}' not found or invalid. Content user prompt might be incomplete.")
|
||||||
|
# Decide whether to return error or continue with potentially incomplete prompt
|
||||||
|
|
||||||
|
# 1. 添加Demand部分 (based on topic_item['logic'])
|
||||||
|
try:
|
||||||
|
logic_file = f"{topic_item['logic']}.txt"
|
||||||
|
demand_path = os.path.join(prompts_dir, "Demand", logic_file)
|
||||||
|
demand_content = ResourceLoader.load_file_content(demand_path)
|
||||||
|
if demand_content:
|
||||||
|
user_prompt += f"Demand:\n{demand_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Demand file not found or empty: {demand_path}")
|
||||||
|
except KeyError:
|
||||||
|
print("Warning: 'logic' key missing in topic_item for Demand prompt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing Demand prompt: {e}")
|
||||||
|
|
||||||
|
# 2. 添加Object信息 (based on topic_item['object'])
|
||||||
|
try:
|
||||||
|
object_name_base = topic_item['object'] # This might be '景点信息-XXX.txt'
|
||||||
|
object_file_path = None
|
||||||
|
# Find the full path for the object file from config
|
||||||
|
for dir_info in resource_dir_config:
|
||||||
|
if dir_info.get("type") == "Object":
|
||||||
|
for file_path in dir_info.get("file_path", []):
|
||||||
|
# Match basename, assuming topic_item['object'] is the basename
|
||||||
|
if os.path.basename(file_path) == object_name_base:
|
||||||
|
object_file_path = file_path
|
||||||
|
break
|
||||||
|
if object_file_path: break
|
||||||
|
|
||||||
|
if object_file_path:
|
||||||
|
object_content = ResourceLoader.load_file_content(object_file_path)
|
||||||
|
if object_content:
|
||||||
|
user_prompt += f"Object信息:\n{object_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Object file could not be loaded: {object_file_path}")
|
||||||
|
else:
|
||||||
|
# If basename match fails, maybe topic_item['object'] is just 'XXX'?
|
||||||
|
# Try finding based on substring? This might be ambiguous.
|
||||||
|
print(f"Warning: Object file path not found in config matching basename: {object_name_base}")
|
||||||
|
except KeyError:
|
||||||
|
print("Warning: 'object' key missing in topic_item for Object prompt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing Object prompt: {e}")
|
||||||
|
|
||||||
|
# 3. 添加Product信息 (if applicable, based on topic_item['product'] and ['product_logic'])
|
||||||
|
try:
|
||||||
|
product_name = topic_item.get('product')
|
||||||
|
product_logic = topic_item.get('product_logic')
|
||||||
|
if product_name and product_logic:
|
||||||
|
product_logic_file = f"{product_logic}.txt"
|
||||||
|
product_logic_path = os.path.join(prompts_dir, "Demand", product_logic_file) # Assuming product logic is also in Demand?
|
||||||
|
product_logic_content = ResourceLoader.load_file_content(product_logic_path)
|
||||||
|
if product_logic_content:
|
||||||
|
user_prompt += f"Produce Demand:\n{product_logic_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Product Demand file not found or empty: {product_logic_path}")
|
||||||
|
|
||||||
|
product_file_path = None
|
||||||
|
for dir_info in resource_dir_config:
|
||||||
|
if dir_info.get("type") == "Product":
|
||||||
|
for file_path in dir_info.get("file_path", []):
|
||||||
|
# Match basename
|
||||||
|
if os.path.basename(file_path) == product_name:
|
||||||
|
product_file_path = file_path
|
||||||
|
break
|
||||||
|
if product_file_path: break
|
||||||
|
|
||||||
|
if product_file_path:
|
||||||
|
product_content = ResourceLoader.load_file_content(product_file_path)
|
||||||
|
if product_content:
|
||||||
|
user_prompt += f"Product信息:\n{product_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Product file could not be loaded: {product_file_path}")
|
||||||
|
else:
|
||||||
|
print(f"Warning: Product file path not found in config for: {product_name}")
|
||||||
|
except KeyError as e:
|
||||||
|
print(f"Warning: Missing 'product' or 'product_logic' key in topic_item for Product prompt: {e}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing Product prompt: {e}")
|
||||||
|
|
||||||
|
# 4. 添加Style信息 (based on topic_item['style'])
|
||||||
|
try:
|
||||||
|
style_file = f"{topic_item['style']}.txt"
|
||||||
|
style_path = os.path.join(prompts_dir, "Style", style_file)
|
||||||
|
style_content = ResourceLoader.load_file_content(style_path)
|
||||||
|
if style_content:
|
||||||
|
user_prompt += f"Style:\n{style_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Style file not found or empty: {style_path}")
|
||||||
|
except KeyError:
|
||||||
|
print("Warning: 'style' key missing in topic_item for Style prompt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing Style prompt: {e}")
|
||||||
|
|
||||||
|
# 5. 添加Refer信息 (based on topic_item['style_logic'])
|
||||||
|
try:
|
||||||
|
refer_file = f"{topic_item['style_logic']}.txt"
|
||||||
|
refer_path = os.path.join(prompts_dir, "Refer", refer_file)
|
||||||
|
refer_content = ResourceLoader.load_file_content(refer_path)
|
||||||
|
if refer_content:
|
||||||
|
user_prompt += f"Refer:\n{refer_content}\n"
|
||||||
|
else:
|
||||||
|
print(f"Warning: Refer file not found or empty: {refer_path}")
|
||||||
|
except KeyError:
|
||||||
|
print("Warning: 'style_logic' key missing in topic_item for Refer prompt.")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error processing Refer prompt: {e}")
|
||||||
|
|
||||||
|
# --- End of moved logic ---
|
||||||
|
|
||||||
|
print(f"Content prompts constructed. System: {len(system_prompt)} chars, User: {len(user_prompt)} chars.")
|
||||||
|
return system_prompt, user_prompt
|
||||||
|
|
||||||
|
except KeyError as e:
|
||||||
|
# Catch potential KeyErrors from accessing topic_item if a required key is missing early on
|
||||||
|
print(f"Error constructing content prompts: Missing essential key '{e}' in topic_item: {topic_item}")
|
||||||
|
return None, None
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error constructing content prompts: {e}")
|
||||||
|
traceback.print_exc()
|
||||||
|
return None, None
|
||||||
@ -14,25 +14,33 @@ class ResourceLoader:
|
|||||||
return content
|
return content
|
||||||
else:
|
else:
|
||||||
print(f"文件不存在: {file_path}")
|
print(f"文件不存在: {file_path}")
|
||||||
return ""
|
# Return None for non-existent file to distinguish from empty file
|
||||||
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"加载文件内容失败: {e}")
|
print(f"加载文件 '{file_path}' 内容失败: {e}")
|
||||||
return ""
|
# Return None on error as well
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_all_refer_files(refer_dir, refer_content_length=50):
|
def load_all_refer_files(refer_dir, refer_content_length=50):
|
||||||
"""加载Refer目录下的所有文件内容"""
|
"""加载Refer目录下的所有文件内容"""
|
||||||
refer_content = ""
|
refer_content = ""
|
||||||
|
if not refer_dir or not os.path.isdir(refer_dir):
|
||||||
|
print(f"Warning: Refer directory '{refer_dir}' not found or invalid.")
|
||||||
|
return ""
|
||||||
try:
|
try:
|
||||||
if os.path.exists(refer_dir):
|
|
||||||
files = os.listdir(refer_dir)
|
files = os.listdir(refer_dir)
|
||||||
for file in files:
|
for file in files:
|
||||||
file_path = os.path.join(refer_dir, file)
|
file_path = os.path.join(refer_dir, file)
|
||||||
if os.path.isfile(file_path):
|
if os.path.isfile(file_path):
|
||||||
|
# Use the updated load_file_content
|
||||||
content = ResourceLoader.load_file_content(file_path)
|
content = ResourceLoader.load_file_content(file_path)
|
||||||
|
if content: # Check if content was loaded successfully
|
||||||
# 用\n分割content,取前length条
|
# 用\n分割content,取前length条
|
||||||
content_lines = content.split("\n")
|
content_lines = content.split("\n")
|
||||||
content_lines = random.sample(content_lines, refer_content_length)
|
# Ensure refer_content_length doesn't exceed available lines
|
||||||
|
sample_size = min(refer_content_length, len(content_lines))
|
||||||
|
content_lines = random.sample(content_lines, sample_size)
|
||||||
content = "\n".join(content_lines)
|
content = "\n".join(content_lines)
|
||||||
refer_content += f"## {file}\n{content}\n\n"
|
refer_content += f"## {file}\n{content}\n\n"
|
||||||
return refer_content
|
return refer_content
|
||||||
@ -43,6 +51,8 @@ class ResourceLoader:
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def find_file_by_name(directory, file_name, exact_match=True):
|
def find_file_by_name(directory, file_name, exact_match=True):
|
||||||
"""查找文件,支持精确匹配和模糊匹配"""
|
"""查找文件,支持精确匹配和模糊匹配"""
|
||||||
|
if not directory or not file_name:
|
||||||
|
return None
|
||||||
try:
|
try:
|
||||||
# 确保传入的文件名包含后缀
|
# 确保传入的文件名包含后缀
|
||||||
if not file_name.endswith(".txt"):
|
if not file_name.endswith(".txt"):
|
||||||
@ -50,122 +60,21 @@ class ResourceLoader:
|
|||||||
|
|
||||||
# 精确匹配
|
# 精确匹配
|
||||||
exact_path = os.path.join(directory, file_name)
|
exact_path = os.path.join(directory, file_name)
|
||||||
if os.path.exists(exact_path):
|
if os.path.exists(exact_path) and os.path.isfile(exact_path):
|
||||||
return exact_path
|
return exact_path
|
||||||
|
|
||||||
# 如果不需要精确匹配,尝试模糊匹配
|
# 如果不需要精确匹配,尝试模糊匹配
|
||||||
if not exact_match and os.path.exists(directory):
|
if not exact_match and os.path.isdir(directory):
|
||||||
file_name_base = file_name.replace(".txt", "")
|
file_name_base = file_name.replace(".txt", "")
|
||||||
for file in os.listdir(directory):
|
for file in os.listdir(directory):
|
||||||
if file_name_base in file:
|
if os.path.isfile(os.path.join(directory, file)) and file_name_base in file:
|
||||||
return os.path.join(directory, file)
|
return os.path.join(directory, file)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"查找文件失败: {e}")
|
print(f"查找文件 '{file_name}' 在 '{directory}' 失败: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def build_user_prompt(item, prompts_dir, resource_dir):
|
|
||||||
"""根据选题信息构建用户提示词"""
|
|
||||||
batch_prompt = f"选题日期:{item['date']}\n"
|
|
||||||
|
|
||||||
# 基础目录设置
|
|
||||||
style_dir = os.path.join(prompts_dir, "Style")
|
|
||||||
demand_dir = os.path.join(prompts_dir, "Demand")
|
|
||||||
refer_dir = os.path.join(prompts_dir, "Refer")
|
|
||||||
|
|
||||||
# 从resource_dir中获取Object和Product资源
|
|
||||||
object_resource = next((res for res in resource_dir if res["type"] == "Object"), None)
|
|
||||||
product_resource = next((res for res in resource_dir if res["type"] == "Product"), None)
|
|
||||||
|
|
||||||
# 添加所有标签内容到批处理提示中
|
|
||||||
if 'index' in item and item['index']:
|
|
||||||
batch_prompt += f"选题序号:{item['index']}\n"
|
|
||||||
if 'logic' in item and item['logic']:
|
|
||||||
batch_prompt += f"选定逻辑:{item['logic']}\n"
|
|
||||||
|
|
||||||
# 处理Object信息
|
|
||||||
if 'object' in item and item['object'] and object_resource:
|
|
||||||
batch_prompt += f"选定对象:{item['object']}\n"
|
|
||||||
# 查找包含对象名称的文件路径
|
|
||||||
object_file = None
|
|
||||||
for file_path in object_resource["file_path"]:
|
|
||||||
if item['object'] in file_path:
|
|
||||||
object_file = file_path
|
|
||||||
break
|
|
||||||
|
|
||||||
if object_file:
|
|
||||||
object_content = ResourceLoader.load_file_content(object_file)
|
|
||||||
batch_prompt += f"对象信息:\n{object_content}\n"
|
|
||||||
|
|
||||||
# 处理Product信息
|
|
||||||
if 'product' in item and item['product'] and product_resource:
|
|
||||||
batch_prompt += f"选定产品:{item['product']}\n"
|
|
||||||
# 尝试从产品名称中提取前缀
|
|
||||||
product_parts = item['product'].split("-")
|
|
||||||
product_prefix = product_parts[0] if product_parts and product_parts[0] else item['product']
|
|
||||||
|
|
||||||
# 查找包含产品前缀的文件路径
|
|
||||||
product_file = None
|
|
||||||
for file_path in product_resource["file_path"]:
|
|
||||||
if product_prefix in file_path:
|
|
||||||
product_file = file_path
|
|
||||||
break
|
|
||||||
|
|
||||||
if product_file:
|
|
||||||
product_content = ResourceLoader.load_file_content(product_file)
|
|
||||||
batch_prompt += f"产品信息:\n{product_content}\n"
|
|
||||||
|
|
||||||
# 处理Product Logic
|
|
||||||
if 'product_logic' in item and item['product_logic']:
|
|
||||||
batch_prompt += f"选定产品的逻辑:{item['product_logic']}\n"
|
|
||||||
|
|
||||||
# 处理Style信息
|
|
||||||
if 'style' in item and item['style']:
|
|
||||||
batch_prompt += f"选题风格:{item['style']}\n"
|
|
||||||
|
|
||||||
# 加载风格提示词
|
|
||||||
style_file = ResourceLoader.find_file_by_name(style_dir, item['style'], False)
|
|
||||||
if style_file:
|
|
||||||
style_content = ResourceLoader.load_file_content(style_file)
|
|
||||||
batch_prompt += f"风格提示词:\n{style_content}\n"
|
|
||||||
|
|
||||||
# 处理Style Logic
|
|
||||||
if 'style_logic' in item and item['style_logic']:
|
|
||||||
batch_prompt += f"选题风格的逻辑:{item['style_logic']}\n"
|
|
||||||
|
|
||||||
# 处理Target Audience
|
|
||||||
if 'target_audience' in item and item['target_audience']:
|
|
||||||
batch_prompt += f"目标受众:{item['target_audience']}\n"
|
|
||||||
# 尝试加载目标受众文件
|
|
||||||
audience_file = ResourceLoader.find_file_by_name(demand_dir, item['target_audience'], False)
|
|
||||||
if audience_file:
|
|
||||||
audience_content = ResourceLoader.load_file_content(audience_file)
|
|
||||||
batch_prompt += f"目标受众信息:\n{audience_content}\n"
|
|
||||||
|
|
||||||
# 处理Target Audience Logic
|
|
||||||
if 'target_audience_logic' in item and item['target_audience_logic']:
|
|
||||||
batch_prompt += f"目标受众逻辑:{item['target_audience_logic']}\n"
|
|
||||||
|
|
||||||
# 加载所有Refer文件
|
|
||||||
refer_content = ResourceLoader.load_all_refer_files(refer_dir)
|
|
||||||
if refer_content:
|
|
||||||
batch_prompt += f"\n参考资料:\n{refer_content}\n"
|
|
||||||
|
|
||||||
return batch_prompt
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def load_system_prompt(prompt_file):
|
|
||||||
"""加载系统提示词文件"""
|
|
||||||
try:
|
|
||||||
with open(prompt_file, 'r', encoding='utf-8') as f:
|
|
||||||
system_prompt = f.read()
|
|
||||||
return system_prompt
|
|
||||||
except Exception as e:
|
|
||||||
print(f"加载系统提示词文件失败: {e}")
|
|
||||||
return ""
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def create_summary_file(output_dir, run_id, topics_count):
|
def create_summary_file(output_dir, run_id, topics_count):
|
||||||
"""创建汇总文件并返回路径"""
|
"""创建汇总文件并返回路径"""
|
||||||
|
|||||||
@ -13,7 +13,9 @@ sys.path.append('/root/autodl-tmp')
|
|||||||
# 从本地模块导入
|
# 从本地模块导入
|
||||||
from TravelContentCreator.core.ai_agent import AI_Agent
|
from TravelContentCreator.core.ai_agent import AI_Agent
|
||||||
from TravelContentCreator.core.topic_parser import TopicParser
|
from TravelContentCreator.core.topic_parser import TopicParser
|
||||||
from TravelContentCreator.utils.resource_loader import ResourceLoader
|
# ResourceLoader is now used implicitly via PromptManager
|
||||||
|
# from TravelContentCreator.utils.resource_loader import ResourceLoader
|
||||||
|
from TravelContentCreator.utils.prompt_manager import PromptManager # Import PromptManager
|
||||||
|
|
||||||
class tweetTopic:
|
class tweetTopic:
|
||||||
def __init__(self, index, date, logic, object, product, product_logic, style, style_logic, target_audience, target_audience_logic):
|
def __init__(self, index, date, logic, object, product, product_logic, style, style_logic, target_audience, target_audience_logic):
|
||||||
@ -132,13 +134,19 @@ def generate_topics(ai_agent, system_prompt, user_prompt, output_dir, temperatur
|
|||||||
return run_id, tweet_topic_record
|
return run_id, tweet_topic_record
|
||||||
|
|
||||||
|
|
||||||
def generate_single_content(ai_agent, system_prompt, item, prompts_dir, resource_dir, output_dir, run_id,
|
def generate_single_content(ai_agent, system_prompt, user_prompt, item, output_dir, run_id,
|
||||||
article_index, variant_index, temperature=0.3, top_p=0.4, presence_penalty=1.5):
|
article_index, variant_index, temperature=0.3, top_p=0.4, presence_penalty=1.5):
|
||||||
"""生成单篇文章内容"""
|
"""生成单篇文章内容. Requires prompts to be passed in."""
|
||||||
try:
|
try:
|
||||||
# 构建提示词
|
# Prompts are now passed directly as arguments
|
||||||
user_prompt = ResourceLoader.build_user_prompt(item, prompts_dir, resource_dir)
|
# No longer build user_prompt here
|
||||||
print(f"完成提示词构建,长度为 {len(user_prompt)} 字符")
|
# user_prompt = ResourceLoader.build_user_prompt(item, prompts_dir, resource_dir)
|
||||||
|
|
||||||
|
if not system_prompt or not user_prompt:
|
||||||
|
print("Error: System or User prompt is empty. Cannot generate content.")
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
print(f"Using pre-constructed prompts. User prompt length: {len(user_prompt)}")
|
||||||
|
|
||||||
# 添加随机停顿,避免请求过于频繁
|
# 添加随机停顿,避免请求过于频繁
|
||||||
time.sleep(random.random() * 0.5 + 0.1)
|
time.sleep(random.random() * 0.5 + 0.1)
|
||||||
@ -190,8 +198,7 @@ def generate_content(ai_agent, system_prompt, topics, output_dir, run_id, prompt
|
|||||||
|
|
||||||
# 调用单篇文章生成函数
|
# 调用单篇文章生成函数
|
||||||
tweet_content, result = generate_single_content(
|
tweet_content, result = generate_single_content(
|
||||||
ai_agent, system_prompt, item, prompts_dir, resource_dir,
|
ai_agent, system_prompt, item, output_dir, run_id, i+1, j+1, temperature
|
||||||
output_dir, run_id, i+1, j+1, temperature
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if tweet_content:
|
if tweet_content:
|
||||||
@ -206,73 +213,53 @@ def generate_content(ai_agent, system_prompt, topics, output_dir, run_id, prompt
|
|||||||
|
|
||||||
|
|
||||||
def prepare_topic_generation(
|
def prepare_topic_generation(
|
||||||
select_date, select_num,
|
config # Pass the whole config dictionary now
|
||||||
system_prompt_path, user_prompt_path,
|
# select_date, select_num,
|
||||||
base_url="vllm", model_name="qwenQWQ", api_key="EMPTY",
|
# system_prompt_path, user_prompt_path,
|
||||||
gen_prompts_path="/root/autodl-tmp/TravelContentCreator/genPrompts",
|
# base_url="vllm", model_name="qwenQWQ", api_key="EMPTY",
|
||||||
resource_dir="/root/autodl-tmp/TravelContentCreator/resource",
|
# gen_prompts_path="/root/autodl-tmp/TravelContentCreator/genPrompts",
|
||||||
output_dir="/root/autodl-tmp/TravelContentCreator/result"
|
# resource_dir="/root/autodl-tmp/TravelContentCreator/resource",
|
||||||
|
# output_dir="/root/autodl-tmp/TravelContentCreator/result"
|
||||||
):
|
):
|
||||||
"""准备选题生成的环境和参数"""
|
"""准备选题生成的环境和参数. Returns agent and prompts."""
|
||||||
# 创建AI Agent
|
|
||||||
ai_agent = AI_Agent(base_url, model_name, api_key)
|
|
||||||
|
|
||||||
# 加载系统提示词
|
# Initialize PromptManager
|
||||||
with open(system_prompt_path, "r", encoding="utf-8") as f:
|
prompt_manager = PromptManager(config)
|
||||||
system_prompt = f.read()
|
|
||||||
|
|
||||||
# 构建用户提示词
|
# Get prompts using PromptManager
|
||||||
user_prompt = "你拥有的创作资料如下:\n"
|
system_prompt, user_prompt = prompt_manager.get_topic_prompts()
|
||||||
|
|
||||||
# 加载genPrompts目录下的文件
|
if not system_prompt or not user_prompt:
|
||||||
gen_prompts_list = os.listdir(gen_prompts_path)
|
print("Error: Failed to get topic generation prompts.")
|
||||||
for gen_prompt_folder in gen_prompts_list:
|
return None, None, None, None
|
||||||
folder_path = os.path.join(gen_prompts_path, gen_prompt_folder)
|
|
||||||
# 检查是否为目录
|
|
||||||
if os.path.isdir(folder_path):
|
|
||||||
gen_prompts = os.listdir(folder_path)
|
|
||||||
user_prompt += f"{gen_prompt_folder}\n{gen_prompts}\n"
|
|
||||||
|
|
||||||
# 加载source文档内的目标文件
|
# 创建AI Agent (still create agent here for the topic generation phase)
|
||||||
## 其实只会有Object和Product两个文件夹
|
try:
|
||||||
## 所以可以简化代码
|
print("Initializing AI Agent for topic generation...")
|
||||||
for dir in resource_dir:
|
ai_agent = AI_Agent(config["api_url"], config["model"], config["api_key"])
|
||||||
source_type = dir["type"]
|
except Exception as e:
|
||||||
# source_num = dir["num"]
|
print(f"Error initializing AI Agent for topic generation: {e}")
|
||||||
source_file_path = dir["file_path"]
|
traceback.print_exc()
|
||||||
for file in source_file_path:
|
return None, None, None, None
|
||||||
with open(file, "r", encoding="utf-8") as f:
|
|
||||||
user_prompt += f"{source_type}信息:\n{file.split('/')[-1]}\n{f.read()}\n\n"
|
|
||||||
|
|
||||||
# 加载日期信息
|
# Removed prompt loading/building logic, now handled by PromptManager
|
||||||
dateline_path = os.path.join(os.path.dirname(user_prompt_path), "2025各月节日宣传节点时间表.md")
|
|
||||||
if os.path.exists(dateline_path):
|
|
||||||
with open(dateline_path, "r", encoding="utf-8") as f:
|
|
||||||
dateline = f.read()
|
|
||||||
user_prompt += f"\n{dateline}"
|
|
||||||
|
|
||||||
# 加载用户提示词模板
|
# Return agent and the generated prompts
|
||||||
with open(user_prompt_path, "r", encoding="utf-8") as f:
|
return ai_agent, system_prompt, user_prompt, config["output_dir"]
|
||||||
user_prompt += f.read()
|
|
||||||
|
|
||||||
# 添加选题数量和日期
|
|
||||||
user_prompt += f"\n选题数量:{select_num}\n选题日期:{select_date}\n"
|
|
||||||
|
|
||||||
return ai_agent, system_prompt, user_prompt, output_dir
|
|
||||||
|
|
||||||
def run_topic_generation_pipeline(config):
|
def run_topic_generation_pipeline(config):
|
||||||
"""Runs the complete topic generation pipeline based on the configuration."""
|
"""Runs the complete topic generation pipeline based on the configuration."""
|
||||||
print("Step 1: Generating Topics...")
|
print("Step 1: Generating Topics...")
|
||||||
|
|
||||||
# Prepare necessary inputs and the AI agent for topic generation
|
# Prepare necessary inputs and the AI agent for topic generation
|
||||||
# Note: prepare_topic_generation already initializes an AI_Agent
|
ai_agent, system_prompt, user_prompt, base_output_dir = None, None, None, None
|
||||||
try:
|
try:
|
||||||
ai_agent, system_prompt, user_prompt, base_output_dir = prepare_topic_generation(
|
# Pass the config directly to prepare_topic_generation
|
||||||
config.get("date", datetime.now().strftime("%Y-%m-%d")), # Use current date if not specified
|
ai_agent, system_prompt, user_prompt, base_output_dir = prepare_topic_generation(config)
|
||||||
config["num"], config["topic_system_prompt"], config["topic_user_prompt"],
|
|
||||||
config["api_url"], config["model"], config["api_key"], config["prompts_dir"],
|
if not ai_agent or not system_prompt or not user_prompt:
|
||||||
config["resource_dir"], config["output_dir"]
|
raise ValueError("Failed to prepare topic generation (agent or prompts missing).")
|
||||||
)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error during topic generation preparation: {e}")
|
print(f"Error during topic generation preparation: {e}")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@ -356,8 +343,7 @@ def main():
|
|||||||
if True:
|
if True:
|
||||||
# 1. 首先生成选题
|
# 1. 首先生成选题
|
||||||
ai_agent, system_prompt, user_prompt, output_dir = prepare_topic_generation(
|
ai_agent, system_prompt, user_prompt, output_dir = prepare_topic_generation(
|
||||||
config_file["date"], config_file["num"], config_file["topic_system_prompt"], config_file["topic_user_prompt"],
|
config_file
|
||||||
config_file["api_url"], config_file["model"], config_file["api_key"], config_file["prompts_dir"], config_file["resource_dir"], config_file["output_dir"]
|
|
||||||
)
|
)
|
||||||
|
|
||||||
run_id, tweet_topic_record = generate_topics(
|
run_id, tweet_topic_record = generate_topics(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user