This commit is contained in:
Ubuntu
2026-07-03 16:58:28 +08:00
commit 32b43f85bd
6240 changed files with 1987678 additions and 0 deletions
+303
View File
@@ -0,0 +1,303 @@
#!/usr/bin/env python3
"""
AI模型处理器 - 自动跟随nanobot配置的模型
用于文章翻译和总结
"""
import os
import json
import logging
import requests
from typing import Dict, Optional, Tuple
logger = logging.getLogger(__name__)
class AIProcessor:
"""AI模型处理器 - 自动使用nanobot配置的模型"""
def __init__(self, config_path=None):
"""初始化处理器"""
self.config_path = config_path or "/home/ubuntu/nanocode/it_automation_enhanced/config/config.json"
self.load_config()
# 导入配置加载器
try:
from config_loader import get_current_model_config
self.model_config = get_current_model_config()
self.provider = self.model_config['provider']
self.model = self.model_config['model']
logger.info(f"使用nanobot配置的模型: {self.provider}/{self.model}")
except Exception as e:
logger.warning(f"无法加载配置加载器: {e},使用默认配置")
self.model_config = None
self.provider = 'moonshot'
self.model = 'kimi-k2.5'
def load_config(self):
"""加载项目配置"""
try:
with open(self.config_path, 'r', encoding='utf-8') as f:
self.config = json.load(f)
logger.info(f"项目配置加载成功")
except Exception as e:
logger.error(f"配置加载失败: {e}")
self.config = {}
def call_api(self, prompt: str, max_tokens: int = None) -> Optional[str]:
"""调用AI API - 自动使用nanobot配置的模型"""
# 使用配置加载器获取的模型配置
if self.model_config:
api_key = self.model_config['api_key']
api_base = self.model_config['api_base']
model = self.model_config['model']
default_max_tokens = self.model_config['max_tokens']
else:
# 回退到项目配置
provider_config = self.config.get(self.provider, {})
api_key = provider_config.get('api_key')
api_base = provider_config.get('api_base', 'https://api.moonshot.cn/v1')
model = provider_config.get('model', 'kimi-k2.5')
default_max_tokens = 4000
if not api_key or api_key.startswith('{{'):
logger.warning(f"{self.provider} API密钥未配置,跳过API调用")
return None
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
data = {
'model': model,
'messages': [
{'role': 'user', 'content': prompt}
],
'max_tokens': max_tokens or default_max_tokens
}
# 构建API端点URL
if api_base.endswith('/v1'):
endpoint = f'{api_base}/chat/completions'
else:
endpoint = f'{api_base}/chat/completions'
try:
logger.info(f"调用 {self.provider} API: {model}")
response = requests.post(
endpoint,
headers=headers,
json=data,
timeout=60
)
if response.status_code == 200:
result = response.json()
content = result['choices'][0]['message']['content']
logger.info(f"{self.provider} API调用成功,返回 {len(content)} 字符")
return content
else:
logger.error(f"{self.provider} API调用失败: {response.status_code} - {response.text[:200]}")
return None
except Exception as e:
logger.error(f"{self.provider} API调用异常: {e}")
return None
def translate_article(self, content: str, source_lang: str = 'en', target_lang: str = 'zh') -> Optional[str]:
"""翻译文章"""
if not self.config.get('processing', {}).get('enable_translation', True):
logger.info("翻译功能已禁用,跳过")
return content
# 使用配置加载器的提示词或项目配置的提示词
if self.model_config:
prompt_template = self.model_config.get('translation_prompt',
f"请将以下{source_lang}文技术文章翻译成{target_lang}文,保持技术准确性,语言自然流畅:\n\n{{content}}")
else:
provider_config = self.config.get(self.provider, {})
prompt_template = provider_config.get('translation_prompt',
f"请将以下{source_lang}文技术文章翻译成{target_lang}文,保持技术准确性,语言自然流畅:\n\n{{content}}")
prompt = prompt_template.format(content=content)
# 如果内容太长,分段处理
max_length = self.config.get('processing', {}).get('max_content_length', 10000)
if len(content) > max_length:
logger.warning(f"文章过长 ({len(content)}字符),将分段翻译")
return self._translate_long_content(content, prompt, max_length)
translated = self.call_api(prompt)
return translated
def _translate_long_content(self, content: str, prompt_template: str, chunk_size: int = 3000) -> Optional[str]:
"""翻译长内容(分段处理)"""
# 按段落分割
paragraphs = content.split('\n\n')
translated_paragraphs = []
current_chunk = ""
chunk_count = 0
for i, paragraph in enumerate(paragraphs):
if len(current_chunk) + len(paragraph) > chunk_size:
# 翻译当前块
chunk_count += 1
logger.info(f"翻译第 {chunk_count} 块 ({len(current_chunk)} 字符)")
prompt = prompt_template.format(content=current_chunk)
translated_chunk = self.call_api(prompt)
if translated_chunk:
translated_paragraphs.append(translated_chunk)
else:
logger.warning(f"第 {chunk_count} 块翻译失败")
translated_paragraphs.append(current_chunk) # 保留原文
current_chunk = paragraph
else:
if current_chunk:
current_chunk += "\n\n" + paragraph
else:
current_chunk = paragraph
# 翻译最后一块
if current_chunk:
chunk_count += 1
logger.info(f"翻译第 {chunk_count} 块 ({len(current_chunk)} 字符)")
prompt = prompt_template.format(content=current_chunk)
translated_chunk = self.call_api(prompt)
if translated_chunk:
translated_paragraphs.append(translated_chunk)
else:
logger.warning(f"第 {chunk_count} 块翻译失败")
translated_paragraphs.append(current_chunk)
return "\n\n".join(translated_paragraphs)
def summarize_article(self, content: str) -> Optional[str]:
"""总结文章"""
if not self.config.get('processing', {}).get('enable_summarization', True):
logger.info("总结功能已禁用,跳过")
return None
# 使用配置加载器的提示词或项目配置的提示词
if self.model_config:
prompt_template = self.model_config.get('summarization_prompt',
"请用中文总结以下技术文章的核心内容,突出技术要点和创新点:\n\n{content}")
else:
provider_config = self.config.get(self.provider, {})
prompt_template = provider_config.get('summarization_prompt',
"请用中文总结以下技术文章的核心内容,突出技术要点和创新点:\n\n{content}")
# 限制内容长度
max_length = self.config.get('processing', {}).get('max_content_length', 10000)
if len(content) > max_length:
content = content[:max_length] + "...[内容已截断]"
prompt = prompt_template.format(content=content)
summary = self.call_api(prompt, max_tokens=1000)
return summary
def rewrite_article(self, content: str) -> Optional[str]:
"""改写文章(中文润色)"""
if not self.config.get('processing', {}).get('enable_translation', True):
logger.info("改写功能已禁用,跳过")
return content
prompt = f"""请对以下技术文章进行改写和润色:
要求:
1. 保持原意和技术准确性
2. 调整句式结构,避免重复表达
3. 优化语言流畅度
4. 保留关键技术术语
5. 输出约原文80%长度的内容
原文:
{content[:8000]}
"""
rewritten = self.call_api(prompt)
return rewritten
def process_article(self, title: str, content: str, url: str = "") -> Dict:
"""完整处理文章"""
logger.info(f"开始处理文章: {title}")
result = {
'title': title,
'original_content': content,
'original_length': len(content),
'url': url,
'translated': None,
'summary': None,
'processed': False
}
# 1. 翻译
if self.config.get('processing', {}).get('enable_translation', True):
logger.info("翻译文章...")
translated = self.translate_article(content)
if translated:
result['translated'] = translated
result['translated_length'] = len(translated)
logger.info(f"翻译完成: {len(translated)} 字符")
else:
logger.warning("翻译失败")
# 2. 总结
if self.config.get('processing', {}).get('enable_summarization', True):
logger.info("总结文章...")
summary = self.summarize_article(content)
if summary:
result['summary'] = summary
logger.info(f"总结完成: {len(summary)} 字符")
else:
logger.warning("总结失败")
result['processed'] = True
logger.info(f"文章处理完成: {title}")
return result
def test_processor():
"""测试处理器"""
import sys
logging.basicConfig(level=logging.INFO)
processor = AIProcessor()
# 测试内容
test_content = """Artificial intelligence is transforming the technology landscape.
Recent advances in machine learning have enabled breakthroughs in natural language processing,
computer vision, and autonomous systems. Companies are investing heavily in AI research
and development to gain competitive advantages."""
print(f"测试AI处理器 (使用 {processor.provider}/{processor.model})...")
# 测试翻译
print("\n1. 测试翻译...")
translated = processor.translate_article(test_content)
if translated:
print(f"翻译结果: {translated[:100]}...")
else:
print("翻译测试跳过(API未配置)")
# 测试总结
print("\n2. 测试总结...")
summary = processor.summarize_article(test_content)
if summary:
print(f"总结结果: {summary[:100]}...")
else:
print("总结测试跳过(API未配置)")
print("\n测试完成")
if __name__ == "__main__":
test_processor()