ITPub博客

首页 > 人工智能 > 人工智能 > 利用AI和事件驱动设计自动化播客推广

利用AI和事件驱动设计自动化播客推广

人工智能 作者:ITPUB社群 时间:1970-01-01 08:33:45 0 删除 编辑


我主持两档播客节目——Software Engineering Daily 和 Software Huddle,也经常作为嘉宾出现在其他节目中。推广这些节目——无论是我主持还是作为嘉宾参与——有助于突出我所进行的精彩对话,但要为每一期节目精心撰写一篇 LinkedIn 帖子,实在很难挤出时间。在主持节目、工作和生活之间,坐下来为每一期节目精心撰写一篇 LinkedIn 帖子,并不总能做到。

为了让生活更轻松(同时又不辜负这些节目),我构建了一个由 AI 驱动的 LinkedIn 帖子生成器。它会下载播客节目,将音频转换为文本,并据此生成帖子。这为我节省了时间,让我的内容保持一致,并确保每一期节目都能获得应有的关注。

在这篇文章中,我将详细拆解我如何使用 Next.js、OpenAI 的 GPT 和 Whisper 模型、Apache Kafka ® 以及 Apache Flink ® 构建这个工具。更重要的是,我将展示 Kafka 和 Flink 如何驱动事件驱动架构,使其具备可扩展性和响应性——这是实时 AI 应用的关键模式。

注意:如果你只想查看代码,请前往我的 GitHub 仓库 这里 。

设计一个 LinkedIn 帖子助手

这个应用的目标非常明确:帮助我为我主持或参与过的播客创建 LinkedIn 帖子,同时不占用我太多时间。

为了满足我的需求,我希望能够提供一个播客 feed 的 URL,拉取所有节目的列表,然后为我选择的任意一期节目生成 LinkedIn 帖子。很简单,对吧?当然,在底层还有一些繁重的工作要让这一切运转起来:

  • 下载所选节目的 MP3

  • 使用 OpenAI 的 Whisper 模型将音频转换为文本

  • 由于 Whisper 有 25MB 的文件大小限制,如有需要,将 MP3 拆分为更小的块

  • 最后,使用转录文本组装提示词,并让 LLM(大语言模型) 为我生成 LinkedIn 帖子

除了功能之外,我还有另一个重要目标:让前端应用与 AI 工作流完全解耦。为什么?因为在真实的 AI 应用程序中,团队通常负责技术栈的不同部分。你的前端开发人员不应该为了构建面向用户的应用而需要了解任何 AI 知识。此外,我还希望拥有以下灵活性:

  • 独立扩展系统的不同部分

  • 随着不断发展的生成式 AI 技术栈的演进,替换模型或框架

为了实现这一切,我使用 Confluent Cloud 实现了事件驱动架构。这种方法不仅保持了模块化,还为应用在未来 AI 技术不可避免的变化中做好了准备。

为什么 AI 需要事件驱动架构?

事件驱动架构(EDA)的出现是为了应对传统单体系统的局限性,这些系统依赖于僵化的同步通信模式。在计算早期,应用程序围绕静态工作流构建,通常与批处理或紧密耦合的交互绑定在一起。

这些设计并不十分复杂,但也不具备良好的可扩展性。它们难以处理动态或不可预测的输入,在需要实时响应的环境中导致效率低下和瓶颈问题。

随着技术的发展和可扩展性与适应性需求的增长——尤其是分布式系统和微服务的兴起——EDA 成为了一种自然的解决方案。

通过将事件——如状态变化、用户操作或系统触发器——视为交互的核心单元,EDA 使系统能够解耦组件并异步通信。

这种方法使用数据流式处理,其中生产者和消费者通过共享的、不可变的日志进行交互。事件以保证的顺序持久化,使系统能够动态且独立地处理和响应变化。

其结果是形成了一个更加敏捷和有弹性的架构,能够处理复杂、动态的环境。通过解耦组件,EDA 使应用程序能够灵活扩展、适应新需求,并与不断演进的技术无缝集成。

将我的 Web 应用与 AI 工作流解耦

回到当前的任务,我的 Web 应用程序不需要了解任何 AI 知识。

为了将面向用户的应用程序与 AI 解耦,我使用了 Confluent Cloud 的 Data Streaming Platform,它将 Kafka、Flink 和 AI 模型作为一等公民支持,使得构建真正可扩展的 AI 应用程序变得容易。

设计概述

当用户点击播客列表时,应用程序会请求服务器检查后端缓存中是否存在现有的 LinkedIn 帖子。如果找到,则返回并显示。

你可以将这些 LinkedIn 帖子存储在数据库中,但我选择了临时缓存,因为我并不需要长期持久化这些内容。

如果不存在 LinkedIn 帖子,后端会向 Kafka 主题写入一个事件,包含 MP3 URL 和剧集描述。这会触发工作流来生成 LinkedIn 帖子。

下图展示了这个事件驱动系统的完整架构,我将在下一节中更详细地解释。

下载并生成转录文本

工作流的这一部分相当直接。Web 应用程序将请求写入一个名为 LinkedIn Post Request 的 Kafka 主题。使用 Confluent Cloud,我配置了一个 HTTP Sink Connector,将新消息转发到 API(应用程序编程接口) 端点。

