Type something to search...
使用 LangChain 和 Ollama 构建 YouTube 转载代理:分步指南

使用 LangChain 和 Ollama 构建 YouTube 转载代理:分步指南

AI代理现在无处不在。新的实现、新的想法和无尽的可能性。但跟上这一切可能会让人感到不知所措,有时整个概念似乎比实际更复杂。在本指南中,我们将以简单、结构化的方式来解析这一切。到最后,您不仅会理解AI代理是什么,还会亲自构建一个。

什么是AI代理?

随着大语言模型(LLMs)的发展,新的应用进入了我们的生活。AI代理就是其中之一。LLMs本质上处于静态状态。它们无法根据所训练的数据做出响应,也无法执行当今的发展和一些特殊任务。AI代理是能够与其自身环境互动的系统。它们赋予LLMs访问工具的能力,从而使其能够满足超出LLM范围的所需请求。

AI代理由两个部分组成:

  1. AI模型(LLMs): 执行推理、规划和选择最佳行动。
  2. 工具: 这些是AI代理使用的特殊功能。它们的发展决定了模型能够执行的能力。

AI代理可以为您搜索互联网并带来最合适的结果,分析文档并通过API检索数据。您可以根据需要扩展这些使用领域。

AI代理是如何工作的?

你可以把AI代理看作智能助手。当你提出一个问题时,它首先分析你的问题,决定需要做什么,然后使用适当的工具进行处理并给出答案。

Image 2

代理工作流程图(图片由作者提供)

有一个流程图展示了上述代理的工作方式。工作逻辑如下:

  1. 用户输入一个输入。这可以是一个问题或需要执行的动作。
  2. 如有必要,处理输入。(这取决于你将采取的动作。我在这里添加它是因为它在我的例子中)
  3. 如果代理需要使用工具,它会向该工具提供适当的输入并运行它。
  4. 观察部分,接收来自工具的响应,并评估其是否为足够的响应。
  5. 如果响应不够充分,循环可以继续。
  6. 当最后的响应足够充分时,停止生成令牌并返回响应。

代理最重要的特征是,当动作完成时,它们可以停止生成新的令牌。

什么是工具?

工具是使代理能够采取行动的结构。实际上,如果我们简单地思考,工具就是函数。这些函数被提供给 LLM,LLM 预计通过选择正确的函数来完成所需的任务。

在准备工具时,使用 正确的结构 是非常重要的。工具应该清楚地反映你的目的。 不应有任何解释的余地。

工具(函数)应该有一个 文档字符串。如果你熟悉 Python,当你在使用不同库的函数时,将鼠标悬停在 IDE 中的一个函数上,会弹出一个窗口,写出该函数的目的、它接受的参数和返回的结果。这就是文档字符串,也应该出现在工具中。

工具可以有不同的形状并服务于不同的目的。以下是一些最常用工具的示例:

  • Web 搜索
  • 图像生成
  • 使用外部 API

LangChain 中 AI 代理开发简介

到目前为止,我们已经讨论了代理是什么、它们是如何工作的以及工具的作用。当我们想将这些概念转化为实际应用时,LangChain 就派上用场了。

LangChain 是用于开发基于 LLM 的应用程序的框架之一。它支持代理结构并促进工具的使用。

我们可以用 LangChain 做什么?

使用 LangChain;

  • 我们可以开发与 LLM 对话的代理。
  • 我们可以开发与外部 API 交互的工具。
  • 我们可以指定代理将使用哪个工具以及何时使用。
  • 我们可以为复杂过程创建多重推理过程。

通过 LangChain,我们可以用非常少的代码将这些组件结合在一起,开发一个可工作的 AI 代理。特别是在进行实际应用时,我们将清楚地看到 LangChain 提供的灵活性和强大功能。

什么是 Ollama,为什么我们使用它?

Ollama 是一个可以本地运行并且便于管理 LLMs 的框架。 使用 Ollama,我们可以在自己的计算机上运行大型语言模型,而不是使用像 OpenAI API 这样的基于云的解决方案。这提供了隐私优势,并消除了外部 API 调用的费用。

如果我们来看一下优势:

  • 通过本地运行模型来确保数据隐私
  • Ollama 被优化为更快、更高效地运行 LLMs。
  • 与 LangChain 直接兼容。
  • 作为开源软件,我们可以使用和自定义不同的模型。

在这个项目中,我们使用Ollama + Llama3模型构建了一个强大的 AI Agent,以总结视频的文字记录并提取重要信息。

示例项目:YouTube 视频摘要 AI 代理

在之前的部分,我们讨论了什么是 AI 驱动的代理,它们是如何工作的,以及如何使用 LangChain 开发它们。现在是时候将我们所学的付诸实践了。在这一部分,我们将通过一个实际项目逐步开发一个 AI 代理。

