添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
logo
/
使用Api2d将chatGPT接入 siri
Get a copy
  • README.md
    arrow

    Siri ChatGPT 使用教程

    将 Siri 接入 ChatGPT,直接语音唤醒,并且支持连续对话。

    第一步:拷贝项目

    点击右上角「Get a copy」,这会打开 AirCode ,并基于此模板创建一个你自己的项目。如果没登录的话,可能会先跳转到登录页面,推荐使用 GitHub 登录,会快一些。

    在弹出的创建对话框中,输入你的项目名称,并点击「Create」完成创建。

    至此,你完成了所有配置过程,直接在手机中通过「嘿 Siri,打开机器人」就可以唤醒 ChatGPT,然后问问题了。

    另外,你也可以在快捷指令的编辑页面中,点击下方的「分享」按钮,在弹出的菜单中选择「添加到主屏幕」,这样就可以在桌面通过点击打开对话框。

    Enjoy your life with ChatGPT!

  • 可以加入我们的 飞书用户群
  • 我们的 GitHub 仓库 ,可以提 issue 或者直接贡献代码
  • 欢迎加入我们的 Discord 讨论区
  • 也可以直接发邮件给我们 [email protected]
  • 用 JavaScript 开发钉钉 ChatGPT 机器人
  • 用 JavaScript 开发企业微信 ChatGPT 机器人
  • 用 JavaScript 开发飞书 ChatGPT 机器人
  • chat.js
    arrow
    1// @see https://docs.aircode.io/guide/functions/
    2const aircode = require('aircode');
    3const { v4: uuidv4 } = require('uuid');
    4const Api2d = require('./api2d.js');
    6const { db } = aircode;
    7const ChatTable = db.table('chat');
    9// Setup OpenAI configurations
    10const OPENAI_KEY = process.env.OPENAI_KEY || '';
    11const OPENAI_MODEL = process.env.MODEL || 'gpt-3.5-turbo';
    12const MAX_MESSAGES_PER_CHAT = process.env.MESSAGE_COUNT || 5;
    14const API_BASE_URL = 'https://openai.api2d.net';
    16const systemContent = 'You are a helpful assistant.';
    18module.exports = async function (params, context) {
    19    console.log('Received params:', params);
    20    const { question, cid } = params;
    22    // Create a chat ID if not provided
    23    const chatId = cid ? cid : uuidv4();
    25    // Save user's question to the ChatTable
    26    await ChatTable.save({ chatId, role: 'user', content: question });
    28    // Retrieve chat history
    29    const chats = await ChatTable.where({ chatId }).sort({ createdAt: -1 }).limit(MAX_MESSAGES_PER_CHAT).find();
    31    // Construct message array for GPT-3.5 Turbo
    32    const messages = [{ role: 'system', content: 'You are a helpful assistant.' }, ...chats.reverse().map((one) => ({ role: one.role, content: one.content }))];
    34    const api = new Api2d(OPENAI_KEY, API_BASE_URL);
    36    try {
    37        // Request completion from GPT-3.5 Turbo
    38        const completion = await api.completion({
    39            model: OPENAI_MODEL,
    40            messages,
    41            temperature: 1,
    42            n: 1,
    43            stream: false
    44        });
    46        // console.log('completion', completion);
    48        const responseMessage = completion.choices[0].message;
    50        // Save generated response to ChatTable
    51        await ChatTable.save({ chatId, ...responseMessage });
    53        // Return response message and chat ID
    54        return { reply: responseMessage.content, cid: chatId };
    55    } catch (error) {
    56        // Set the response status to 500 (Internal Server Error)
    57        context.status(500);
    58        // Log the error
    59        console.log('error', error.response || error);
    61        // Initialize an error message variable
    62        let errorMessage;
    64        // If there is a response object in the error,
    65        // it means the request was made and the server responded with an error status
    66        if (error.response) {
    67            const { status, statusText, data } = error.response;
    69            if (status === 401) {
    70                // If the status code is 401, set a specific error message related to the OpenAI API key
    71                errorMessage = 'Unauthorized: Invalid OpenAI API key, please check your API key in the AirCode Environments tab.';
    72            } else if (data.error && data.error.message) {
    73                // If there is an error message in the data, use it as the error message
    74                errorMessage = data.error.message;
    75            } else {
    76                // Otherwise, use the status code and status text as the error message
    77                errorMessage = `Request failed with status code ${status}: ${statusText}`;
    79        } else if (error.request) {
    80            // If there is a request object in the error,
    81            // it means the request was made but no response was received
    82            errorMessage = 'No response received from the server';
    83        } else if (error.code === 'ENOTFOUND' || error.code === 'ECONNREFUSED') {
    84            // If there is a network error, such as DNS resolution or connection refused
    85            errorMessage = `Network error: ${error.message}`;
    86        } else {
    87            // If none of the above conditions are met,
    88            // it means there was an error setting up the request
    89            errorMessage = `Request setup error: ${error.message}`;
    92        // Return an object containing the error message
    93        return { error: errorMessage };
    95};
    96
  • api2d.js
    arrow
    1const fetchEventSource = require('@microsoft/fetch-event-source');
    2const fetch = require('node-fetch');
    3module.exports = class Api2d {
    4    // 设置key和apiBaseUrl
    5    constructor(key = null, apiBaseUrl = null, timeout = 60000) {
    6        this.key = key;
    7        this.apiBaseUrl = apiBaseUrl || (key && key.startsWith('fk') ? 'https://stream.api2d.net' : 'https://api.openai.com');
    8        this.timeout = timeout;
    9        this.controller = new AbortController();
    12    // set key
    13    setKey(key) {
    14        this.key = key;
    17    // set apiBaseUrl
    18    setApiBaseUrl(apiBaseUrl) {
    19        this.apiBaseUrl = apiBaseUrl;
    22    setTimeout(timeout) {
    23        this.timeout = parseInt(timeout) || 60 * 1000;
    26    abort() {
    27        this.controller.abort();
    30    // Completion
    31    async completion(options) {
    32        // 拼接目标URL
    33        const url = this.apiBaseUrl + '/v1/chat/completions';
    34        // 拼接headers
    35        const headers = {
    36            'Content-Type': 'application/json',
    37            Authorization: 'Bearer ' + this.key
    38        };
    40        const { onMessage, onEnd, model, ...restOptions } = options;
    42        // 如果是流式返回,且有回调函数
    43        if (restOptions.stream && onMessage) {
    44            // 返回一个 Promise
    45            return new Promise(async (resolve, reject) => {
    46                try {
    47                    let chars = '';
    48                    console.log('in stream');
    49                    // 使用 fetchEventSource 发送请求
    50                    const timeout_handle = setTimeout(() => {
    51                        this.controller.abort();
    52                        // throw new Error( "Timeout "+ this.timeout );
    53                        reject(new Error(`[408]:Timeout by ${this.timeout} ms`));
    54                    }, this.timeout);
    55                    const response = await fetchEventSource(url, {
    56                        signal: this.controller.signal,
    57                        method: 'POST',
    58                        headers: { ...headers, Accept: 'text/event-stream' },
    59                        body: JSON.stringify({ ...restOptions, model: model || 'gpt-3.5-turbo' }),
    60                        async onopen(response) {
    61                            if (response.status != 200) {
    62                                throw new Error(`[${response.status}]:${response.statusText}`);
    64                        },
    65                        onmessage: (e) => {
    66                            if (timeout_handle) {
    67                                clearTimeout(timeout_handle);
    69                            if (e.data == '[DONE]') {
    70                                // console.log( 'DONE' );
    71                                if (onEnd) onEnd(chars);
    72                                resolve(chars);
    73                            } else {
    74                                // console.log( e.data );
    75                                const event = JSON.parse(e.data);
    76                                if (event.choices[0].delta.content) chars += event.choices[0].delta.content;
    77                                if (onMessage) onMessage(chars);
    79                        },
    80                        onerror: (error) => {
    81                            console.log(error);
    82                            throw new Error(String(error)?.match(/\[(\d+)\]/)?.[1] ? error : `[500]:${error}`);
    84                    });
    86                    // const ret = await response.json();
    87                } catch (error) {
    88                    console.log(error);
    89                    reject(error);
    91            });
    92        } else {
    93            // 使用 fetch 发送请求
    94            const response = await fetch(url, {
    95                signal: this.controller.signal,
    96                method: 'POST',
    97                headers: headers,
    98                body: JSON.stringify({ ...restOptions, model: model || 'gpt-3.5-turbo' })
    99            });
    100            const timeout_handle = setTimeout(() => {
    101                this.controller.abort();
    102            }, this.timeout);
    103            const ret = await response.json();
    104            clearTimeout(timeout_handle);
    105            return ret;
    106        }
    107    }
    109    async embeddings(options) {
    110        // 拼接目标URL
    111        const url = this.apiBaseUrl + '/v1/embeddings';
    112        // 拼接headers
    113        const headers = {
    114            'Content-Type': 'application/json',
    115            Authorization: 'Bearer ' + this.key
    116        };
    117        const { model, ...restOptions } = options;
    118        // 使用 fetch 发送请求
    119        const response = await fetch(url, {
    120            signal: this.controller.signal,
    121            method: 'POST',
    122            headers: headers,
    123            body: JSON.stringify({ ...restOptions, model: model || 'text-embedding-ada-002' })
    124        });
    125        const timeout_handle = setTimeout(() => {
    126            this.controller.abort();
    127        }, this.timeout);
    128        const ret = await response.json();
    129        clearTimeout(timeout_handle);
    130        return ret;
    131    }
    133    async billing() {
    134        const url = this.apiBaseUrl + '/dashboard/billing/credit_grants';
    135        const headers = {
    136            'Content-Type': 'application/json',
    137            Authorization: 'Bearer ' + this.key
    138        };
    139        const response = await fetch(url, {
    140            signal: this.controller.signal,
    141            method: 'GET',
    142            headers: headers
    143        });
    144        const timeout_handle = setTimeout(() => {
    145            this.controller.abort();
    146        }, this.timeout);
    
  •