基于 ChatGPT API 的划词翻译浏览器脚本实现

sxkk20082年前知识分享208

前言

最近 GitHub 上有个基于 ChatGPT API 的浏览器脚本,openai-translator, 短时间内 star 冲到了 9.7k, 功能上除了支持翻译外,还支持润色和总结功能,除了浏览器插件外,还使用了 tauri 打包了一个桌面客户端,那抛开 tauri 是使用 rust 部分,那浏览器部分实现还是比较简单的,今天我们就来手动实现一下。

openAI 提供的接口

比如我们可以复制以下代码,在浏览器控制台中发起请求,就可以完成翻译

//这是示例
const OPENAI_API_KEY = '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'

const prompt = `Translate this into Chinese:
        hello world`
const res = await fetch('https://api.openai.com/v1/completions', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    authorization: `Bearer ${OPENAI_API_KEY}`,
  },
  body: JSON.stringify({
    model: 'text-davinci-003',
    prompt,
    max_tokens: 1000,
    temperature: 0,
  }),
})
const response = await res.json()

const result = response.choices[0].text

上述代码中 OPONAI_API_KEY 需要替换成你自己的。

实现划词翻译

划词翻译是一种常见的网页功能,用户选择一个单词或一段文本时,自动弹出一个小窗口,显示该单词或文本的翻译。

  1. 首先,在 HTML 页面中添加一个空的 DIV 元素和一个触发翻译的按钮
let keyword
const translation = document.createElement('div')
translation.id = 'translation'
const icon = document.createElement('img')
icon.style.width = '30px'
icon.style.height = '30px'
icon.src = 'http://example.com/icon.png'
translation.appendChild(icon)
  1. 为页面添加一个鼠标抬起事件监听器,当用户选择一段文本时,设置搜索关键词。
document.addEventListener("mouseup", (event) => {
  const selection = window.getSelection().toString().trim();
  if (selection) {
    keyword=selection;
  }
});
  1. 鼠标点击执行翻译逻辑。可以使用 AJAX 请求从后台获取翻译结果并将其显示在 DIV 元素中。
function translate() {
  if (keyword) {
    // 执行翻译逻辑
  }
}
icon.addEventListener('mouseover', translate)
  1. 在 CSS 样式表中为 DIV 元素添加样式,使其浮动在页面上显示。
#translation {
  position: fixed;
  top: 10px;
  right: 10px;
  max-width: 300px;
  padding: 5px;
  background-color: #f7f7f7;
  border: 1px solid #ccc;
  box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
  z-index: 9999;
}

以上这些步骤就能实现划词翻译的基本功能,一起来看下效果。

react + antd 实现

上面的代码只是实现了一个最简单的版本,样式也不够美观,因此我们可以使用 webpack + react + antd 来实现一个现代化的插件, 这里我使用一个之前创建的模版tampermonkey-starter

使用 antd 的 Popover 组件来显示,使用 react 重构下 js 代码,我们就可以实现如下效果。

image.png

点击翻译按钮,就会通过接口请求,将翻译结果显示在下方。但是翻译结果需要等 api 完全返回,才会显示出来,这样会等待较慢,我们可以使用 Stream,OpenAI 的接口支持流渲染吗,这样结果就会一个字一个字蹦出来。

import { createParser } from 'eventsource-parser'

const translate = async (text: string) => {
  const resp = await fetch('https://api.openai.com/v1/completions', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      authorization: `Bearer ${OPENAI_API_KEY}`,
    },
    body: JSON.stringify({
      model: 'text-davinci-003',
      prompt: `Translate this into Chinese:
          ${text}`,
      max_tokens: 1000,
      temperature: 0,
      frequency_penalty: 0,
      stream: true,
    }),
  })
  if (resp.status !== 200) {
    const res = await resp.json()
    setLoading(false)
    console.error(res)
    return
  }
  const parser = createParser((event) => {
    if (event.type === 'event') {
      const data = event.data
      if (data === '[DONE]') {
        setLoading(false)
      }
      try {
        let json = JSON.parse(event.data)
        setResult((prev) => {
          return prev + json.choices[0].text
        })
      } catch (error) {
        console.log(error)
      }
    }
  })
  const data = resp.body
  if (!data) {
    console.log('Error: No data received from API')
    return
  }
  const reader = resp.body.getReader()
  try {
    while (true) {
      const { done, value } = await reader.read()
      if (done) {
        setLoading(false)
        break
      }
      const str = new TextDecoder().decode(value)
      parser.feed(str)
    }
  } finally {
    reader.releaseLock()
  }
}

