235 lines
6.9 KiB
Python
235 lines
6.9 KiB
Python
"""
|
|||
|
|
响应生成模块
|
||
|
|
使用 Claude 生成自然语言响应
|
||
|
|
"""
|
||
|
|
|
||
|
|
import logging
|
||
|
|
from typing import Dict, Any, Optional, List
|
||
|
|
|
||
|
|
from ..dependency_manager import get_dependency_manager
|
||
|
|
|
||
|
|
# Try to import anthropic with graceful degradation
|
||
|
|
dependency_manager = get_dependency_manager()
|
||
|
|
Anthropic = dependency_manager.get_class_from_module('anthropic', 'Anthropic')
|
||
|
|
|
||
|
|
|
||
|
|
class ResponseGenerator:
|
||
|
|
"""响应生成器,使用 Claude 生成自然语言响应"""
|
||
|
|
|
||
|
|
def __init__(self, config: Optional[Dict[str, Any]] = None) -> None:
|
||
|
|
"""
|
||
|
|
初始化响应生成器
|
||
|
|
|
||
|
|
Args:
|
||
|
|
config: 配置字典
|
||
|
|
"""
|
||
|
|
self.config: Dict[str, Any] = config or {}
|
||
|
|
self.logger: logging.Logger = logging.getLogger("ResponseGenerator")
|
||
|
|
|
||
|
|
# Initialize Anthropic client with dependency checking
|
||
|
|
if Anthropic is not None:
|
||
|
|
try:
|
||
|
|
self.client: Optional[Anthropic] = Anthropic()
|
||
|
|
except Exception as e:
|
||
|
|
self.logger.error(f"Failed to initialize Anthropic client: {e}")
|
||
|
|
self.client = None
|
||
|
|
else:
|
||
|
|
self.client = None
|
||
|
|
self.logger.warning("Anthropic library not available - AI response generation disabled")
|
||
|
|
|
||
|
|
async def generate_success_response(
|
||
|
|
self, command: str, result: Any, user_message: str
|
||
|
|
) -> str:
|
||
|
|
"""
|
||
|
|
生成成功响应
|
||
|
|
|
||
|
|
Args:
|
||
|
|
command: 执行的命令
|
||
|
|
result: 命令执行结果
|
||
|
|
user_message: 原始用户消息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
生成的响应文本
|
||
|
|
"""
|
||
|
|
prompt: str = self._build_success_prompt(command, result, user_message)
|
||
|
|
return await self._generate_response(prompt)
|
||
|
|
|
||
|
|
async def generate_error_response(
|
||
|
|
self, command: str, error: str, user_message: str
|
||
|
|
) -> str:
|
||
|
|
"""
|
||
|
|
生成错误响应
|
||
|
|
|
||
|
|
Args:
|
||
|
|
command: 执行的命令
|
||
|
|
error: 错误信息
|
||
|
|
user_message: 原始用户消息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
生成的响应文本
|
||
|
|
"""
|
||
|
|
prompt: str = self._build_error_prompt(command, error, user_message)
|
||
|
|
return await self._generate_response(prompt)
|
||
|
|
|
||
|
|
async def generate_clarification_response(self, question: str) -> str:
|
||
|
|
"""
|
||
|
|
生成澄清问题的响应
|
||
|
|
|
||
|
|
Args:
|
||
|
|
question: 澄清问题
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
生成的响应文本
|
||
|
|
"""
|
||
|
|
return question
|
||
|
|
|
||
|
|
async def generate_welcome_message(self) -> str:
|
||
|
|
"""
|
||
|
|
生成欢迎消息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
欢迎消息
|
||
|
|
"""
|
||
|
|
return "👋 欢迎使用 Obsidian 日记整理助手!我可以帮您整理日记、分析内容、导出总结等。请告诉我您想要做什么?"
|
||
|
|
|
||
|
|
async def generate_suggestions(
|
||
|
|
self, context: Optional[Dict[str, Any]] = None
|
||
|
|
) -> List[str]:
|
||
|
|
"""
|
||
|
|
生成智能建议
|
||
|
|
|
||
|
|
Args:
|
||
|
|
context: 上下文信息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
建议列表
|
||
|
|
"""
|
||
|
|
suggestions: List[str] = ["整理今天的日记", "分析本周的主题", "导出月度总结", "查看最近的经验"]
|
||
|
|
|
||
|
|
# 可以根据上下文生成更个性化的建议
|
||
|
|
if context:
|
||
|
|
# 例如,如果是周五,建议生成周总结
|
||
|
|
from datetime import datetime
|
||
|
|
|
||
|
|
if datetime.now().weekday() == 4: # 周五
|
||
|
|
suggestions.insert(0, "生成本周总结")
|
||
|
|
|
||
|
|
return suggestions
|
||
|
|
|
||
|
|
def _build_success_prompt(
|
||
|
|
self, command: str, result: Any, user_message: str
|
||
|
|
) -> str:
|
||
|
|
"""
|
||
|
|
构建成功响应的提示
|
||
|
|
|
||
|
|
Args:
|
||
|
|
command: 执行的命令
|
||
|
|
result: 命令执行结果
|
||
|
|
user_message: 原始用户消息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
提示文本
|
||
|
|
"""
|
||
|
|
result_str: str = self._format_result(result)
|
||
|
|
|
||
|
|
prompt: str = f"""你是一个友好的 Obsidian 日记整理助手。
|
||
|
|
|
||
|
|
用户问: "{user_message}"
|
||
|
|
|
||
|
|
你已经成功执行了 "{command}" 命令。
|
||
|
|
|
||
|
|
执行结果:
|
||
|
|
{result_str}
|
||
|
|
|
||
|
|
请用友好、自然的语言总结结果。保持回复简洁(1-3 句话)。
|
||
|
|
如果有重要的数据或统计信息,请突出显示。
|
||
|
|
|
||
|
|
示例回复:
|
||
|
|
- "✓ 已成功整理您今天的日记。提取了 5 条经验、3 条待办事项和 2 个问题。"
|
||
|
|
- "✓ 分析完成!本周的主题主要集中在项目管理和技术学习两个方面。"
|
||
|
|
"""
|
||
|
|
|
||
|
|
return prompt
|
||
|
|
|
||
|
|
def _build_error_prompt(self, command: str, error: str, user_message: str) -> str:
|
||
|
|
"""
|
||
|
|
构建错误响应的提示
|
||
|
|
|
||
|
|
Args:
|
||
|
|
command: 执行的命令
|
||
|
|
error: 错误信息
|
||
|
|
user_message: 原始用户消息
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
提示文本
|
||
|
|
"""
|
||
|
|
prompt: str = f"""你是一个友好的 Obsidian 日记整理助手。
|
||
|
|
|
||
|
|
用户问: "{user_message}"
|
||
|
|
|
||
|
|
执行 "{command}" 命令时出现了错误:
|
||
|
|
{error}
|
||
|
|
|
||
|
|
请用友好、有帮助的语言解释错误,并建议可能的解决方案。保持回复简洁(1-2 句话)。
|
||
|
|
|
||
|
|
示例回复:
|
||
|
|
- "✗ 抱歉,找不到该日期的日记。请检查日期格式是否正确(YYYY-MM-DD)。"
|
||
|
|
- "✗ 执行过程中出现了问题。请稍后重试,或检查您的配置设置。"
|
||
|
|
"""
|
||
|
|
|
||
|
|
return prompt
|
||
|
|
|
||
|
|
def _format_result(self, result: Any) -> str:
|
||
|
|
"""
|
||
|
|
格式化结果
|
||
|
|
|
||
|
|
Args:
|
||
|
|
result: 结果对象
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
格式化的结果字符串
|
||
|
|
"""
|
||
|
|
if isinstance(result, dict):
|
||
|
|
lines: List[str] = []
|
||
|
|
for key, value in result.items():
|
||
|
|
if isinstance(value, (list, dict)):
|
||
|
|
lines.append(f"- {key}: {len(value)} 项")
|
||
|
|
else:
|
||
|
|
lines.append(f"- {key}: {value}")
|
||
|
|
return "\n".join(lines)
|
||
|
|
elif isinstance(result, list):
|
||
|
|
return "\n".join([f"- {item}" for item in result])
|
||
|
|
else:
|
||
|
|
return str(result)
|
||
|
|
|
||
|
|
async def _generate_response(self, prompt: str) -> str:
|
||
|
|
"""
|
||
|
|
使用 Claude 生成响应
|
||
|
|
|
||
|
|
Args:
|
||
|
|
prompt: 提示文本
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
生成的响应
|
||
|
|
"""
|
||
|
|
# Check if Claude is available
|
||
|
|
if self.client is None:
|
||
|
|
self.logger.warning("Claude client not available, using fallback response")
|
||
|
|
return "✓ 操作已完成。(注意:AI 响应生成功能暂时不可用)"
|
||
|
|
|
||
|
|
try:
|
||
|
|
response = self.client.messages.create(
|
||
|
|
model="claude-3-5-sonnet-20241022",
|
||
|
|
max_tokens=300,
|
||
|
|
messages=[{"role": "user", "content": prompt}],
|
||
|
|
)
|
||
|
|
|
||
|
|
response_text: str = response.content[0].text.strip()
|
||
|
|
self.logger.debug(f"生成响应: {response_text[:100]}...")
|
||
|
|
|
||
|
|
return response_text
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
self.logger.error(f"生成响应失败: {str(e)}")
|
||
|
|
return "✓ 操作已完成。(注意:AI 响应生成遇到问题,请检查网络连接和 API 配置)"
|