[TOC]
前言
自从换了Macbook Pro后,一直想在电脑用上Chat GPT帮我翻译,虽然有了Bob
这个翻译软件 + Mac自带翻译,感觉还是差点意思,总是有些句子翻译的不是很好,几句话一起翻译直接摆烂,我真的是服了。后面在网上找了一圈,还真有大佬搞出了个Bob里面的第三方接入ChatGPT翻译的插件,看了一遍代码,写的挺简单,但是JS我是真的没怎么搞过,心想就算了吧。搞搞API绑卡也就算了。说到API绑卡这个,我直接一直用Depay绑卡都被拒绝,后面进了Telegram官方群后,一张管理员发的图片帮了我。我也发到这里吧。
后面逛着GitHub时偶然发现有个Python版本的网页ChatGPT API,我心想,不然我把翻译插件的网址调用自己电脑上服务器(类似伪基站,中间人),然后服务器在调用ChatGPT平台不就完事了嘛!
方案
当时我方案一下就想好了,就Flask + Docker。我也担心写这玩意用的时间多,索性试试ChatGPT写小工程可以不可以。
方案如下:
- 测试ChatGPT Python API,封装成函数,除了这个没用GPT,剩下都有使用到ChatGPT,主要是测试能不能用。
- 让ChatGPT帮我把JS前端的链接部分放入Python当中。这一步等下我直接演示步骤。
- 接入第一步封装函数。
- 封装Dockerfile以及Docker-compose,做调整。
方案第二步:JS To Python
以下是ChatGPT交流内容1,代码写出来了,但是Debug有点脑壳疼。
type: reason,
message: `接口响应错误 - ${resp.data.error.message}`,
addition: JSON.stringify(resp),
},
});
} else {
const { result } = resp.data;
if (!result) {
completion({
error: {
type: "api",
message: "接口未返回结果",
},
});
return;
}
completion({
result: {
from: result.from,
to: result.to,
toParagraphs: result.toParagraphs,
},
});
}
})().catch((err) => {
completion({
error: {
type: err._type || “unknown”,
message: err._message || “未知错误”,
addition: err._addition,
},
});
});
}
exports.supportLanguages = supportLanguages;
exports.translate = translate;
1 |
|
这个修改使用request.get_json(force=True)
确保即使没有设置正确的Content-Type
头,也能从请求中获取JSON数据。另外,我们还检查了请求中是否包含必要的query
和option
数据,如果缺少数据,则返回一个包含错误信息的JSON响应。
1 / 1
你重新写一遍吧
1 / 1
当然,这里是完整的修改后的Flask服务器代码,包括上述修改:
python
1 | from flask import Flask, request, jsonify |
现在,服务器应该能正确处理输入数据,并在缺少必要数据时返回包含错误信息的响应。请尝试使用此代码重新运行Flask服务器,看看是否解决了问题。
1 / 1
js前端报错400,`接口响应错误 - 缺少必要的输入数据`,需要修复一下python代码
1 / 1
了解了。这个问题可能是由于JavaScript前端向Flask服务器发送的数据格式与服务器期望的格式不匹配引起的。为了解决这个问题,请尝试将下面的代码片段替换到前端JavaScript代码的translate
函数中:
javascript
1 | // Prepare data for the Flask server request |
1 / 1
不要替换前端代码,只修改python后端代码
1 / 1
了解了。考虑到您希望只修改后端Python代码,我们需要确保后端正确地从前端请求中提取数据。我将添加一些临时打印语句来识别可能的问题。请将以下代码替换为当前的translate()
函数:
python
1 |
|
使用这个修改后的代码运行Flask服务器,然后再次尝试从前端发起请求。现在,每次请求到达时,服务器都会在控制台输出接收到的数据。这将帮助您识别可能的问题。如果您在输出中发现了问题,请在此处提供相关信息,以便我为您提供进一步的帮助。
1 / 1
完整代码打一遍
1 / 1
这里是完整的修改后的Flask服务器代码,包括上述修改:
python
1 | from flask import Flask, request, jsonify |
现在,每次请求到达时,服务器都会在控制台输出接收到的数据。这将帮助您识别可能
1 / 1
继续
1 / 1
的问题。如果您在输出中发现了问题,请在此处提供相关信息,以便我为您提供进一步的帮助。
运行这个修改后的Flask服务器代码,请确保在Python环境中安装了所需的依赖项,比如Flask和requests库。在终端中,您可以使用以下命令安装这些库(如果还没有安装):
sh
1 | pip install flask requests |
然后,在包含Flask服务器代码的文件夹中运行以下命令启动服务器:
sh
1 | python <your_server_filename>.py |
例如,如果您将代码保存在名为app.py
的文件中,则运行python app.py
。
启动服务器后,您可以通过前端发起请求来测试后端。观察控制台输出,看看是否可以找到导致问题的原因。如果有任何疑问或需要进一步的帮助,请随时在此处提问。
1 / 1
python报错数据如下```Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”请随时在此处提问” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:24:38] “POST /v1/chat/completions HTTP/1.1” 400 -```
1 / 1
从您提供的数据来看,服务器没有正确解析前端传来的数据。根据您的前端代码,我们需要将后端代码中的translate()
函数修改如下:
python
1 |
|
这个修改应该可以解决问题。替换现有的translate()
函数,然后再次尝试运行服务器并测试前端请求。如果仍然遇到问题,请提供详细信息,以便我能为您提供更多帮助。
1 / 1
全部代码写一遍,以后都是这样
1 / 1
根据您的要求,以下是修改后的完整代码:
python
1 | from flask import Flask, request, jsonify |
将此代码替换到您的Flask服务器文件中,然后运行服务器并测试前端请求。这个修改后的代码应该可以正常工作。如果您遇到任何问题,请随时在此处提问,以便我能为您提供进一步的帮助。
1 / 1
js前端报错`接口响应错误 - 缺少必要的输入数据`,Python后端数据如下`Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”帮助” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:28:17] “POST /v1/chat/completions HTTP/1.1” 400 -`
1 / 1
抱歉给您带来的困扰。请根据以下修改后的代码更新您的 Flask 服务器。这次我添加了更多的错误检查,以确保接收到的数据格式正确。
python
1 | from flask import Flask, request, jsonify |
现在,这个修改后的代码应该可以正确处理前端请求。如果您仍然遇到问题,请告知我以便提供进一步的帮助。
1 / 1
js前端报错`接口响应错误 - 缺少必要的输入数据`,Python后端数据如下`Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”抱歉” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000}`
1 / 1
我注意到我之前的代码中有一个错误。在发送 POST 请求到 OpenAI API 时,我应该使用 data
而不是 option
作为 JSON 数据。请使用以下修复后的代码替换 Flask 服务器的代码:
python
1 | from flask import Flask, request, jsonify |
现在,这个修改后的代码应该可以正确处理前端请求。如果您仍然遇到问题,请告知我以便提供进一步的帮助。
1 / 1
js前端报错`接口响应错误 - 缺少必要的输入数据`,Python后端数据如下`Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”帮助” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000}`
1 / 1
抱歉之前的修复没有解决问题。请再次检查后端代码,我们需要确保为 OpenAI API 提供正确格式的数据。在这种情况下,我们需要添加一个角色为“user”的消息,其内容是要翻译的文本。请使用以下修复后的代码替换 Flask 服务器的代码:
python
1 | from flask import Flask, request, jsonify |
现在,这个修改后的代码应该可以正确处理前端请求。如果您仍然遇到问题,请告知我以便提供进一步的帮助。
1 / 1
js前端报错`接口响应错误 - 缺少必要的输入数据`,Python后端数据如下`Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”帮助” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:38:47] “POST /v1/chat/completions HTTP/1.1” 400 -`。还有就是输出时,把def translate之前的内容全部去掉,加快速度
1 / 1
抱歉之前的修复没有解决问题。请将下面的代码替换为您的 Flask 服务器代码。这次的修改应该可以正确处理前端请求:
python
1 | from flask import Flask, request, jsonify |
现在,请尝试再次运行这段代码。希望这次可以解决您的问题。如果您仍然遇到问题,请告诉我,我会提供进
1 / 1
js前端报错`接口响应错误 - 缺少必要的输入数据`,Python后端数据如下`Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”现在” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:42:32] “POST /v1/chat/completions HTTP/1.1” 400 -`。还有就是输出时,把def translate之前的内容全部去掉,加快速度
1 / 1
经过再次审查,我发现问题可能在于从前端发送到后端的数据格式上。后端代码似乎无法正确地解析前端发送的数据。为了解决这个问题,我们将在后端代码中添加一些额外的调试信息以找出问题。我还注意到您要求去掉def translate
之前的内容。这段代码为前端提供了一个翻译API,因此我们需要保留它。
请尝试将以下代码替换为您的 Flask 服务器代码:
python
1 | from flask import Flask, request, jsonify |
1 / 1
继续
1 / 1
或者,如果 target_txt 以 ‘」’ 结尾,则将其删除:
css
1 | if target_txt.endswith('"') or target_txt.endswith('」'): |
if name == ‘main‘: app.run(debug=True)
现在,请再次运行此代码。此次,您应该能在控制台看到一些额外的调试输出,其中包括从前端收到的数据以及从中提取的查询数据。如果您仍然遇到问题,请提供此额外的调试输出,以便我们更好地了解问题所在并提供解决方案。
这个是第二次对话,因为我感觉上一个对话它会把自己搞懵逼了。
Model: GPT-4
1 / 1
这是js前端代码,主要用于读取文本进行翻译。 ``` var lang = require(“./lang.js”); function supportLanguages() { return lang.supportLanguages.map(([standardLang]) => standardLang); } function translate(query, completion) { const ChatGPTModels = [ “gpt-3.5-turbo”, “gpt-3.5-turbo-0301”, “gpt-4”, “gpt-4-0314”, “gpt-4-32k”, “gpt-4-32k-0314” ]; const api_keys = $option.api_keys.split(“,”).map((key) => key.trim()); const api_key = api_keys[Math.floor(Math.random() * api_keys.length)]; const isChatGPTModel = ChatGPTModels.indexOf($option.model) > -1; const isAzureServiceProvider = $option.api_url.includes(“openai.azure.com”); const apiUrlPath = $option.api_url_path ? $option.api_url_path : (isChatGPTModel ? “/v1/chat/completions” : “/v1/completions”); let systemPrompt = “You are a translation engine that can only translate text and cannot interpret it.”; let userPrompt = `translate from ${lang.langMap.get(query.detectFrom) || query.detectFrom } to ${lang.langMap.get(query.detectTo) || query.detectTo}`; if (query.detectTo === “wyw” || query.detectTo === “yue”) { userPrompt = `翻译成${lang.langMap.get(query.detectTo) || query.detectTo}`; } if ( query.detectFrom === “wyw” || query.detectFrom === “zh-Hans” || query.detectFrom === “zh-Hant” ) { if (query.detectTo === “zh-Hant”) { userPrompt = “翻译成繁体白话文”; } else if (query.detectTo === “zh-Hans”) { userPrompt = “翻译成简体白话文”; } else if (query.detectTo === “yue”) { userPrompt = “翻译成粤语白话文”; } } if (query.detectFrom === query.detectTo) { systemPrompt = “You are a text embellisher, you can only embellish the text, don’t interpret it.”; if (query.detectTo === “zh-Hant” || query.detectTo === “zh-Hans”) { userPrompt = “润色此句”; } else { userPrompt = “polish this sentence”; } } const header = { “Content-Type”: “application/json”, }; const body = { model: $option.model, temperature: 0, max_tokens: 1000, top_p: 1, frequency_penalty: 1, presence_penalty: 1, }; userPrompt = `${userPrompt}:\n\n”${query.text}” =>`; if (isAzureServiceProvider) { header[“api-key”] = `${api_key}` } else { header[“Authorization”] = `Bearer ${api_key}` } if (isChatGPTModel) { body[“messages”] = [ { role: “system”, content: systemPrompt, }, { role: “user”, content: userPrompt, }, { role: “user”, content: `“${query.text}”` }, ]; } else { body[“prompt”] = userPrompt; } (async () => { const resp = await $http.request({ method: “POST”, url: $option.api_url + apiUrlPath, header, body, }); if (resp.error) { const { statusCode } = resp.response; let reason; if (statusCode >= 400 && statusCode < 500) { reason = “param”; } else { reason = “api”; } completion({ error: { type: reason, message: `接口响应错误 - ${resp.data.error.message}`, addition: JSON.stringify(resp), }, }); } else { const { choices } = resp.data; if (!choices || choices.length === 0) { completion({ error: { type: “api”, message: “接口未返回结果”, }, }); return; } if (isChatGPTModel) { targetTxt = choices[0].message.content.trim(); } else { targetTxt = choices[0].text.trim(); } if (targetTxt.startsWith(‘“‘) || targetTxt.startsWith(“「”)) { targetTxt = targetTxt.slice(1); } if (targetTxt.endsWith(‘“‘) || targetTxt.endsWith(“」”)) { targetTxt = targetTxt.slice(0, -1); } completion({ result: { from: query.detectFrom, to: query.detectTo, toParagraphs: targetTxt.split(“\n”), }, }); } })().catch((err) => { completion({ error: { type: err._type || “unknown”, message: err._message || “未知错误”, addition: err._addition, }, }); }); } exports.supportLanguages = supportLanguages; exports.translate = translate; ``` 这个是我写的Python后端代码。 ``` import chatgpt from flask import Flask, request, jsonify import requests import json app = Flask(__name__) @app.route(‘/v1/chat/completions’, methods=[‘POST’]) def translate(): data = request.get_json(force=True) print(“Received data:”, data) # Temporary print statement to debug the received data if not data: return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 option = data # Check if the required keys are present in the data required_keys = [‘model’, ‘api_url’, ‘api_url_path’, ‘api_keys’, ‘messages’] if not all(key in option for key in required_keys): return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 # Extract the query data from the messages user_messages = [message for message in option[‘messages’] if message[‘role’] == ‘user’] if not user_messages or len(user_messages) < 2: return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 query = { ‘text’: user_messages[-1][‘content’].strip(‘“‘), ‘detectFrom’: user_messages[-2][‘content’].split()[2], ‘detectTo’: user_messages[-2][‘content’].split()[4] } print(“Query data:”, query) # Temporary print statement to debug the extracted query data # Add the text to be translated as an additional user message data[‘messages’].append({‘role’: ‘user’, ‘content’: query[‘text’]}) api_keys = option[‘api_keys’].split(‘,’) api_key = api_keys[0].strip() headers = { ‘Content-Type’: ‘application/json’, ‘Authorization’: f’Bearer {api_key}’ } response = requests.post( option[‘api_url’] + option[‘api_url_path’], headers=headers, json=data ) if response.status_code == 400: return jsonify({“error”: {“type”: “api”, “message”: “接口响应错误 - 缺少必要的输入数据”}}), 400 if response.status_code >= 400: return jsonify({“error”: {“type”: “api”, “message”: f”接口响应错误 - {response.json()[‘error’][‘message’]}”}}), response.status_code choices = response.json().get(‘choices’) if not choices or len(choices) == 0: return jsonify({“error”: {“type”: “api”, “message”: “接口未返回结果”}}), 400 target_txt = choices[0].get(‘text’, ‘’).strip() if target_txt.startswith(‘“‘) or target_txt.startswith(‘「’): target_txt = target_txt[1:] if target_txt.endswith(‘“‘) or target_txt.endswith(‘」’): target_txt = target_txt[:-1] return jsonify({“result”: { “from”: query[‘detectFrom’], “to”: query[‘detectTo’], “toParagraphs”: target_txt.split(‘\n’) }}) if __name__ == ‘__main__‘: app.run(debug=True) ``` 但是,现在前端报错,原因为 ```接口响应错误 - 缺少必要的输入数据```, Python后端打印的数据以及错误如下 ``` Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”现在” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:46:41] “POST /v1/chat/completions HTTP/1.1” 400 - ```
1 / 1
从你提供的Python后端代码和错误日志来看,问题可能出在传递给GPT的数据上。在你的Python后端代码中,你需要确保从前端接收到的数据包含必需的字段。在这种情况下,model
, api_url
, api_url_path
, 和 api_keys
字段似乎没有正确传递给后端。你需要确保这些字段在请求中包含。
首先,你需要修改你的JavaScript代码中的translate
函数,将这些选项添加到传递给Python后端的请求中。你可以通过将它们添加到body
对象来实现这一点:
javascript
1 | body["api_url"] = $option.api_url; |
然后,在Python后端,你需要从请求数据中提取这些选项。你可以使用以下代码替换你现有的option = data
行:
python
1 | option = { |
这样,你应该能够从前端将所有必需的选项传递给Python后端,并正确处理请求。
另外,请注意,你的Python后端代码中的translate
函数与JavaScript代码中的translate
函数不匹配。这可能会导致问题。你需要确保你的Python后端代码接收到的数据与JavaScript代码中发送的数据匹配。
1 / 1
只修改后端代码,不修改前端代码,把python代码全部写出来
1 / 1
好的,为了不修改前端代码,我们可以从原始请求数据中提取缺失的选项。下面是修改后的Python后端代码:
python
1 | import chatgpt |
1 / 1
继续
1 / 1
css
1
2
3
4
5
6
7
target_txt = target_txt[:-1]
return jsonify({"result": {
"from": query['detectFrom'],
"to": query['detectTo'],
"toParagraphs": target_txt.split('\n')
}})
if name == ‘main‘: app.run(debug=True)
markdown
1 | 这段代码主要修改了以下几点: |
我感觉到上一个对话还是有问题,就切换到下一个,也是最后一个,它把自己的BUG修复了。
Model: GPT-4
1 / 1
这是js前端代码,主要用于读取文本进行翻译。 ``` var lang = require(“./lang.js”); function supportLanguages() { return lang.supportLanguages.map(([standardLang]) => standardLang); } function translate(query, completion) { const ChatGPTModels = [ “gpt-3.5-turbo”, “gpt-3.5-turbo-0301”, “gpt-4”, “gpt-4-0314”, “gpt-4-32k”, “gpt-4-32k-0314” ]; const api_keys = $option.api_keys.split(“,”).map((key) => key.trim()); const api_key = api_keys[Math.floor(Math.random() * api_keys.length)]; const isChatGPTModel = ChatGPTModels.indexOf($option.model) > -1; const isAzureServiceProvider = $option.api_url.includes(“openai.azure.com”); const apiUrlPath = $option.api_url_path ? $option.api_url_path : (isChatGPTModel ? “/v1/chat/completions” : “/v1/completions”); let systemPrompt = “You are a translation engine that can only translate text and cannot interpret it.”; let userPrompt = `translate from ${lang.langMap.get(query.detectFrom) || query.detectFrom } to ${lang.langMap.get(query.detectTo) || query.detectTo}`; if (query.detectTo === “wyw” || query.detectTo === “yue”) { userPrompt = `翻译成${lang.langMap.get(query.detectTo) || query.detectTo}`; } if ( query.detectFrom === “wyw” || query.detectFrom === “zh-Hans” || query.detectFrom === “zh-Hant” ) { if (query.detectTo === “zh-Hant”) { userPrompt = “翻译成繁体白话文”; } else if (query.detectTo === “zh-Hans”) { userPrompt = “翻译成简体白话文”; } else if (query.detectTo === “yue”) { userPrompt = “翻译成粤语白话文”; } } if (query.detectFrom === query.detectTo) { systemPrompt = “You are a text embellisher, you can only embellish the text, don’t interpret it.”; if (query.detectTo === “zh-Hant” || query.detectTo === “zh-Hans”) { userPrompt = “润色此句”; } else { userPrompt = “polish this sentence”; } } const header = { “Content-Type”: “application/json”, }; const body = { model: $option.model, temperature: 0, max_tokens: 1000, top_p: 1, frequency_penalty: 1, presence_penalty: 1, }; userPrompt = `${userPrompt}:\n\n”${query.text}” =>`; if (isAzureServiceProvider) { header[“api-key”] = `${api_key}` } else { header[“Authorization”] = `Bearer ${api_key}` } if (isChatGPTModel) { body[“messages”] = [ { role: “system”, content: systemPrompt, }, { role: “user”, content: userPrompt, }, { role: “user”, content: `“${query.text}”` }, ]; } else { body[“prompt”] = userPrompt; } (async () => { const resp = await $http.request({ method: “POST”, url: $option.api_url + apiUrlPath, header, body, }); if (resp.error) { const { statusCode } = resp.response; let reason; if (statusCode >= 400 && statusCode < 500) { reason = “param”; } else { reason = “api”; } completion({ error: { type: reason, message: `接口响应错误 - ${resp.data.error.message}`, addition: JSON.stringify(resp), }, }); } else { const { choices } = resp.data; if (!choices || choices.length === 0) { completion({ error: { type: “api”, message: “接口未返回结果”, }, }); return; } if (isChatGPTModel) { targetTxt = choices[0].message.content.trim(); } else { targetTxt = choices[0].text.trim(); } if (targetTxt.startsWith(‘“‘) || targetTxt.startsWith(“「”)) { targetTxt = targetTxt.slice(1); } if (targetTxt.endsWith(‘“‘) || targetTxt.endsWith(“」”)) { targetTxt = targetTxt.slice(0, -1); } completion({ result: { from: query.detectFrom, to: query.detectTo, toParagraphs: targetTxt.split(“\n”), }, }); } })().catch((err) => { completion({ error: { type: err._type || “unknown”, message: err._message || “未知错误”, addition: err._addition, }, }); }); } exports.supportLanguages = supportLanguages; exports.translate = translate; ``` 这个是我写的Python后端代码。 ``` import chatgpt from flask import Flask, request, jsonify import requests import json app = Flask(__name__) @app.route(‘/v1/chat/completions’, methods=[‘POST’]) def translate(): data = request.get_json(force=True) print(“Received data:”, data) # Temporary print statement to debug the received data if not data: return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 option = data # Check if the required keys are present in the data required_keys = [‘model’, ‘messages’] if not all(key in option for key in required_keys): return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 # Extract the query data from the messages user_messages = [message for message in option[‘messages’] if message[‘role’] == ‘user’] if not user_messages or len(user_messages) < 2: return jsonify({“error”: {“type”: “param”, “message”: “缺少必要的输入数据”}}), 400 query = { ‘text’: user_messages[-1][‘content’].strip(‘“‘), ‘detectFrom’: user_messages[-2][‘content’].split()[2], ‘detectTo’: user_messages[-2][‘content’].split()[4] } print(“Query data:”, query) # Temporary print statement to debug the extracted query data # Add the text to be translated as an additional user message data[‘messages’].append({‘role’: ‘user’, ‘content’: query[‘text’]}) # Extract the API key from the request headers authorization = request.headers.get(‘Authorization’) if not authorization: return jsonify({“error”: {“type”: “param”, “message”: “缺少API密钥”}}), 400 api_key = authorization.replace(‘Bearer ‘, ‘’) # Set the default API URL and path if they are not present in the data api_url = option.get(‘api_url’, ‘https://api.openai.com') api_url_path = option.get(‘api_url_path’, ‘/v1/engines/davinci-codex/completions’) headers = { ‘Content-Type’: ‘application/json’, ‘Authorization’: f’Bearer {api_key}’ } response = requests.post( api_url + api_url_path, headers=headers, json=data ) if response.status_code == 400: return jsonify({“error”: {“type”: “api”, “message”: “接口响应错误 - 缺少必要的输入数据”}}), 400 if response.status_code >= 400: return jsonify({“error”: {“type”: “api”, “message”: f”接口响应错误 - {response.json()[‘error’][‘message’]}”}}), response.status_code choices = response.json().get(‘choices’) if not choices or len(choices) == 0: return jsonify({“error”: {“type”: “api”, “message”: “接口未返回结果”}}), 400 target_txt = choices[0].get(‘text’, ‘’).strip() if target_txt.startswith(‘“‘) or target_txt.startswith(‘「’): target_txt = target_txt[1:] if target_txt.endswith(‘“‘) or target_txt.endswith(‘」’): target_txt = target_txt[:-1] return jsonify({“result”: { “from”: query[‘detectFrom’], “to”: query[‘detectTo’], “toParagraphs”: target_txt.split(‘\n’) }}) if __name__ == ‘__main__‘: app.run(debug=True) ``` 但是,现在前端报错,原因为 ```接口响应错误 - 缺少必要的输入数据```, Python后端打印的数据以及错误如下 ``` Received data: {‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from zh-CN to en:\n\n”提供” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000} 127.0.0.1 - - [01/Apr/2023 00:57:18] “POST /v1/chat/completions HTTP/1.1” 400 - ``` 注意,只能修改python代码!!!
1 / 1
从报错信息来看,问题出在发送到后端的数据缺少必要的输入数据。具体来说,后端代码期望在 messages 中有两个用户消息:一个表示翻译方向,另一个是要翻译的文本。然而,从你提供的错误日志中,我们可以看到,messages 列表中只有一个用户消息,即表示翻译方向的消息。
要解决这个问题,你需要在 Python 后端代码中稍作修改以适应前端发来的数据。具体来说,你需要修改 translate
函数中提取 query 数据的部分,使其能够正确处理只有一个用户消息的情况。
下面是修改过的代码:
python
1 | # Extract the query data from the messages |
这个修改后的代码会检查是否有至少一个用户消息,然后从这个消息中提取翻译方向和要翻译的文本。这样一来,后端应该能够正确处理从前端收到的数据了。
第三步:结合
对话只有一个。
Model: GPT-4
1 / 1
使用python写出以下需求的代码:提取input的content内容,合并后输入到chat_with_gpt函数中,对输出的string进行封装到output的content中,其中 input的格式为`{‘messages’: [{‘content’: ‘You are a translation engine that can only translate text and cannot interpret it.’, ‘role’: ‘system’}, {‘content’: ‘translate from en to zh-CN:\n\n”status code” =>’, ‘role’: ‘user’}], ‘frequency_penalty’: 1, ‘model’: ‘gpt-3.5-turbo’, ‘temperature’: 0, ‘presence_penalty’: 1, ‘top_p’: 1, ‘max_tokens’: 1000}`; output的格式为`{‘id’: ‘chatcmpl-70D64JgXAOgjbkLBbOWahCWVszGd5’, ‘object’: ‘chat.completion’, ‘created’: 1680284700, ‘model’: ‘gpt-3.5-turbo-0301’, ‘usage’: {‘prompt_tokens’: 46, ‘completion_tokens’: 11, ‘total_tokens’: 57}, ‘choices’: [{‘message’: {‘role’: ‘assistant’, ‘content’: ‘“调试器已激活!”‘}, ‘finish_reason’: ‘stop’, ‘index’: 0}]}`
1 / 1
根据您的需求,下面是使用Python编写的代码:
python
1 | import json |
请注意,您需要在chat_with_gpt
函数中添加与GPT交互的逻辑。根据您的输入和输出格式,我已为您提供了从输入中提取内容、合并内容、调用chat_with_gpt
函数以及封装输出的完整流程。
第四步,Docker部分
Model: GPT-4
1 / 1
写一个Dockerfile构建Flask服务器,里面需要import的模块如下:`from revChatGPT.V1 import Chatbot import copy from flask import Flask, request, jsonify import requests import json`
1 / 1
以下是一个简单的Dockerfile,用于构建一个包含所需模块的Flask服务器:
Dockerfile
1 | # 使用官方的Python基础镜像作为基础 |
同时,请在您的项目目录中创建一个名为requirements.txt
的文件,其中包含您需要安装的Python包。根据您提供的代码,您需要以下包:
Flask requests
注意,我没有在requirements.txt
文件中包含revChatGPT.V1
,因为这似乎是您自己的模块。请确保将该模块与app.py
放在同一目录下,并在Docker容器中适当地导入它。
最后,在包含Dockerfile的目录中运行以下命令以构建和运行Docker容器:
arduino
1 | docker build -t your-image-name . |
这将使用Dockerfile构建一个名为your-image-name
的镜像,并将容器的80端口映射到宿主机的4000端口。之后,您可以通过访问http://localhost:4000
来访问您的Flask服务器。
1 / 1
有两个问题:1、没有“requirements.txt”。2、环境定义变量去掉,后面通过容器调用在进行定义,重新修改一下Dockerfile
1 / 1
根据您的要求,我已去掉了requirements.txt
文件并删除了环境变量定义。以下是修改后的Dockerfile:
Dockerfile
1 | # 使用官方的Python基础镜像作为基础 |
现在,Dockerfile会直接安装Flask和requests包,而不再依赖于requirements.txt
文件。同时,我已移除了环境变量定义,您可以在运行容器时通过命令行参数来设置环境变量。
在包含Dockerfile的目录中运行以下命令以构建和运行Docker容器:
arduino
1 | docker build -t your-image-name . |
这将使用Dockerfile构建一个名为your-image-name
的镜像,并将容器的80端口映射到宿主机的4000端口。在这个例子中,我们使用-e
参数设置了环境变量NAME
。您可以通过访问http://localhost:4000
来访问您的Flask服务器。
1 / 1
通过上面,构建一个Docker Compose文件,环境变量写到.env文件中
1 / 1
首先,创建一个名为.env
的文件来存储您的环境变量。在本例中,我们将设置NAME
环境变量:
makefile
1 | NAME=World |
接下来,创建一个名为docker-compose.yml
的文件,并使用以下内容定义您的服务:
yaml
1 | version: '3.8' |
这个docker-compose.yml
文件定义了一个名为flask_app
的服务,它将使用您之前创建的Dockerfile进行构建。将容器的80端口映射到宿主机的4000端口,并通过env_file
指令将.env
文件中定义的环境变量加载到容器中。
要使用Docker Compose构建并运行服务,请在包含docker-compose.yml
文件的目录中运行以下命令:
css
1 | docker-compose up --build |
Docker Compose将根据docker-compose.yml
文件构建镜像并启动服务。您可以通过访问http://localhost:4000
来访问您的Flask服务器。要停止服务并删除容器,请使用以下命令:
docker-compose down
1 / 1
DockerCompose文件当中端口从4000改成5000
1 / 1
要将端口从4000更改为5000,只需在docker-compose.yml
文件中修改ports
部分。请参考以下修改后的docker-compose.yml
:
yaml
1 | version: '3.8' |
现在,容器的80端口将映射到宿主机的5000端口。要使用Docker Compose构建并运行服务,请确保您位于包含docker-compose.yml
文件的目录中,然后运行以下命令:
css
1 | docker-compose up --build |
Docker Compose将根据docker-compose.yml
文件构建镜像并启动服务。您可以通过访问http://localhost:5000
来访问您的Flask服务器。要停止服务并删除容器,请使用以下命令:
docker-compose down
最后总结
- 从开始搞11点半到现在博客写完02:55,说实话,我没想多这玩意这么快,主要是我都不太懂JS的代码情况下,帮我写完了。。。
- GitHub地址