在上面代码中,我们使用 fetch API 发送了一个 HTTP 请求,并在响应中获取了一个可读流。我们可以使用 getReader 方法获取一个读取器对象,并使用它来处理流数据,使用了 eventsource-parser这个包来解析服务器推送(Server-sent events)的数据。

这样响应的内容就会根据 Server-sent events(服务器发送的事件)逐个显示了。

2023-03-27 13-41-49.2023-03-27 13_46_07.gif

文本转语音

一般翻译插件都有语音播放的功能,我们可以利用 可以使用 Web Speech API。此 API 提供了两个语音合成接口:SpeechSynthesisSpeechSynthesisUtterance

function speak(text) {
  if ('speechSynthesis' in window) {
    const utterance = new SpeechSynthesisUtterance(text)
    utterance.voice = speechSynthesis.getVoices()[0]
    utterance.pitch = 1
    utterance.rate = 1
    speechSynthesis.speak(utterance)
  }
}

然后直接调用这个函数,传入需要朗读的文本,就可以实现语音播放

speak('Hello, world!')

小结

本文介绍了如何实现划词翻译的基本功能,包括使用 OpenAI 提供的接口进行翻译、在 HTML 页面中添加触发翻译的按钮和鼠标抬起事件监听事件、使用 AJAX 请求从接口获取翻译结果并将其显示在 DIV 元素中等。同时还介绍了如何使用 webpack + react + antd 实现一个现代化的插件,并利用 Web Speech API 实现语音播放功能。

本文正在参加「金石计划」

相关文章

打字机效果的实现与应用

打字机效果的实现与应用

前言在 web 应用中,模拟编辑器或者模拟输入框中文字啪啦啪啦输入的效果,往往能够吸引人们的眼球,让用户的注意力聚焦在输入的内容上,其实使用的是 web 动画模拟打字机效果,本文将和大家探讨打字机效果...

AI技术广泛应用:从医疗到金融的探索与挑战

AI技术广泛应用:从医疗到金融的探索与挑战

  近年来,随着技术的不断进步,人工智能(AI)逐渐实现了从科幻梦想到现实应用的转变。尤其是在医疗、金融等领域,AI技术正在广泛应用,为人类创造了更多的可持续发展和公平共享的...

AI新手入门教程:从零开始掌握人工智能技术

AI新手入门教程:从零开始掌握人工智能技术

  人工智能(Artificial Intelligence,简称AI)是当今科技领域的热门话题,引发了广泛的关注和研究。作为一个AI新手,想要快速入门并掌握这一领域的基...

人工智能:探索未来智能化世界的契机

人工智能:探索未来智能化世界的契机

  近年来,人工智能的发展取得了巨大进展,成为推动社会进步的重要力量之一。从机器学习到深度学习,从语音识别到图像识别,人工智能正在逐渐融入生产、服务、交通、医疗等各个领域。在...

AI技术正在颠覆世界的未来-可持续性发展的新机遇和挑战

AI技术正在颠覆世界的未来-可持续性发展的新机遇和挑战

  随着全球人口和经济增长的不断加速,人类对自然资源和环境的需求和压力正在不断增加。传统的经济增长模式正逐渐暴露出其所带来的后果,包括气候变化、自然生态破坏、资源匮乏、生态遭...

人工智能技术缺陷:挑战与改进措施

人工智能技术缺陷:挑战与改进措施

  人工智能作为一种前沿技术,近年来取得了显著的发展和应用。然而,人工智能技术在应用过程中也存在着一些明显的缺陷。  首先,人工智能技术的一个主要缺陷是其对数据的依赖性。人工...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。