当前位置: 首页 > article >正文

Langchain检索YouTube字幕

创建一个简单搜索引擎,将用户原始问题传递该搜索系统

本文重点:获取保存文档——保存向量数据库——加载向量数据库

专注于youtube的字幕,利用youtube的公开接口,获取元数据

pip install youtube-transscript-api pytube

初始化

import datetime
import os
from operator import itemgetter
from typing import Optional, Listimport bs4
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.history_aware_retriever import create_history_aware_retriever
from langchain.chains.retrieval import create_retrieval_chain
from langchain.chains.sql_database.query import create_sql_query_chain
from langchain_chroma import Chroma
from langchain_community.agent_toolkits import SQLDatabaseToolkit
from langchain_community.document_loaders import WebBaseLoader, YoutubeLoader
from langchain_community.tools import QuerySQLDataBaseTool
from langchain_community.utilities import SQLDatabase
from langchain_core.documents import Document
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder, PromptTemplate
from langchain_core.runnables import RunnableWithMessageHistory, RunnablePassthrough
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langgraph.prebuilt import chat_agent_executor
from pydantic.v1 import BaseModel, Fieldos.environ['http_proxy'] = '127.0.0.1:7890'
os.environ['https_proxy'] = '127.0.0.1:7890'os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_PROJECT"] = "LangchainDemo"
os.environ["LANGCHAIN_API_KEY"] = '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'
# os.environ["TAVILY_API_KEY"] = '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'# 聊天机器人案例
# 创建模型
model = ChatOpenAI(model='gpt-4-turbo')
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')

 创建持久化向量数据库

存放向量数据库的目录

persist_dir = 'chroma_data_dir'  # 存放向量数据库的目录

获取&保存文档

YoutubeLoader是 langchain_community.document_loaders

 ##一个Youtube的视频对应一个document

# 一些YouTube的视频连接
urls = ["https://www.youtube.com/watch?v=HAn9vnJy6S4","https://www.youtube.com/watch?v=dA1cHGACXCo","https://www.youtube.com/watch?v=ZcEMLz27sL4","https://www.youtube.com/watch?v=hvAPnpSfSGo","https://www.youtube.com/watch?v=EhlPDL4QrWY","https://www.youtube.com/watch?v=mmBo8nlu2j0","https://www.youtube.com/watch?v=rQdibOsL1ps","https://www.youtube.com/watch?v=28lC4fqukoc","https://www.youtube.com/watch?v=es-9MgxB-uc","https://www.youtube.com/watch?v=wLRHwKuKvOE","https://www.youtube.com/watch?v=ObIltMaRJvY","https://www.youtube.com/watch?v=DjuXACWYkkU","https://www.youtube.com/watch?v=o7C9ld6Ln-M",
]docs = []  # document的数组
for url in urls:
#     # 一个Youtube的视频对应一个documentdocs.extend(YoutubeLoader.from_youtube_url(url, add_video_info=True).load())print(len(docs))
print(docs[0]) #具体document参数,可以在此查看# # 给doc添加额外的元数据: 视频发布的年份
# for doc in docs:
#     doc.metadata['publish_year'] = int(
#         datetime.datetime.strptime(doc.metadata['publish_date'], '%Y-%m-%d %H:%M:%S').strftime('%Y'))
#
#
# print(docs[0].metadata)
# print(docs[0].page_content[:500])  # 第一个视频的字幕内容
#

len、docs[0]、docs[0].metadata、docs[0].page_content[:500]

构建向量数据库

文档切割——》向量数据库持久化

persist_directory=persist_dir 持久化到磁盘

# # 根据多个doc构建向量数据库
text_splitter = RecursiveCharacterTextSplitter(chunk_size=2000, chunk_overlap=30)
split_doc = text_splitter.split_documents(docs)# # 向量数据库的持久化 # 并且把向量数据库持久化到磁盘
vectorstore = Chroma.from_documents(split_doc, embeddings, persist_directory=persist_dir)  

加载磁盘向量数据库

#vectorstore = Chroma(persist_directory=persist_dir, embedding_function=embeddings)

此处persist_dir、Embedding要和上文一致。

## 相似检索结果result【0】【0】才是一个结果。result【0】=(Document,score)

## 若不需要分数,使用.similarity_search

vectorstore = Chroma(persist_directory=persist_dir, embedding_function=embeddings)# 测试向量数据库的相似检索
# result = vectorstore.similarity_search_with_score('how do I build a RAG agent')
# print(result[0])
# print(result[0][0].metadata['publish_year'])

# 测试结果

整合LLM

Prompt

