ChatGPT Anywhere:零成本集成ChatGPT的浏览器扩展开发框架

news2026/5/7 15:59:24
1. 项目概述与核心价值最近在折腾浏览器扩展发现一个挺有意思的开源项目叫 ChatGPT Anywhere。简单来说它提供了一个“骨架”让你能直接在浏览器扩展里调用 ChatGPT而且最关键的是它不走 OpenAI 的官方收费 API而是直接和 ChatGPT 网页版的接口对话。这意味着什么意味着只要你有一个能正常登录使用的 ChatGPT 账号无论是免费版还是 Plus 版你就能在你的扩展里免费、无限次地调用它的能力而不用为每一次 API 调用付费。这个思路其实挺巧妙的。OpenAI 的官方 API 是按 token 收费的虽然单价不高但对于需要频繁调用或者开发面向大量用户工具的个人开发者和小团队来说长期来看也是一笔不小的开销。而 ChatGPT 的网页版只要你登录了理论上对话是“免费”的当然Plus 订阅是另一回事。ChatGPT Anywhere 这个项目本质上就是通过浏览器扩展这个“中间人”模拟了你在网页上跟 ChatGPT 聊天的过程然后把对话的输入输出桥接到了你的扩展代码里。我花了一些时间深入研究它的源码和设计发现它不仅仅是一个“白嫖”API 成本的工具更是一个设计相当优雅的、用于构建基于 ChatGPT 的浏览器扩展的开发框架。它帮你处理了最麻烦的部分与 ChatGPT 网页版的认证、会话维持、消息收发。作为开发者你只需要关心你的扩展业务逻辑比如你想让 ChatGPT 帮你总结网页内容、翻译选中的文本、还是根据页面信息生成代码剩下的通信脏活累活它都包了。2. 核心原理与架构拆解要理解 ChatGPT Anywhere 怎么工作得先明白浏览器扩展和 ChatGPT 网页版是怎么交互的。这不像调用一个简单的 HTTP API 那么简单因为 ChatGPT 网页版是一个复杂的单页应用 (SPA)有它自己的认证状态、会话管理和实时通信机制。2.1 技术实现路径内容脚本与后台服务的协作ChatGPT Anywhere 的核心是一个典型的浏览器扩展结构主要包含以下几个部分manifest.json: 扩展的配置文件定义了权限、需要注入的脚本、后台服务等。content-script.js(内容脚本): 这个脚本会直接注入到 ChatGPT 的网页通常是chat.openai.com中。它运行在网页的上下文中因此可以“看到”并操作网页的 DOM文档对象模型也能访问网页的 JavaScript 环境。这是与 ChatGPT 交互的关键。它的任务是监听我们扩展发来的指令然后在 ChatGPT 页面上“模拟”用户操作找到输入框、填入问题、点击发送按钮然后监听回复区域的更新再把回复内容抓取出来。background.js(后台脚本/服务工作者): 这是一个长期运行在浏览器后台的脚本不依赖于任何特定网页。它负责协调整个扩展的工作流。当你的扩展弹出窗口Popup或别的部分想要向 ChatGPT 提问时消息会先发送到background.js再由它转发给那个已经注入到 ChatGPT 页面的content-script.js。openai.js(核心 API 类): 这是项目封装的精髓——OpenAIConversation类。它提供了一个非常简洁的 Promise-based 或 callback-based 的 API。你在扩展的业务逻辑里只需要new一个这个类的实例然后调用ask(question)方法它就会在内部处理好与background.js和content-script.js的通信最终把 ChatGPT 的回复返回给你。它还内置了会话历史管理多次ask会保持对话的连续性。整个数据流可以这样概括你的扩展业务逻辑 -OpenAIConversation实例 -background.js(消息路由) -content-script.js(在 ChatGPT 页面执行操作) - ChatGPT 服务器 - 返回回复 - 逆向传回给你的业务逻辑。注意这种方式的合法性取决于 OpenAI 的服务条款。它本质上是在自动化使用其网页服务。虽然项目是开源的主要用于学习和开发原型但在构建面向大众的成熟产品时务必仔细阅读相关条款评估风险。个人和小范围使用通常问题不大。2.2 为何选择此方案成本与灵活性的权衡选择绕过官方 API直接与网页交互核心驱动力就是成本。对于原型验证、个人工具、或用户量不大的小众工具官方 API 的费用可能成为阻碍。此方案将成本转移到了终端用户的 ChatGPT 账号上用户需要自行登录实现了开发者侧的“零 API 成本”。其次是功能同步性。网页版 ChatGPT 往往是功能最先更新的地方比如新的模型版本、新的界面特性。通过直接与网页交互你的扩展能几乎“零延迟”地享受到这些更新而不需要等待 OpenAI 官方 API 的更新和支持。当然缺点也很明显稳定性风险高度依赖 ChatGPT 网页的 DOM 结构和接口一旦 OpenAI 前端改版扩展就可能失效需要及时更新选择器或交互逻辑。速率限制受限于网页版自身的速率限制无法像付费 API 那样通过提升套餐来增加调用频率。无官方保障这不是官方支持的集成方式出现问题没有官方渠道支持。用户体验需要用户预先登录 ChatGPT 网页并保持登录状态。对于未登录用户扩展无法工作。3. 环境搭建与项目初始化实操让我们动手把这个项目跑起来看看它到底是怎么工作的。这里我以 Chrome 浏览器为例Firefox 的流程大同小异。3.1 获取源码与依赖安装首先把代码克隆到本地。打开你的终端命令行工具找一个合适的目录。# 克隆项目仓库 git clone https://github.com/AkashKarnatak/chatgpt-anywhere.git # 进入项目文件夹 cd chatgpt-anywhere项目使用 npm 进行包管理我们需要安装依赖。确保你的电脑已经安装了 Node.js (建议使用 LTS 版本)。# 安装项目依赖 npm install这个命令会根据package.json文件下载所有必要的开发依赖比如构建工具、代码打包器通常是 Webpack 或类似的等。如果网络状况不佳可以考虑配置 npm 镜像源。3.2 构建扩展包依赖安装完成后就可以构建扩展了。项目脚本已经配置好可以同时生成 Chrome 和 Firefox 版本的扩展包。# 执行构建命令 npm run build构建过程通常包括将源代码如 JS、CSS进行打包、压缩、转换以符合浏览器扩展的规范。构建完成后你会在项目根目录下看到两个新生成的文件夹chrome-extension/firefox-extension/这两个文件夹里就是可以直接加载到浏览器里的扩展程序包。3.3 加载未打包的扩展程序由于我们处于开发阶段需要加载的是“未打包”的扩展程序即刚才生成的文件夹。以 Chrome 为例打开 Chrome 浏览器在地址栏输入chrome://extensions/并回车进入扩展管理页面。确保右上角的“开发者模式”开关是打开的状态。点击左上角的“加载已解压的扩展程序”按钮。在弹出的文件选择器中导航到你的chatgpt-anywhere项目目录选择刚刚生成的chrome-extension文件夹然后点击“选择文件夹”。此时扩展列表中应该会出现 “ChatGPT Anywhere” 这个扩展并且图标会出现在浏览器工具栏。Firefox 的操作类似访问about:debugging#/runtime/this-firefox点击“临时载入附加组件”然后选择firefox-extension文件夹内的manifest.json文件。实操心得在开发过程中每次修改了源代码除了manifest.json等配置文件都需要重新执行npm run build命令来更新chrome-extension文件夹里的内容。然后回到chrome://extensions/页面找到你加载的 ChatGPT Anywhere 扩展点击其卡片上的刷新图标即可更新扩展无需重新加载整个文件夹。这能极大提升开发调试效率。4. 核心 APIOpenAIConversation 类深度解析ChatGPT Anywhere 的灵魂是OpenAIConversation类。它被设计得非常易用将底层复杂的通信细节完全封装了起来。让我们深入看看它的用法和内部机制。4.1 初始化与基础使用这个类通常在你扩展的“后台页面”background page或“弹出窗口”popup的脚本中使用。假设你有一个popup.js文件当用户点击扩展图标时运行。首先你需要确保能访问到这个类。在项目中它通过模块化的方式导出。在你的脚本里可以这样使用// 在 popup.js 或你的业务逻辑脚本中 // 假设 openai.js 已经被打包工具正确处理或者通过其他方式引入 // 项目中的 content-script.js 已经能直接访问 OpenAIConversation因为它在同一个上下文中。 // 但对于popup或background你可能需要通过消息传递来间接使用或者调整构建配置使其可用。 // 这里以最直接的使用场景在content script中为例 // 创建一个新的对话实例 const conversation new OpenAIConversation({ // 收到消息时的回调函数 onMessage: (content, conversationId) { console.log(收到ChatGPT回复:, content); console.log(当前会话ID:, conversationId); // 在这里更新你的UI比如把回复显示在popup的某个div里 document.getElementById(response-area).textContent content; }, // 发生错误时的回调函数 onError: (error) { console.error(与ChatGPT通信时出错:, error); alert(请求失败: error.message); }, // 可选指定使用的模型版本例如 gpt-4需要用户有对应权限 model: gpt-4 }); // 发送一个问题 document.getElementById(ask-button).addEventListener(click, async () { const question document.getElementById(question-input).value; if (!question.trim()) return; // 调用ask方法。注意这个方法内部是异步的。 // 回复会通过上面定义的onMessage回调返回。 try { await conversation.ask(question); // ask方法本身可能resolve时只表示“请求已发送”实际回复走onMessage console.log(问题已发送); } catch (err) { // 这里捕获的是发送请求本身的错误如网络问题、未登录 onError(err); } });关键点在于onMessage回调。因为与网页的交互是异步且基于事件监听的所以采用回调模式比单纯的async/await更合适。ask方法发送问题而回复则“推送”到你的回调函数中。4.2 会话管理与上下文保持OpenAIConversation实例的一个强大之处在于它自动维护了会话历史。每次你调用conversation.ask(新问题)它内部会确保这次提问是基于之前同一实例下所有问答的上下文进行的。这意味着你可以实现多轮对话。// 连续提问ChatGPT会记得之前的对话 await conversation.ask(什么是JavaScript); // 几秒后onMessage会收到关于JavaScript的解释 // 然后接着问 await conversation.ask(它和Java有什么关系); // 这次的回复会基于上一个关于JavaScript的问题来回答理解“它”指代JavaScript。如果你需要开始一个全新的、不关联历史的对话很简单创建一个新的OpenAIConversation实例即可。const newTopicConversation new OpenAIConversation({ onMessage, onError }); await newTopicConversation.ask(写一首关于春天的诗); // 这个对话与之前的conversation实例完全独立4.3 模型选择与高级配置项目还提供了一个功能允许用户在扩展的弹出窗口中选择不同的 ChatGPT 模型例如 GPT-3.5 Turbo 或 GPT-4。这通过向OpenAIConversation构造函数传递model参数实现。在扩展的popup.html中你可以设计一个下拉菜单select idmodel-selector option valuedefault默认 (GPT-3.5)/option option valuegpt-4GPT-4/option /select然后在 JS 中根据选择来创建实例document.getElementById(start-chat).addEventListener(click, () { const selectedModel document.getElementById(model-selector).value; const model selectedModel default ? null : selectedModel; currentConversation new OpenAIConversation({ onMessage: handleResponse, onError: handleError, model: model // 传入选择的模型 }); });注意事项模型选择功能是否生效完全取决于用户的 ChatGPT 账号权限。免费用户可能只能使用默认模型GPT-3.5选择 GPT-4 会被 ChatGPT 网页端拒绝或降级。Plus 订阅用户才能稳定使用 GPT-4。你的扩展代码需要做好错误处理当用户选择无权使用的模型时给予友好提示。5. 实战基于 ChatGPT Anywhere 开发你的第一个扩展理解了核心 API 后我们来动手做一个简单的、真正有用的扩展。假设我们要做一个“页面总结器”用户点击扩展图标弹出窗口点击一个按钮就能获取当前浏览器标签页正文内容的简要总结。5.1 项目结构与规划我们将创建一个新的扩展项目但复用 ChatGPT Anywhere 的核心通信模块。为了清晰我们新建一个目录。my-page-summarizer/ ├── manifest.json ├── popup.html ├── popup.js ├── content-script.js (用于获取页面内容) ├── background.js ├── icons/ └── node_modules/ (或通过构建工具引入chatgpt-anywhere的核心模块)更实际的做法是将 ChatGPT Anywhere 项目作为我们项目的子模块git submodule或 npm 依赖直接引用其openai.js和相关的通信基础设施。但为了简化演示我们假设已经将必要的文件复制到了我们的项目中。5.2 关键代码实现1.manifest.json配置这个文件告诉浏览器我们的扩展是什么以及它需要什么权限。{ manifest_version: 3, name: 页面智能总结器, version: 1.0, description: 使用ChatGPT快速总结当前网页内容, permissions: [ activeTab, // 获取当前活动标签页的权限 scripting // 为了执行内容脚本 ], host_permissions: [ https://chat.openai.com/* // 必须允许与ChatGPT网站交互 ], action: { default_popup: popup.html, default_icon: icons/icon48.png }, background: { service_worker: background.js }, content_scripts: [ { matches: [all_urls], // 向所有页面注入一个脚本用于提取文本 js: [content-script.js], run_at: document_idle } ], icons: { 48: icons/icon48.png, 128: icons/icon128.png } }2.popup.html与popup.js(用户界面)这是一个简单的弹出窗口界面。!DOCTYPE html html head style body { width: 300px; padding: 15px; font-family: sans-serif; } #summary { margin-top: 10px; padding: 10px; border: 1px solid #ccc; min-height: 100px; white-space: pre-wrap; } button { padding: 8px 15px; } .loading { color: #666; font-style: italic; } /style /head body h3页面总结器/h3 p点击按钮使用ChatGPT总结当前页面核心内容。/p button idsummarize-btn开始总结/button div idsummary等待操作.../div script srcpopup.js/script /body /html// popup.js document.addEventListener(DOMContentLoaded, function() { const button document.getElementById(summarize-btn); const summaryDiv document.getElementById(summary); let isProcessing false; button.addEventListener(click, async function() { if (isProcessing) return; isProcessing true; button.disabled true; summaryDiv.textContent 正在提取页面内容并发送给ChatGPT请稍候...; summaryDiv.className loading; try { // 第一步获取当前活动标签页的ID const [tab] await chrome.tabs.query({ active: true, currentWindow: true }); // 第二步向该标签页的内容脚本发送消息要求获取页面文本 // 注意这里需要content-script.js配合 const response await chrome.tabs.sendMessage(tab.id, { action: getPageText }); if (!response || !response.text) { throw new Error(无法获取页面文本内容。); } const pageText response.text; // 简单截断避免文本过长ChatGPT有上下文长度限制 const textToSummarize pageText.substring(0, 3000); // 第三步使用ChatGPT Anywhere的API进行总结 // 这里假设我们已经通过某种方式在popup环境中获得了OpenAIConversation类 // 实际上更常见的做法是popup将任务委托给background script由background来管理ChatGPT对话。 // 为了简化我们假设有一个全局的、在background中初始化的conversation实例可以通过消息调用。 // 通过background script来调用ChatGPT const chatResponse await chrome.runtime.sendMessage({ action: askChatGPT, prompt: 请用中文简要总结以下内容的核心要点\n\n${textToSummarize} }); if (chatResponse.error) { throw new Error(chatResponse.error); } summaryDiv.textContent chatResponse.content || 未收到总结内容。; summaryDiv.className ; } catch (error) { summaryDiv.textContent 错误: ${error.message}; summaryDiv.className ; console.error(error); } finally { isProcessing false; button.disabled false; } }); });3.content-script.js(提取页面文本)这个脚本注入到每一个网页中负责提取纯净的正文文本。// content-script.js // 监听来自popup或background的消息 chrome.runtime.onMessage.addListener((request, sender, sendResponse) { if (request.action getPageText) { // 一个简单的方法获取body的文本并清理多余的空格和换行 const bodyText document.body.innerText || document.body.textContent; // 进行一些基本的清理 const cleanedText bodyText .replace(/\s/g, ) // 将多个空白字符替换为单个空格 .trim() .substring(0, 5000); // 再次限制长度防止消息传递过大 sendResponse({ text: cleanedText }); } // 保持异步响应通道打开如果需要异步操作 return true; });4.background.js(后台服务与 ChatGPT 中枢)这是核心枢纽它持有OpenAIConversation实例并处理所有与 ChatGPT 的通信。// background.js // 这里需要引入ChatGPT Anywhere的核心模块。假设我们通过构建工具将其打包进来。 // 或者如果openai.js依赖于DOM则需要在特定的“内容脚本”环境中运行background不能直接使用。 // 更标准的做法是background script不直接操作OpenAIConversation而是通过一个长期存在于ChatGPT页面中的“代理”内容脚本来中转。 // 项目原版的设计就是如此OpenAIConversation在注入到chat.openai.com的content script中运行。 // 因此我们需要建立background与chatgpt页面content script之间的桥梁。 // 首先确保有一个标签页打开了chat.openai.com并保持登录。 let chatGptTabId null; // 监听来自popup的请求 chrome.runtime.onMessage.addListener((request, sender, sendResponse) { if (request.action askChatGPT) { handleChatGPTRequest(request.prompt, sendResponse); // 保持异步响应 return true; } }); async function handleChatGPTRequest(prompt, sendResponse) { try { // 1. 寻找或创建一个已登录的ChatGPT标签页 const tabs await chrome.tabs.query({ url: https://chat.openai.com/* }); let tab tabs[0]; if (!tab) { // 如果没有打开的ChatGPT页面则创建一个 tab await chrome.tabs.create({ url: https://chat.openai.com/, active: false }); // 等待页面加载完成这里简化处理实际需要更完善的等待逻辑 await new Promise(resolve setTimeout(resolve, 3000)); } chatGptTabId tab.id; // 2. 向该标签页的content script发送消息要求其执行提问操作 // 我们需要确保chat.openai.com页面已经注入了我们的“代理”content script。 // 这通常通过在manifest的content_scripts中匹配chat.openai.com来实现。 // 假设我们已经有一个content script在chatgpt页面上运行并监听特定的消息。 const responseFromChatGpt await chrome.tabs.sendMessage(chatGptTabId, { action: askViaOpenAIConversation, prompt: prompt }); // 3. 将结果返回给最初的调用者popup sendResponse({ content: responseFromChatGpt.content }); } catch (error) { console.error(Background处理ChatGPT请求失败:, error); sendResponse({ error: error.message }); } } // 此外我们需要一个专门注入到chat.openai.com的content script。 // 这个脚本负责实例化OpenAIConversation并处理ask请求。 // 我们可以把它和之前提取文本的content-script分开通过manifest单独注入到chat.openai.com。 // 假设这个文件叫 chatgpt-proxy.js5.chatgpt-proxy.js(ChatGPT 页面代理)这个脚本只注入到chat.openai.com。// chatgpt-proxy.js // 这个脚本运行在chat.openai.com的上下文中可以访问OpenAIConversation let conversationInstance null; // 初始化一个对话实例 function initConversation() { if (conversationInstance) return conversationInstance; conversationInstance new OpenAIConversation({ onMessage: (content) { // 这里可以处理流式输出但简单起见我们假设一次返回完整内容。 // 实际通信需要通过chrome.runtime.sendMessage将内容送回background。 // 为了简化我们在ask方法里用Promise包装。 console.log(ChatGPT回复:, content); }, onError: (error) { console.error(ChatGPT错误:, error); } }); return conversationInstance; } // 监听来自background script的请求 chrome.runtime.onMessage.addListener((request, sender, sendResponse) { if (request.action askViaOpenAIConversation) { handleAskRequest(request.prompt, sendResponse); return true; // 异步响应 } }); async function handleAskRequest(prompt, sendResponse) { try { const conv initConversation(); // 这里需要将回调式的API转换为Promise以便于通过sendResponse返回。 // OpenAIConversation.ask() 可能不会直接返回Promise我们需要自己封装。 await new Promise((resolve, reject) { // 我们需要临时覆盖onMessage来捕获本次请求的回复 const originalOnMessage conv.onMessage; conv.onMessage (content) { // 恢复原回调 conv.onMessage originalOnMessage; // 将结果通过sendResponse传回 sendResponse({ content: content }); resolve(); }; // 同样处理错误 const originalOnError conv.onError; conv.onError (error) { conv.onError originalOnError; sendResponse({ error: error.message }); reject(error); }; // 发送问题 conv.ask(prompt).catch(reject); }); } catch (error) { sendResponse({ error: 代理请求失败: ${error.message} }); } }你需要更新manifest.json的content_scripts部分将chatgpt-proxy.js只注入到 ChatGPT 的域名content_scripts: [ { matches: [all_urls], js: [content-script.js], run_at: document_idle }, { matches: [https://chat.openai.com/*], js: [chatgpt-proxy.js], run_at: document_idle } ]5.3 构建与测试将上述文件按照结构放置好并确保openai.js等核心文件在正确的位置通常需要和chatgpt-proxy.js放在一起并通过打包工具处理依赖。然后使用类似 ChatGPT Anywhere 项目的构建流程如果有或直接加载这些文件作为未打包的扩展。加载扩展后打开任何一个有大量文本的网页比如一篇新闻文章点击你的扩展图标点击“开始总结”按钮。后台会依次执行提取文本 - 发送到后台 - 后台找到/打开 ChatGPT 页面 - 通过代理脚本提问 - 获取总结 - 返回并显示在弹出窗口中。6. 常见问题、调试技巧与进阶优化在实际开发中你肯定会遇到各种问题。这里记录一些我踩过的坑和解决方案。6.1 常见问题排查表问题现象可能原因排查步骤与解决方案扩展图标点击无反应1.manifest.json配置错误。2.popup.html路径错误或语法错误。3. 扩展未成功加载。1. 检查chrome://extensions/页面是否有错误提示通常为黄色感叹号。2. 右键点击扩展图标 - “检查弹出内容”打开开发者工具查看控制台报错。3. 确保manifest.json中action.default_popup路径正确。点击按钮后一直显示“等待”或超时1. 内容脚本未正确注入或通信失败。2. ChatGPT 页面未登录或加载失败。3.OpenAIConversation初始化失败。1. 在目标网页和 ChatGPT 网页的控制台查看是否有错误。在chrome://extensions/页面点击“服务工作者”链接检查 background script 控制台。2. 手动访问chat.openai.com确保已登录且能正常对话。3. 检查chatgpt-proxy.js是否成功注入到 ChatGPT 页面在 ChatGPT 页面打开开发者工具Sources 标签页查看。4. 在chatgpt-proxy.js中增加详细的console.log跟踪OpenAIConversation初始化和ask过程。收到“无法获取页面文本”错误1. 内容脚本content-script.js未注入到当前标签页。2. 页面结构特殊document.body.innerText获取不到有效内容。1. 确认manifest.json中content_scripts.matches包含了当前网页的 URL 模式。2. 尝试更健壮的文本提取方法例如使用Readability.js这样的库来提取文章主体内容。ChatGPT 回复为空或错误1. 提问的 prompt 设计不佳。2. 页面文本过长超出模型上下文。3. ChatGPT 服务器端错误或网络问题。1. 优化你的 prompt例如“请用中文总结以下内容列出3-5个要点”。2. 对提取的文本进行长度限制和清理如去除过多空格、脚本代码等。3. 在onError回调中打印详细错误信息看是否是网络超时或 ChatGPT 返回了错误。模型切换不生效1. 用户账号不支持所选模型如免费用户选 GPT-4。2.OpenAIConversation的model参数传递或处理有误。1. 在 UI 上做好提示告知用户模型可用性取决于其 ChatGPT 账号权限。2. 在chatgpt-proxy.js中检查传入的model参数是否正确传递给了OpenAIConversation构造函数。6.2 调试技巧实录分层调试不要所有代码写完了再测试。先确保content-script.js能正确获取页面文本单独写个测试按钮输出文本。再确保background.js和chatgpt-proxy.js能正常通信互相发送测试消息。最后再整合 ChatGPT 问答功能。利用 Chrome 开发者工具弹出窗口右键点击扩展图标 - “检查弹出内容”可以调试 popup 页面的 JS 和 DOM。后台脚本在chrome://extensions/页面找到你的扩展点击“服务工作者”链接Manifest V3或“背景页”链接Manifest V2打开开发者工具。内容脚本直接在目标网页或 ChatGPT 网页按 F12 打开开发者工具切换到 Console 面板其上下文Context选择你的扩展名对应的内容脚本即可看到该脚本的console.log输出。消息传递调试在chrome.runtime.sendMessage和chrome.runtime.onMessage.addListener处大量使用console.log打印发送和接收的消息体确保数据流畅通。6.3 进阶优化方向会话持久化目前的OpenAIConversation实例存在于内存中一旦 ChatGPT 标签页刷新或扩展重启会话历史就丢失了。可以考虑将会话 ID 或关键的对话历史摘要存储到chrome.storageAPI 中实现一定程度的持久化。流式输出ChatGPT 网页版是流式输出文字的。当前的实现是等待全部输出完毕再一次性返回。可以修改chatgpt-proxy.js中的onMessage回调使其能分片接收内容并通过chrome.runtime.sendMessage实时传回前端实现打字机效果体验更好。错误恢复与重试网络是不稳定的。增加自动重试机制当onError收到超时或网络错误时自动重试 1-2 次。多标签页并发管理如果用户同时在不同网页触发总结需要管理好多个并发的 ChatGPT 请求队列避免冲突。可以在 background script 中实现一个简单的请求队列。更优雅的文本提取使用专业的库如Mozilla Readability来提取网页正文能有效去除导航栏、广告、评论等噪音内容得到更纯净的总结素材。隐私考虑明确告知用户扩展会将网页文本内容发送到 ChatGPT 的服务器进行处理。可以提供选项让用户选择是否启用此功能或者允许他们手动审核要发送的文本。这个项目作为一个起点已经极大地降低了开发门槛。围绕它构建真正有价值的生产力工具剩下的就是发挥你的产品思维和前端工程能力了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2591952.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…