我们将开发的项目是 YouTube 视频摘要 AI 代理。 该代理的目的是通过获取 YouTube 视频的转录文本进行基于文本的分析。用户可以通过向代理提问,快速获取摘要、主要观点和重要引用,而无需观看冗长的视频。因此,他们将能够节省时间,并高效地从内容中受益。

如果你准备好了,我们就开始吧。

所需安装

在本项目中,我们将使用 LangChain、Ollama 和 YouTubeTranscriptAPI 等库。如果这些库尚未安装在您的系统上,您可以通过运行以下命令进行安装:

pip install langchain langchain_ollama youtube-transcript-api

此外,由于我们将使用 Ollama 模型,您需要在计算机上安装 Ollama。如果您尚未安装 Ollama,可以按照以下步骤进行:

  1. 下载并安装 Ollama: https://ollama.com/
  2. 要将模型下载到您的系统,您可以在终端中运行以下命令:

I chose the llama3 model because it works more easily in my local, but you can also try different models.

从YouTube视频提取文本

我们的第一步是转录YouTube视频中的演讲。为此,我们将使用YouTubeTranscriptAPI库。该API获取YouTube的自动字幕,并以纯文本格式呈现给我们。

以下函数接受一个YouTube视频URL并提取视频的文本:

def parse\_url(url: str) -\> str:
    """
    从URL中提取视频ID。

    参数: 
        url(str): youtube视频url

    返回:
        YouTube视频的ID
    
    """
    if "=" in url:
        return url.split("=")\[-1\]

    return url

def get\_text\_from\_video(url: str) -\> str:
    """
    从YouTube视频中获取文本。

    参数:
        url(str): youtube视频url

    返回:
        YouTube视频的转录文本
    
    """
    video\_id = parse\_url(url)
    
    try:
        transcript = YouTubeTranscriptApi.get\_transcript(video\_id)
        transcript\_text = " ".join(\[entry\["text"\] for entry in transcript\])
        transcript\_text = transcript\_text.replace("\\n", " ").replace("'", "")
        return transcript\_text
    except Exception as e:
        return f"无法获取转录文本: {str(e)}"
  • parse_url(url: str) -> str: 它接受YouTube URL并从中提取视频ID。
  • get_text_from_video(url: str) -> str: 它使用parse_url函数获取视频ID。它使用YouTubeTranscriptAPI获取视频的转录,并将其返回为编辑后的字符串。

在这一步结束时,我们将拥有视频的转录文本。然而,由于长文本可能难以处理,我们将在下一步将文本拆分成较小的部分(块)。

将文本拆分为较小的部分 (Chunking)

在从YouTube视频获取转录文本后,我们需要将其拆分为小块(chunks),而不是直接处理。这是因为大型语言模型通常有一定的令牌限制。如果我们直接将文本输入模型,可能会超出模型的容量或失去上下文。

因此,通过将长文本拆分为更有意义的部分进行处理,不仅可以帮助我们获得更准确的答案,还可以使模型更高效地工作。在这里,我们将使用LangChain的RecursiveCharacterTextSplitter工具将文本拆分成不同的部分。

def create\_chunks(transcript\_text: str) -\> list:
    """
    Split transcript text into processable chunks.

    Args:
        transcript\_text (str): Youtube video's transcripted text

    Returns:
        processable chunks
    
    """
    text\_splitter = RecursiveCharacterTextSplitter(chunk\_size=1000, chunk\_overlap=100)
    chunks = text\_splitter.split\_text(transcript\_text)
    return chunks

RecursiveCharacterTextSplitter将文本拆分为1000个字符的部分。它保留100个字符的重叠,以便在部分之间保持语义完整性。给定的文本随后被拆分成片段并作为列表返回。

使用 AI 模型进行总结

现在我们已经从 YouTube 视频中获取了转录文本,并将其分解为更小、更有意义的部分,我们可以开始使用 LLM 对这些文本进行总结。在这一步中,我们将使用 LangChain 和 Ollama 为每个部分生成摘要,然后将所有摘要组合在一起以获得一个整体摘要。

def get\_summary(chunks: list) -\> str:
    """
    Summarize text chunks and create a single summary.
    
    Args:
        chunks (list): processable chunks of transcriptted text

    Returns:
        A single summary for youtube video
    """
    llm = OllamaLLM(model="llama3")

    template = """Text: {text}
    Goal: Summarize given text.
    Answer: """

    prompt = ChatPromptTemplate.from\_template(template)
    chain = prompt | llm

    summaries = \[chain.invoke({"text": chunk}) for chunk in chunks\]
    
    combined\_summary = " ".join(summaries)
    
    
    final\_summary\_prompt = ChatPromptTemplate.from\_template(
        "Multiple summaries: {summaries}\\nGoal: Create a coherent single summary.\\nAnswer: "
    )
    final\_summary\_chain = final\_summary\_prompt | llm
    final\_summary = final\_summary\_chain.invoke({"summaries": combined\_summary})
    
    return final\_summary

