最终效果图如下.
基于webman,首先要安装好webman
然后安装 OpenAI 的官方php库
composer require openai-php/client
composer require guzzlehttp/guzzle
api在国内已被墙,但官方库(< v0.4.0)不支持使用代理,所以需要手动修改官方库,添加代理支持
打开 vendor\openai-php\client\src\OpenAI.php
将在 第29行 附近的代码 $client = new GuzzleClient();
改为
$client = new GuzzleClient([
"proxy"=>"你的代理 http://ip:端口"
]);
比如我的代理地址是 127.0.0.1:7890
则修改后是:
$client = new GuzzleClient([
"proxy"=>"http://127.0.0.1:7890"
]);
新版 >= 0.4 以后 openai库有变化,无需再改动官方库了
将该文件放在某个控制器目录下,然后访问 http://域名/chatgpt 如果有模块,则访问 http://域名/模块/chatgpt
php start.php restart 重启你的应用
<?php
namespace app\controller;
use support\Request;
use OpenAI\Client;
// openai 的 key
// 全局代理后,在这里注册登录 https://platform.openai.com/signup
define('OPENAI_KEY', '填写你的key');
class ChatgptController
{
// 初始化获取全部已回答
public function all(Request $request){
$messages = $request->session()->get('messages', []);
return json([
"code"=>0,
"msg"=>"ok",
"data"=>$messages
]);
}
// 单次查询
public function query(Request $request)
{
$messages = $request->session()->get('messages', []);
$messages[] = ['role' => 'user', 'content' => $request->input('message')];
$current=[];
try {
// 旧版 <0.4 OpenAI 库 使用该代码
$response = OpenAI::client(OPENAI_KEY)->chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => $messages
]);
// 新版 >=0.4 OpenAI 库使用该代码
/*
$response=OpenAI::factory()
->withApiKey(OPENAI_KEY)
->withHttpClient(new \GuzzleHttp\Client([
"proxy"=>"你的代理 http://ip:端口"
]))->make()->chat()->create([
'model' => 'gpt-3.5-turbo',
'messages' => $messages
])
*/
$current = ['role' => 'assistant', 'content' => nl2br($response->choices[0]->message->content)];
} catch (\Exception $e) {
$current = ['role' => 'assistant', 'content' => $e->getMessage()];
}
$messages[]=$current;
$request->session()->put('messages', $messages);
return json([
"code"=>0,
"msg"=>"ok",
"data"=>$current['content']
]);
}
// 清除
public function clear(Request $request)
{
return redirect("/");
}
public function index(Request $request)
{
$html=<<<'EOF'
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ChatGPT</title>
<link href="https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/tailwindcss/2.2.19/tailwind.min.css" type="text/css" rel="stylesheet" />
</head>
<body class="antialiased mx-auto" style="max-width:1000px">
<div class="flex flex-col space-y-4 py-4 overflow-auto" id="body"></div>
<div class="text-center text-red-400" id="loading"></div>
<div class="py-4 flex flex-col space-x-1 justify-center items-center">
<textarea required onkeypress="submit(this)" placeholder="输入后 ctrl+回车 或点击右侧 发送 按钮" name="message" class="border p-2 flex-1 w-full" id="message"></textarea>
<div class="flex justify-center items-center mt-2">
<input type="button" onclick="submit(this,'click')" class="cursor-pointer bg-green-500 text-white p-2 mx-1" value="发送请求" />
<a class="bg-gray-200 text-white p-2 mx-1" href="./clear" title="出现错误时,可尝试清除提问记录">清除记录</a>
</div>
</div>
<script>
// 名称
window.chatgptConfig = {
"assistant": "ChatGPT",
"user": "我"
};
window.onload = function() {
fetch("./all", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
body: ''
})
.then(response => response.json())
.then(json => {
if (json.data) {
json.data.forEach(it => {
append(it['content'], window.chatgptConfig[it.role]);
});
}
})
.catch(error => {
console.error(error);
});
};
function submit(el, type) {
if (type === 'click' || (event.ctrlKey && event.keyCode === 10)) {
if (el.getAttribute('disabled')) {
alert("正在等待上次提问的回复,请稍等");
return;
}
var msg = document.getElementById('message').value.trim();
if (!msg) {
alert("必须输入问题");
return;
}
el.setAttribute('disabled', 'disabled');
append(msg, window.chatgptConfig['user']);
document.getElementById('loading').innerHTML = "努力思考中,稍等哦...";
document.documentElement.scrollTop+=50;
fetch("./query", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
},
body: JSON.stringify({ message: msg})
})
.then(response => response.json())
.then(json => {
append(json.data, window.chatgptConfig["assistant"]);
document.getElementById('loading').innerHTML = '';
document.getElementById('message').value = '';
el.removeAttribute('disabled', 'disabled');
})
.catch(error => {
console.error(error);
el.removeAttribute('disabled', 'disabled');
});
}
}
function append(msg, name) {
var html = `
<div class="ml-4">
<div class="text-lg">
<a href="#" class="font-medium ${name==window.chatgptConfig['assistant']?'text-green-400':'text-gray-900'}">${name}:</a>
</div>
<div class="mt-1">
<p class="text-gray-800">
${msg}
</p>
</div>
</div>
`;
const newDiv = document.createElement("div");
newDiv.className=`overflow-auto flex p-4 ${name==window.chatgptConfig['assistant']?'bg-gray-100 border flex-reverse':""}`;
newDiv.innerHTML = html;
const bodyDiv = document.getElementById("body");
bodyDiv.appendChild(newDiv);
}
</script>
</body>
</html>
EOF;
return $html;
}
}
https 域名的怎么代理呢
只要你的代理支持https就行,一样填写 http://ip:port
这里没有$client = new GuzzleClient();这行代码怎么整
新版的 OpenAI 库有变化,不要手动去修改官方库了
直接将请求时的代码
改为
{
"code": 500,
"msg": "OpenAI\Factory::withHttpClient(): Argument #1 ($client) must be of type Psr\Http\Client\ClientInterface, GuzzleHttp\Client given, called in D:\Desktop\chatGptApi\app\controller\ChatgptController.php on line 30",
"traces": "TypeError: OpenAI\Factory::withHttpClient(): Argument #1 ($client) must be of type Psr\Http\Client\ClientInterface, GuzzleHttp\Client given, called in D:\Desktop\chatGptApi\app\controller\ChatgptController.php on line 30 and defined in D:\Desktop\chatGptApi\vendor\openai-php\client\src\Factory.php:73\nStack trace:\n#0 D:\Desktop\chatGptApi\app\controller\ChatgptController.php(30): OpenAI\Factory->withHttpClient(Object(GuzzleHttp\Client))\n#1 D:\Desktop\chatGptApi\vendor\workerman\webman-framework\src\App.php(319): app\controller\ChatgptController->query(Object(support\Request))\n#2 D:\Desktop\chatGptApi\vendor\workerman\webman-framework\src\App.php(141): Webman\App::Webman\{closure}(Object(support\Request))\n#3 D:\Desktop\chatGptApi\vendor\workerman\workerman\Connection\TcpConnection.php(646): Webman\App->onMessage(Object(Workerman\Connection\TcpConnection), Object(support\Request))\n#4 D:\Desktop\chatGptApi\vendor\workerman\workerman\Events\Select.php(311): Workerman\Connection\TcpConnection->baseRead(Resource id #130)\n#5 D:\Desktop\chatGptApi\vendor\workerman\workerman\Worker.php(1479): Workerman\Events\Select->loop()\n#6 D:\Desktop\chatGptApi\vendor\workerman\workerman\Worker.php(1399): Workerman\Worker::forkWorkersForWindows()\n#7 D:\Desktop\chatGptApi\vendor\workerman\workerman\Worker.php(560): Workerman\Worker::forkWorkers()\n#8 D:\Desktop\chatGptApi\vendor\workerman\webman-framework\src\support\App.php(131): Workerman\Worker::runAll()\n#9 D:\Desktop\chatGptApi\start.php(4): support\App::run()\n#10 {main}"
}
替换完之后报这个错了
<?php
use OpenAI\Client;
实测无问题,有可能你的 guzzlehttp库太久了吧。更新下
composer require guzzlehttp/guzzle
升级后可以了,感谢分享
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) for https://api.openai.com/v1/chat/completions
这个怎么调
请问这个代理和端口怎么配置?