多语言大师:“AI出海实战”

365 阅读6分钟

本文正在参加金石计划附加挑战赛——第一期命题

写在开始

大家都知道,在处理国际业务时,面对多语种用户群体,有时需要借助翻译工具来进行代码开发。那么,如何利用现有的资源高效地处理多语言业务呢?答案是:构建一个基于AI的语言处理器,并通过调用OpenAI接口来迅速应对代码中的多语言需求。接下来,我们将通过一个简单的例子来说明这一过程。

"La performance du systeme est plus lente que d'habitude.", /// 系统的性能比平时慢
"Mi monitor tiene pixeles que no se iluminan.", // 我的显示器有些像素不亮
"Il mio mouse non funziona", // 我的鼠标不工作了
"M6j klawisz Ctrl jest zepsuty", // 我的Ctrl键坏了

朋友们,上面的句子是英文吗?

实际上并不是。这些句子分别来自意大利语、法语和西班牙语。当遇到这样的情况时,如果不知道原文是什么语言,直接使用翻译工具可能会面临挑战,因为需要先确定源语言才能准确翻译。但是,现在有了AI的帮助,我们可以轻松解决这个问题。 下面,就让我们来看看如何将AI翻译功能集成到我们的代码中,实现无缝多语言支持

出海“AI翻译”

1.环境搭建

1.Node.js环境下创建LLM项目的代码工程:

  • 打开之前安装过 OpenAI 的项目的package.json,将其中的dependencies: {} 部分(即项目运行时所依赖的npm包)拷贝到我们新项目的package.json中。代码:
"dependencies": {
    "dotenv": "^16.4.5",
    "openai": "^4.73.0"
  },
  • 再输入npm i这样就可以搭建好了。

链接:详细配置教程和prompt知识点看这

2.使用dotenv管理环境变量

使用dotenv是程序员安全意识的一个重要体现,因为我们的 key 等重要信息不能以明文出现,所以我们通过使用dotenv 在项目的根目录下创建一个名为.env的文件来存储配置信息(如API密钥等敏感数据),这些信息不会被提交到git等之中,这样就可以保证我们敏感信息的安全性。

接下来我们就来演示如何正确地使用dotenv:

  • import dotenv from "dotenv";:导入dotenv模板。
  • 创建.env文件,并且将我们的 key 放入其中。
  • dotenv.config();:将.env 读入process.env 对象中。

这样我们就可以安全的调用key ,通过process.env来获取key。

实战步骤:

  • 1.创建函数,并且用户提供prompt 生成响应
// es6 默认参数值
// 通用的LLM 聊天完成接口函数, 复用
// 封装 通用大模型聊天接口函数,初始化聊天接口,
const getCompletion =  async (prompt, model="gpt-3.5-turbo") => {
  // 用户提的问题
  const messages = [{
    role: 'user',
    content: prompt
  }];
  // AIGC chat 接口
  // 
  const response = await client.chat.completions.create({
    model: model,
    messages: messages,
    // LLM 生成内容的随机性
    temperature: 0.9
  }) 
  // 解析返回结果 js对象里面的结果
  return response.choices[0].message.content
}
  • 2.重点部分,处理用户信息,使用异步进行处理“翻译这个过程”。这段代码套用其他业务也是可以的
const main = async () => {
    const user_messages = [
        "La performance du système est plus lente que d'habitude.",  //系统的性能比平时慢         
        "Mi monitor tiene píxeles que no se iluminan.",              //我的显示器有些像素点不亮。
        "Il mio mouse non funziona",                                // 我的鼠标坏了
        "Mój klawisz Ctrl jest zepsuty",                            // 我的Ctrl键坏了
        "我的屏幕在闪烁"                    
    ]
// for of es6遍历:
    for(let issue of user_messages) {
         const resultPrompt = `请翻译为中文语: ${issue}`;
         const result = await getCompletion(resultPrompt)
          console.log(`意思是:${result}`);
    } 
}

结果:

image.png

  • 同样可以增加语言判断,使用async 和await异步调用getCompletion函数
const main = async () => {
    const user_messages = [
        "La performance du système est plus lente que d'habitude.",  //系统的性能比平时慢         
        "Mi monitor tiene píxeles que no se iluminan.",              //我的显示器有些像素点不亮。
        "Il mio mouse non funziona",                                // 我的鼠标坏了
        "Mój klawisz Ctrl jest zepsuty",                            // 我的Ctrl键坏了
        "我的屏幕在闪烁"                    
    ]
// for of es6遍历:
    for(let issue of user_messages) {
         const resultPrompt = `请翻译为中文语: ${issue}`;
         const result = await getCompletion(resultPrompt)
          console.log(`语句意思是:${result}`);
        
    } 
    const prompt = `
     Tell me what language this is "${user_messages}"
     `
     const countryLanguage = await getCompletion(prompt);

     const resultPrompt = `
       帮我翻译以下文字到中文,"${countryLanguage}"
       `
      const result = await getCompletion(resultPrompt)
       console.log(`是${countryLanguage},翻译结果是:${result}`);

}