system = """You are an expert at converting user questions into database queries. \
You have access to a database of tutorial videos about a software library for building LLM-powered applications. \
Given a question, return a list of database queries optimized to retrieve the most relevant results.If there are acronyms or words you are not familiar with, do not try to rephrase them."""
prompt = ChatPromptTemplate.from_messages([("system", system),("human", "{question}"),]
)

pydantic Model

# 如果chain中仅用model(不使用.with_structured_output);那么只能检索content;但我们还需要进行metadata检索,提取结构化参数。那么可以采用pydantic(用于数据管理的库);

这里Search是数据模型、pydantic的model,非LLM;

Search 的核心作用​

  • ​标准化检索参数​​:将非结构化文本(用户问题)转化为结构化的 query 和 publish_year,确保后续检索系统能精准处理。
  • ​错误预防​​:通过类型检查(如 publish_year 必须为整数)避免无效参数传递。
  • ​可解释性​​:明确每个字段的用途(通过 description),便于团队协作和维护

Optional:表示可选字段

# pydantic
class Search(BaseModel):"""定义了一个数据模型进行metadata检索"""# 内容的相似性和发布年份query: str = Field(None, description='Similarity search query applied to video transcripts.')publish_year: Optional[int] = Field(None, description='Year video was published')

chain

RunnablePassthrough:让值 可以滞后传递。

model.with_structured_output(Search):要求模型生成符合 Search 类定义的结构化输出(而非自由文本)

chain = {'question': RunnablePassthrough()} | prompt | model.with_structured_output(Search)# resp1 = chain.invoke('how do I build a RAG agent?')
# print(resp1)
# resp2 = chain.invoke('videos on RAG published in 2023')
# print(resp2)

chain简单测试:这里只是生成指令并未搜索

执行搜索

自定义一个检索器。

#" $eq"是Chroma向量数据库的固定语法: search.publish_year==向量数据库'publish_year'

def retrieval(search: Search) -> List[Document]:_filter = Noneif search.publish_year:# 根据publish_year,存在得到一个检索条件# "$eq"是Chroma向量数据库的固定语法_filter = {'publish_year': {"$eq": search.publish_year}}return vectorstore.similarity_search(search.query, filter=_filter)new_chain = chain | retrieval# result = new_chain.invoke('videos on RAG published in 2023')
result = new_chain.invoke('RAG tutorial')
print([(doc.metadata['title'], doc.metadata['publish_year']) for doc in result])

结构化数据检索

非结构化检索

相关文章:

Langchain检索YouTube字幕

创建一个简单搜索引擎,将用户原始问题传递该搜索系统 本文重点:获取保存文档——保存向量数据库——加载向量数据库 专注于youtube的字幕,利用youtube的公开接口,获取元数据 pip install youtube-transscript-api pytube 初始化 …...

【Linux网络】应用层自定义协议与序列化及Socket模拟封装

📢博客主页:https://blog.csdn.net/2301_779549673 📢博客仓库:https://gitee.com/JohnKingW/linux_test/tree/master/lesson 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! &…...

客户案例:西范优选通过日事清实现流程与项目管理的优化

近几年来,新零售行业返璞归真,从线上销售重返线下发展,满足消费者更加多元化的需求,国内家居集合店如井喷式崛起。为在激烈的市场竞争中立于不败之地,西范优选专注于加强管理能力、优化协作效率的“内功修炼”&#xf…...

LabVIEW实现Voronoi图绘制功能

该 LabVIEW 虚拟仪器(VI)借助 MathScript 节点,实现基于手机信号塔位置计算 Voronoi 图的功能。通过操作演示,能直观展示 Voronoi 图在空间划分上的应用。 各部分功能详细说明 随机地形创建部分 功能:根据 “Maximum a…...

【C++基础知识】namespace前加 inline

在C中,inline namespace(内联命名空间)是一种特殊的命名空间声明方式,inline关键字在这里的含义是让该命名空间的内容在其外层命名空间中“直接可见”,从而简化代码的版本管理和符号查找规则。以下是详细解释&#xff…...

离线部署kubernetes

麒麟Linux服务器 AMR架构 🧰 离线部署 Kubernetes v1.25.9(麒麟系统 Docker) 一、验证Docker部署状态 ‌检查Docker服务运行状态‌ systemctl status docker 预期输出应显示 Active: active (running),表明服务已启动‌18。 ‌…...

【AI提示词】私人教练

提示说明 以专业且细致的方式帮助客户实现健康与健身目标,提升整体生活质量。 提示词 # Role: 私人教练## Profile - language: 中文 - description: 以专业且细致的方式帮助客户实现健康与健身目标,提升整体生活质量 - background: 具备丰富的健身经…...

爬虫学习——获取动态网页信息

