如何利用人工智能和事件驅動設計實現播客推廣的自動化 原創
本文介紹如何使用Next.js、OpenAI的GPT和Whisper模型、Apache Kafka和Apache Flink構建一個由人工智能驅動的LinkedIn帖子生成器。
為了普及知識和推廣技術,人工智能專家、本文作者Sean Falconer主持著兩個播客——《Software Engineering Daily》和《Software Huddle》,并經常以嘉賓身份亮相于其他節目。無論是主持播客還是作為嘉賓,他推廣的節目都有助于凸顯其精彩的對話內容。然而對他來說,在緊張的工作和生活中騰出時間為每期節目撰寫一篇具有思想深度的LinkedIn帖子是一項挑戰,并非每次都能實現。
為了讓工作和生活更輕松,同時也讓每一期節目更精彩,他構建了一個人工智能驅動的LinkedIn帖子生成器。該生成器可以下載播客片段,將音頻轉換為文本,并用它來創建帖子。這一工具節省了更多的時間,保持了內容的一致性,并確保每一期節目都獲得應有的關注。
Falconer在本文中將詳細介紹他如何使用Next.js、OpenAI的GPT和Whisper模型、Apache Kafka和Apache Flink構建這個工具。更重要的是,將展示Kafka和Flink如何支持事件驅動的架構,使其具有可擴展性和響應性——這是實時人工智能應用的關鍵模式。
注:如果只想看代碼,可以在??這里??查看GitHub repo。?
設計LinkedIn帖子助手
設計這個應用程序的目標非常明確:在不占用Falconer太多時間的情況下,幫助他主持的播客或作為嘉賓參與的播客節目創建LinkedIn帖子。
為了滿足需求,Falconer希望能夠為播客提要提供一個URL,可以獲取所有播客節目的詳盡列表,然后為選擇的任何一期節目生成一個LinkedIn帖子。這很簡單,是吧?當然,要讓這一切正常工作,還有一些繁重的工作要做:
- 下載所選播客節目的MP3文件。
- 使用OpenAI的Whisper模型將音頻轉換為文本。
- 由于Whisper有25MB的文件大小限制,如果需要,可以將MP3文件分成更小的塊。
- 最后,使用轉錄文本組裝一個提示,并采用LLM生成LinkedIn帖子。
除了這些功能之外,還有另一個重要的目標:保持前端應用程序與人工智能工作流程完全解耦。為什么?因為在現實世界的人工智能應用程序中,開發團隊通常會處理堆棧的不同部分。前端開發人員不需要了解任何關于人工智能的知識來構建面向用戶的應用程序。此外,還希望具備以下靈活性:
- 獨立擴展系統的不同部分。
- 隨著不斷增長的生成式人工智能堆棧的發展,能夠更換模型或框架。
為了實現這些目標使用Confluent Cloud實現了一個事件驅動的架構。這種方法不僅使架構保持模塊化,而且隨著人工智能技術不可避免地發生變化,為面向未來的應用程序奠定了基礎。
人工智能為什么采用事件驅動架構?
事件驅動架構(EDA)的出現是對依賴于嚴格的同步通信模式的傳統單體系統局限性的回應。在計算的早期,應用程序是圍繞靜態工作流構建的,通常與批處理或緊密耦合的交互聯系在一起。
單體服務器的架構
隨著技術的發展和對可擴展性和適應性的需求的增長,特別是隨著分布式系統和微服務的興起,EDA成為一種自然的解決方案。
通過將事件(例如狀態更改、用戶操作或系統觸發器)作為交互的核心單元,EDA使系統能夠解耦組件并進行異步通信。
這種方法使用數據流,生產者和消費者通過共享的、不可變的日志進行交互。事件以有保證的順序持久化,允許系統動態地、獨立地處理和響應更改。
事件生產者和消費者的高級概述
將My Web App與人工智能工作流解耦
回到當前的任務,My Web App不需要了解任何關于人工智能的知識。
為了將面向用戶的應用程序與人工智能工作流解耦,Falconer使用了Confluent Cloud的數據流平臺,該平臺支持Kafka、Flink和人工智能模型視為核心組件,使構建真正可擴展的人工智能應用程序變得容易。
當用戶點擊播客列表時,該應用程序會要求服務器檢查后端緩存中是否存在LinkedIn帖子。如果找到,它將返回并顯示該帖子。
雖然可以將這些LinkedIn帖子存儲在數據庫中,但Falconer選擇了臨時緩存,因為實際上不需要長時間保存這些帖子。
如果沒有LinkedIn帖子,后端將事件寫入Kafka主題,包括MP3的URL和節目描述。這將觸發生成LinkedIn帖子的工作流。
下圖展示了這個事件驅動系統的完整架構,下一節中將對此進行更詳細的解釋。
人工智能生成的LinkedIn帖子的事件驅動工作流
下載和生成轉錄文本
工作流程的這一部分相當簡單。Web應用程序請求寫入名為LinkedIn Post Request的Kafka主題。使用Confluent Cloud,配置了一個HTTP Sink Connector來將新消息轉發到API端點。
API端點使用提供的URL下載MP3文件,如果有必要,可以將MP3文件分割成25MB的塊,并使用Whisper處理音頻以生成轉錄文本。在轉錄完成之后,它們被寫入另一個名為“播客轉錄文本”的Kafka主題。
這就是工作流變得有趣的地方——流處理開始處理繁重的工作。
生成LinkedIn帖子
Apache Flink是一個開源流處理框架,旨在實時處理大量數據。它擅長于高吞吐量,低延遲的場景,使其非常適合實時人工智能應用程序。如果用戶對數據庫有所了解,可以將Flink SQL視為類似于標準SQL,但不同的是,Flink SQL查詢的是數據流而非數據庫表。
為了使用Flink將播客內容轉化為LinkedIn帖子,需要整合一個外部LLM。Flink SQL允許為廣泛使用的LLM定義模型,從而簡化了這一過程。可以指定任務(例如,text_generation)并提供一個系統提示符來指導輸出,如下所示:
1 CREATE MODEL `linkedin_post_generation`
2 INPUT (text STRING)
3 OUTPUT (response STRING)
4 WITH (
5 'openai.connection'='openai-connection',
6 'provider'='openai',
7 'task'='text_generation',
8 'openai.model_version' = 'gpt-4',
9 'openai.system_prompt' = 'You are an expert in AI, databases, and data engineering.
10 You need to write a LinkedIn post based on the following podcast transcription and description.
11 The post should summarize the key points, be concise, direct, free of jargon, but thought-provoking.
12 The post should demonstrate a deep understanding of the material, adding your own takes on the material.
13 Speak plainly and avoid language that might feel like a marketing person wrote it.
14 Avoid words like "delve", "thought-provoking".
15 Make sure to mention the guest by name and the company they work for.
16 Keep the tone professional and engaging, and tailor the post to a technical audience. Use emojis sparingly.'
17 );
為了創建LinkedIn帖子,首先根據MP3的URL加入了LinkedIn帖子請求主題和播客轉錄主題,將播客節目描述和轉錄組合成一個提示值,并存儲在視圖中。使用視圖可以提高可讀性和可維護性;雖然可以直接在ml_predict調用中嵌入字符串連接,但這樣做會使工作流更難修改。
1 CREATE VIEW podcast_prompt AS
2 SELECT
3 mp3.key AS key,
4 mp3.mp3Url AS mp3Url,
5 CONCAT(
6 'Generate a concise LinkedIn post that highlights the main points of the podcast while mentioning the guest and their company.',
7 CHR(13), CHR(13),
8 'Podcast Description:', CHR(13),
9 rqst.episodeDescription, CHR(13), CHR(13),
10 'Podcast Transcript:', CHR(13),
11 mp3.transcriptionText
12 ) AS prompt
13 FROM
14 `linkedin-podcast-mp3` AS mp3
15 JOIN
16 `linkedin-generation-request` AS rqst
17 ON
18 mp3.mp3Url = rqst.mp3Url
19 WHERE
20 mp3.transcriptionText IS NOT NULL;
在視圖中準備好提示之后,使用另一個Flink SQL語句通過將提示傳遞給之前設置的LLM模型來生成LinkedIn帖子。完成的帖子然后被寫入新的Kafka主題——“已完成的LinkedIn帖子”。這種方法簡化了流程,同時保持了工作流的可擴展性和靈活性。
1 INSERT INTO `linkedin-request-complete`
2 SELECT
3 podcast.key,
4 podcast.mp3Url,
5 prediction.response
6 FROM
7 `podcast_prompt` AS podcast
8 CROSS JOIN
9 LATERAL TABLE (
10 ml_predict(
11 'linkedin_post_generation',
12 podcast.prompt
13 )
14 ) AS prediction;
將帖子寫入緩存
最后一步是在Confluent Cloud中配置另一個HTTP Sink Connector,將完成的LinkedIn帖子發送到API端點。該端點將數據寫入后端緩存。
一旦寫入緩存,LinkedIn帖子就可以供前端應用程序使用,一旦準備就緒,前端應用程序就會自動顯示結果。
關鍵要點
構建人工智能驅動的LinkedIn帖子生成器,不僅僅是節省時間的一種方法,更是設計一個現代的、可擴展的、解耦的事件驅動系統的實踐。
與任何軟件項目一樣,預先選擇合適的架構至關重要。生成式人工智能領域正在迅速發展,新的模型、框架和工具不斷涌現。通過解耦組件并采用事件驅動的設計,可以使系統面向未來,從而更容易采用新技術,而無需徹底重建整個技術棧。
解耦工作流,采用事件驅動的系統,并確保架構能夠無縫擴展和適應。無論是構建LinkedIn帖子生成器,還是處理更復雜的人工智能用例,這些原則都是通用的。
如果對這個項目感興趣,可以在??GitHub???上探索代碼,或在??LinkedIn??進一步討論。?
原文標題:??Automating Podcast Promotion With AI and Event-Driven Design??,作者:Sean Falconer?
