GH/utils/ai_copywriter.py
AI Developer 2ec2c0a1ab feat: 完整的数据提取与转换器项目
- 添加MDF文件导出功能
- 集成阿里云OCR大模型识别
- 添加百度智能云AI照片评分
- 集成DeepSeek大模型创意文案生成
- 完善文档和配置管理
- 使用uv进行现代化依赖管理
- 添加完整的.gitignore配置
2026-01-08 20:25:49 +08:00

438 lines
18 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
"""
AI文案生成服务集成
使用AI大模型为照片生成创意文案
支持多种文案风格和用途
支持DeepSeek和DashScope两种大模型
"""
import os
import json
import requests
from dotenv import load_dotenv
# 加载环境变量
load_dotenv()
class AICopywriter:
"""AI文案生成服务类"""
def __init__(self, provider='deepseek'):
"""初始化AI文案生成客户端"""
self.provider = provider
if provider == 'deepseek':
self.api_key = os.getenv('DEEPSEEK_API_KEY')
if not self.api_key:
raise Exception("DeepSeek API密钥未配置请在.env文件中设置DEEPSEEK_API_KEY")
self.base_url = "https://api.deepseek.com/v1/chat/completions"
elif provider == 'dashscope':
self.api_key = os.getenv('DASHSCOPE_API_KEY')
if not self.api_key:
raise Exception("DashScope API密钥未配置请在.env文件中设置DASHSCOPE_API_KEY")
else:
raise Exception(f"不支持的AI提供商: {provider}")
def generate_photo_caption(self, image_description, style='creative', length='medium'):
"""为照片生成文案"""
try:
if self.provider == 'deepseek':
return self._generate_with_deepseek(image_description, style, length)
elif self.provider == 'dashscope':
return self._generate_with_dashscope(image_description, style, length)
else:
raise Exception(f"不支持的AI提供商: {self.provider}")
except Exception as e:
raise Exception(f"AI文案生成失败: {str(e)}")
def _generate_with_deepseek(self, image_description, style, length):
"""使用DeepSeek生成文案"""
try:
prompt = self._build_prompt(image_description, style, length)
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
data = {
'model': 'deepseek-chat',
'messages': [
{
'role': 'system',
'content': '你是一个专业的创意文案创作助手,擅长为照片生成各种风格的创意文案。你具有丰富的文学素养和营销知识,能够根据照片内容创作出富有创意和感染力的文案。'
},
{
'role': 'user',
'content': prompt
}
],
'max_tokens': 500,
'temperature': 0.8,
'top_p': 0.9
}
response = requests.post(self.base_url, headers=headers, json=data)
result = response.json()
if 'choices' in result and len(result['choices']) > 0:
caption = result['choices'][0]['message']['content'].strip()
# 清理可能的格式标记
caption = caption.replace('"', '').replace('\n', ' ').strip()
return caption
else:
# 如果API调用失败使用备用文案生成
return self._generate_fallback_caption(image_description, style, length)
except Exception as e:
# API调用失败时使用备用方案
return self._generate_fallback_caption(image_description, style, length)
def _generate_with_dashscope(self, image_description, style, length):
"""使用DashScope生成文案"""
try:
url = "https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation"
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
# 根据风格和长度构建提示词
prompt = self._build_prompt(image_description, style, length)
data = {
'model': 'qwen-turbo',
'input': {
'messages': [
{
'role': 'system',
'content': '你是一个专业的文案创作助手,擅长为照片生成各种风格的创意文案。'
},
{
'role': 'user',
'content': prompt
}
]
},
'parameters': {
'max_tokens': 500,
'temperature': 0.8
}
}
response = requests.post(url, headers=headers, json=data)
result = response.json()
if 'output' in result and 'text' in result['output']:
return result['output']['text']
else:
# 如果API调用失败使用备用文案生成
return self._generate_fallback_caption(image_description, style, length)
except Exception as e:
# API调用失败时使用备用方案
return self._generate_fallback_caption(image_description, style, length)
def _build_prompt(self, image_description, style, length):
"""构建AI提示词"""
style_descriptions = {
'creative': '创意文艺风格,富有诗意和想象力',
'professional': '专业正式风格,简洁明了',
'social': '社交媒体风格,活泼有趣,适合朋友圈',
'marketing': '营销推广风格,吸引眼球,促进转化',
'simple': '简单描述风格,直接明了',
'emotional': '情感表达风格,温暖感人'
}
length_descriptions = {
'short': '10-20字简洁精炼',
'medium': '30-50字适中长度',
'long': '80-120字详细描述'
}
prompt = f"""
请为以下照片内容生成{style_descriptions.get(style, '创意')}的文案,要求{length_descriptions.get(length, '适中长度')}
照片内容描述:{image_description}
文案要求:
1. 符合{style}风格
2. 长度{length}
3. 有创意,吸引人
4. 适合社交媒体分享
请直接输出文案内容,不要添加其他说明。
"""
return prompt.strip()
def _generate_fallback_caption(self, image_description, style, length):
"""备用文案生成当AI服务不可用时"""
# 基于照片描述的简单文案生成
keywords = image_description.lower().split()
# 提取关键信息
objects = []
scenes = []
# 简单的关键词分类实际应用中可以使用更复杂的NLP处理
object_keywords = ['', '建筑', '天空', '', '', '动物', '', '食物', '', '']
scene_keywords = ['户外', '室内', '自然', '城市', '夜景', '日出', '日落', '海滩', '森林']
for word in keywords:
if any(obj in word for obj in object_keywords):
objects.append(word)
if any(scene in word for scene in scene_keywords):
scenes.append(word)
# 根据风格生成文案
if style == 'creative':
if scenes:
caption = f"{scenes[0]}的怀抱中,时光静静流淌"
elif objects:
caption = f"{objects[0]}的美丽瞬间,定格永恒"
else:
caption = "捕捉生活中的美好,让每一刻都值得珍藏"
elif style == 'social':
if objects:
caption = f"今天遇到的{objects[0]}太可爱了!分享给大家~"
else:
caption = "分享一张美照,希望大家喜欢!"
elif style == 'professional':
if scenes and objects:
caption = f"专业拍摄:{scenes[0]}场景中的{objects[0]}特写"
else:
caption = "专业摄影作品展示"
elif style == 'marketing':
if objects:
caption = f"惊艳!这个{objects[0]}你一定要看看!"
else:
caption = "不容错过的精彩瞬间,点击了解更多!"
else: # simple or emotional
if objects:
caption = f"美丽的{objects[0]}照片"
else:
caption = "一张值得分享的照片"
# 根据长度调整
if length == 'long' and len(caption) < 50:
caption += "。这张照片记录了珍贵的瞬间,展现了生活的美好,值得细细品味和珍藏。"
elif length == 'short' and len(caption) > 20:
# 简化长文案
caption = caption[:20] + "..."
return caption
def generate_multiple_captions(self, image_description, count=3, style='creative'):
"""生成多个文案选项"""
try:
if self.provider == 'deepseek':
return self._generate_multiple_with_deepseek(image_description, count, style)
elif self.provider == 'dashscope':
return self._generate_multiple_with_dashscope(image_description, count, style)
else:
raise Exception(f"不支持的AI提供商: {self.provider}")
except Exception as e:
raise Exception(f"生成多个文案失败: {str(e)}")
def _generate_multiple_with_deepseek(self, image_description, count=3, style='creative'):
"""使用DeepSeek生成多个文案选项"""
try:
captions = []
# 使用不同的提示词变体生成多个文案
prompt_variants = [
f"请为'{image_description}'照片创作一个{style}风格的文案,要求新颖独特",
f"基于照片内容'{image_description}',写一个{style}风格的创意文案",
f"为这张'{image_description}'的照片设计一个{style}风格的吸引人文案"
]
for i in range(min(count, len(prompt_variants))):
prompt = prompt_variants[i]
headers = {
'Authorization': f'Bearer {self.api_key}',
'Content-Type': 'application/json'
}
data = {
'model': 'deepseek-chat',
'messages': [
{
'role': 'system',
'content': '你是专业的创意文案专家,擅长为照片创作多种风格的文案。'
},
{
'role': 'user',
'content': prompt
}
],
'max_tokens': 200,
'temperature': 0.9, # 提高温度增加多样性
'top_p': 0.95
}
response = requests.post(self.base_url, headers=headers, json=data)
result = response.json()
if 'choices' in result and len(result['choices']) > 0:
caption = result['choices'][0]['message']['content'].strip()
caption = caption.replace('"', '').replace('\n', ' ').strip()
captions.append({
'option': i + 1,
'caption': caption,
'style': style,
'char_count': len(caption)
})
return captions
except Exception as e:
raise Exception(f"DeepSeek多文案生成失败: {str(e)}")
def _generate_multiple_with_dashscope(self, image_description, count=3, style='creative'):
"""使用DashScope生成多个文案选项"""
try:
captions = []
# 尝试使用不同的长度和微调风格
lengths = ['short', 'medium', 'long']
for i in range(min(count, len(lengths))):
caption = self.generate_photo_caption(image_description, style, lengths[i])
captions.append({
'option': i + 1,
'caption': caption,
'length': lengths[i],
'char_count': len(caption)
})
# 如果数量不足,使用不同风格补充
if len(captions) < count:
additional_styles = ['social', 'professional', 'emotional']
for i, add_style in enumerate(additional_styles):
if len(captions) >= count:
break
caption = self.generate_photo_caption(image_description, add_style, 'medium')
captions.append({
'option': len(captions) + 1,
'caption': caption,
'style': add_style,
'char_count': len(caption)
})
return captions
except Exception as e:
raise Exception(f"DashScope多文案生成失败: {str(e)}")
def analyze_photo_suitability(self, image_description):
"""分析照片适合的文案风格"""
try:
# 简单的风格适合性分析
keywords = image_description.lower()
suitability = {
'creative': 0,
'professional': 0,
'social': 0,
'marketing': 0,
'emotional': 0
}
# 关键词匹配实际应用中可以使用更复杂的NLP分析
creative_words = ['美丽', '艺术', '创意', '独特', '梦幻']
professional_words = ['专业', '商业', '产品', '展示', '特写']
social_words = ['朋友', '聚会', '日常', '分享', '生活']
marketing_words = ['促销', '优惠', '新品', '限时', '推荐']
emotional_words = ['情感', '感动', '回忆', '温暖', '幸福']
for word in creative_words:
if word in keywords:
suitability['creative'] += 1
for word in professional_words:
if word in keywords:
suitability['professional'] += 1
for word in social_words:
if word in keywords:
suitability['social'] += 1
for word in marketing_words:
if word in keywords:
suitability['marketing'] += 1
for word in emotional_words:
if word in keywords:
suitability['emotional'] += 1
# 排序并返回推荐
recommended = sorted(suitability.items(), key=lambda x: x[1], reverse=True)
return {
'suitability_scores': suitability,
'recommended_styles': [style for style, score in recommended if score > 0],
'most_suitable': recommended[0][0] if recommended[0][1] > 0 else 'creative'
}
except Exception as e:
raise Exception(f"照片适合性分析失败: {str(e)}")
def generate_photo_caption(image_description, style='creative', length='medium', provider='dashscope'):
"""为照片生成文案"""
try:
copywriter = AICopywriter(provider)
return copywriter.generate_photo_caption(image_description, style, length)
except Exception as e:
raise Exception(f"照片文案生成失败: {str(e)}")
def generate_multiple_captions(image_description, count=3, style='creative', provider='dashscope'):
"""生成多个文案选项"""
try:
copywriter = AICopywriter(provider)
return copywriter.generate_multiple_captions(image_description, count, style)
except Exception as e:
raise Exception(f"多文案生成失败: {str(e)}")
def analyze_photo_suitability(image_description, provider='dashscope'):
"""分析照片适合的文案风格"""
try:
copywriter = AICopywriter(provider)
return copywriter.analyze_photo_suitability(image_description)
except Exception as e:
raise Exception(f"照片适合性分析失败: {str(e)}")
def check_copywriter_config(provider='deepseek'):
"""检查AI文案生成配置是否完整"""
try:
if provider == 'deepseek':
api_key = os.getenv('DEEPSEEK_API_KEY')
if not api_key:
return False, "DeepSeek API密钥未配置"
# 测试连接
copywriter = AICopywriter(provider)
return True, "AI文案生成配置正确DeepSeek大模型"
elif provider == 'dashscope':
api_key = os.getenv('DASHSCOPE_API_KEY')
if not api_key:
return False, "DashScope API密钥未配置"
# 测试连接
copywriter = AICopywriter(provider)
return True, "AI文案生成配置正确DashScope"
else:
return False, f"不支持的AI提供商: {provider}"
except Exception as e:
return False, f"AI文案生成配置错误: {str(e)}"