背景
:
現在主流的博客平臺AI接入不夠完善,如CSDN接入的AI助手不支持
多模態數據
的交互、稀土掘金的編輯器AI功能似乎還沒能很好接入(哈哈哈,似乎在考慮布局什么?)
痛點
分析:
- 用戶常常以截圖的形式截取內容,但是如果單純的用解析工具,解析的為單純文本,而在撰寫博客時常常MD編輯器,這就可能要blogger繼續借助第三方工具將內容轉換為md格式,此過程繁瑣(結合自身博客撰寫遇到的問題)
支持PDF等文檔格式解析
:PDF等格式也是常用的內容記錄格式,但是如果需要將內容發布成博客,一是
要復制文檔內容,二是
文檔內容常常不是凝練好的常常有冗余,三是
還需借助外部工具轉化為MD格式才好發成MD格式- 文字常常不易理解,現主流博客編輯不支持將博客內容總結,生成一個
思維導圖
,這讓普通用戶讀起來或者blogger自己回顧起來可能有點吃力(調研騰訊文檔
)
功能
:
- 標題輔助生成、摘要總結(基本,調研CSDN)
- 支持多模態數據的交互:圖片和PDF等格式
- 總結生成思維導圖
- 流式展示(Fetch+SSE,自己封裝SSEWrapper和MessaageService,處理異常[瀏覽器主動斷開、刷新])
支持多模態數據解析
圖片
了解object_string多模態數據組織結構
當進行多模態數據進行對話時,首先了解對話的內容的數據結構是什么?object_string
官方說明文檔
當了解數據結構之后,我們不難知道,當單純是普通文本對話時,內容為text格式,而涉及到多模態數據是就是object_string
多模態數據內容改如何傳入到對話中(file_id和file_url)
解決這個問題,另外一個問題就是多模態數據如何處理?如何加入到對話中?
[{"type": "text","text": "你好我有一個帽衫,我想問問它好看么,你幫我看看"}, {"type": "image","file_id": "{{file_id_1}}"}, {"type": "pdf","file_id": "{{file_id_2}}"},
]
看上面object_string組織不難理解,需要一個file_id
或者file_url
,file_id可以上傳文件到Coze空間返回內容就有file_id,而file_url就需自己上傳至自己的云存儲器中,返回得到公網可訪問的url地址
- file_id獲取
上傳文件
上傳文件測試
需要注意的就是,Post請求,必須使用multipart/form-data
方式上傳文件。
// Step 1: Upload the file to Coze files API to get a file_idconst uploadResult = await fetch('https://api.coze.cn/v1/files/upload', {method: 'POST',headers: {"Authorization": `Bearer ${process.env.NEXT_PUBLIC_KEY}`,},body: formData,});if (!uploadResult.ok) {const errorData = await uploadResult.json();throw new Error(errorData.error || errorData.message || '文件上傳到Coze失敗。');}const uploadResponse = await uploadResult.json();console.log("Coze File upload response:", uploadResponse);const fileId = uploadResponse.data?.id;
- file_url獲取
file_id轉file_url
案例:設計了一個工作流,輸入數據為File格式(按正常是需要file_url,但是我避開,直接借助file_id
)
如下面,按正常PDF_Reader需要一個PDFURL,就是一個公網可訪問的pdf連接,但是臨時去搭建比較繁瑣,想著相傳文件到Coze空間了,而且也有了file_id了,應該要糾結的就是id和url如何映射,CozeAPI有自動封裝嗎?
然后去創建工作流這去看,果然可以講file_id傳入參數中,自動會解析成url,file_id->file_url,但是我在對話中試了調用Agent,Agent自動調用并傳參給工作流還是有問題——TODO
:如何傳參給Agent,Agent調用合適工作流并使用參數
原話
:工作流開始節點的輸入參數及取值,你可以在指定工作流的編排頁面查看參數列表。
如果工作流輸入參數為 Image 等類型的文件(條件1)
,可以調用上傳文件 API 獲取 file_id(條件2)
,在調用此 API 時,在 parameters 中以序列化之后的 JSON 格式傳入 file_id。例如 “parameters” : { “input”: “{“file_id”: “xxxxx”}” }
const handleSend = useCallback(async (content: string, queryParams?: EventSourceConfig['queryParams'], isTitleGeneration: boolean = false) => {if (!content.trim() && uploadedFiles.length === 0) {message.warn('消息內容或文件不能為空!');return;}if (loading) {message.warn('AI 正在處理上一個請求,請稍候。');return;}const pdfFile = uploadedFiles.find(file => file.type === 'pdf');if (pdfFile) {// If a PDF is uploaded, trigger the workflowawait executePdfWorkflowBackend(pdfFile.id, pdfFile.name);// Optionally, clear the input or add a user message for the PDF actionsetAiInput(''); // Clear the input after triggering PDF workflowsetUploadedFiles([]); // Clear uploaded files after workflow triggerreturn; // Exit as the workflow is handled}let finalContentToSend: string;let finalContentType: ContentType;if (uploadedFiles.length > 0) {finalContentType = ContentType.MULTIMODAL;const objectContent: any[] = [{ type: 'text', text: content }];uploadedFiles.forEach(file => {objectContent.push({type: file.type === 'pdf' ? 'file' : file.type, // Coze treats PDF as 'file' type for multimodalfile_id: file.id});});finalContentToSend = JSON.stringify(objectContent);} else {finalContentType = ContentType.TXT;finalContentToSend = content;}setLastRequestContent(finalContentToSend);console.log("AIDialogContent: Sending content:", finalContentToSend, "with contentType:", finalContentType);try {await messageService.send(finalContentToSend, {...queryParams,contentType: finalContentType,llmProvider: selectedModel,onComplete: (latestMessageContent: string) => {if (isTitleGeneration && onGenerateTitlePrompt) {onGenerateTitlePrompt(latestMessageContent);}}});} catch (error) {console.error("AIDialogContent: Error during message sending process:", error);if (!isStreamingMessage) {setLoading(false);}} finally {setAiInput('');console.log("AIDialogContent: Input cleared.");}}, [loading, isStreamingMessage, messageService, uploadedFiles, selectedModel, onGenerateTitlePrompt, executePdfWorkflowBackend]);
官方案例:解析文檔
大模型本身并不具備文件讀取和解析的能力
,無法直接處理文件字節流。對于支持工具調用(Function calling)的模型,扣子提供插件功能來幫助大模型調用外部工具 API
,拓展大模型的能力邊界。扣子插件商店提供海量官方插件和第三方插件,例如鏈接讀取插件可以將鏈接對應的文件內容解析為純文本傳遞給大模型
。