309 lines
12 KiB
Python
309 lines
12 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
"""
|
|||
|
|
DeepSeek大模型文案生成服务集成
|
|||
|
|
使用DeepSeek AI大模型为照片生成创意文案
|
|||
|
|
支持多种文案风格和用途
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import os
|
|||
|
|
import json
|
|||
|
|
import requests
|
|||
|
|
from dotenv import load_dotenv
|
|||
|
|
|
|||
|
|
# 加载环境变量
|
|||
|
|
load_dotenv()
|
|||
|
|
|
|||
|
|
class DeepSeekCopywriter:
|
|||
|
|
"""DeepSeek大模型文案生成服务类"""
|
|||
|
|
|
|||
|
|
def __init__(self, api_key=None):
|
|||
|
|
"""初始化DeepSeek大模型客户端"""
|
|||
|
|
self.api_key = api_key or os.getenv('DEEPSEEK_API_KEY')
|
|||
|
|
self.base_url = "https://api.deepseek.com/v1/chat/completions"
|
|||
|
|
|
|||
|
|
if not self.api_key:
|
|||
|
|
raise Exception("DeepSeek API密钥未配置,请在.env文件中设置DEEPSEEK_API_KEY")
|
|||
|
|
|
|||
|
|
def generate_photo_caption(self, image_description, style='creative', length='medium'):
|
|||
|
|
"""为照片生成文案"""
|
|||
|
|
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 _build_prompt(self, image_description, style, length):
|
|||
|
|
"""构建DeepSeek大模型提示词"""
|
|||
|
|
|
|||
|
|
style_descriptions = {
|
|||
|
|
'creative': '富有诗意和想象力的创意文艺风格,使用优美的修辞和意象',
|
|||
|
|
'professional': '专业正式的商务风格,简洁明了,注重专业性和可信度',
|
|||
|
|
'social': '活泼有趣的社交媒体风格,适合朋友圈分享,具有互动性',
|
|||
|
|
'marketing': '吸引眼球的营销推广风格,具有说服力,促进转化',
|
|||
|
|
'emotional': '温暖感人的情感表达风格,注重情感共鸣和人文关怀',
|
|||
|
|
'simple': '简单直接的描述风格,清晰明了,易于理解'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
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_descriptions.get(style, '创意')}
|
|||
|
|
2. 长度:{length_descriptions.get(length, '适中长度')}
|
|||
|
|
3. 创意性:富有创意,避免陈词滥调
|
|||
|
|
4. 吸引力:能够吸引目标受众的注意力
|
|||
|
|
5. 情感表达:根据风格适当表达情感
|
|||
|
|
6. 适用场景:适合社交媒体分享或商业用途
|
|||
|
|
|
|||
|
|
请直接输出文案内容,不要添加任何额外的说明或标记。文案应该是一个完整的、可以直接使用的文本。
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
return prompt.strip()
|
|||
|
|
|
|||
|
|
def generate_multiple_captions(self, image_description, count=3, style='creative'):
|
|||
|
|
"""生成多个文案选项"""
|
|||
|
|
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"生成多个文案失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def analyze_photo_suitability(self, image_description):
|
|||
|
|
"""分析照片适合的文案风格"""
|
|||
|
|
try:
|
|||
|
|
prompt = f"""
|
|||
|
|
请分析以下照片内容最适合的文案风格:
|
|||
|
|
|
|||
|
|
照片内容:{image_description}
|
|||
|
|
|
|||
|
|
请从以下风格中选择最适合的3个,并按适合度排序:
|
|||
|
|
1. 创意文艺 - 富有诗意和想象力
|
|||
|
|
2. 专业正式 - 简洁专业
|
|||
|
|
3. 社交媒体 - 活泼有趣
|
|||
|
|
4. 营销推广 - 吸引眼球
|
|||
|
|
5. 情感表达 - 温暖感人
|
|||
|
|
6. 简单描述 - 直接明了
|
|||
|
|
|
|||
|
|
请直接返回风格名称列表,用逗号分隔,例如:"社交媒体,创意文艺,情感表达"
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
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': 100,
|
|||
|
|
'temperature': 0.3 # 降低温度增加确定性
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
response = requests.post(self.base_url, headers=headers, json=data)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if 'choices' in result and len(result['choices']) > 0:
|
|||
|
|
analysis = result['choices'][0]['message']['content'].strip()
|
|||
|
|
|
|||
|
|
# 解析返回的风格列表
|
|||
|
|
styles = [s.strip() for s in analysis.split(',')]
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
'recommended_styles': styles[:3],
|
|||
|
|
'most_suitable': styles[0] if styles else 'creative',
|
|||
|
|
'analysis': analysis
|
|||
|
|
}
|
|||
|
|
else:
|
|||
|
|
return self._fallback_suitability_analysis()
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
return self._fallback_suitability_analysis()
|
|||
|
|
|
|||
|
|
def _generate_fallback_caption(self, image_description, style, length):
|
|||
|
|
"""备用文案生成(当DeepSeek服务不可用时)"""
|
|||
|
|
|
|||
|
|
# 基于照片描述的简单文案生成
|
|||
|
|
base_captions = {
|
|||
|
|
'creative': [
|
|||
|
|
f"在{image_description}的瞬间,时光静静流淌",
|
|||
|
|
f"捕捉{image_description}的诗意,定格永恒美好",
|
|||
|
|
f"{image_description}的艺术之美,值得细细品味"
|
|||
|
|
],
|
|||
|
|
'social': [
|
|||
|
|
f"分享一张{image_description}的美照,希望大家喜欢!",
|
|||
|
|
f"今天遇到的{image_description}太棒了,必须分享!",
|
|||
|
|
f"{image_description}的精彩瞬间,与大家共赏"
|
|||
|
|
],
|
|||
|
|
'professional': [
|
|||
|
|
f"专业拍摄:{image_description}的精彩呈现",
|
|||
|
|
f"{image_description}的专业影像记录",
|
|||
|
|
f"高品质{image_description}摄影作品"
|
|||
|
|
],
|
|||
|
|
'marketing': [
|
|||
|
|
f"惊艳!这个{image_description}你一定要看看!",
|
|||
|
|
f"不容错过的{image_description}精彩瞬间",
|
|||
|
|
f"{image_description}的魅力,等你来发现"
|
|||
|
|
],
|
|||
|
|
'emotional': [
|
|||
|
|
f"{image_description}的温暖瞬间,触动心灵",
|
|||
|
|
f"在{image_description}中感受生活的美好",
|
|||
|
|
f"{image_description}的情感表达,真挚动人"
|
|||
|
|
]
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
import random
|
|||
|
|
captions = base_captions.get(style, base_captions['creative'])
|
|||
|
|
caption = random.choice(captions)
|
|||
|
|
|
|||
|
|
# 根据长度调整
|
|||
|
|
if length == 'long' and len(caption) < 50:
|
|||
|
|
caption += "。这张照片记录了珍贵的瞬间,展现了生活的美好,值得细细品味和珍藏。"
|
|||
|
|
elif length == 'short' and len(caption) > 20:
|
|||
|
|
caption = caption[:20] + "..."
|
|||
|
|
|
|||
|
|
return caption
|
|||
|
|
|
|||
|
|
def _fallback_suitability_analysis(self):
|
|||
|
|
"""备用风格分析"""
|
|||
|
|
return {
|
|||
|
|
'recommended_styles': ['creative', 'social', 'emotional'],
|
|||
|
|
'most_suitable': 'creative',
|
|||
|
|
'analysis': '创意文艺风格最适合表达照片的艺术美感'
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
def generate_photo_caption_deepseek(image_description, style='creative', length='medium'):
|
|||
|
|
"""使用DeepSeek为照片生成文案"""
|
|||
|
|
try:
|
|||
|
|
copywriter = DeepSeekCopywriter()
|
|||
|
|
return copywriter.generate_photo_caption(image_description, style, length)
|
|||
|
|
except Exception as e:
|
|||
|
|
raise Exception(f"DeepSeek文案生成失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def generate_multiple_captions_deepseek(image_description, count=3, style='creative'):
|
|||
|
|
"""使用DeepSeek生成多个文案选项"""
|
|||
|
|
try:
|
|||
|
|
copywriter = DeepSeekCopywriter()
|
|||
|
|
return copywriter.generate_multiple_captions(image_description, count, style)
|
|||
|
|
except Exception as e:
|
|||
|
|
raise Exception(f"DeepSeek多文案生成失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def analyze_photo_suitability_deepseek(image_description):
|
|||
|
|
"""使用DeepSeek分析照片适合的文案风格"""
|
|||
|
|
try:
|
|||
|
|
copywriter = DeepSeekCopywriter()
|
|||
|
|
return copywriter.analyze_photo_suitability(image_description)
|
|||
|
|
except Exception as e:
|
|||
|
|
raise Exception(f"DeepSeek风格分析失败: {str(e)}")
|
|||
|
|
|
|||
|
|
def check_deepseek_config():
|
|||
|
|
"""检查DeepSeek配置是否完整"""
|
|||
|
|
try:
|
|||
|
|
api_key = os.getenv('DEEPSEEK_API_KEY')
|
|||
|
|
if not api_key:
|
|||
|
|
return False, "DeepSeek API密钥未配置"
|
|||
|
|
|
|||
|
|
# 测试连接
|
|||
|
|
copywriter = DeepSeekCopywriter()
|
|||
|
|
return True, "DeepSeek配置正确"
|
|||
|
|
except Exception as e:
|
|||
|
|
return False, f"DeepSeek配置错误: {str(e)}"
|