如何在Node.js中与OPEN AI通信

关于 Node.js介绍

作为一个异步事件驱动的 JavaScript 运行时,Node.js 被设计用来构建可扩展的网络应用。在下面的 “Hello World” 示例中,可以并发处理许多连接,每一个连接都会触发一个回调,而当没有可做的事情时,Node.js 就会进入休眠状态。

Node.js 在设计上类似于 Ruby 的 Event Machine 或 Python 的 Twisted 之类的系统。但 Node.js 更深入地考虑了事件模型,它将事件循环作为一个运行时结构而不是作为一个库来呈现。在其他系统中,总是有一个阻塞调用来启动事件循环。通常情况下,要执行的行为是通过脚本开始时的回调来定义的,然后通过 EventMachine::run() 这样的阻塞调用来启动服务器。而在 Node.js 中,没有这种启动事件循环的调用。Node.js 在执行输入脚本后直接进入事件循环,当没有更多的回调要执行时,Node.js 就会退出事件循环。这种行为就像浏览器的 JavaScript 一样 —— 事件循环对用户是隐藏的。

如何在Node.js中与OPEN AI通信

ChatGPT还不能作为公共API使用。因此,要使用它,我们必须设法进入——这意味着我们将执行一个完整的浏览器自动化,登录到OpenAI网站,解决验证码,并用OpenAI cookie发送API请求。

幸运的是,有一个公共库可以做到这一点,并且已经作为项目需求的一部分安装了。

导入ChatGPT API库,并创建一个向ChatGPT发送请求的函数。

import { ChatGPTAPIBrowser } from "chatgpt";

async function chatgptFunction(content) {
    // use puppeteer to bypass cloudflare (headful because of captchas)
    const api = new ChatGPTAPIBrowser({
        email: "<CHATGPT_EMAIL_ADDRESS>",
        password: "<CHATGPT_PASSWORD>",
    });
    await api.initSession();
    //👇🏻 Extracts the brand name from the website content
    const getBrandName = await api.sendMessage(
        `I have a raw text of a website, what is the brand name in a single word? ${content}`
    );
    //👇🏻 Extracts the brand description from the website content
    const getBrandDescription = await api.sendMessage(
        `I have a raw text of a website, can you extract the description of the website from the raw text. I need only the description and nothing else. ${content}`
    );
    //👇🏻 Returns the response from ChatGPT
    return {
        brandName: getBrandName.response,
        brandDescription: getBrandDescription.response,
    };
}

chatgptFunction 功能使用puppeteer绕过cloudflare(因为验证码麻烦)

Chat GPT是超级智能的,它会回答我们提出的任何问题。所以基本上,我们会把它写我们的品牌名称和描述基于完整的网站HTML。品牌名称通常可以在“og:site_name”中找到,但为了向您展示它有多酷,我们将让ChatGPT提取它。至于描述,简直太疯狂了。它会告诉我们网站是关于什么,并总结一切!

接下来,更新api/url路由如下所示:

//👇🏻 holds all the ChatGPT result
const database = [];
//👇🏻 generates a random string as ID
const generateID = () => Math.random().toString(36).substring(2, 10);

app.post("/api/url", (req, res) => {
    const { url } = req.body;

    (async () => {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(url);
        const websiteContent = await page.evaluate(() => {
            return document.documentElement.innerText.trim();
        });
        const websiteOgImage = await page.evaluate(() => {
            const metas = document.getElementsByTagName("meta");
            for (let i = 0; i < metas.length; i++) {
                if (metas[i].getAttribute("property") === "og:image") {
                    return metas[i].getAttribute("content");
                }
            }
        });
        //👇🏻 accepts the website content as a parameter
        let result = await chatgptFunction(websiteContent);
        //👇🏻 adds the brand image and ID to the result
        result.brandImage = websiteOgImage;
        result.id = generateID();
    //👇🏻 adds the result to the array
        database.push(result);
    //👇🏻 returns the results
        return res.json({
            message: "Request successful!",
            database,
        });

        await browser.close();
    })();
});

database 保存所有ChatGPT结果

generateID 生成一个随机字符串作为ID

要在React应用程序中显示响应,请创建一个保存服务器响应的状态。

const [websiteContent, setWebsiteContent] = useState([]);

async function sendURL() {
    try {
        const request = await fetch("http://localhost:4000/api/url", {
            method: "POST",
            body: JSON.stringify({
                url,
            }),
            headers: {
                Accept: "application/json",
                "Content-Type": "application/json",
            },
        });
        const data = await request.json();
        if (data.message) {
            setLoading(false);
            //👇🏻 update the state with the server response
            setWebsiteContent(data.database);
        }
    } catch (err) {
        console.error(err);
    }
}

最后,更新App.js布局以显示服务器对用户的响应。

const App = () => {
    //...other code statements
//👇🏻 remove the quotation marks around the description
const trimDescription = (content) =>
        content.match(/(?:"[^"]*"|^[^"]*$)/)[0].replace(/"/g, "");

    return (
        <div className='home'>
            <form className='home__form'>
                <h2>Website Aggregator</h2>
                <label htmlFor='url'>Provide the website URL</label>
                <input
                    type='url'
                    name='url'
                    id='url'
                    value={url}
                    onChange={(e) => setURL(e.target.value)}
                />
                <button onClick={handleSubmit}>ADD WEBSITE</button>
            </form>
            <main className='website__container '>
                {websiteContent.map((item) => (
                    <div className='website__item' key={item.id}>
                        <img src={item?.brandImage} alt={item?.brandName} />
                        <h3>{item?.brandName}</h3>
                        <p>{trimDescription(item?.brandDescription)}</p>
                    </div>
                ))}
            </main>
        </div>
    );
};

恭喜你!🎉您已经完成了本教程的项目。

下面是应用程序得到的结果示例:

如何在Node.js中与OPEN AI通信

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
心中带点小风骚的头像心中带点小风骚普通用户
上一篇 2023年3月19日 上午11:32
下一篇 2023年3月19日 下午12:16

相关推荐