AI Agent技术完整指南 第四部分:实战项目

第四部分:实战项目

  1. [第十一章:电影解说AI Agent实战](#第十一章:电影解说AI Agent实战)

第十一章:电影解说AI Agent实战

11.1 项目概述

11.1.1 项目目标

本项目构建一个电影解说AI Agent,能够:

  • 接收电影名称或相关信息
  • 搜索电影详细信息(剧情、演员、评分等)
  • 生成专业的电影解说文案
  • 支持多轮对话,回答关于电影的各类问题
11.1.2 技术栈

电影解说Agent
LangChain Agent
DeepSeek/OpenAI LLM
电影搜索工具
记忆系统

11.2 系统架构设计

11.2.1 架构流程图

记忆系统 电影搜索工具 GPT-4 电影解说Agent 用户 记忆系统 电影搜索工具 GPT-4 电影解说Agent 用户 "请解说《肖申克的救赎》" 分析用户意图 需要搜索电影信息 搜索电影详情 返回电影信息 生成解说文案 返回解说内容 保存对话历史 返回电影解说 "这部电影的导演是谁?" 获取对话历史 返回历史信息 基于历史回答问题 返回答案 "导演是弗兰克·德拉邦特"

11.2.2 核心组件
组件 功能 实现方式
Agent核心 任务编排和决策 LangChain Agent
LLM引擎 理解和生成 GPT-4
搜索工具 获取电影信息 自定义Tool
记忆系统 保存对话历史 ConversationBufferMemory
Prompt模板 指导生成风格 专业电影解说Prompt

11.3 核心Prompt设计

11.3.1 系统Prompt
python 复制代码
MOVIE_COMMENTATOR_SYSTEM_PROMPT = """
你是一位专业的电影解说员,具有以下特点:

1. **专业素养**
   - 对电影艺术有深入理解
   - 熟悉各种电影类型和风格
   - 能够分析电影的深层含义

2. **解说风格**
   - 语言生动有趣,引人入胜
   - 结构清晰,逻辑严密
   - 既有专业分析,又通俗易懂

3. **内容要求**
   - 介绍电影基本信息(导演、演员、类型等)
   - 概述剧情(避免剧透关键情节)
   - 分析电影主题和艺术特色
   - 评价电影的艺术价值和观赏价值

4. **交互方式**
   - 回答用户关于电影的各种问题
   - 基于对话历史提供连贯的回答
   - 如果信息不足,主动使用搜索工具获取信息

请始终以专业、友好、生动的语调与用户交流。
"""
11.3.2 电影搜索Prompt
python 复制代码
MOVIE_SEARCH_PROMPT = """
请搜索以下电影的信息:
电影名称:{movie_name}

需要获取的信息:
1. 基本信息:导演、主演、上映时间、类型
2. 剧情简介
3. 评分和评价
4. 获奖情况(如有)
5. 其他重要信息

请返回结构化的电影信息。
"""

11.4 工具设计

11.4.1 电影搜索工具
python 复制代码
def search_movie_info(movie_name: str) -> str:
    """
    搜索电影信息
    
    注意:这是一个示例实现,实际项目中可以:
    1. 调用电影API(如TMDB API)
    2. 使用网络搜索
    3. 查询本地电影数据库
    """
    # 示例电影数据库(实际应使用真实API)
    movie_database = {
        "肖申克的救赎": {
            "导演": "弗兰克·德拉邦特",
            "主演": "蒂姆·罗宾斯、摩根·弗里曼",
            "上映时间": "1994年",
            "类型": "剧情、犯罪",
            "评分": "9.7分(豆瓣)",
            "剧情": "银行家安迪因被误判谋杀而入狱,在肖申克监狱中..."
        },
        # 可以添加更多电影
    }
    
    movie_name_clean = movie_name.strip().replace("《", "").replace("》", "")
    
    if movie_name_clean in movie_database:
        info = movie_database[movie_name_clean]
        return f"""
电影名称:{movie_name_clean}
导演:{info['导演']}
主演:{info['主演']}
上映时间:{info['上映时间']}
类型:{info['类型']}
评分:{info['评分']}
剧情简介:{info['剧情']}
"""
    else:
        return f"抱歉,未找到电影《{movie_name_clean}》的详细信息。请确认电影名称是否正确。"

11.5 完整实现代码

11.5.1 电影解说Agent类
python 复制代码
import os
import sys
from typing import Optional

# 兼容新旧版本的LangChain导入
NEW_API = False
ChatOpenAI = None
AgentExecutor = None
create_openai_tools_agent = None
Tool = None
ConversationBufferMemory = None
MessagesPlaceholder = None
ChatPromptTemplate = None
SystemMessagePromptTemplate = None
HumanMessagePromptTemplate = None
initialize_agent = None
AgentType = None
SystemMessage = None

# 尝试导入新版本LangChain (>=0.1.0)
try:
    from langchain_openai import ChatOpenAI
    from langchain.agents import AgentExecutor, create_openai_tools_agent
    from langchain.tools import Tool
    from langchain.memory import ConversationBufferMemory
    from langchain_core.prompts import (
        MessagesPlaceholder,
        ChatPromptTemplate,
        SystemMessagePromptTemplate,
        HumanMessagePromptTemplate
    )
    NEW_API = True
except ImportError:
    # 尝试使用旧版本LangChain (<0.1.0)
    try:
        from langchain.chat_models import ChatOpenAI
        from langchain.agents import initialize_agent, AgentType, Tool
        from langchain.memory import ConversationBufferMemory
        from langchain.prompts import MessagesPlaceholder
        from langchain.schema import SystemMessage
        NEW_API = False
    except ImportError:
        raise ImportError("LangChain导入失败,请安装: pip install langchain langchain-openai")

# 系统Prompt
MOVIE_COMMENTATOR_SYSTEM_PROMPT = """
你是一位专业的电影解说员,具有以下特点:

1. **专业素养**
   - 对电影艺术有深入理解
   - 熟悉各种电影类型和风格
   - 能够分析电影的深层含义

2. **解说风格**
   - 语言生动有趣,引人入胜
   - 结构清晰,逻辑严密
   - 既有专业分析,又通俗易懂

3. **内容要求**
   - 介绍电影基本信息(导演、演员、类型等)
   - 概述剧情(避免剧透关键情节)
   - 分析电影主题和艺术特色
   - 评价电影的艺术价值和观赏价值

4. **交互方式**
   - 回答用户关于电影的各种问题
   - 基于对话历史提供连贯的回答
   - 如果信息不足,主动使用SearchMovieInfo工具获取信息

请始终以专业、友好、生动的语调与用户交流。
"""

class MovieCommentatorAgent:
    """
    电影解说AI Agent
    
    功能:
    1. 搜索电影信息
    2. 生成专业电影解说
    3. 回答电影相关问题
    4. 支持多轮对话
    """
    
    def __init__(self, api_key: Optional[str] = None, model: str = "gpt-3.5-turbo", use_deepseek: bool = False):
        """
        初始化电影解说Agent
        
        Args:
            api_key: API密钥(OpenAI或DeepSeek)
            model: 使用的模型名称
                - OpenAI: "gpt-3.5-turbo", "gpt-4" 等
                - DeepSeek: "deepseek-chat"
            use_deepseek: 是否使用DeepSeek API,默认False(使用OpenAI)
        """
        if not api_key:
            raise ValueError("请提供API密钥")

        # 初始化LLM(兼容新旧版本,支持OpenAI和DeepSeek)
        if use_deepseek:
            # 使用DeepSeek API
            deepseek_base_url = "https://api.deepseek.com"
            if NEW_API:
                self.llm = ChatOpenAI(
                    model="deepseek-chat",
                    openai_api_key=api_key,
                    openai_api_base=deepseek_base_url,
                    temperature=0.7,
                    max_tokens=2000
                )
            else:
                self.llm = ChatOpenAI(
                    model_name="deepseek-chat",
                    openai_api_key=api_key,
                    openai_api_base=deepseek_base_url,
                    temperature=0.7,
                    max_tokens=2000
                )
        else:
            # 使用OpenAI API
            if NEW_API:
                self.llm = ChatOpenAI(
                    model=model,
                    openai_api_key=api_key,
                    temperature=0.7,
                    max_tokens=2000
                )
            else:
                self.llm = ChatOpenAI(
                    model_name=model,
                    openai_api_key=api_key,
                    temperature=0.7,
                    max_tokens=2000
                )
        
        # 初始化记忆系统
        self.memory = ConversationBufferMemory(
            memory_key="chat_history",
            return_messages=True
        )
        
        # 创建工具
        self.tools = self._create_tools()
        
        # 创建Agent
        self.agent = self._create_agent()
    
    def _create_tools(self):
        """创建工具集"""
        def search_movie_info(movie_name: str) -> str:
            """
            搜索电影详细信息

            Args:
                movie_name: 电影名称

            Returns:
                电影详细信息字符串
            """
            # 电影数据库(实际项目中应使用真实API,如TMDB API)
            movie_database = {
                "肖申克的救赎": {
                    "导演": "弗兰克·德拉邦特",
                    "主演": "蒂姆·罗宾斯、摩根·弗里曼",
                    "上映时间": "1994年",
                    "类型": "剧情、犯罪",
                    "评分": "9.7分(豆瓣)",
                    "剧情": "银行家安迪因被误判谋杀妻子和她的情人而入狱,在肖申克监狱中遇到了瑞德。安迪利用自己的金融知识帮助监狱长处理财务,同时策划越狱。经过19年的努力,安迪成功越狱并获得自由。",
                    "主题": "希望、自由、友谊、救赎",
                    "获奖": "1995年奥斯卡最佳影片提名",
                    "经典台词": "希望是美好的,也许是人间至善,而美好的事物永不消逝。"
                },
                "阿甘正传": {
                    "导演": "罗伯特·泽米吉斯",
                    "主演": "汤姆·汉克斯、罗宾·怀特",
                    "上映时间": "1994年",
                    "类型": "剧情、爱情",
                    "评分": "9.5分(豆瓣)",
                    "剧情": "智商只有75的阿甘,通过自己的努力和坚持,在人生各个阶段都取得了成功,包括成为橄榄球明星、越战英雄、乒乓球外交使者、亿万富翁。",
                    "主题": "坚持、纯真、人生意义",
                    "获奖": "1995年奥斯卡最佳影片",
                    "经典台词": "生活就像一盒巧克力,你永远不知道下一颗是什么味道。"
                },
                "泰坦尼克号": {
                    "导演": "詹姆斯·卡梅隆",
                    "主演": "莱昂纳多·迪卡普里奥、凯特·温丝莱特",
                    "上映时间": "1997年",
                    "类型": "爱情、灾难",
                    "评分": "9.4分(豆瓣)",
                    "剧情": "1912年泰坦尼克号邮轮在其处女航时触礁冰山而沉没,讲述了处于不同阶层的两个人------穷画家杰克和贵族露丝抛弃世俗的偏见坠入爱河,最终杰克把生存的机会让给了露丝的感人故事。",
                    "主题": "爱情、阶级、灾难、牺牲",
                    "获奖": "1998年奥斯卡最佳影片",
                    "经典台词": "你跳,我也跳。"
                },
                "盗梦空间": {
                    "导演": "克里斯托弗·诺兰",
                    "主演": "莱昂纳多·迪卡普里奥、玛丽昂·歌迪亚",
                    "上映时间": "2010年",
                    "类型": "科幻、悬疑、动作",
                    "评分": "9.3分(豆瓣)",
                    "剧情": "多姆·柯布是一位经验丰富的窃贼,专门潜入他人梦境中窃取潜意识里的秘密。他接受了一项新任务,不是窃取思想,而是植入思想。",
                    "主题": "梦境、现实、记忆、救赎",
                    "获奖": "2011年奥斯卡最佳视觉效果",
                    "经典台词": "你永远记不起一个梦的开始。"
                },
                "星际穿越": {
                    "导演": "克里斯托弗·诺兰",
                    "主演": "马修·麦康纳、安妮·海瑟薇",
                    "上映时间": "2014年",
                    "类型": "科幻、冒险",
                    "评分": "9.4分(豆瓣)",
                    "剧情": "在不远的未来,地球环境恶化,人类面临生存危机。前NASA飞行员库珀接受任务,驾驶飞船穿越虫洞寻找适合人类居住的星球。",
                    "主题": "爱、时间、牺牲、希望",
                    "获奖": "2015年奥斯卡最佳视觉效果",
                    "经典台词": "爱是唯一可以超越时间和空间的东西。"
                }
            }

            # 清理电影名称(去除书名号等)
            movie_name_clean = movie_name.strip().replace("《", "").replace("》", "").replace("\"", "").replace("'", "")

            if movie_name_clean in movie_database:
                info = movie_database[movie_name_clean]
                return f"""
电影名称:{movie_name_clean}

【基本信息】
导演:{info['导演']}
主演:{info['主演']}
上映时间:{info['上映时间']}
类型:{info['类型']}
评分:{info['评分']}

【剧情简介】
{info['剧情']}

【主题】
{info['主题']}

【获奖情况】
{info.get('获奖', '暂无')}

【经典台词】
{info.get('经典台词', '暂无')}
"""
            else:
                available_movies = "、".join(movie_database.keys())
                return f"""抱歉,未找到电影《{movie_name_clean}》的详细信息。

当前数据库包含以下电影:
{available_movies}

提示:你可以直接询问这些电影的信息,我会为你详细介绍。"""

        tools = [
            Tool(
                name="SearchMovieInfo",
                func=search_movie_info,
                description="""搜索电影的详细信息。输入应该是电影名称(可以带或不带书名号)。

返回的信息包括:
- 基本信息:导演、主演、上映时间、类型、评分
- 剧情简介
- 主题分析
- 获奖情况
- 经典台词

使用场景:
- 当用户询问电影信息时
- 当需要生成电影解说时
- 当需要回答关于电影的问题时

示例输入:
- "肖申克的救赎"
- "《阿甘正传》"
- "泰坦尼克号"
"""
            )
        ]

        return tools
    
    def _create_agent(self):
        """创建Agent(兼容新旧版本LangChain)"""
        if NEW_API:
            # 新版本LangChain API
            from langchain_core.prompts import ChatPromptTemplate

            # 创建Prompt模板
            prompt = ChatPromptTemplate.from_messages([
                SystemMessagePromptTemplate.from_template(MOVIE_COMMENTATOR_SYSTEM_PROMPT),
                MessagesPlaceholder(variable_name="chat_history"),
                HumanMessagePromptTemplate.from_template("{input}"),
                MessagesPlaceholder(variable_name="agent_scratchpad"),
            ])

            # 创建Agent
            agent = create_openai_tools_agent(self.llm, self.tools, prompt)

            # 创建AgentExecutor
            agent_executor = AgentExecutor(
                agent=agent,
                tools=self.tools,
                memory=self.memory,
                verbose=False,
                handle_parsing_errors=True
            )

            return agent_executor
        else:
            # 旧版本LangChain API
            try:
                from langchain.schema import SystemMessage
            except ImportError:
                from langchain_core.messages import SystemMessage

            agent_kwargs = {
                "system_message": SystemMessage(content=MOVIE_COMMENTATOR_SYSTEM_PROMPT),
                "extra_prompt_messages": [MessagesPlaceholder(variable_name="chat_history")]
            }

            agent = initialize_agent(
                tools=self.tools,
                llm=self.llm,
                agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
                memory=self.memory,
                agent_kwargs=agent_kwargs,
                verbose=False,
                handle_parsing_errors=True
            )

            return agent
    
    def comment(self, movie_name: str) -> str:
        """
        生成电影解说

        Args:
            movie_name: 电影名称

        Returns:
            电影解说文案
        """
        prompt = f"请为电影《{movie_name}》生成一份专业的解说文案,要求生动有趣、结构清晰,包括基本信息、剧情概述、主题分析和评价。"
        try:
            if NEW_API:
                # 新版本使用invoke方法
                response = self.agent.invoke({"input": prompt})
                return response.get("output", str(response))
            else:
                # 旧版本使用run方法
                response = self.agent.run(input=prompt)
                return response
        except Exception as e:
            return f"生成解说时出错:{str(e)}"

    def ask(self, question: str) -> str:
        """
        回答关于电影的问题

        Args:
            question: 用户问题

        Returns:
            回答内容
        """
        try:
            if NEW_API:
                # 新版本使用invoke方法
                response = self.agent.invoke({"input": question})
                return response.get("output", str(response))
            else:
                # 旧版本使用run方法
                response = self.agent.run(input=question)
                return response
        except Exception as e:
            return f"回答问题时出错:{str(e)}"

    def reset_memory(self):
        """重置对话记忆"""
        self.memory.clear()
        print("对话记忆已重置")

11.6 使用示例

11.6.1 基础使用
python 复制代码
from ai_agent import MovieCommentatorAgent

# 初始化Agent(支持OpenAI和DeepSeek)
# 推荐使用DeepSeek API(性价比高)
agent = MovieCommentatorAgent(
    api_key="your-deepseek-api-key",  # DeepSeek API密钥
    use_deepseek=True  # 使用DeepSeek
)

# 或使用OpenAI API
# agent = MovieCommentatorAgent(
#     api_key="your-openai-api-key",
#     use_deepseek=False,
#     model="gpt-3.5-turbo"  # 或 "gpt-4"
# )

# 生成电影解说
commentary = agent.comment("肖申克的救赎")
print(commentary)

# 回答问题
answer = agent.ask("这部电影的导演是谁?")
print(answer)

# 继续对话(Agent会记住之前的对话)
answer2 = agent.ask("这部电影的主题是什么?")
print(answer2)
11.6.2 完整对话示例
python 复制代码
from ai_agent import MovieCommentatorAgent, demo_movie_commentator, interactive_mode

# 方式1: 使用演示模式
if __name__ == "__main__":
    # 设置API密钥(推荐使用DeepSeek)
    DEEPSEEK_API_KEY = "your-deepseek-api-key"  # DeepSeek API密钥
    OPENAI_API_KEY = None  # OpenAI API密钥(可选)
    
    # 使用DeepSeek(推荐,性价比高)
    demo_movie_commentator(api_key=DEEPSEEK_API_KEY, use_deepseek=True)
    
    # 或使用OpenAI
    # demo_movie_commentator(api_key=OPENAI_API_KEY, use_deepseek=False)

# 方式2: 使用交互模式
# interactive_mode(api_key=DEEPSEEK_API_KEY, use_deepseek=True)

# 方式3: 命令行运行
# python ai_agent.py --mode demo --use-deepseek
# python ai_agent.py --mode interactive --use-deepseek

11.7 项目优化建议

11.7.1 功能扩展
  1. 集成真实API:使用TMDB、IMDb等电影API
  2. 多语言支持:支持英文、日文等电影解说
  3. 视频生成:结合TTS和视频生成技术
  4. 个性化推荐:基于用户喜好推荐电影
11.7.2 性能优化
  1. 缓存机制:缓存电影信息减少API调用
  2. 异步处理:支持异步请求提升响应速度
  3. 批量处理:支持批量生成多个电影解说
11.7.3 用户体验
  1. 流式输出:使用流式输出提升体验
  2. 错误处理:完善的错误处理和提示
  3. 交互优化:支持更自然的对话交互

总结与最佳实践

技术栈总结

技术栈关系图

AI Agent
LLM

核心推理引擎
LangChain

应用框架
LangGraph

图工作流
Agent

智能代理
Prompt

指令设计
RAG

知识增强
Vector DB

知识存储
Observability

可观测性
LangSmith

监控平台
PromptLayer

Prompt管理

技术栈层次结构
复制代码
AI Agent完整技术栈

┌──────────┐
│   LLM    │ → 核心推理引擎
└────┬─────┘
     │
┌────▼─────┐
│LangChain │ → 应用框架
│LangGraph │ → 图工作流
└────┬─────┘
     │
┌────▼─────┐
│  Agent   │ → 智能代理
└────┬─────┘
     │
┌────▼─────┐
│  Prompt  │ → 指令设计
└────┬─────┘
     │
┌────▼─────┐
│   RAG    │ → 知识增强
└────┬─────┘
     │
┌────▼─────┐
│Vector DB │ → 知识存储
└────┬─────┘
     │
┌────▼─────┐
│Observability│ → 可观测性
│LangSmith │ → 监控调试
│PromptLayer│ → Prompt管理
└──────────┘

最佳实践清单

✅ LLM使用
  1. 选择合适的模型:根据任务选择GPT-4、Claude或开源模型
  2. 参数调优:temperature、max_tokens等根据场景调整
  3. 错误处理:添加重试机制和错误处理
  4. 成本控制:监控token使用,优化Prompt长度
✅ LangChain开发
  1. 模块化设计:使用Chains、Agents等组件
  2. 记忆管理:根据场景选择合适的Memory类型
  3. 工具设计:创建清晰、可复用的工具
  4. 链式组合:合理组合多个Chain
✅ LangGraph使用
  1. 状态设计:合理设计状态结构
  2. 检查点使用:长时间任务使用检查点
  3. 可视化调试:利用可视化功能调试
  4. 错误处理:在节点中添加错误处理
✅ Agent开发
  1. 类型选择:根据任务选择合适的Agent类型
  2. 工具设计:工具描述要清晰准确
  3. 调用限制:限制工具调用次数避免循环
  4. 日志记录:记录Agent决策过程
✅ Observability实现
  1. 全面追踪:追踪所有LLM调用和工具执行
  2. 结构化日志:使用结构化日志格式
  3. 关键指标:监控延迟、错误率、成本
  4. 告警设置:设置异常告警
✅ LangSmith使用
  1. 项目组织:按项目组织追踪数据
  2. 标签使用:使用标签分类追踪
  3. 定期评估:定期运行评估测试
  4. 成本监控:监控Token使用和成本
✅ PromptLayer使用
  1. 版本管理:使用版本控制管理Prompt
  2. A/B测试:定期进行A/B测试优化
  3. 性能监控:监控Prompt效果
  4. 团队协作:建立Prompt评审流程
✅ Prompt工程
  1. 清晰明确:Prompt要具体、明确
  2. 提供示例:使用Few-shot示例
  3. 迭代优化:根据结果不断改进
  4. 模板化:创建可复用的Prompt模板
✅ RAG实现
  1. 文档预处理:合理分割文档
  2. 检索优化:使用混合检索、重排序
  3. 上下文管理:控制上下文长度
  4. 来源追踪:保留文档来源信息
✅ 向量数据库
  1. 选择合适的数据库:根据规模、需求选择
  2. 索引优化:使用合适的索引算法
  3. 批量操作:批量插入提高性能
  4. 监控维护:定期监控和优化

常见问题与解决方案

问题1: LLM回答不准确

解决方案

  • 改进Prompt,提供更多上下文
  • 使用RAG增强知识
  • 降低temperature提高确定性
问题2: RAG检索不相关

解决方案

  • 优化文档分割策略
  • 使用混合检索(关键词+向量)
  • 调整检索数量k值
  • 使用重排序
问题3: 响应速度慢

解决方案

  • 使用缓存
  • 异步处理
  • 优化向量数据库索引
  • 减少检索文档数量
问题4: Token消耗大

解决方案

  • 使用摘要Memory替代完整Memory
  • 优化Prompt长度
  • 压缩检索到的文档
  • 使用更小的模型

未来发展方向

  1. 多模态Agent:结合图像、音频等多模态输入
  2. 自主Agent:能够自主规划和执行复杂任务
  3. Agent协作:多个Agent协同工作
  4. 实时学习:Agent能够从交互中学习改进

附录:

requirement.txt

python 复制代码
# python3.10
langchain>=0.1.0,<1.0.0
langchain-openai>=0.1.0,<1.0.0
langchain-core>=0.1.0,<1.0.0
langchain-community>=0.1.0,<1.0.0

# OpenAI API(必须)
openai>=1.0.0
# 向量数据库
chromadb>=0.4.0
faiss-cpu>=1.7.4

# 文档处理
pypdf>=3.17.0
python-docx>=1.1.0
unstructured>=0.11.0
markdown>=3.5.0

# 文本处理
sentence-transformers>=2.2.0
tiktoken>=0.5.0

# 机器学习工具
scikit-learn>=1.3.0
numpy>=1.24.0

# 工具和工具链
python-dotenv>=1.0.0
requests>=2.31.0
jupyter>=1.0.0
ipython>=8.17.0

完整代码:

python 复制代码
from typing import Optional

# 兼容新旧版本的LangChain导入
NEW_API = False
ChatOpenAI = None
AgentExecutor = None
create_openai_tools_agent = None
Tool = None
ConversationBufferMemory = None
MessagesPlaceholder = None
ChatPromptTemplate = None
SystemMessagePromptTemplate = None
HumanMessagePromptTemplate = None
initialize_agent = None
AgentType = None
SystemMessage = None

# 尝试导入新版本LangChain (>=0.1.0)
try:
    from langchain_openai import ChatOpenAI
    from langchain.agents import AgentExecutor, create_openai_tools_agent
    from langchain.tools import Tool
    from langchain.memory import ConversationBufferMemory
    from langchain_core.prompts import (
        MessagesPlaceholder,
        ChatPromptTemplate,
        SystemMessagePromptTemplate,
        HumanMessagePromptTemplate
    )

    NEW_API = True
    print("✓ 使用新版本LangChain API")
except ImportError as e1:
    # 尝试使用旧版本LangChain (<0.1.0)
    try:
        from langchain.chat_models import ChatOpenAI
        from langchain.agents import initialize_agent, AgentType, Tool
        from langchain.memory import ConversationBufferMemory
        from langchain.prompts import MessagesPlaceholder
        from langchain.schema import SystemMessage

        NEW_API = False
        print("✓ 使用旧版本LangChain API")
    except ImportError as e2:
        # 尝试其他可能的导入方式
        try:
            # 尝试直接从langchain导入
            import langchain

            langchain_version = getattr(langchain, '__version__', 'unknown')
            print(f"检测到LangChain版本: {langchain_version}")

            # 尝试多种导入方式
            try:
                from langchain_community.chat_models import ChatOpenAI
            except:
                try:
                    from langchain_openai import ChatOpenAI
                except:
                    try:
                        from langchain.chat_models import ChatOpenAI
                    except:
                        raise ImportError("无法导入ChatOpenAI")

            # 尝试导入其他必要模块
            try:
                from langchain.agents import AgentExecutor, create_openai_tools_agent

                NEW_API = True
            except:
                try:
                    from langchain.agents import initialize_agent, AgentType

                    NEW_API = False
                except:
                    raise ImportError("无法导入Agent相关模块")

            from langchain.tools import Tool
            from langchain.memory import ConversationBufferMemory

            if NEW_API:
                from langchain_core.prompts import (
                    MessagesPlaceholder,
                    ChatPromptTemplate,
                    SystemMessagePromptTemplate,
                    HumanMessagePromptTemplate
                )
            else:
                from langchain.prompts import MessagesPlaceholder
                from langchain.schema import SystemMessage

        except Exception as e3:
            # 检查当前安装的LangChain版本
            try:
                import langchain

                installed_version = getattr(langchain, '__version__', 'unknown')
            except:
                installed_version = '未安装'

            error_msg = f"""
{'=' * 70}
❌ LangChain导入失败!
{'=' * 70}

当前LangChain版本: {installed_version}

【解决方案 - 推荐】

使用requirements文件安装(最简单):
    pip install -r requirements_ai_agent.txt

如果requirements文件不存在,手动安装核心依赖:
    pip uninstall langchain langchain-openai langchain-core langchain-community -y
    pip install langchain langchain-openai langchain-core langchain-community openai

【错误详情】
- 新版本导入错误: {str(e1)[:200]}
- 旧版本导入错误: {str(e2)[:200]}
- 其他错误: {str(e3)[:200]}

【验证安装】
安装后运行以下命令验证:
    python -c "from langchain_openai import ChatOpenAI; print('✓ 安装成功')"
{'=' * 70}
"""
            print(error_msg)
            raise ImportError("LangChain导入失败,请运行: pip install -r requirements_ai_agent.txt")

# 系统Prompt
MOVIE_COMMENTATOR_SYSTEM_PROMPT = """
你是一位专业的电影解说员,具有以下特点:

1. **专业素养**
   - 对电影艺术有深入理解
   - 熟悉各种电影类型和风格
   - 能够分析电影的深层含义

2. **解说风格**
   - 语言生动有趣,引人入胜
   - 结构清晰,逻辑严密
   - 既有专业分析,又通俗易懂

3. **内容要求**
   - 介绍电影基本信息(导演、演员、类型等)
   - 概述剧情(避免剧透关键情节)
   - 分析电影主题和艺术特色
   - 评价电影的艺术价值和观赏价值

4. **交互方式**
   - 回答用户关于电影的各种问题
   - 基于对话历史提供连贯的回答
   - 如果信息不足,主动使用SearchMovieInfo工具获取信息

请始终以专业、友好、生动的语调与用户交流。
"""


class MovieCommentatorAgent:
    """
    电影解说AI Agent

    功能:
    1. 搜索电影信息
    2. 生成专业电影解说
    3. 回答电影相关问题
    4. 支持多轮对话
    """

    def __init__(self, api_key: Optional[str] = None, model: str = "gpt-3.5-turbo", use_deepseek: bool = False):
        """
        初始化电影解说Agent

        Args:
            api_key: API密钥(OpenAI或DeepSeek)
            model: 使用的模型名称
                - OpenAI: "gpt-3.5-turbo", "gpt-4" 等
                - DeepSeek: "deepseek-chat"
            use_deepseek: 是否使用DeepSeek API,默认False(使用OpenAI)
        """
        if not api_key:
            raise ValueError("请提供API密钥")

        # 初始化LLM(兼容新旧版本)
        if use_deepseek:
            # 使用DeepSeek API
            deepseek_base_url = "https://api.deepseek.com"
            if NEW_API:
                self.llm = ChatOpenAI(
                    model="deepseek-chat",
                    openai_api_key=api_key,
                    openai_api_base=deepseek_base_url,
                    temperature=0.7,
                    max_tokens=2000
                )
            else:
                self.llm = ChatOpenAI(
                    model_name="deepseek-chat",
                    openai_api_key=api_key,
                    openai_api_base=deepseek_base_url,
                    temperature=0.7,
                    max_tokens=2000
                )
        else:
            # 使用OpenAI API
            if NEW_API:
                self.llm = ChatOpenAI(
                    model=model,
                    openai_api_key=api_key,
                    temperature=0.7,
                    max_tokens=2000
                )
            else:
                self.llm = ChatOpenAI(
                    model_name=model,
                    openai_api_key=api_key,
                    temperature=0.7,
                    max_tokens=2000
                )

        # 初始化记忆系统
        self.memory = ConversationBufferMemory(
            memory_key="chat_history",
            return_messages=True
        )

        # 创建工具
        self.tools = self._create_tools()

        # 创建Agent
        self.agent = self._create_agent()

    def _create_tools(self):
        """创建工具集"""

        def search_movie_info(movie_name: str) -> str:
            """
            搜索电影详细信息

            Args:
                movie_name: 电影名称

            Returns:
                电影详细信息字符串
            """
            # 电影数据库(实际项目中应使用真实API,如TMDB API)
            movie_database = {
                "肖申克的救赎": {
                    "导演": "弗兰克·德拉邦特",
                    "主演": "蒂姆·罗宾斯、摩根·弗里曼",
                    "上映时间": "1994年",
                    "类型": "剧情、犯罪",
                    "评分": "9.7分(豆瓣)",
                    "剧情": "银行家安迪因被误判谋杀妻子和她的情人而入狱,在肖申克监狱中遇到了瑞德。安迪利用自己的金融知识帮助监狱长处理财务,同时策划越狱。经过19年的努力,安迪成功越狱并获得自由。",
                    "主题": "希望、自由、友谊、救赎",
                    "获奖": "1995年奥斯卡最佳影片提名",
                    "经典台词": "希望是美好的,也许是人间至善,而美好的事物永不消逝。"
                },
                "阿甘正传": {
                    "导演": "罗伯特·泽米吉斯",
                    "主演": "汤姆·汉克斯、罗宾·怀特",
                    "上映时间": "1994年",
                    "类型": "剧情、爱情",
                    "评分": "9.5分(豆瓣)",
                    "剧情": "智商只有75的阿甘,通过自己的努力和坚持,在人生各个阶段都取得了成功,包括成为橄榄球明星、越战英雄、乒乓球外交使者、亿万富翁。",
                    "主题": "坚持、纯真、人生意义",
                    "获奖": "1995年奥斯卡最佳影片",
                    "经典台词": "生活就像一盒巧克力,你永远不知道下一颗是什么味道。"
                },
                "泰坦尼克号": {
                    "导演": "詹姆斯·卡梅隆",
                    "主演": "莱昂纳多·迪卡普里奥、凯特·温丝莱特",
                    "上映时间": "1997年",
                    "类型": "爱情、灾难",
                    "评分": "9.4分(豆瓣)",
                    "剧情": "1912年泰坦尼克号邮轮在其处女航时触礁冰山而沉没,讲述了处于不同阶层的两个人------穷画家杰克和贵族露丝抛弃世俗的偏见坠入爱河,最终杰克把生存的机会让给了露丝的感人故事。",
                    "主题": "爱情、阶级、灾难、牺牲",
                    "获奖": "1998年奥斯卡最佳影片",
                    "经典台词": "你跳,我也跳。"
                },
                "盗梦空间": {
                    "导演": "克里斯托弗·诺兰",
                    "主演": "莱昂纳多·迪卡普里奥、玛丽昂·歌迪亚",
                    "上映时间": "2010年",
                    "类型": "科幻、悬疑、动作",
                    "评分": "9.3分(豆瓣)",
                    "剧情": "多姆·柯布是一位经验丰富的窃贼,专门潜入他人梦境中窃取潜意识里的秘密。他接受了一项新任务,不是窃取思想,而是植入思想。",
                    "主题": "梦境、现实、记忆、救赎",
                    "获奖": "2011年奥斯卡最佳视觉效果",
                    "经典台词": "你永远记不起一个梦的开始。"
                },
                "星际穿越": {
                    "导演": "克里斯托弗·诺兰",
                    "主演": "马修·麦康纳、安妮·海瑟薇",
                    "上映时间": "2014年",
                    "类型": "科幻、冒险",
                    "评分": "9.4分(豆瓣)",
                    "剧情": "在不远的未来,地球环境恶化,人类面临生存危机。前NASA飞行员库珀接受任务,驾驶飞船穿越虫洞寻找适合人类居住的星球。",
                    "主题": "爱、时间、牺牲、希望",
                    "获奖": "2015年奥斯卡最佳视觉效果",
                    "经典台词": "爱是唯一可以超越时间和空间的东西。"
                }
            }

            # 清理电影名称(去除书名号等)
            movie_name_clean = movie_name.strip().replace("《", "").replace("》", "").replace("\"", "").replace("'", "")

            if movie_name_clean in movie_database:
                info = movie_database[movie_name_clean]
                return f"""
电影名称:{movie_name_clean}

【基本信息】
导演:{info['导演']}
主演:{info['主演']}
上映时间:{info['上映时间']}
类型:{info['类型']}
评分:{info['评分']}

【剧情简介】
{info['剧情']}

【主题】
{info['主题']}

【获奖情况】
{info.get('获奖', '暂无')}

【经典台词】
{info.get('经典台词', '暂无')}
"""
            else:
                available_movies = "、".join(movie_database.keys())
                return f"""抱歉,未找到电影《{movie_name_clean}》的详细信息。

当前数据库包含以下电影:
{available_movies}

提示:你可以直接询问这些电影的信息,我会为你详细介绍。"""

        tools = [
            Tool(
                name="SearchMovieInfo",
                func=search_movie_info,
                description="""搜索电影的详细信息。输入应该是电影名称(可以带或不带书名号)。

返回的信息包括:
- 基本信息:导演、主演、上映时间、类型、评分
- 剧情简介
- 主题分析
- 获奖情况
- 经典台词

使用场景:
- 当用户询问电影信息时
- 当需要生成电影解说时
- 当需要回答关于电影的问题时

示例输入:
- "肖申克的救赎"
- "《阿甘正传》"
- "泰坦尼克号"
"""
            )
        ]

        return tools

    def _create_agent(self):
        """创建Agent(兼容新旧版本LangChain)"""
        if NEW_API:
            # 新版本LangChain API
            from langchain_core.prompts import ChatPromptTemplate

            # 创建Prompt模板
            prompt = ChatPromptTemplate.from_messages([
                SystemMessagePromptTemplate.from_template(MOVIE_COMMENTATOR_SYSTEM_PROMPT),
                MessagesPlaceholder(variable_name="chat_history"),
                HumanMessagePromptTemplate.from_template("{input}"),
                MessagesPlaceholder(variable_name="agent_scratchpad"),
            ])

            # 创建Agent
            agent = create_openai_tools_agent(self.llm, self.tools, prompt)

            # 创建AgentExecutor
            agent_executor = AgentExecutor(
                agent=agent,
                tools=self.tools,
                memory=self.memory,
                verbose=False,
                handle_parsing_errors=True
            )

            return agent_executor
        else:
            # 旧版本LangChain API
            try:
                from langchain.schema import SystemMessage
            except ImportError:
                from langchain_core.messages import SystemMessage

            agent_kwargs = {
                "system_message": SystemMessage(content=MOVIE_COMMENTATOR_SYSTEM_PROMPT),
                "extra_prompt_messages": [MessagesPlaceholder(variable_name="chat_history")]
            }

            agent = initialize_agent(
                tools=self.tools,
                llm=self.llm,
                agent=AgentType.CHAT_CONVERSATIONAL_REACT_DESCRIPTION,
                memory=self.memory,
                agent_kwargs=agent_kwargs,
                verbose=False,
                handle_parsing_errors=True
            )

            return agent

    def comment(self, movie_name: str) -> str:
        """
        生成电影解说

        Args:
            movie_name: 电影名称

        Returns:
            电影解说文案
        """
        prompt = f"请为电影《{movie_name}》生成一份专业的解说文案,要求生动有趣、结构清晰,包括基本信息、剧情概述、主题分析和评价。"
        try:
            if NEW_API:
                # 新版本使用invoke方法
                response = self.agent.invoke({"input": prompt})
                return response.get("output", str(response))
            else:
                # 旧版本使用run方法
                response = self.agent.run(input=prompt)
                return response
        except Exception as e:
            return f"生成解说时出错:{str(e)}"

    def ask(self, question: str) -> str:
        """
        回答关于电影的问题

        Args:
            question: 用户问题

        Returns:
            回答内容
        """
        try:
            if NEW_API:
                # 新版本使用invoke方法
                response = self.agent.invoke({"input": question})
                return response.get("output", str(response))
            else:
                # 旧版本使用run方法
                response = self.agent.run(input=question)
                return response
        except Exception as e:
            return f"回答问题时出错:{str(e)}"

    def reset_memory(self):
        """重置对话记忆"""
        self.memory.clear()
        print("对话记忆已重置")


def demo_movie_commentator(api_key: Optional[str] = None, use_deepseek: bool = False):
    """电影解说Agent演示

    Args:
        api_key: API密钥(OpenAI或DeepSeek)
        use_deepseek: 是否使用DeepSeek API
    """
    print("=" * 70)
    print("🎬 电影解说AI Agent演示")
    print("=" * 70)

    # 检查API密钥
    if not api_key:
        print("\n❌ 错误:未提供API密钥")
        print("请在main函数中设置api_key")
        return

    try:
        # 初始化Agent
        print("\n📝 正在初始化电影解说Agent...")
        agent = MovieCommentatorAgent(api_key=api_key, use_deepseek=use_deepseek)
        print("✅ Agent初始化成功!\n")

        # 场景1: 生成电影解说
        print("=" * 70)
        print("【场景1】生成电影解说")
        print("=" * 70)
        print("\n用户: 请为《肖申克的救赎》生成一份专业的解说")
        print("\n" + "-" * 70)
        commentary = agent.comment("肖申克的救赎")
        print(f"\nAgent:\n{commentary}\n")

        # 场景2: 回答问题
        print("\n" + "=" * 70)
        print("【场景2】回答电影相关问题")
        print("=" * 70)
        questions = [
            "这部电影的导演是谁?",
            "主演有哪些?",
            "这部电影的主题是什么?",
            "这部电影获得了什么奖项?"
        ]

        for question in questions:
            print(f"\n用户: {question}")
            print("-" * 70)
            answer = agent.ask(question)
            print(f"Agent: {answer}")

        # 场景3: 多轮对话
        print("\n" + "=" * 70)
        print("【场景3】多轮对话 - 介绍新电影")
        print("=" * 70)
        agent.reset_memory()

        print("\n用户: 请介绍一下《盗梦空间》")
        print("-" * 70)
        answer1 = agent.ask("请介绍一下《盗梦空间》")
        print(f"Agent: {answer1}\n")

        print("用户: 这部电影的评分是多少?")
        print("-" * 70)
        answer2 = agent.ask("这部电影的评分是多少?")
        print(f"Agent: {answer2}\n")

        print("用户: 导演还拍过哪些经典电影?")
        print("-" * 70)
        answer3 = agent.ask("导演还拍过哪些经典电影?")
        print(f"Agent: {answer3}\n")

        print("=" * 70)
        print("✅ 演示完成!")
        print("=" * 70)

    except Exception as e:
        print(f"\n❌ 发生错误:{str(e)}")
        import traceback
        traceback.print_exc()


def interactive_mode(api_key: Optional[str] = None, use_deepseek: bool = False):
    """交互模式

    Args:
        api_key: API密钥(OpenAI或DeepSeek)
        use_deepseek: 是否使用DeepSeek API
    """
    print("=" * 70)
    print("🎬 电影解说AI Agent - 交互模式")
    print("=" * 70)
    print("\n提示:")
    print("  - 输入电影名称可以生成解说(如:请解说《肖申克的救赎》)")
    print("  - 输入问题可以询问电影信息(如:这部电影的导演是谁?)")
    print("  - 输入 'reset' 可以重置对话记忆")
    print("  - 输入 'quit' 或 'exit' 退出")
    print("=" * 70)

    if not api_key:
        print("\n❌ 错误:未提供API密钥")
        print("请在main函数中设置api_key")
        return

    try:
        agent = MovieCommentatorAgent(api_key=api_key, use_deepseek=use_deepseek)
        print("\n✅ Agent已就绪,开始对话吧!\n")

        while True:
            user_input = input("\n你: ").strip()

            if not user_input:
                continue

            if user_input.lower() in ['quit', 'exit', '退出']:
                print("\n👋 再见!")
                break

            if user_input.lower() == 'reset':
                agent.reset_memory()
                continue

            try:
                response = agent.ask(user_input)
                print(f"\nAgent: {response}")
            except Exception as e:
                print(f"\n❌ 错误:{str(e)}")

    except KeyboardInterrupt:
        print("\n\n👋 再见!")
    except Exception as e:
        print(f"\n❌ 发生错误:{str(e)}")
        import traceback
        traceback.print_exc()


if __name__ == "__main__":
    import argparse

    # 在main函数中直接设置API密钥
    # 支持OpenAI和DeepSeek
    DEEPSEEK_API_KEY = "sk-82bbcd7562414210891e7f50e0d1ef66"  # DeepSeek API密钥
    OPENAI_API_KEY = None  # OpenAI API密钥(如果需要使用OpenAI,请设置)

    # 选择使用的API(True=DeepSeek, False=OpenAI)
    USE_DEEPSEEK = True

    parser = argparse.ArgumentParser(description="电影解说AI Agent")
    parser.add_argument(
        "--mode",
        choices=["demo", "interactive"],
        default="demo",
        help="运行模式:demo(演示)或 interactive(交互)"
    )
    parser.add_argument(
        "--api-key",
        type=str,
        help="API密钥(可选,会覆盖main函数中的设置)"
    )
    parser.add_argument(
        "--use-deepseek",
        action="store_true",
        help="使用DeepSeek API(默认使用main函数中的设置)"
    )

    args = parser.parse_args()

    # 确定使用的API密钥和类型
    if args.api_key:
        api_key = args.api_key
        use_deepseek = args.use_deepseek if args.use_deepseek else USE_DEEPSEEK
    else:
        if USE_DEEPSEEK:
            api_key = DEEPSEEK_API_KEY
            use_deepseek = True
        else:
            api_key = OPENAI_API_KEY
            use_deepseek = False

    if not api_key:
        print("❌ 错误:未设置API密钥")
        print("请在main函数中设置DEEPSEEK_API_KEY或OPENAI_API_KEY")
        exit(1)

    if args.mode == "demo":
        demo_movie_commentator(api_key=api_key, use_deepseek=use_deepseek)
    else:
        interactive_mode(api_key=api_key, use_deepseek=use_deepseek)
相关推荐
程序员JerrySUN2 小时前
用 OP-TEE 给 AI 模型“上锁”:密文存储、TEE 解密放行、推理后销毁(实战可落地)
人工智能·系统安全·安全架构·安全性测试
xfchsjh2 小时前
在2025AI体验时代,看深圳河北上海设计公司重新定义数字科技展厅
人工智能·科技·设计·艺术·展厅设计·科技展厅设计·数字展厅设计
Brian Xia2 小时前
从0开始手写AI Agent框架:nano-agentscope(一)项目介绍
人工智能·python·ai
奔袭的算法工程师2 小时前
论文解读--FocalFormer3D : Focusing on Hard Instance for 3D Object Detection
人工智能·目标检测·计算机视觉
Sui_Network2 小时前
Sui 2025→2026 直播回顾中文版
大数据·前端·人工智能·深度学习·区块链
小宋加油啊2 小时前
lora大模型微调小例子
人工智能
天云数据2 小时前
【报名开启】“智防于心·安产于行”——AI赋能能源安全新质生产力研讨会(北京)
人工智能·安全·能源
富唯智能2 小时前
解锁“试管自动抓取搬运”新纪元:富唯智能复合机器人重塑精准物流
人工智能·机器人
ZPC82103 小时前
FANUC 机器人 PR 寄存器
人工智能·python·算法·机器人