效果展示

与AI扮演的乔布斯谈天:

如何基于GPT快速构建一个的AI应用

与AI扮演的特朗普谈天:

如何基于GPT快速构建一个的AI应用

整体设计

首先咱们希望做一个与AI扮演的名人谈天的运用,运用的核心运用GPT。能够挑选让AI扮演哪位名人。

获取上下文

既然是谈天,咱们就需求对上下文有了解,这样聊的才会顺利。怎么才能让AI了解上下文,这儿运用的计划是每次将谈天的上下文全部作为prompt传递给gpt模型。

怎么让AI进入扮演状况

GPT是十分强大的,咱们只需求在prompt最初的时分告诉它:pretend you are xxx.即可

整体流程

如何基于GPT快速构建一个的AI应用

back-end(后端)

咱们这儿运用express建立后端服务

npm i express
npm i cors // 解决前端同源战略
npm i body-parser // 解析http req的格局
const express = require('express');
const cors = require('cors')
const bodyParser = require('body-parser')
const app = express();
app.use(cors())
app.use(bodyParser.json())
app.post('/chat_ai', async (req, res) => {
    const prompt = req.body.prompt;
    const openAiRes = await requestOpenAi(prompt);
    const data = { chat_res: openAiRes };
    res.send(data);
});
app.listen(8111, () => {
    console.log('Server is running at http://localhost:8111')
})

然后咱们使openAI官方供给的npm包来调用GPT。

npm i openai
async function requestOpenAi(prompt) {
    const OpenAi = require("openai")
    const { Configuration, OpenAIApi } = OpenAi
    const configuration = new Configuration({
        organization: "xx",
        apiKey: "xx",
    });
    const openai = new OpenAIApi(configuration);
    const response = await openai.createCompletion({
        model: "text-davinci-003",
        prompt: prompt,
        temperature: 0.9,
        max_tokens: 500,
        top_p: 1,
        frequency_penalty: 0.0,
        presence_penalty: 0.6,
    });
    const resText = response.data.choices[0].text;
    return resText;
}

其中oranization与apiKey 别离能够下面2个地方找到:

  • beta.openai.com/account/org…
  • beta.openai.com/account/api…

front-end (前端)

运用react + bootstrap建立前端

npx create-react-app ai-frontend
npm i sass
npm i bootstrap

自界说网络恳求办法,后边网络相关的通用逻辑能够在这儿处理

export function customFetch(input: string, init?: RequestInit): Promise<Response> {
    input = "http://localhost:8111" + input;
    const url = input;
    const headers_value = { ...(init?.headers), "Content-Type": "application/json" };
    init = { ...init, headers: headers_value }
    return fetch(url, init);
}

接下来便是咱们的首要业务逻辑

如最开端的效果图所示,咱们一共有2个输入性元素,1个输出性元素,2个输入性元素别离用来挑选AI扮演的名人和输入谈天内容,1个输出性元素是1个列表即展示咱们的对话列表。

function App() {
  function listItem(data, index) {
    console.log("listItem index:" + index + " data: " + data);
    const isMe = data.startsWith("Me: ");
    return <li className={['list-group-item', 'chat_item', isMe ? "me" : null].join(' ')} key={index}>{data}</li>
  }
  function listRole(data, index) {
    console.log("listRole index:" + index + " data: " + data);
    return <option value = {data} > {data}</option>
  }
  return (
    <div className='root'>
    <div className="App">
      <ul className='list-group chat_list'>
          {chatList.map((data, index) => listItem(data, index))}
      </ul>
      <div className='row chat_input'>
          <select class="form-select select_role" aria-label="role selector" onChange={onRoleSelect} >
            <option selected>select role</option>
            {roleList.map((data, index) => listRole(data, index))}
          </select>
          <input type="text" className="form-control col" id="chat_input" placeholder="please input" value={inputValue} onChange={handleChange} />
          <button className="btn btn-primary col-md-auto send_btn" onClick={sendClick}>send</button>
      </div>
    </div>
    </div>
  );
}

然后咱们针对这2个输入的元素和1个输出的元素别离界说状况,并将其关联到ui组件上:

const [chatList, setChatList] = useReducer((olddata, newdata) => {
      if (newdata === "clear") {
         return [];
      }
      return olddata.concat(newdata)
  }, [])
  const [inputValue, setInputValue] = useState("");
  const [role, setRole] = useState("");
  function onRoleSelect(event) {
    console.log("select value is" + event.target.value);
    if ("select role" === event.target.value) {
      setRole("")
    }
    setRole(event.target.value)
    setChatList("clear")
  }
  const handleChange = (event) => {
    console.log("input value is" + event.target.value);
    setInputValue(event.target.value);
  }

一起界说一组可扮演名人的选项

  let roleList = ["AI", "Steve Jobs", "Donald John Trump", "Ma Yun", "Ray Dalio"];

咱们需求在对话前面加上谁说的这句话,所以咱们供给统一前缀

 function genChatName(role) {
    return role + ": "
}

接下来处理点击事情,首先会校验是否现已挑选和让AI扮演哪位名人,接下来将输入内容格局化为”Me: xxx”的形式,展示在谈天列表中并恳求后端。恳求后端前,需求生成prompt,如最初所说,完成上下文的方式是将所有谈天内容都组合作为prompt传给GPT。所以咱们需求经过chatList生成对应的prompt。恳求完成后,将结果放入chatList中展示即可。

  function sendClick() {
    if (role === "") {
       alert("please select a role to chat with you")
       return
    }
    const fullInput = genChatName("Me") + inputValue;
    let newList = chatList.concat(fullInput);
    setChatList(fullInput)
    submit(genPrompt(newList));
  }
  function submit(text) {
    const api = "/chat_ai";
    const body = { prompt: text, role: genChatName(role)}
    customFetch(api, {body: JSON.stringify(body), method: "POST"}).then(async (res) => {
        const data = await res.json();
        setChatList(genChatName(role) + data.chat_res)
    }).catch((e) => {
        console.error(e);
    })
  }
  function genPrompt(chatList) {
    let prompt = genTopic(role);
     chatList.forEach(e => {
        prompt=prompt + e + "\n";
     });
     prompt = prompt + genChatName(role);
     return prompt;
  }

最终

openAI推出chatGPT以来让咱们见识了通用言语模型的威力,越来越多的idea在GPT这个模型的基础上爆发,也有越来越多的运用融入了GPT能力。期待下一代GPT模型的到来,给更多的运用层开发者带来创新的机会。