上周花了点时间开发一个微信小程序,接入了ChatGpt接口。实现了简单的上下文对话。
核心代码
/**
* 请求openai接口
* @param int $selType
* @param $params
* @return mixed
* @throws GuzzleException|ApiException
* @throws Exception
*/
protected function sendRequest(int $selType, $params) :mixed
{
// 每个账号最多五个key,所以可以做相关轮训自增次数 防止限流(未尝试过是否有效 仅是个人认为的)。
$this->keys = ApiKey::getKeys();
if(!$this->keys) {
throw new Exception('未配置Api Key');
}
// 代理地址
$proxyUrl = config('chatgpt.proxy_url');
// 本地代理 还是第三方代理(云函数提供的地址)
if (config('chatgpt.proxy_model') === 'vpn') {
$proxy = config('chatgpt.proxy');
$options = [
'verify' => false,
'proxy' => $proxy, //本地或者服务器代理地址
'timeout' => 50
];
} else {
$options = [
'verify' => false,
'timeout' => 50
];
}
$response = (new Client($options))->request('POST', "$proxyUrl/v1/chat/completions", [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => "Bearer $this->keys",
],
'body' => json_encode([
'model' => config('chatgpt.model'),
'messages' => $this->getMessages($selType,$params),
'stop' => '\n',
], JSON_UNESCAPED_UNICODE)
]);
switch ($response->getStatusCode()) {
case 200:
return json_decode($response->getBody()->getContents(), true);
case 443:
Log::channel('chat')->info('服务不可用-443',[
'params' => $response
]);
throw new ApiException('服务不可用');
default:
Log::channel('chat')->info('服务不可用-网络异常',[
'params' => $response
]);
throw new ApiException('网络异常');
}
}
/**
* 组装消息内容
* @param int $selType
* @param $params
* @return array[]
*/
protected function getMessages(int $selType,$params) :array
{
return match ($selType) {
ChatEnum::MESSAGE_TYPE_TEXT => [
[
'role' => 'user',
'content' => $params['message']
]
],
ChatEnum::MESSAGE_TYPE_DIALOGUE => is_array($params['examples_context']) ? $params['examples_context'] : [],
default => [],
};
}
/**
* 获取对话模式以及消息
* @param string $message
* @return array
*/
protected function getContextMessage(string $message): array
{
$msg = [];
$startTime = time() - 60 * 10;
$endTime = time();
$data = ChatMessage::query()
->where('user_id', $this->userId)
->where('add_time', '>', $startTime)
->where('add_time', '<', $endTime)
->limit(6) // 查询最多6条上下文 进行分析。
->orderBy('add_time')
->select()
->get();
if ($data->isEmpty()) {
return [$message, ChatEnum::MESSAGE_TYPE_TEXT];
} else {
$data->each(function ($value) use (&$msg) {
if ($value->is_question == ChatEnum::IS_QUESTION_NO) {
$msg[] = [
'role' => 'user',
'content' => $value->message
];
} else {
$msg[] = [
'role' => 'system',
'content' => $value->message
];
}
});
$msg[] = [
'role' => 'user',
'content' => $message
];
return [$msg, ChatEnum::MESSAGE_TYPE_DIALOGUE];
}
}
关于如何注册chatgpt就不做相关教程了,网上教程太多了。尽量使用google邮箱注册,同时因为国内原因调用接口需要代理,如果部署服务器尽量使用海外服务器或者各大云厂商提供的云函数服务。
最后
因为接口调用并不是免费的,所以每个人都会有30次数限制(小程序)。同时openai对每个账号提供了18美刀接口的免费额度。
感谢PS& 如何自己开发
:point_right: openai接口文档
文章评论