上面的函数是我们将作为工具使用的函数之一。首先,让我们检查一下函数的结构。

  • 函数接受的参数及其类型已给出。
  • 函数返回的结果类型指定为**“-> str”。**
  • 在函数开头的注释行中,我们首先写出函数的功能。
  • Args 部分,我们写出函数接受的参数、它们的类型和解释。
  • Return 部分,我们解释函数返回的结果。

我们将在每个函数中执行这些操作,因此可以将其视为通用结构。

当这些过程完成后,我们开始使用 Ollama 的“llama3”模型的大型语言模型。该模型具有语言理解、推理和总结的能力。

我们创建一个提示模板来总结每个文本片段。使用 ChatPromptTemplate 工具,我们将此提示调整为我们将使用的模型的结构。在 “chain = prompt | llm” 部分,我们将提示与模型连接。通过这种方式,每个部分将自动发送到模型进行总结。在逐个总结这些部分后,摘要将被组合。这个组合的摘要再次发送到模型以获得最终摘要,并且函数返回该摘要。

提取主要主题

在这个阶段,我们将专注于通过识别YouTube视频的转录文本中的主要主题来提取内容的基本构建块。通过这样做,我们将创建一个摘要,帮助我们快速理解视频的主要思想。

def extract\_topics(chunks:list) -\> list:
    """
    Extract main topics from text chunks.
    
    Args:
        chunks (list): processable chunks of transcriptted text
    
    Returns:
        Main topic list
    """
    llm = OllamaLLM(model="llama3")

    template = """Text: {text}
    Goal: Extract main topics from the given text.
    Answer: List the key topics separated by commas."""

    prompt = ChatPromptTemplate.from\_template(template)
    chain = prompt | llm

    topics\_list = \[chain.invoke({"text": chunk}) for chunk in chunks\]

    
    all\_topics = set()
    for topics in topics\_list:
        
        topic\_items = \[t.strip() for t in topics.split(",")\]
        all\_topics.update(topic\_items)

    
    all\_topics = {topic for topic in all\_topics if topic}
    
    return list(all\_topics)

首先,我们再次定义我们的模型并创建我们的示例模板。然后,与第一个函数一样,我们将文本块发送给模型,这次我们希望它分离主要主题。所选的主要主题作为列表存储,并消除重复数据。

提取重要引用

在这一步中,我们编写了一个函数,用于识别视频转录文本中最重要和引人注目的引用。我们的目标是直接从视频中识别出最有效的引用,而不是对视频内容进行总结。

def extract\_quotes(chunks:list) -\> list:
    """
    Extract important quotes from text chunks.
    
    Args:
        chunks (list): processable chunks of transcriptted text
    
    Returns:
        important quotes list
    """
    llm = OllamaLLM(model="llama3")
    template = """Text: {text}
    Goal: Extract the most important quote from this text.
    Answer: Provide the quote as plain text."""

    prompt = ChatPromptTemplate.from\_template(template)
    chain = prompt | llm

    quotes = \[chain.invoke({"text": chunk}) for chunk in chunks\]
    
    
    unique\_quotes = \[\]
    seen\_quotes = set()
    
    for quote in quotes:
        
        normalized = quote.strip().lower()
        if normalized and normalized not in seen\_quotes:
            unique\_quotes.append(quote.strip())
            seen\_quotes.add(normalized)
    
    return unique\_quotes

这个函数的工作结构实际上与之前的函数相同。我们定义模型并创建提示模板。然后我们使引用唯一。

创建代理结构

我们已经创建了所有工具。现在是将它们组合在一起的时候。为此,我们将使用以下函数。

def process_user_query(query, chunks, url):
    """根据用户查询选择合适的工具并生成响应。"""

    llm = OllamaLLM(model="llama3")
    
    
    def get_summary_wrapper(input_str=""):
        return get_summary(chunks)
    
    def extract_topics_wrapper(input_str=""):
        return extract_topics(chunks)
    
    def extract_quotes_wrapper(input_str=""):
        return extract_quotes(chunks)
    
    
    tools = [
        Tool(
            name="get_summary",
            func=get_summary_wrapper,
            description="提供逐字稿的详细摘要。"
        ),
        Tool(
            name="extract_topics",
            func=extract_topics_wrapper,
            description="从逐字稿中提取主要主题。"
        ),
        Tool(
            name="extract_quotes",
            func=extract_quotes_wrapper,
            description="从逐字稿中提取重要引用。"
        )
    ]

    agent = initialize_agent(
        tools=tools,
        llm=llm,
        agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
        verbose=True
    )

    
    response = agent.invoke(input=query, handle_parsing_errors=True)

    return response

