基於 ChatGpt Api 開發的微信小程式

Latent發表於2023-03-11

上週花了點時間開發一個微信小程式,接入了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介面文件

分享 小程式二維碼

本作品採用《CC 協議》,轉載必須註明作者和本文連結
不成大牛,不改個簽

相關文章