API 端点使用提供的 URL 下载 MP3,如有必要将文件分割成 25 MB 的块,并使用 Whisper 处理音频以生成转录文本。转录完成后,它们会被写入另一个名为 Podcast Transcript 的 Kafka 主题。

这就是工作流变得有趣的地方——流处理开始承担繁重的工作。

生成 LinkedIn 帖子

Apache Flink 是一个开源流处理框架,旨在实时处理大量数据。它擅长高吞吐量、低延迟的场景,非常适合实时 AI 应用程序。如果你熟悉数据库,可以将 Flink SQL 视为类似于标准 SQL,但不是查询数据库表,而是查询数据流。

要使用 Flink 将播客剧集转换为 LinkedIn 帖子,我需要集成一个外部 LLM。Flink SQL 通过允许你为广泛使用的 LLM 定义模型,使这一过程变得简单直接。你可以指定任务(例如 text_generation),并提供系统提示来引导输出,如下所示。

CREATE MODEL `linkedin_post_generation`
INPUT (text STRING)
OUTPUT (response STRING)
WITH (
  'openai.connection'='openai-connection',
  'provider'='openai',
  'task'='text_generation',
  'openai.model_version' = 'gpt-4',
  'openai.system_prompt' = 'You are an expert in AI, databases, and data engineering.
    You need to write a LinkedIn post based on the following podcast transcription and description.
    The post should summarize the key points, be concise, direct, free of jargon, but thought-provoking.
    The post should demonstrate a deep understanding of the material, adding your own takes on the material.
    Speak plainly and avoid language that might feel like a marketing person wrote it.
    Avoid words like "delve", "thought-provoking".
    Make sure to mention the guest by name and the company they work for.
    Keep the tone professional and engaging, and tailor the post to a technical audience. Use emojis sparingly.'
);

要创建 LinkedIn 帖子,我首先基于 MP3 URL 连接 LinkedIn Post Request topic 和 Podcast Transcript topic,将剧集描述和转录文本合并为一个提示值,并将其存储在一个视图中。使用视图可以提高可读性和可维护性;虽然我可以将字符串拼接直接嵌入 ml_predict 调用中,但这样做会使工作流更难修改。

CREATE VIEW podcast_prompt AS
SELECT
    mp3.key AS key,
    mp3.mp3Url AS mp3Url,
    CONCAT(
        'Generate a concise LinkedIn post that highlights the main points of the podcast while mentioning the guest and their company.',
        CHR(13), CHR(13),
        'Podcast Description:', CHR(13),
        rqst.episodeDescription, CHR(13), CHR(13),
        'Podcast Transcript:', CHR(13),
        mp3.transcriptionText
    ) AS prompt
FROM 
  `linkedin-podcast-mp3` AS mp3
JOIN 
    `linkedin-generation-request` AS rqst
ON 
    mp3.mp3Url = rqst.mp3Url
WHERE 
    mp3.transcriptionText IS NOT NULL;

一旦提示在视图中准备好,我就使用另一条 Flink SQL 语句,通过将提示传递给之前设置的 LLM 模型来生成 LinkedIn 帖子。完成的帖子随后被写入一个新的 Kafka topic,即 Completed LinkedIn Posts。这种方法简化了流程,同时保持了工作流的可扩展性和灵活性。

INSERT INTO `linkedin-request-complete`
SELECT
    podcast.key,
    podcast.mp3Url,
    prediction.response
FROM 
    `podcast_prompt` AS podcast
CROSS JOIN 
    LATERAL TABLE (
        ml_predict(
            'linkedin_post_generation', 
            podcast.prompt
        )
    ) AS prediction;

将帖子写入缓存

最后一步是在 Confluent Cloud 中配置另一个 HTTP Sink Connector,将完成的 LinkedIn 帖子发送到一个 API 端点。该端点将数据写入后端缓存。

一旦缓存完成,LinkedIn 帖子就可供前端应用程序使用,后者会在结果准备好后立即自动显示。

关键要点

构建一个由 AI 驱动的 LinkedIn 帖子生成器不仅仅是一种节省时间的方式——它也是一次设计现代、可扩展且解耦的事件驱动系统的实践。

与任何软件项目一样,从一开始就选择正确的架构至关重要。生成式 AI 领域正在快速发展,新的模型、框架和工具不断涌现。通过解耦组件并采用事件驱动设计,你可以让系统面向未来,从而更容易采用新技术,而无需彻底改造整个技术栈。

解耦你的工作流,采用事件驱动系统,并确保你的架构支持无缝扩展和适应。无论你是在构建 LinkedIn 帖子生成器,还是在处理更复杂的 AI 用例,这些原则都是通用的。

如果这个项目引起了你的共鸣,欢迎在 GitHub 上探索代码,或在 LinkedIn 上联系我进一步讨论。祝你构建愉快!

Confluent 及相关标记是 Confluent, Inc. 的商标或注册商标。Apache ®、Apache Kafka ® 和 Apache Flink ® 是 Apache Software Foundation 在美国和/或其他国家的注册商标或商标。使用这些标记并不意味着 Apache Software Foundation 的认可。所有其他商标均为其各自所有者的财产。



转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:Confluent Blog

原创地址:https://www.confluent.io/blog/automating-podcast-promotion-with-ai-and-event-driven-design/

原文作者:Sean Falconer;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-11-21

  • 博文量
    1090
  • 访问量
    546652