基于AI智能体的YouTube视频自动摘要系统:从原理到实践
1. 项目概述:一个能自动总结YouTube视频的AI智能体
最近在捣鼓AI智能体(Agent)开发,发现一个特别有意思的应用场景:自动总结YouTube视频。想想看,每天有海量的视频内容发布,我们根本没时间一个个看完。如果能有一个智能助手,扔给它一个视频链接,它就能自动抓取、转录、分析,最后给你一份结构清晰的文字摘要,是不是效率神器?这个“YouTube Summarizer Agent”项目,就是基于这个痛点诞生的。它本质上是一个集成了多种AI能力的自动化工作流,核心目标是把冗长的视频内容,提炼成几分钟就能读完的精华。
这个项目非常适合对AI应用开发、自动化工具感兴趣的朋友,无论你是想提升个人学习效率的内容消费者,还是希望为自己的产品增加智能摘要功能的开发者,都能从中获得启发。整个实现过程会涉及到视频信息获取、音频转录、大语言模型(LLM)调用、提示词工程等多个环节,是一个综合性很强的练手项目。接下来,我会带你从零开始,拆解这个智能体的核心设计思路、技术选型考量,并手把手实现一个可运行的原型。
2. 核心设计思路与技术选型
2.1 工作流拆解:智能体如何“看懂”视频?
要让AI智能体总结视频,我们不能指望它直接“看”画面。更可行的路径是将其转化为AI更擅长的文本处理问题。因此,整个工作流可以分解为几个清晰的步骤:
- 输入与解析:用户提供一个YouTube视频链接。智能体首先需要验证链接的有效性,并从中提取出视频的唯一标识(如视频ID)。
- 内容获取:这是关键一步。我们需要获取视频的音频或字幕内容。理想情况下是直接获取官方字幕(CC),准确率最高。如果没有,则需要下载音频流,通过语音转文本(ASR)服务生成转录文本。
- 文本处理:获得的原始文本(字幕或转录稿)通常包含时间戳、说话人标记(如果有)、大量的语气词和重复内容。需要进行清洗,比如移除时间戳、合并断句、去除无关噪音,得到一篇连贯的文稿。
- 智能摘要:将清洗后的文稿,连同我们的摘要要求(如长度、风格、重点),通过精心设计的提示词(Prompt)提交给大语言模型(LLM)。LLM负责理解内容,并生成结构化的摘要。
- 输出与交付:将LLM生成的摘要以友好格式(如Markdown、纯文本)返回给用户,可以包含视频标题、原链接、摘要正文,甚至关键要点列表。
这个流程就像一个流水线,每个环节的稳定性和质量都直接影响最终结果。设计时,我们必须考虑异常处理,比如链接无效、视频无字幕且ASR失败、LLM返回内容不合规等情况。
2.2 技术栈选型背后的逻辑
围绕上述工作流,我们需要选择合适的技术组件。选型没有绝对标准,但核心原则是:在可靠性、成本、开发效率之间找到最佳平衡点。
编程语言与框架:Python是首选。它在AI和数据处理领域生态极其丰富,有大量现成的库支持网络请求、文本处理、API调用。对于构建智能体,我们可以从简单的脚本开始,也可以使用像LangChain或LlamaIndex这类框架。它们提供了连接各种工具(如网络搜索、计算器)和模型的标准接口,能大幅简化智能体的编排逻辑。对于这个项目,为了更清晰地理解底层原理,我们先从纯脚本实现开始,后期再考虑引入框架进行增强。
视频内容提取:这里有几个选择。
youtube-dl/yt-dlp:这是最强大、最流行的命令行工具之一,yt-dlp是其活跃分支。它们能直接从YouTube下载视频或音频,并提取字幕。优势是功能全面、稳定;劣势是需要作为子进程调用,且YouTube经常更新反爬机制,需要保持工具版本最新。- YouTube Data API v3:谷歌官方API。通过它可以直接获取视频的元数据(标题、描述)和字幕(如果存在且可访问)。优势是稳定、合规;劣势是有配额限制,且无法直接处理无字幕视频的音频。
- Pytube:一个纯Python库,用于从YouTube下载视频。它轻量、易于集成,但功能相对
yt-dlp简单,且稳定性有时会因YouTube改动而受影响。我的选择是:yt-dlp。因为它能最可靠地获取到音频流,这是应对无字幕视频的兜底方案。我们将用它来下载音频或字幕文件。
语音转文本(ASR):当视频没有现成字幕时,这是必需的。
- OpenAI Whisper:开源标杆,准确率高,支持多语言,有不同规模的模型(
tiny,base,small,medium,large)权衡速度与精度。可以本地运行,但大模型需要一定的GPU资源。 - 云服务API:如Google Cloud Speech-to-Text, Azure Cognitive Services Speech。准确率极高,尤其是对嘈杂环境,但会产生持续费用。
- 其他开源模型:如Facebook的Wav2Vec2。对于个人项目或原型,Whisper是最佳选择。我们使用其
base或small模型,在普通CPU上也能获得不错的效果,且完全免费。
- OpenAI Whisper:开源标杆,准确率高,支持多语言,有不同规模的模型(
大语言模型(LLM):这是生成摘要的“大脑”。
- OpenAI GPT系列:
gpt-3.5-turbo,gpt-4。易用性最好,效果稳定,提示词响应能力强。但需要API密钥和付费。 - 开源模型:如Llama 3、Mistral、Qwen系列。可以本地部署或通过如Ollama、LM Studio运行,数据隐私性好,无持续成本。但需要本地计算资源,且提示词工程可能需要更多调整。
- 其他云API:Anthropic Claude, Google Gemini。考虑到开发的便捷性和效果的可靠性,初期我会选择
gpt-3.5-turbo作为核心。它的成本对于文本摘要任务来说非常低,且能快速验证想法。后续可以轻松替换为其他模型。
- OpenAI GPT系列:
提示词工程:这是决定摘要质量的关键。一个糟糕的提示词可能让LLM复述原文或遗漏重点。我们需要设计一个结构化的提示词,明确告诉LLM:
- 它的角色(一个专业的视频内容总结助手)。
- 它的任务(基于提供的文稿生成摘要)。
- 摘要的具体要求(如:用中文输出;先概述视频核心主题;然后分3-5个要点阐述主要内容;最后总结视频的价值或观点;总字数控制在300-500字)。
- 输出格式(如使用Markdown标题和列表)。
注意:技术选型不是一成不变的。例如,如果你极度关注隐私,可以将
Whisper和Llama 3都部署在本地,打造一个完全离线的总结工具。如果你追求极致的转录准确率(特别是对于专业术语多的视频),那么投资云ASR服务是值得的。
3. 分步实现与核心代码解析
下面,我们按照工作流,用Python一步步实现这个智能体。请确保你的Python环境在3.8以上。
3.1 环境准备与依赖安装
首先,创建项目目录并安装必要的库。我们使用pip进行管理。
# 创建项目目录并进入 mkdir youtube-summarizer-agent && cd youtube-summarizer-agent # 创建虚拟环境(推荐) python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # macOS/Linux: source venv/bin/activate # 安装核心依赖 pip install yt-dlp openai-whisper openai # 安装其他辅助库 pip install requests python-dotenv这里解释一下:
yt-dlp: 用于下载YouTube音频和字幕。openai-whisper: OpenAI开源的语音识别库。openai: OpenAI的官方Python SDK,用于调用GPT API。requests: 用于可能的HTTP请求(如下一步用到的字幕解析)。python-dotenv: 用于从.env文件加载环境变量(如API密钥),避免硬编码。
创建一个.env文件来保存你的OpenAI API密钥:
OPENAI_API_KEY=你的_api_key_在这里3.2 步骤一:获取视频内容(音频/字幕)
我们编写一个函数,输入YouTube URL,输出干净的文本文稿。优先尝试获取字幕,失败则下载音频并用Whisper转录。
import yt_dlp import whisper import os from urllib.parse import urlparse, parse_qs import requests import re def get_video_transcript(video_url): """ 从YouTube视频获取文本转录稿。 返回: (video_title, transcript_text) """ video_id = extract_video_id(video_url) if not video_id: raise ValueError("无法从URL中提取有效的视频ID") # 方法1: 尝试通过yt-dlp获取自动生成或上传的字幕 transcript = try_get_subtitles_with_ytdlp(video_id) if transcript: print(f"[INFO] 成功通过yt-dlp获取视频字幕。") # 通常需要从yt-dlp返回的数据结构中提取文本并清理时间戳 # 这里假设返回的是纯文本或VTT格式文本 cleaned_text = clean_subtitle_text(transcript) return get_video_title(video_id), cleaned_text # 方法2: 下载音频并用Whisper转录 (兜底方案) print(f"[INFO] 未找到可用字幕,开始下载音频并转录...") audio_path = download_audio(video_url) transcript_text = transcribe_audio_with_whisper(audio_path) # 清理临时音频文件 os.remove(audio_path) print(f"[INFO] 音频转录完成。") return get_video_title(video_id), transcript_text def extract_video_id(url): """从各种格式的YouTube URL中提取视频ID。""" parsed = urlparse(url) if parsed.hostname in ('youtu.be',): return parsed.path[1:] if parsed.hostname in ('www.youtube.com', 'youtube.com', 'm.youtube.com'): if parsed.path == '/watch': return parse_qs(parsed.query).get('v', [None])[0] elif parsed.path.startswith('/embed/'): return parsed.path.split('/')[2] elif parsed.path.startswith('/v/'): return parsed.path.split('/')[2] return None def try_get_subtitles_with_ytdlp(video_id): """使用yt-dlp尝试获取字幕,优先选择中文或英文。""" ydl_opts = { 'skip_download': True, 'writesubtitles': True, 'writeautomaticsub': True, 'subtitleslangs': ['zh', 'en', 'zh-Hans', 'zh-CN', 'en-US'], # 优先中英文 'quiet': True, 'no_warnings': True, } try: with yt_dlp.YoutubeDL(ydl_opts) as ydl: # 获取信息,不下载视频 info = ydl.extract_info(f'https://www.youtube.com/watch?v={video_id}', download=False) subtitles = info.get('subtitles') or info.get('automatic_captions') if subtitles: # 优先返回中文字幕,其次英文 for lang in ['zh', 'zh-Hans', 'zh-CN', 'en', 'en-US']: if lang in subtitles: sub_url = subtitles[lang][0]['url'] # 下载字幕文件(通常是VTT格式) response = requests.get(sub_url) return response.text except Exception as e: print(f"[WARN] 通过yt-dlp获取字幕失败: {e}") return None def clean_subtitle_text(raw_subtitle_text): """清理VTT等字幕格式中的时间戳和无关标记。""" # 这是一个简单的清洗示例,实际中可能需要更复杂的正则表达式 # 移除WEBVTT头部、时间行(如 00:00:01.000 --> 00:00:04.000) lines = raw_subtitle_text.split('\n') cleaned_lines = [] for line in lines: line = line.strip() if not line or line.startswith('WEBVTT') or '-->' in line or line.isdigit(): continue cleaned_lines.append(line) # 合并被断开的句子 cleaned_text = ' '.join(cleaned_lines) # 合并过多的空格 cleaned_text = re.sub(r'\s+', ' ', cleaned_text) return cleaned_text.strip() def download_audio(video_url, output_template='temp_audio.%(ext)s'): """使用yt-dlp下载音频文件,返回本地文件路径。""" ydl_opts = { 'format': 'bestaudio/best', 'outtmpl': output_template, 'quiet': True, 'no_warnings': True, 'postprocessors': [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', # 或 'm4a', 'webm' 'preferredquality': '192', }], } with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(video_url, download=True) # yt-dlp会根据postprocessor重命名文件,通常是原模板名加上.mp3后缀 audio_filename = ydl.prepare_filename(info).rsplit('.', 1)[0] + '.mp3' # 确保文件存在 if os.path.exists(audio_filename): return audio_filename else: # 备用查找逻辑 for ext in ['.mp3', '.m4a', '.webm']: possible_file = output_template.replace('%(ext)s', ext.lstrip('.')) if os.path.exists(possible_file): return possible_file raise FileNotFoundError(f"无法找到下载的音频文件") def transcribe_audio_with_whisper(audio_path, model_size='base'): """使用Whisper模型转录音频文件。""" print(f"[INFO] 正在加载Whisper {model_size}模型...") model = whisper.load_model(model_size) print(f"[INFO] 开始转录 {audio_path} ...") result = model.transcribe(audio_path, fp16=False) # CPU上fp16=False return result['text'] def get_video_title(video_id): """获取视频标题。""" try: ydl_opts = {'quiet': True, 'no_warnings': True} with yt_dlp.YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(f'https://www.youtube.com/watch?v={video_id}', download=False) return info.get('title', '未知标题') except: return '未知标题'实操心得:
yt-dlp的writesubtitles和writeautomaticsub选项是关键,前者获取上传的字幕,后者获取自动生成的字幕。- Whisper模型大小选择:
tiny和base速度最快,适合演示;small和medium准确率显著提升;large最准但也最慢。对于摘要任务,base或small通常已足够,因为LLM对转录中的少量错误有一定容错性。 - 下载音频时,格式选择
mp3兼容性最好。整个过程可能会产生几百MB的临时音频文件,处理完后务必删除。
3.3 步骤二:设计提示词与调用LLM生成摘要
获得干净的文稿后,我们需要设计一个有效的提示词来引导GPT生成高质量的摘要。
from openai import OpenAI import os from dotenv import load_dotenv load_dotenv() # 加载.env文件中的环境变量 def generate_summary_with_gpt(transcript_text, video_title, language='中文'): """ 使用OpenAI GPT模型生成视频摘要。 """ client = OpenAI(api_key=os.getenv('OPENAI_API_KEY')) # 精心设计的提示词 (System Message + User Message) system_prompt = f"""你是一个专业的视频内容分析助手。你的任务是根据用户提供的视频转录文本,生成一份高质量、结构清晰的摘要。摘要语言请使用{language}。""" user_prompt = f"""请为以下YouTube视频生成一份摘要。 视频标题:{video_title} 视频转录文本: {transcript_text} 请按照以下要求生成摘要: 1. **核心概述**:用一两句话概括整个视频的核心主题与价值。 2. **主要内容**:分点(3-5点)阐述视频中讨论的关键内容、步骤或观点。每一点应简洁明了。 3. **结论与启示**:总结视频得出的主要结论、给观众的建议或带来的启发。 4. **目标观众**:简要说明这个视频最适合哪类人群观看。 请确保摘要: - 基于转录文本,忠实于原视频内容。 - 语言流畅、逻辑清晰。 - 总字数控制在400字左右。 - 使用恰当的Markdown格式进行排版,如使用**加粗**强调重点,使用列表排列要点。 """ try: response = client.chat.completions.create( model="gpt-3.5-turbo", # 或 "gpt-4" messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt} ], temperature=0.5, # 控制创造性。摘要任务需要较低的温度以保证忠实度。 max_tokens=800, # 控制生成摘要的最大长度 ) summary = response.choices[0].message.content return summary except Exception as e: return f"生成摘要时出错: {e}"提示词设计解析:
- 系统提示(System Prompt):定义了AI的“角色”和“任务”,让它进入正确的状态。
- 用户提示(User Prompt):提供了具体的“上下文”(标题和文稿)和清晰的“指令”。指令被结构化,明确要求了摘要的组成部分(概述、要点、结论、受众)和格式要求。这比简单地说“请总结一下”效果要好得多。
- 参数设置:
temperature=0.5是一个平衡值,既不会太死板也不会太天马行空。max_tokens=800确保了回复不会过长。
3.4 步骤三:组装智能体与主函数
现在,我们把所有部件组装起来,形成一个完整的脚本。
def main(): print("=== YouTube视频摘要智能体 ===") video_url = input("请输入YouTube视频链接: ").strip() try: print("正在处理视频链接...") video_title, transcript = get_video_transcript(video_url) if not transcript or len(transcript.strip()) < 50: # 简单检查转录文本是否有效 print("错误:无法获取有效的视频转录内容。可能是视频不可访问、无音频或转录失败。") return print(f"视频标题: {video_title}") print(f"获取到转录文本长度: {len(transcript)} 字符") print("-" * 40) print("正在调用AI生成摘要...") summary = generate_summary_with_gpt(transcript, video_title) print("\n" + "="*50) print("生成摘要完成!\n") print(summary) print("\n" + "="*50) # 可选:将摘要保存到文件 save_to_file = input("\n是否将摘要保存到文件?(y/n): ").lower().strip() if save_to_file == 'y': filename = f"summary_{video_title[:30]}.md".replace(' ', '_').replace('/', '_') with open(filename, 'w', encoding='utf-8') as f: f.write(f"# 视频摘要: {video_title}\n\n") f.write(f"**原视频链接**: {video_url}\n\n") f.write(f"**生成时间**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n") f.write("---\n\n") f.write(summary) print(f"摘要已保存至: {filename}") except Exception as e: print(f"程序运行过程中出现错误: {e}") import traceback traceback.print_exc() if __name__ == "__main__": from datetime import datetime main()这个main函数提供了一个简单的命令行交互界面。它串联了整个流程:获取输入、提取内容、生成摘要、输出结果。你可以将其包装成Web API(使用FastAPI或Flask)、桌面应用(使用Tkinter或PyQt)或聊天机器人插件,使其更易用。
4. 进阶优化与问题排查
一个基础版本跑通后,我们可以从多个角度进行优化,让它更健壮、更智能。
4.1 性能与成本优化策略
- 缓存转录结果:对于同一个视频,重复处理是一种浪费。可以建立简单的缓存机制,将
video_id和对应的transcript以及summary存入本地数据库(如SQLite)或文件。下次请求时先检查缓存,命中则直接返回摘要,避免重复调用昂贵的ASR和LLM API。 - 摘要文本长度优化:超长视频的转录稿可能达到数万字,直接扔给GPT不仅成本高(按Token计费),还可能超过模型的上下文窗口限制。解决方案是分块摘要:
- 将长文稿按语义分割成若干块(例如每1000字一块)。
- 对每一块生成一个“分块摘要”。
- 将所有“分块摘要”拼接起来,再让GPT基于这些分块摘要生成最终的“全局摘要”。
- 这可以通过递归调用
generate_summary_with_gpt函数实现,或者使用LangChain的map_reduce链。
- 模型降级与替代:对于摘要任务,
gpt-3.5-turbo在大多数情况下已经足够好且成本更低。只有在需要极高质量、复杂推理或处理非常专业晦涩的内容时,才考虑使用gpt-4。此外,可以集成开源模型作为备选,当OpenAI API不可用时自动切换。 - 并行处理:如果构建批量处理系统,可以并行下载和转录多个视频,但要注意网络和计算资源的限制。
4.2 提升摘要质量的技巧
- 提示词迭代:摘要的质量极度依赖提示词。你可以尝试:
- 指定风格:“用活泼的口语化风格总结”、“用学术报告的风格总结”。
- 聚焦重点:“请重点关注视频中关于‘神经网络架构’的部分”、“请忽略开头的赞助商广告内容”。
- 输出特定格式:“生成一个包含‘问题’、‘分析’、‘解决方案’三部分的摘要”、“以QA形式列出视频解答的三个主要问题”。
- 后处理与润色:GPT生成的摘要有时会有冗余或格式小问题。可以编写简单的后处理函数,例如移除重复的标题、标准化列表格式、检查并修正明显的错别字(虽然GPT很少犯)。
- 多语言支持:我们的提示词中已经包含了
language参数。你可以让用户选择摘要语言,甚至实现“视频是英文,摘要输出中文”的跨语言摘要功能。这只需要在提示词中明确说明“请将以下英文内容总结为中文”即可,GPT能很好地处理。 - 提取关键时间戳:在摘要中标注“关于XX的讨论在视频第10分钟开始”,这对用户非常有用。这需要我们在清洗字幕时保留时间戳与文本的映射关系,并在提示词中要求GPT在总结时引用相关时间点。
4.3 常见问题与解决方案实录
在实际操作中,你肯定会遇到各种问题。下面是我踩过的一些坑和解决办法:
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
yt-dlp下载失败,报错Unable to extract uploader id或Video unavailable | 1. 视频链接无效或私密。 2. yt-dlp版本过旧,无法应对YouTube更新。3. 网络问题或地区限制。 | 1. 手动在浏览器中打开链接确认视频可访问。 2. 运行 pip install -U yt-dlp升级到最新版。3. 尝试使用 --proxy参数配置代理(注意:此处代理指常规网络代理,用于解决网络连通性问题,必须合规使用)。4. 尝试使用 --cookies参数提供浏览器Cookie(用于年龄限制视频)。 |
| Whisper转录速度极慢,或内存不足 | 1. 使用了过大的模型(如large)。2. 音频文件很长。 3. CPU性能不足,且未使用GPU。 | 1. 换用更小的模型,如base或small。2. 对于长音频,考虑先使用 ffmpeg将其分割成15-30分钟的小段再分别转录。3. 如果拥有支持CUDA的NVIDIA GPU,确保安装了 pip install openai-whisper[gpu]或对应的PyTorch GPU版本。 |
OpenAI API调用返回错误InvalidRequestError: This model's maximum context length is ... | 输入的转录文本太长,超过了模型的最大上下文长度(如gpt-3.5-turbo通常是16K tokens)。 | 1.最有效方案:实施上文提到的“分块摘要”策略。 2. 在调用API前,先计算文本的token数(可用 tiktoken库),如果超长则自动触发分块处理。3. 对于极长视频,考虑先使用GPT或其他方法生成一个极简大纲,再针对各部分细化。 |
| 生成的摘要偏离主题或包含幻觉内容 | 1. 提示词不够明确。 2. 转录文本质量太差(ASR错误多)。 3. LLM的 temperature参数设置过高。 | 1. 优化提示词,加入“严格基于提供的文本”、“不要添加文本中不存在的信息”等约束。 2. 尝试使用更准确的Whisper模型( medium,large)或云ASR服务提升转录质量。3. 将 temperature调低至0.3或0.2,减少随机性。 |
程序在download_audio阶段卡住或无响应 | 1. 网络连接不稳定。 2. yt-dlp在尝试下载最佳格式时遇到问题。3. FFmpeg未安装或不在系统路径中。 | 1. 为yt-dlp设置超时参数--socket-timeout和--retries。2. 指定一个明确的、稳定的音频格式,如 'format': 'bestaudio[ext=m4a]/bestaudio'。3.确保FFmpeg已正确安装。这是 yt-dlp进行后处理(提取音频)的必需组件。去FFmpeg官网下载并添加到系统环境变量PATH中。 |
| 无法获取字幕,即使视频有CC字幕 | 1. 字幕语言代码不匹配。 2. 字幕格式 yt-dlp无法解析。3. 该字幕是付费功能或区域限制。 | 1. 扩展subtitleslangs列表,尝试更多语言变种,如['zh.*', 'en.*', 'a.*'](a.*代表自动生成字幕)。2. 查看 yt-dlp返回的info字典,手动检查subtitles和automatic_captions的具体结构。3. 接受现实,有些视频的字幕就是无法通过API获取,此时兜底的音频转录方案是必须的。 |
一个关键的避坑技巧:在处理任何用户输入的URL时,一定要做有效性验证和清理。除了提取video_id,还应检查URL的格式,防止注入恶意命令(虽然通过yt-dlp直接执行用户输入的风险相对较低,但良好的习惯很重要)。可以使用正则表达式严格匹配YouTube的URL模式。
5. 从脚本到智能体:赋予它“思考”和“行动”的能力
到目前为止,我们构建的是一个线性的、确定性的脚本。一个真正的“智能体”(Agent)应该能更自主地处理复杂情况。我们可以借助LangChain来重构它,使其具备以下能力:
- 工具使用:将“下载并转录视频”和“调用LLM总结”封装成两个独立的
Tool。智能体可以自行决定何时使用哪个工具。 - 记忆与多轮对话:让智能体记住用户的历史请求,例如用户可以说“总结我上次发给你的那个视频的关键论点”,或者“用更简短的话再说一遍”。
- 处理模糊指令:用户可能说“给我讲讲这个视频”,智能体需要理解这是要求总结,然后自动执行整个流程。
下面是一个使用LangChain框架的概念性代码结构,展示如何将我们的功能“智能体化”:
# 示例:使用LangChain重构(概念代码,需安装langchain, langchain-openai等库) from langchain.agents import AgentExecutor, create_react_agent from langchain.tools import Tool from langchain_openai import ChatOpenAI from langchain.prompts import PromptTemplate from langchain.memory import ConversationBufferMemory # 1. 将我们的功能包装成Tool def get_video_transcript_tool(video_url: str) -> str: """工具:获取视频转录稿。输入是YouTube URL,输出是文本。""" title, transcript = get_video_transcript(video_url) return f"视频标题:《{title}》\n\n转录文本:{transcript[:2000]}..." # 返回部分文本 def summarize_text_tool(text: str) -> str: """工具:总结文本。输入是长文本,输出是摘要。""" # 这里可以复用之前的generate_summary_with_gpt函数,或设计新的提示词 summary = generate_summary_with_gpt(text, "提供的文本") return summary tools = [ Tool( name="GetVideoTranscript", func=get_video_transcript_tool, description="当用户提供一个YouTube视频链接时,使用此工具获取视频的标题和文字转录稿。" ), Tool( name="SummarizeText", func=summarize_text_tool, description="当有一段长文本需要概括总结时,使用此工具生成一份简洁的摘要。" ), ] # 2. 创建LLM和带有记忆的智能体 llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0) memory = ConversationBufferMemory(memory_key="chat_history") agent_prompt = PromptTemplate.from_template( """你是一个YouTube视频总结助手。你可以通过工具获取视频的转录文本并对其进行总结。 你有权使用以下工具: {tools} 使用以下格式: 问题:用户输入的问题 思考:你需要思考现在应该做什么,可以使用哪个工具 行动:要使用的工具名称,必须是[{tool_names}]中的一个 行动输入:工具的输入 观察:工具返回的结果 ... (这个思考/行动/观察循环可以重复多次) 思考:我现在有最终答案了 最终答案:对用户问题的最终回答 开始! 之前的对话记录: {chat_history} 问题:{input} 思考:{agent_scratchpad}""" ) agent = create_react_agent(llm, tools, agent_prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, memory=memory, verbose=True) # 3. 运行智能体 result = agent_executor.invoke({"input": "请总结一下这个视频:https://www.youtube.com/watch?v=example_id"}) print(result["output"])在这个框架下,智能体可以自行推理:“用户给了我一个链接,我需要先获取内容(使用GetVideoTranscript工具),拿到内容后,我需要总结它(使用SummarizeText工具)”。这为处理更复杂的请求(如“比较这两个视频的观点差异”)奠定了基础。
构建这个YouTube总结智能体的过程,是一次完整的AI应用开发实践。它涉及了数据获取、预处理、核心AI模型调用、提示词工程、系统集成和问题排查。从简单的脚本开始,逐步迭代优化,最终可以扩展成一个功能强大、鲁棒性高的自动化工具。最重要的是,这个框架可以迁移到无数其他场景——总结播客、分析PDF文档、解读长篇报道——其核心模式(获取内容->处理内容->LLM提炼->输出)是相通的。
