n8n YouTube Assistant:用 n8n + Supabase 构建可检索的 YouTube 视频知识库 Agent
【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents
导读
本文围绕 n8n-youtube-agent 展开,它是由 Dominik Fretz 编写、托管在 oTTomator Live Agent Studio 平台上的一个开源 n8n Agent 工作流:只需粘贴一个 YouTube 链接,工作流便会自动抓取视频字幕、调用大模型生成摘要/要点/行动项/金句/标签,并把全文与向量化切片一并写入 Supabase,之后你就可以像聊天一样对它提问——获取单个视频的总结、追问题或跨视频语义搜索。读完本文,你将掌握该工作流从 Webhook 入口、意图分类、字幕抓取、向量入库到检索问答的完整节点链路,能够将其导入自己的 n8n 实例、配置四类凭证并落地运行。
一、Agent 概览:它是如何工作的
根据 README,该 Agent 的核心职责是:根据视频 URL 加载 YouTube 字幕,将字幕写入向量存储(vector store),同时生成摘要、关键要点、引文等信息并存入 Supabase 数据库。在此基础上,你可以与已入库的视频对话:请求摘要、针对特定视频追问,或跨视频检索(例如"之前哪个视频讲到过某本书/某个工具/某个人")。
从 YouTube_Agent.json 的节点清单可以看到,工作流共包含56 个节点,其中既有n8n-nodes-base的基础节点(Webhook、HTTP Request、Code、Switch、Set、Merge、XML、Supabase),也有@n8n/n8n-nodes-langchain的 AI 编排节点(AI Agent、Structured Output Parser、Vector Store、Embeddings、Text Splitter、Buffer Memory、Chat Model),整体可拆解为四条主流程:
| 流程 | 关键节点 | 职责 |
|---|---|---|
| 入口与意图识别 | Webhook → Prep Input Fields → AI Agent(分类器)→ Switch | 接收请求,把用户输入分类为add / summarize / search / respond |
| 添加视频(add) | Code 提取 ID → 查重 → 抓取字幕 → 生成摘要/标签 → 写入 videos 表与向量库 | 把新视频完整入库 |
| 总结视频(summarize) | 按 videoId 查 videos 表 → AI Agent1 → Gather output data | 基于已存摘要回答追问 |
| 搜索视频(search) | Search Agent + Supabase Vector Store(检索工具) | 向量检索历史视频并作答 |
二、依赖与凭证:运行前需要准备什么
README 明确列出了四项核心依赖:
- Claude Haiku(Anthropic)——负责所有 LLM 推理任务;
- OpenAI Embedding Model——生成文本向量;
- Supabase——关系表 + 向量存储 + 检索函数;
- Supadata——第三方 YouTube 字幕抓取 API。
对应的必须配置的凭证(见 README "Required configuration setup"):
- YouTube Data API 凭证:用于 "Fetch video details" 节点,抓取视频标题、描述、频道名(节点使用
youTubeOAuth2Api凭证类型); - Supadata 凭证:用于
https://api.supadata.ai/v1/youtube/transcript接口(HTTP Headerx-api-key); - OpenAI 凭证:用于
embeddingsOpenAi节点生成向量; - Anthropic Claude 凭证:用于 5 个 Agent 节点共用的
lmChatAnthropic聊天模型。
此外,还需通过supabase.table.sql在 Supabase 中建表。值得注意的是,除 Supadata 路径外,工作流还内置了一套备用字幕获取方案(见 Sticky Note 说明):直接请求https://www.youtube.com/watch?v={video_id}页面,从 HTML 中解析"captions"JSON 得到字幕 baseUrl,再抓取字幕 XML 并解析拼接。该方案的优势是不依赖第三方 API,但工作流作者在 Sticky Note 中明确警告:"如果你这样用得太多,可能会被迫登录以证明你不是机器人"——因此建议优先使用 Supadata。
三、数据库设计:videos 表与向量检索函数
supabase.table.sql 定义了整套数据层,分为三个部分。
3.1 videos 表:视频结构化信息
create table public.videos ( id bigint generated by default as identity not null, created_at timestamp with time zone not null default now(), video_id text null, title text null, description text null, summary text null, keypoints text[] null, actionable text[] null, quotes text[] null, tags text[] null, channel text null, transcript text null, constraint videos_pkey primary key (id) ) TABLESPACE pg_default;这张表是"添加视频"分支的落点,字段与 LLM 输出一一对应:video_id(去重主键依据)、title/channel/description(来自 YouTube Data API)、summary/keypoints/actionable/quotes/tags(来自 Claude 的结构化输出)、transcript(完整字幕文本)。
3.2 youtube_agent_data 表:向量存储
create table youtube_agent_data ( id bigserial primary key, content text, -- 对应 Document.pageContent metadata jsonb, -- 对应 Document.metadata embedding vector(1536) -- 1536 维,适配 OpenAI 嵌入模型,按需修改 );这张表存的是字幕切片的向量化结果。注释明确说明content对应 LangChain 的Document.pageContent、metadata对应Document.metadata——与 n8n 的 Supabase Vector Store 节点(tableName: youtube_agent_data)直接对接。vector(1536)是 OpenAI 默认嵌入(text-embedding-3-small 等)的输出维度,若更换其他嵌入模型(如 3072 维的 text-embedding-3-large)需同步调整。
3.3 match_youtube_data 函数:语义检索
create function match_youtube_data ( query_embedding vector(1536), match_count int default null, filter jsonb DEFAULT '{}' ) returns table ( id bigint, content text, metadata jsonb, similarity float ) language plpgsql as $$ #variable_conflict use_column begin return query select id, content, metadata, 1 - (youtube_agent_data.embedding <=> query_embedding) as similarity from youtube_agent_data where metadata @> filter order by youtube_agent_data.embedding <=> query_embedding limit match_count; end; $$;这是 pgvector 标准的余弦距离检索函数:<=>为余弦距离,1 - distance得到相似度;metadata @> filter支持按 JSONB 元数据过滤;limit match_count控制返回条数。n8n 的 Vector Store 节点(Insert / Retrieve)都通过queryName: match_youtube_data引用该函数。
四、入口与意图分类:把"人话"变成结构化指令
4.1 Webhook 入口
工作流以 HTTP Webhook(路径invoke-youtube-agent,POST 方法,headerAuth认证)接收外部请求。下游 "Prep Input Fields" 节点从{{ $json.body }}中提取四个字段:
| 字段 | 表达式 | 说明 |
|---|---|---|
query | {{ $json.body.query }} | 用户问题文本 |
user_id | {{ $json.body.user_id }} | 用户标识 |
request_id | {{ $json.body.request_id }} | 请求唯一 ID |
session_id | {{ $json.body.session_id }} | 会话标识,用于对话记忆 |
同时,"Add User Message to DB" 节点会把用户消息以 LangChainHumanMessage的 JSON 结构(type: human、content)写入messages表,作为会话历史持久化。
4.2 分类 Agent:结构化输出 + 分支路由
分类 Agent(AI Agent 节点)的 System Prompt 非常关键,它把用户输入归类为四类动作:
{ "action_type": "add|summarize|search|respond", "video_url": "<url or null>", "video_title": "<title or null>", "search_query": "<search terms or null>", "confidence": <0.0-1.0>, "response": "response" }规则如下:
- 用户只给 YouTube 链接 →
add; - 用户针对某视频(带 URL 或标题)询问内容 →
summarize; - 用户想从历史视频中找特定信息 →
search; - 能直接回答的问题 →
respond(此时必须返回response字段给用户)。
Prompt 中给出了 8 个示例,覆盖了"直接贴链接""带指令添加""要求总结""按主题回忆视频""询问能力"等典型场景。该 Agent 通过 Structured Output Parser 节点(jsonSchemaExample定义了action_type / video_url / video_title / search_query / confidence / response字段)强制输出合法 JSON,随后由 Switch 节点按action_type值分发到四条分支(add、respond、summarize、search)。
五、Add 流程:从链接到完整知识库条目
这是工作流最复杂的部分,Sticky Note 将其标注为 "# Add",由多个子阶段串联而成。
5.1 提取视频 ID 并查重
"Code" 节点内置了getYouTubeVideoId()函数,用正则匹配四种 URL 形态:
const patterns = [ /(?:youtube\.com\/watch\?v=|youtu\.be\/|youtube\.com\/embed\/)([^&?/]+)/, /youtube\.com\/v\/([^&?/]+)/, /youtube\.com\/shorts\/([^&?/]+)/ ];即支持youtube.com/watch?v=、youtu.be/、youtube.com/embed/、youtube.com/v/、youtube.com/shorts/五种常见链接格式。拿到videoId后,"Check if video exists" 节点以 Rest 风格查询 Supabase:
https://[Your Supabase Project ID].supabase.co/rest/v1/videos?video_id=eq.{{ $json.videoId }}&select=id&limit=1若记录已存在(If row exists 判断),则直接返回提示:"The video with the id xxx is already in the database.",避免重复入库。
5.2 抓取视频信息与字幕
未重复的视频进入 "Get Video ID" 节点,并行触发两个请求:
- Fetch Video Details:调用 YouTube Data API
https://www.googleapis.com/youtube/v3/videos?part=snippet&id={video_id}(使用 YouTube OAuth2 凭证),再经 "Extract video details" 节点取出title、description、channelName(分别对应响应的items[0].snippet.title / description / channelTitle); - Get transcript from SUPADATA:调用
https://api.supadata.ai/v1/youtube/transcript?text=true&videoId={video_id},Header 携带x-api-key(Supadata API key),返回纯文本字幕,经 "Join transcript in code1" 节点整理为{ transcript }。
两条结果在 "Merge1" 节点汇合后,分别喂给两个并行的 Agent:
- Summarize agent:System Prompt 要求"作为 YouTube 字幕专家",输出四要素 JSON——
summary(摘要)、keypoints(关键要点)、actionable-tasks(可执行任务)、extracted-quotes(原文金句),配套的 Structured Output Parser2 的 schema 示例与此一致; - Tag generator agent:要求生成"至少 10 个标签"用于后续分类检索,System Prompt 明确"只返回 JSON,不要任何多余文字",配套 Structured Output Parser1 的 schema 为
{ "tags": ["tag"] }。
两个 Agent 的输出经 "Merge" 节点按索引合并(Summarize 在 index 0、Tag 在 index 1),再统一写入 Supabase。
5.3 结构化入库与向量化切片
"Add video to supabase" 节点把 10 个字段写入videos表,其中 summary/keypoints/actionable/quotes/tags 直接来自 Merge 合并后的结构化输出,title/channel/description 来自 YouTube API,video_id/transcript 来自前面节点——字段名与 supabase.table.sql 中的列严格对应。
与此同时,向量入库链路由四个 LangChain 节点协作完成:
| 节点 | 配置 | 作用 |
|---|---|---|
| Recursive Character Text Splitter | chunkOverlap: 100 | 递归字符切分器,切片间保留 100 字符重叠以维持上下文连续性 |
| Default Data Loader | jsonData: {{ $json.data }},metadata 携带video_id | 把字幕文本包装成带元数据的 Document |
| Embeddings OpenAI | 默认配置 | 生成 1536 维向量 |
| Insert documents | tableName: youtube_agent_data,queryName: match_youtube_data | 写入 Supabase 向量表 |
注意 metadata 中的video_id被注入到每个切片的metadata字段——这正对应match_youtube_data函数中metadata @> filter的过滤能力,使得后续检索可以按视频维度精确定位。
入库成功后,"Generate output message" 节点拼接成功提示:"The video '{title}' by {channelName} was added successfully!",最终所有分支的输出统一经 "Add AI Message to DB"(以 LangChainAIMessage结构写入messages表)→ "Prep Output Fields"(包装成success: true+message.content)→ "Respond to Webhook" 返回给调用方。
六、Summarize / Search 流程:与知识库对话
6.1 按视频总结(summarize)
"Code1" 节点复用同一个getYouTubeVideoId()函数解析 URL,随后 "Supabase" 节点按video_id查询videos表,由 "Gather fields" 节点把title / description / summary / keypoints / actionable / channel / query / videoId / session_id组装起来,交给AI Agent1。该 Agent 的 Prompt 把已入库的结构化信息以 XML 标签的形式注入:
<title>{{ $json.title }}</title> <channel>{{ $json.channel }}</channel> <description>{{ $json.description }}</description> <summary>{{ $json.summary }}</summary> <key-points>{{ $json.keypoints }}</key-points> <tasks>{{ $json['actionable-tasks'] }}</tasks> <human>{{ $json.query }}</human>Prompt 同时约束了输出风格:"直接回答用户问题,不要提'Based on the provided summary'"。这意味着 summarize 分支不再重复调用 LLM 分析长字幕,而是基于入库时已生成的摘要做轻量推理,响应更快、成本更低。
6.2 跨视频语义搜索(search)
搜索分支由Search Agent驱动,它挂载了两个工具:
- Supabase Vector Store(retrieve-as-tool 模式):工具名
video_transcript_query,描述为"使用搜索词从向量库中检索相关视频",topK: 6(每次检索返回最多 6 条最相关切片),Embedding 同样来自 OpenAI; - get_video_by_videoId(supabaseTool):通过
$fromAI('videoId')让 Agent 自行决定按视频 ID 查询结构化记录。
Search Agent 的 Prompt 会把分类器输出的search_query传入:"Use your tool to search for relevant videos and respond to the human",并要求在回答后把命中的video_id以<video_ids>标签列表返回,每项前缀 YouTube URL——这样用户不仅能看到答案,还能拿到原始视频链接,例如:
<video_ids> <video_id>https://www.youtube.com/watch?v=xyz123</video_id> </video_ids>6.3 会话记忆
"Window Buffer Memory" 节点使用自定义会话键{{ $json.session_id }},挂载到分类 Agent 与 AI Agent1 上,为多轮对话提供滑动窗口式上下文记忆;配合messages表的持久化,Agent 可以在跨请求的会话中保持连贯。
七、如何部署到自己的 n8n 实例
参照 README 的说明,部署步骤可以归纳为:
- 准备依赖服务:注册并准备 Supabase 项目、Anthropic API Key、OpenAI API Key、YouTube Data API OAuth2 凭证、Supadata API Key;
- 初始化数据库:在 Supabase SQL Editor 中执行 supabase.table.sql,一次性创建
videos表、youtube_agent_data向量表与match_youtube_data检索函数(需启用 pgvector 扩展); - 导入工作流:在 n8n 中新建 Workflow → Import from File,选择 YouTube_Agent.json;
- 配置凭证:为 Supabase、OpenAI、Anthropic、YouTube OAuth2、Supadata(HTTP Header)分别创建 Credential,并替换各节点 URL 中的
[Your Supabase Project ID]占位符与x-api-key值; - 激活 Webhook:启动工作流后,向
POST /webhook/invoke-youtube-agent发送包含query(及可选user_id / request_id / session_id)的 JSON 请求即可调用。
八、源码级细节与可扩展方向
- 备用字幕方案的代价:工作流内置的"从 YouTube 页面 HTML 解析字幕"分支(Extract transcript url → Fetch transcript → XML → Join transcript in code)会先做多重错误判断——检测到
g-recaptcha时返回 "Too Many Requests"、缺少playabilityStatus返回 "Transcript unavailable"、无captionTracks时返回 "Transcript disabled"——作者在 Sticky Note 中建议仅在 Supadata 不可用时启用,避免触发反爬限制。 - 去重是设计的默认行为:Check if video exists 的
select=id&limit=1与 If row exists 分支保证了同一视频不会被重复抓取与重复向量化,避免知识库膨胀。 - 可扩展方向:
match_youtube_data的filter jsonb参数已具备按元数据(如video_id、未来可加的channel)过滤检索的能力;vector(1536)维度、topK: 6、chunkOverlap: 100均可按嵌入模型与业务场景调整;分类 Agent 的 System Prompt 也可扩展更多动作类型(如"翻译字幕""导出笔记")。
该 Agent 是 oTTomator agents 集合的一部分,完整的源码级工作流定义见 YouTube_Agent.json,数据库脚本见 supabase.table.sql,整体能力说明与配置清单见 README。
【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考