第四部分:实战项目
- [第十一章:电影解说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 功能扩展
- 集成真实API:使用TMDB、IMDb等电影API
- 多语言支持:支持英文、日文等电影解说
- 视频生成:结合TTS和视频生成技术
- 个性化推荐:基于用户喜好推荐电影
11.7.2 性能优化
- 缓存机制:缓存电影信息减少API调用
- 异步处理:支持异步请求提升响应速度
- 批量处理:支持批量生成多个电影解说
11.7.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使用
- 选择合适的模型:根据任务选择GPT-4、Claude或开源模型
- 参数调优:temperature、max_tokens等根据场景调整
- 错误处理:添加重试机制和错误处理
- 成本控制:监控token使用,优化Prompt长度
✅ LangChain开发
- 模块化设计:使用Chains、Agents等组件
- 记忆管理:根据场景选择合适的Memory类型
- 工具设计:创建清晰、可复用的工具
- 链式组合:合理组合多个Chain
✅ LangGraph使用
- 状态设计:合理设计状态结构
- 检查点使用:长时间任务使用检查点
- 可视化调试:利用可视化功能调试
- 错误处理:在节点中添加错误处理
✅ Agent开发
- 类型选择:根据任务选择合适的Agent类型
- 工具设计:工具描述要清晰准确
- 调用限制:限制工具调用次数避免循环
- 日志记录:记录Agent决策过程
✅ Observability实现
- 全面追踪:追踪所有LLM调用和工具执行
- 结构化日志:使用结构化日志格式
- 关键指标:监控延迟、错误率、成本
- 告警设置:设置异常告警
✅ LangSmith使用
- 项目组织:按项目组织追踪数据
- 标签使用:使用标签分类追踪
- 定期评估:定期运行评估测试
- 成本监控:监控Token使用和成本
✅ PromptLayer使用
- 版本管理:使用版本控制管理Prompt
- A/B测试:定期进行A/B测试优化
- 性能监控:监控Prompt效果
- 团队协作:建立Prompt评审流程
✅ Prompt工程
- 清晰明确:Prompt要具体、明确
- 提供示例:使用Few-shot示例
- 迭代优化:根据结果不断改进
- 模板化:创建可复用的Prompt模板
✅ RAG实现
- 文档预处理:合理分割文档
- 检索优化:使用混合检索、重排序
- 上下文管理:控制上下文长度
- 来源追踪:保留文档来源信息
✅ 向量数据库
- 选择合适的数据库:根据规模、需求选择
- 索引优化:使用合适的索引算法
- 批量操作:批量插入提高性能
- 监控维护:定期监控和优化
常见问题与解决方案
问题1: LLM回答不准确
解决方案:
- 改进Prompt,提供更多上下文
- 使用RAG增强知识
- 降低temperature提高确定性
问题2: RAG检索不相关
解决方案:
- 优化文档分割策略
- 使用混合检索(关键词+向量)
- 调整检索数量k值
- 使用重排序
问题3: 响应速度慢
解决方案:
- 使用缓存
- 异步处理
- 优化向量数据库索引
- 减少检索文档数量
问题4: Token消耗大
解决方案:
- 使用摘要Memory替代完整Memory
- 优化Prompt长度
- 压缩检索到的文档
- 使用更小的模型
未来发展方向
- 多模态Agent:结合图像、音频等多模态输入
- 自主Agent:能够自主规划和执行复杂任务
- Agent协作:多个Agent协同工作
- 实时学习: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)