""" 对话式 Agent 的命令行入口 支持交互式对话 """ import argparse import asyncio import logging import sys from typing import Dict, Any, Optional, List from typing import Dict, Any, Optional, List # Handle imports with both relative and absolute paths try: from .main import JournalOrganizerAgent from .conversation import ConversationalAgent except ImportError: # Fallback to absolute imports when running as script from main import JournalOrganizerAgent from conversation import ConversationalAgent class ChatInterface: """对话式 Agent 的命令行界面""" def __init__(self, config_file: Optional[str] = None) -> None: """ 初始化聊天界面 Args: config_file: 配置文件路径 """ self.logger: logging.Logger = logging.getLogger("ChatInterface") # 初始化 Agent self.journal_agent: JournalOrganizerAgent = JournalOrganizerAgent(config_file) self.conversational_agent: ConversationalAgent = ConversationalAgent( self.journal_agent.agent, self.journal_agent.config ) async def run_interactive(self) -> None: """ 运行交互式对话 """ print(f"\n{'='*60}") print("Obsidian 智能日记整理 Agent - 对话模式") print(f"{'='*60}\n") # 显示欢迎消息 welcome_msg = await self.conversational_agent.initialize() print(f"\n🤖 助手: {welcome_msg}\n") # 交互循环 while True: try: # 获取用户输入 user_input: str = input("👤 您: ").strip() if not user_input: continue # 处理特殊命令 if user_input.lower() in ["exit", "quit", "退出"]: print("\n👋 再见!\n") break if user_input.lower() in ["help", "帮助"]: self._show_help() continue if user_input.lower() in ["history", "历史"]: self._show_history() continue if user_input.lower() in ["status", "状态"]: self._show_status() continue if user_input.lower() in ["clear", "清除"]: self.conversational_agent.clear_history() print("\n✓ 对话历史已清除\n") continue # 处理用户消息 print("\n⏳ 处理中...\n") response = await self.conversational_agent.chat(user_input) # 显示响应 print(f"🤖 助手: {response.message}") # 显示建议 if response.suggestions: print("\n💡 您可以尝试:") for i, suggestion in enumerate(response.suggestions, 1): print(f" {i}. {suggestion}") print() except KeyboardInterrupt: print("\n\n👋 再见!\n") break except Exception as e: self.logger.error(f"错误: {str(e)}", exc_info=True) print(f"\n❌ 发生错误: {str(e)}\n") async def run_single_query(self, query: str) -> None: """ 运行单个查询 Args: query: 用户查询 """ # 初始化 await self.conversational_agent.initialize() # 处理查询 response = await self.conversational_agent.chat(query) # 输出结果 output_data: Dict[str, Any] = { "message": response.message, "status": response.status, "suggestions": response.suggestions, "metadata": response.metadata, } print(json.dumps(output_data, ensure_ascii=False, indent=2)) def _show_help(self) -> None: """ 显示帮助信息 """ help_text = """ 🆘 可用命令: 对话命令: - 直接输入您的需求,例如: "整理今天的日记" - "分析本周的主题" - "导出月度总结" 系统命令: - help / 帮助 显示此帮助信息 - history / 历史 显示对话历史 - status / 状态 显示当前状态 - clear / 清除 清除对话历史 - exit / quit / 退出 退出程序 示例对话: 👤 您: 帮我整理一下昨天的日记 🤖 助手: 好的,我来帮您整理昨天的日记... 👤 您: 分析一下这周的主题 🤖 助手: 这周的主题主要集中在... """ print(help_text) def _show_history(self) -> None: """ 显示对话历史 """ history: List[ Dict[str, str] ] = self.conversational_agent.get_conversation_history() if not history: print("\n📭 对话历史为空\n") return print("\n📜 对话历史:\n") for msg in history: role: str = "👤 您" if msg["role"] == "user" else "🤖 助手" content: str = msg["content"] if len(content) > 100: content = f"{content[:100]}..." print(f"{role}: {content}") print() def _show_status(self) -> None: """ 显示当前状态 """ summary: Dict[str, Any] = self.conversational_agent.get_state_summary() print("\n📊 当前状态:\n") print(f"总消息数: {summary['total_messages']}") print(f"总任务数: {summary['stats']['total_tasks']}") print(f"成功任务: {summary['stats']['successful_tasks']}") print(f"失败任务: {summary['stats']['failed_tasks']}") if summary["current_task"]: print(f"\n当前任务: {summary['current_task']['command']}") print(f"状态: {summary['current_task']['status']}") print() async def main() -> Optional[int]: """ 主函数 """ parser: argparse.ArgumentParser = argparse.ArgumentParser( description="Obsidian 智能日记整理 Agent - 对话模式", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" 示例: # 启动交互式对话 python -m journal_organizer.chat_main # 处理单个查询 python -m journal_organizer.chat_main --query "整理今天的日记" # 使用指定配置文件 python -m journal_organizer.chat_main --config /path/to/config.yaml """, ) parser.add_argument("--config", type=str, help="配置文件路径") parser.add_argument("--query", type=str, help="单个查询(不进入交互模式)") parser.add_argument( "--log-level", type=str, default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], help="日志级别", ) args: argparse.Namespace = parser.parse_args() # 设置日志 logging.basicConfig( level=getattr(logging, args.log_level), format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", ) # 初始化聊天界面 chat: ChatInterface = ChatInterface(args.config) # 运行 if args.query: # 单个查询模式 await chat.run_single_query(args.query) else: # 交互模式 await chat.run_interactive() return None if __name__ == "__main__": exit_code: Optional[int] = asyncio.run(main()) sys.exit(exit_code or 0)