对于静态网页可以直接研究html网页代码实现内容获取,对于动态网页绝大多数都是页面内容是通过JavaScript脚本动态生成(也就是json数据格式),而不是静态的,故需要使用一些新方法对其进行内容获取。凡是通过静态方法获取不到的内容,…...

第54讲:总结与前沿展望——农业智能化的未来趋势与研究方向

目录 一、本板块内容回顾:人工智能助力农业的多元化应用 ✅ 精准农业与AI ✅ 农业金融与AI ✅ AI与农业政策 ✅ 农业物联网与AI 二、前沿趋势与研究方向:迈向智能、可持续农业的未来 1. AIGC(生成式AI)在农业中的应用 2. 数字孪生农业:虚拟与现实的无缝对接 3. A…...

创新项目实训开发日志4

一、开发简介 核心工作内容&#xff1a;logo实现、注册实现、登录实现、上传gitee 工作时间&#xff1a;第十周 二、logo实现 1.设计logo 2.添加logo const logoUrl new URL(/assets/images/logo.png, import.meta.url).href <div class"aside-first">…...

常见接口测试常见面试题(JMeter)

JMeter 是 Apache 提供的开源性能测试工具&#xff0c;主要用于对 Web 应用、REST API、数据库、FTP 等进行性能、负载和功能测试。​它支持多种协议&#xff0c;如 HTTP、HTTPS、JDBC、SOAP、FTP 等。 在一个线程组中&#xff0c;JMeter 的执行顺序通常为&#xff1a;配置元件…...

发布事件和Insert数据库先后顺序

代码解释 csharp await PublishCreatedAsync(entity).ConfigureAwait(false); await Repository.InsertAsync(entity).ConfigureAwait(false);PublishCreatedAsync(entity)&#xff1a;这是一个异步方法&#xff0c;其功能是发布与实体创建相关的事件。此方法或许会通知其他组…...

函数重载(Function Overloading)

1. 函数重载的核心概念 函数重载允许在 同一作用域内定义多个同名函数&#xff0c;但它们的 参数列表&#xff08;参数类型、顺序或数量&#xff09;必须不同。编译器在编译时根据 调用时的实参类型和数量 静态选择最匹配的函数版本。 2. 源码示例&#xff1a;基础函数重载 示…...

CGAL 网格等高线计算

文章目录 一、简介二、实现代码三、实现效果一、简介 这里等高线的计算其实很简单,使用不同高度的水平面与网格进行相交,最后获取不同高度的相交线即可。 二、实现代码 #include <iostream> #include <iterator> #include <map>...

计算机组成与体系结构:缓存(Cache)

目录 为什么需要 Cache&#xff1f; &#x1f9f1; Cache 的分层设计 &#x1f539; Level 1 Cache&#xff08;L1 Cache&#xff09;一级缓存 &#x1f539; Level 2 Cache&#xff08;L2 Cache&#xff09;二级缓存 &#x1f539; Level 3 Cache&#xff08;L3 Cache&am…...

Flutter 在全新 Platform 和 UI 线程合并后,出现了什么大坑和变化?

Flutter 在全新 Platform 和 UI 线程合并后&#xff0c;出现了什么大坑和变化&#xff1f; 在两个月前&#xff0c;我们就聊过 3.29 上《Platform 和 UI 线程合并》的具体原因和实现方式&#xff0c;而事实上 Platform 和 UI 线程合并&#xff0c;确实为后续原生语言和 Dart 的…...

开发 MCP Proxy(代理)也可以用 Solon AI MCP 哟!

MCP 有三种通讯方式&#xff1a; 通道说明备注stdio本地进程内通讯现有sse http远程 http 通讯现有streamable http远程 http 通讯&#xff08;MCP 官方刚通过决定&#xff0c;mcp-java-sdk 还没实现&#xff09; 也可以按两大类分&#xff1a; 本地进程间通讯远程通讯&…...

JetBrains GoLang IDE无限重置试用期,适用最新2025版

注意本文仅用于学习使用&#xff01;&#xff01;&#xff01; 本文在重置2024.3.5版本亲测有效&#xff0c;环境为window(mac下应该也一样奏效) 之前eval-reset插件只能在比较低的版本才能起作用。 总结起来就一句&#xff1a;卸载重装&#xff0c;额外要删掉旧安装文件和注册…...

python中socket(套接字)库详细解析

目录 1. 前言 2. socket 库基础 2.1 什么是 socket&#xff1f; 2.2 socket 的类型 3. 基于 TCP 的 socket 编程 3.1 TCP 服务器端代码示例 3.2 TCP 客户端代码示例 3.3 代码分析 4. 基于 UDP 的 socket 编程 4.1 UDP 服务器端代码示例 4.2 UDP 客户端代码示例 4.3…...

