158 lines
5.4 KiB
Python
158 lines
5.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
技术文章改写器
|
|
将英文技术文章改写成小红书风格的中文内容
|
|
"""
|
|
import os
|
|
import requests
|
|
import json
|
|
import re
|
|
from typing import Dict
|
|
|
|
|
|
class TechContentRewriter:
|
|
"""技术内容改写器"""
|
|
|
|
def __init__(self):
|
|
self.api_key = os.environ.get('MOONSHOT_API_KEY')
|
|
self.api_base = os.environ.get('MOONSHOT_API_BASE', 'https://api.moonshot.cn/v1')
|
|
self.model = "kimi-k2.5"
|
|
|
|
def rewrite(self, article: Dict) -> Dict[str, str]:
|
|
"""
|
|
改写文章为小红书风格
|
|
|
|
Args:
|
|
article: 包含title, url, content的文章字典
|
|
|
|
Returns:
|
|
改写后的内容字典
|
|
"""
|
|
if not self.api_key:
|
|
print("❌ 未设置MOONSHOT_API_KEY")
|
|
return self._fallback(article)
|
|
|
|
# 构建提示
|
|
prompt = self._build_prompt(article)
|
|
|
|
try:
|
|
response = requests.post(
|
|
f"{self.api_base}/chat/completions",
|
|
headers={
|
|
"Authorization": f"Bearer {self.api_key}",
|
|
"Content-Type": "application/json"
|
|
},
|
|
json={
|
|
"model": self.model,
|
|
"messages": [
|
|
{
|
|
"role": "system",
|
|
"content": "你是科技内容创作专家,擅长将技术文章改写成适合小红书平台的中文内容。"
|
|
},
|
|
{"role": "user", "content": prompt}
|
|
],
|
|
"temperature": 1,
|
|
"max_tokens": 2000
|
|
},
|
|
timeout=120
|
|
)
|
|
|
|
result = response.json()
|
|
|
|
if 'error' in result:
|
|
print(f"API错误: {result['error']}")
|
|
return self._fallback(article)
|
|
|
|
content = result['choices'][0]['message']['content']
|
|
return self._parse_result(content, article)
|
|
|
|
except Exception as e:
|
|
print(f"改写失败: {e}")
|
|
return self._fallback(article)
|
|
|
|
def _build_prompt(self, article: Dict) -> str:
|
|
"""构建改写提示"""
|
|
return f"""请将以下技术文章改写成适合小红书平台的中文笔记。
|
|
|
|
原文信息:
|
|
- 标题: {article['title']}
|
|
- 来源: {article['source']}
|
|
- 原文链接: {article['url']}
|
|
- 原文内容:
|
|
{article['content'][:1500]} # 限制长度避免超出token
|
|
|
|
改写要求:
|
|
1. 标题:20-30字,吸引眼球,不用markdown
|
|
2. 正文:600-800字,用中文表达,保持技术准确性
|
|
3. 结构:使用-作为列表符号,分3-4个要点阐述
|
|
4. 风格:口语化、有个人观点,像朋友分享
|
|
5. 格式:不要加粗(**),标题用自然语言
|
|
6. Emoji:适当使用,增加亲和力
|
|
7. 原创性:基于原文观点重新组织语言,不要直接翻译
|
|
8. 结尾:5个相关话题标签,格式为#标签
|
|
|
|
输出格式:
|
|
标题:[中文标题]
|
|
|
|
正文:[中文正文]
|
|
|
|
标签:#标签1 #标签2 #标签3 #标签4 #标签5"""
|
|
|
|
def _parse_result(self, content: str, article: Dict) -> Dict[str, str]:
|
|
"""解析AI返回的内容"""
|
|
# 提取标题
|
|
title_match = re.search(r'标题:\s*(.+?)(?:\n|$)', content)
|
|
title = title_match.group(1).strip() if title_match else article['title']
|
|
|
|
# 提取正文
|
|
body_match = re.search(r'正文:\s*(.+?)(?:标签:|$)', content, re.DOTALL)
|
|
body = body_match.group(1).strip() if body_match else content
|
|
|
|
# 清理markdown
|
|
body = re.sub(r'\*\*(.+?)\*\*', r'\1', body)
|
|
body = re.sub(r'##?\s*', '', body)
|
|
|
|
# 提取标签
|
|
tags_match = re.search(r'标签:\s*(.+?)(?:\n|$)', content, re.DOTALL)
|
|
tags_str = tags_match.group(1) if tags_match else "#科技趋势 #人工智能"
|
|
tags = [t.strip().replace('#', '') for t in tags_str.split() if t.strip() and '#' in t]
|
|
|
|
return {
|
|
"title": title,
|
|
"body": body,
|
|
"tags": tags[:5],
|
|
"source_title": article['title'],
|
|
"source_url": article['url'],
|
|
"source_name": article['source'],
|
|
"raw": content
|
|
}
|
|
|
|
def _fallback(self, article: Dict) -> Dict[str, str]:
|
|
"""备用内容"""
|
|
return {
|
|
"title": f"【技术分享】{article['title'][:30]}",
|
|
"body": f"今天读到一篇来自{article['source']}的好文章,分享给大家\n\n{article['content'][:500]}...",
|
|
"tags": ["技术分享", "编程", "开发者"],
|
|
"source_title": article['title'],
|
|
"source_url": article['url'],
|
|
"source_name": article['source'],
|
|
"raw": ""
|
|
}
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# 测试
|
|
test_article = {
|
|
"title": "The Future of AI Agents",
|
|
"source": "Test Blog",
|
|
"url": "https://example.com/article",
|
|
"content": "AI agents are becoming more capable. They can now perform complex tasks autonomously. This represents a major shift in how we interact with technology."
|
|
}
|
|
|
|
rewriter = TechContentRewriter()
|
|
result = rewriter.rewrite(test_article)
|
|
|
|
print(f"标题: {result['title']}")
|
|
print(f"\n正文:\n{result['body']}")
|
|
print(f"\n标签: {result['tags']}")
|