openai官方api调用function call测试

无它,只是想看看官方的api如何使用,顺便测试下让chatgpt调用本机api并分析输出而已。 最后,简单封装了个方便使用调用的API类。

import { v4 as uuidv4 } from 'uuid';
import moment from 'moment-timezone';
import {exec} from 'child_process';
import { Configuration, OpenAIApi } from "openai";
import Keyv from "keyv";
import QuickLRU from "quick-lru";

function execShellCommand(cmd) {
    return new Promise((resolve, reject) => {
        exec(cmd, {maxBuffer: 1024 * 1024*500}, (error, stdout, stderr) => {
            if (error) {
                console.log(error);
                reject(error);
            }
            resolve(stdout? stdout : stderr);
        });
    });
}
function wait(time) {
    return new Promise((resolve)=> {
        let t = setTimeout(()=> {
            clearTimeout(t);
            resolve(t);
        }, time);
    });
}
class MyChatGpt {
    constructor(opts) {
        this.config = opts;
        const configuration = new Configuration(opts);
        this.api = new OpenAIApi(configuration);
        this.people_data = {};
        this._messageStore = new Keyv({
            store: new QuickLRU({ maxSize: 1e4 })
        });

    }
    async getMessageById(id) {
        const res = await this._messageStore.get(id);
        return res;
    }
    async setMessage(message) {
        await this._messageStore.set(message.messageId, message);
    }
    // 获取消息及其所有父消息
    async getAllMessageById(messageId) {
        const messages = [];
        // 递归获取父消息
        let getParents = async (currentMessageId) => {
            const message = await this._messageStore.get(currentMessageId);
            if (message) {
                messages.push(message);
                if (message.parentMessageId) {
                    await getParents(message.parentMessageId);
                }
            }
        };

        await getParents(messageId);
        return messages.reverse();
    }
    async sendMessage(people, msg, opts={}) {
        let real_opt = null;
        if(this.people_data[people]) {
            real_opt = {... this.people_data[people],
                        ...opts
                       };
        } else {
            real_opt = {
                ...opts,
                nick: people,
                parentMessageId: uuidv4(),
                start_at: moment(new Date()).tz('Asia/Shanghai'),
                last_at: moment(new Date()).tz('Asia/Shanghai'),
            };
            this.people_data[people] = real_opt;
        }
        let messages = [];
        let functions = opts.functions || [];
        if(real_opt.parentMessageId) {
            messages = await this.getAllMessageById(real_opt.parentMessageId);
        }
        let messageId = uuidv4();
        let message = {
            "body": {
                "role":"user",
                "content": msg,
            },
            messageId,
            "parentMessageId": real_opt.parentMessageId
        };
        await this.setMessage(message);
        messages.push(message);

        let send_msg = async()=> {
            let m_s = messages.map(v=>v.body);
            let chat_ret = await this.api.createChatCompletion({
                model: this.config.completionParams.model,
                messages: m_s,//messages.map(v=>v.body),
                functions,
            });
            let resp = chat_ret.data.choices[0].message;
            let m = {
                "body": resp,
                messageId: uuidv4(),
                parentMessageId: messageId
            };
            messages.push(m);
            messageId = m.messageId;
            await this.setMessage(m);
            await wait(getRandomInt(10000,30000));
            if(resp.function_call) {
                let func_name = resp.function_call.name;
                let args = resp.function_call.arguments;
                if(real_opt.api&& real_opt.api[func_name]) {
                    let f = real_opt.api[func_name];
                    let result = await f(args);
                    m = {
                        body: {
                            "role": "function",
                            "name": func_name,
                            "content": result,
                        },
                        messageId: uuidv4(),
                        parentMessageId: messageId
                    };
                    messages.push(m);
                    messageId = m.messageId;
                    await this.setMessage(m);
                    return await send_msg();
                }
            }
            return m;
        };
        let m = await send_msg();
        real_opt.parentMessageId = m.messageId;
        real_opt.last_at = moment(new Date()).tz('Asia/Shanghai');
        this.people_data[people] = real_opt;
        return m;
    }
}

async function test() {
    let api = new MyChatGpt({
        apiKey: 'sk-xxx',
        completionParams: { model: 'gpt-3.5-turbo-16k-0613' }
    });
    let functions = [
        {
            "name": "exec",
            "description": "执行linux命令,并返回执行输出结果,如果要执行复杂命令,需要将复杂命令创建为脚本,然后再执行",
            "parameters": {
                "type": "object",
                "properties": {
                    "cmd": {
                        "type": "string",
                        "description": "用于执行的linux命令"
                    },
                    "args": {
                        "type": "string",
                        "description": "用于执行的linux命令的参数"
                    }
                },
                "required": ["cmd"],
            }
        }];
    let my_opts = {functions,
                   api:{
                       "exec":async (args)=> {
                           console.log("exec args=", args);
                           try {
                               let result = await execShellCommand(`${args.cmd} ${args.args}`);
                               return result;
                           } catch (e) {
                               return `命令执行出错:${e}`;
                           }
                       }
                   }
                  },
    let ret = await api.sendMessage("me", `我的当前目录是什么?`, my_opts);
    console.log("ret=", ret);
    await wait(getRandomInt(10000,30000));
    ret = await api.sendMessage("me", `我的当前IP是什么?`, my_opts);
    console.log("ret=", ret);
}
try {
    await test();
} catch (e) {
    console.error(e);
}

发表评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据