鸿蒙-状态管理V1和V2在ForEach循环渲染的表现

目录 前提遇到的问题换V2呗 状态管理V2已经出来好长时间了&#xff0c;移除GAP说明也有一段时间了&#xff0c;相信有一部分朋友已经开始着手从V1迁移到V2了&#xff0c;应该也踩了不少坑。 下面向大家分享一下我使用状态管理V1和Foreach时遇到的坑&#xff0c;以及状态管理V2在…...

深入了解递归、堆与栈:C#中的内存管理与函数调用

在编程中&#xff0c;理解如何有效地管理内存以及如何控制程序的执行流程是每个开发者必须掌握的基本概念。C#作为一种高级编程语言&#xff0c;其内存管理和函数调用机制包括递归、堆与栈。本文将详细讲解这三者的工作原理、用途以及它们在C#中的实现和应用。 1. 递归 (Recur…...

图论---Prim堆优化(稀疏图)

题目通常会提示数据范围&#xff1a; 若 V ≤ 500&#xff0c;两种方法均可&#xff08;朴素Prim更稳&#xff09;。 若 V ≤ 1e5&#xff0c;必须用优先队列Prim vector 存图。 #include <iostream> #include <vector> #include <queue> #include <…...

stm32之GPIO函数详解和上机实验

目录 1.LED和蜂鸣器1.1 LED1.2 蜂鸣器 2.实验2.1 库函数&#xff1a;RCC和GPIO2.1.1 RCC函数1. RCC_AHBPeriphClockCmd2. RCC_APB2PeriphClockCmd3. RCC_APB1PeriphClockCmd 2.1.2 GPIO函数1. GPIO_DeInit2. GPIO_AFIODeInit3. GPIO_Init4. GPIO_StructInit5. GPIO_ReadInputDa…...

用 PyQt5 和 asyncio 打造接口并发测试 GUI 工具

接口并发测试是测试工程师日常工作中的重要一环&#xff0c;而一个直观的 GUI 工具能有效提升工作效率和体验。本篇文章将带你用 PyQt5 和 asyncio 从零实现一个美观且功能实用的接口并发测试工具。 我们将实现以下功能&#xff1a; 请求方法选择器 添加了一个下拉框 QComboBo…...

OpenHarmony Camera开发指导(四):相机会话管理(ArkTS)

概述 相机在使用预览、拍照、录像、获取元数据等功能前&#xff0c;都需要先创建相机会话。 相机会话Session的功能如下&#xff1a; 配置相机的输入流和输出流。 配置输入流即添加设备输入&#xff0c;通俗来讲即选择某一个摄像头进行拍照录像&#xff1b;配置输出流&#x…...

深入探索RAG(检索增强生成)模型的优化技巧

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4o-mini模型生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认其准…...

Spring boot 中的IOC容器对Bean的管理

Spring Boot 中 IOC 容器对 Bean 的管理&#xff0c;涵盖从容器启动到 Bean 的生命周期管理的全流程。 步骤 1&#xff1a;理解 Spring Boot 的容器启动 Spring Boot 的 IOC 容器基于 ApplicationContext&#xff0c;在应用启动时自动初始化。 入口类&#xff1a;通过 SpringB…...

Qt实战之将自定义插件(minGW)显示到Qt Creator列表的方法

Qt以其强大的跨平台特性和丰富的功能&#xff0c;成为众多开发者构建图形用户界面&#xff08;GUI&#xff09;应用程序的首选框架。而在Qt开发的过程中&#xff0c;自定义插件能够极大地拓展应用程序的功能边界&#xff0c;让开发者实现各种独特的、个性化的交互效果。想象一下…...

【Vue】TypeScript与Vue3集成

个人主页&#xff1a;Guiat 归属专栏&#xff1a;Vue 文章目录 1. 前言2. 环境准备与基础搭建2.1. 安装 Node.js 与 npm/yarn/pnpm2.2. 创建 Vue3 TypeScript 项目2.2.1. 使用 Vue CLI2.2.2. 使用 Vite&#xff08;推荐&#xff09;2.2.3. 目录结构简述 3. Vue3 TS 基础语法整…...

Linux之七大难命令(The Seven Difficult Commands of Linux)

Linux之七大难命令 、背景 作为Linux的初学者&#xff0c;肯定要先掌握高频使用的指令&#xff0c;这样才能让Linux的学习在短时间内事半功倍。但是&#xff0c;有些指令虽然功能强大&#xff0c;但因参数多而让初学者们很害怕&#xff0c;今天介绍Linux中高频使用&#xff0…...