image.png 使用下面完整代码试一下吧

import OpenAI from "openai";
import dotenv from "dotenv";

dotenv.config() // 读取.env 配置内容到possess.env文件中
// promise 进程对象,
const client = new OpenAI({
  // node 里的进程对象
  apiKey: process.env.OPENAI_API_KEY,
  baseURL:process.env.OPENAI_BASE_URL
})
// es6 默认参数值
// 通用的LLM 聊天完成接口函数, 复用
// 封装 通用大模型聊天接口函数,初始化聊天接口,
const getCompletion =  async (prompt, model="gpt-3.5-turbo") => {
  // 用户提的问题
  const messages = [{
    role: 'user',
    content: prompt
  }];
  // AIGC chat 接口
  // 
  const response = await client.chat.completions.create({
    model: model,
    messages: messages,
    // LLM 生成内容的随机性
    temperature: 0.9
  }) 
  // 解析返回结果 js对象里面的结果
  return response.choices[0].message.content
}

const main = async () => {
    const user_messages = [
        "La performance du système est plus lente que d'habitude.",  //系统的性能比平时慢         
        "Mi monitor tiene píxeles que no se iluminan.",              //我的显示器有些像素点不亮。
        "Il mio mouse non funziona",                                // 我的鼠标坏了
        "Mój klawisz Ctrl jest zepsuty",                            // 我的Ctrl键坏了
        "我的屏幕在闪烁"                    
    ]
// for of es6遍历:
    for(let issue of user_messages) {
         const resultPrompt = `请翻译为中文语: ${issue}`;
         const result = await getCompletion(resultPrompt)
          console.log(`语句意思是:${result}`);
        
    } 
    const prompt = `
     Tell me what language this is "${user_messages}"
     `
     const countryLanguage = await getCompletion(prompt);

     const resultPrompt = `
       帮我翻译以下文字到中文,"${countryLanguage}"
       `
      const result = await getCompletion(resultPrompt)
       console.log(`是${countryLanguage},翻译结果是:${result}`);
}
main();
  • 思考: 为什么for变量设定的变量,外部result不能访问?
  • 词法作用域与块级作用域就很好理解,下面用代码实例进行解释

啥咋解释!?

词法作用域是在编译时决定的,而不是在运行时。这意味着变量的作用范围是在编写代码时就已经确定好了。

不清楚执行上下文和执行栈的伙伴可以看下链接转换台

示例分析

考虑以下代码段:

function foo() {
    var a = 1;
    let b = 2;

    // 块级作用域
    {
        let b = 3;
        var c = 4;
        let d = 5;
        console.log(a); // 输出: 1
        console.log(b); // 输出: 3
    }

    console.log(b); // 输出: 2
    console.log(c); // 输出: 4
    // console.log(d); // 抛出错误: ReferenceError: d is not defined
}
foo();

image.png

在这个例子中,我们观察到了几个关键点:

  • 变量提升var 声明的变量会被提升至函数作用域的顶部,这意味着 a 和 c 实际上在整个 foo 函数体内都是可访问的。
  • 块级作用域let 和 const 引入了块级作用域的概念,即它们只在声明它们的 {} 块内有效。因此,虽然 b 被重新声明为 3 并且只在块内可见,但在块外部调用 b 时,输出的是最外层声明的 2
  • 暂时性死区 (Temporal Dead Zone, TDZ) :尝试在 let 或 const 变量声明前访问它们会导致错误。这是因为这些变量在初始化之前处于一个“暂时性死区”。例如,如果我们在 {} 块外尝试访问 d,将会抛出 ReferenceError

暂时性死区 (TDZ)

另一个示例更好地展示了暂时性死区的概念:

console.log(a, func); // undefined, [Function: func]
// console.log(b); // 抛出错误: ReferenceError: Cannot access 'b' before initialization
var a = 1;
function func() {}

let b = 2;
b++; // 正常操作
console.log(b); // 输出: 3

在这个例子中:

  • var a 声明的变量 a 被提升到了全局作用域的顶部,所以在首次 console.log(a) 时,输出 undefined,因为此时 a 已经存在但还未被赋值。
  • let b 声明的变量 b 由于 TDZ 的存在,在其声明之前尝试访问会引发错误。
  • func 函数声明也会被提升,所以即使在实际声明之前调用 func,也不会有问题。

执行上下文还可以看下面图文和代码进行理解:

var myname = 'lisi';
function bar() {
  console.log(myname);
}
function foo() {
  var myname = 'zhangsan';
  console.log(myname);
}
bar();
foo();

image.png

(小声bb)这样看来接管海外外包,指日可待,AI出海趁了一波人工智能红利~~