此函数的目的是根据用户的输入选择合适的工具,以实现所需的任务并达到结果。

在这个函数中,我们首先加载模型。然后我们创建以下包装函数。LangChain 工具机制不支持调用可以直接传递参数的函数。

def get_summary_wrapper(input_str=""):
    return get_summary(chunks)
    
def extract_topics_wrapper(input_str=""):
    return extract_topics(chunks)
    
def extract_quotes_wrapper(input_str=""):
    return extract_quotes(chunks)

因此,如果你必须像这样使用函数 “get_summary(chunks)”,在将其传递给 Tool 对象时会出现错误。正因如此,我们将想要使用的函数放在一个包装函数中,并像这样发送给 Tool。

Tool(
      name="extract_quotes",
      func=get_summary(chunks),
      description="从逐字稿中提取重要引用。"
  )

我们已经学习了如何使用这个函数。现在是时候将 Tool 属性分配给这些函数了。为此,我们在 langchain.tools 中使用 Tool 对象。它的参数是:

  • name: 工具的名称
  • func: 工具调用的函数
  • description: 工具的用途

我们对所有函数执行此操作,并将它们收集在一个列表中。

我们创建了工具,现在是时候创建代理了。为此,我们使用 initialize_agent。参数:

  • tools: 使用的工具列表
  • llm: 要使用的模型
  • agent — AgentType.ZERO_SHOT_REACT_DESCRIPTION: Zero shot 意味着代理将直接回答,而无需预定义的示例。React description 意味着代理将分析用户查询并选择最佳工具
  • verbose=True: 将显示更详细的操作输出(可选)

最后,用户查询被处理。

response = agent.invoke(input=query, handle_parsing_errors=True)

当上述代码运行时,用户提出的问题将首先发送给 AI 代理。代理将分析问题并选择最合适的工具。

  • handle_parsing_errors=True: 确保函数在可能的错误情况下正常工作。

如果你完成了所有这些步骤,恭喜你,你已经创建了自己的 AI 代理。你可以使用以下代码运行它。

if __name__ == "__main__":
    llm = OllamaLLM(model="llama3")

    url = "youtube_url"

    transcript_text = get_text_from_video(url)

    chunks = create_chunks(transcript_text)

    user_query = "你能给我这个视频的摘要吗?"
    
    result = process_user_query(user_query, chunks, url)
    print(f"响应: {result}")

你可以在 github repo 找到所有代码。

在这个项目中,我们开发了一个使用 LangChain 和 Ollama 分析 YouTube 视频的 AI 代理。首先,我们完成了从视频获取逐字稿的步骤,然后对文本进行分块、总结、提取主要主题和识别重要引用。最后,我们创建了一个动态系统,可以使用 AI 代理结构为用户的问题提供最合适的答案。

你可以进一步开发这个项目。可以通过视频获取更多信息,或者使用 YouTube API 添加接口。我想展示如何使用它以及如何创建自己的工具。

别忘了关注我、给我点赞并留下评论。如果你想查看我的其他文章:

参考文献

Related Posts

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

AI 研究报告和论文写作 合并两个系统指令以获得两个模型的最佳效果 Perplexity AI 的 Deep Research 工具提供专家级的研究报告,而 OpenAI 的 ChatGPT-o3-mini-high 擅长推理。我发现你可以将它们结合起来生成令人难以置信的论文,这些论文比任何一个模型单独撰写的都要好。你只需要将这个一次性提示复制到 **

阅读更多
让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

Non members click here作为一名软件开发人员,多年来的一个发现总是让我感到惊讶,那就是人们还在 Excel

阅读更多
使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

10 个常见问题解答 本文是我推出的一个名为“10 个常见问题解答”的新系列的一部分。在本系列中,我旨在通过回答关于该主题的十个最常见问题来分解复杂的概念。我的目标是使用简单的语言和相关的类比,使这些想法易于理解。 图片来自 [Solen Feyissa](https://unsplash.com/@solenfeyissa?utm_source=medium&utm_medi

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

在AI军备竞赛中分辨事实与虚构 DeepSeek AI真的是它所宣传的游戏规则改变者,还是仅仅聪明的营销和战略炒作?👀 虽然一些人将其视为AI效率的革命性飞跃,但另一些人则认为它的成功建立在借用(甚至窃取的)创新和可疑的做法之上。传言称,DeepSeek的首席执行官在疫情期间像囤积卫生纸一样囤积Nvidia芯片——这只是冰山一角。 从其声称的550万美元培训预算到使用Open

阅读更多
Type something to search...