{"id":1180,"date":"2024-04-24T05:31:17","date_gmt":"2024-04-24T05:31:17","guid":{"rendered":"https:\/\/www.nicekj.com\/?p=1180"},"modified":"2024-04-24T05:31:21","modified_gmt":"2024-04-24T05:31:21","slug":"nextjsopenaiapikuaisuchuangjianchatgptliaotianyingyongjiaocheng","status":"publish","type":"post","link":"https:\/\/www.nicekj.com\/nextjsopenaiapikuaisuchuangjianchatgptliaotianyingyongjiaocheng.html","title":{"rendered":"Next.js + OpenAI API \u5feb\u901f\u521b\u5efa ChatGPT \u804a\u5929\u5e94\u7528\u6559\u7a0b"},"content":{"rendered":"<h2 data-id=\"heading-0\">\u4f7f\u7528 Next.js, TypeScript, TailwindCSS \u6784\u5efa ChatGPT \u5e94\u7528<\/h2>\n<h3 data-id=\"heading-1\">\u5148\u51b3\u6761\u4ef6<\/h3>\n<ul>\n<li>\u672c\u673a\u5df2\u5b89\u88c5 Node.js \u548c npm<\/li>\n<li>\u5bf9 React \u548c TypeScript \u57fa\u672c\u4e86\u89e3<\/li>\n<li>\u4e00\u4e2a OpenAI API key \u2014\u2014 \u4f60\u53ef\u4ee5\u4ece OpenAI \u5b98\u7f51\u4e0a\u6ce8\u518c\u8d26\u53f7\u5e76\u751f\u6210 API key<\/li>\n<\/ul>\n<h3 data-id=\"heading-2\">\u6700\u7ec8\u6548\u679c<\/h3>\n<p>\u8ddf\u7740\u672c\u6559\u7a0b\uff0c\u6211\u4eec\u5c06\u4f7f\u7528 OpenAI API \u6765\u521b\u5efa\u4e00\u4e2a\u7b80\u5355\u7684\u50cf ChatGPT \u4e00\u6837\u7684\u804a\u5929\u5e94\u7528\u3002<\/p>\n<p>\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/www.nicekj.com\/wp-content\/uploads\/replace\/0cb31e094617b6a1a72e12f29908f5c0.png\" alt=\"WX20230621-101804@2x.png\" \/><\/figure>\n<\/p>\n<h2 data-id=\"heading-3\">\u7b2c\u4e00\u6b65\uff1a\u8bbe\u7f6e\u9879\u76ee<\/h2>\n<p>\u6211\u4eec\u5c06\u4f7f\u7528\u6765\u81ea Apideck \u7684 <a href=\"https:\/\/link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fapideck-io%2Fnext-starter-kit\" target=\"_blank\" title=\"https:\/\/github.com\/apideck-io\/next-starter-kit\" ref=\"nofollow noopener noreferrer\" rel=\"noopener\">Next.js Starter Kit<\/a> \u6765\u8bbe\u7f6e\u6211\u4eec\u7684\u9879\u76ee\u3002\u5b83\u5df2\u7ecf\u9884\u5b89\u88c5\u4e86 TypeScirpt, TailwindCSS \u548c <a href=\"https:\/\/link.juejin.cn?target=https%3A%2F%2Fdevelopers.apideck.com%2Fcomponents\" target=\"_blank\" title=\"https:\/\/developers.apideck.com\/components\" ref=\"nofollow noopener noreferrer\" rel=\"noopener\">Apideck Components<\/a> \u5e93\u3002<\/p>\n<ol>\n<li>\u4f7f\u7528\u547d\u4ee4\u884c\u521b\u5efa\u4e00\u4e2a\u65b0\u9879\u76ee<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">lua<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-lua code-block-extension-codeShowNum\" lang=\"lua\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\">yarn <span class=\"hljs-built_in\">create<\/span>-<span class=\"hljs-built_in\">next<\/span>-app <span class=\"hljs-comment\">--example https:\/\/github.com\/apideck-io\/next-starter-kit<\/span><\/span>\n<\/code><\/pre>\n<ol start=\"2\">\n<li>\u8bbe\u7f6e\u4f60\u7684\u9879\u76ee\u540d\u5e76\u9009\u62e9\u65b0\u7684\u76ee\u5f55\u3002\u5728\u9879\u76ee\u6839\u76ee\u5f55\u4e2d\uff0c\u521b\u5efa\u4e00\u4e2a <code>.env.local<\/code> \u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u5185\u5bb9\uff08\u4f7f\u7528\u5b9e\u9645\u7684key\u6765\u66ff\u6362 <code>YOUR_OPENAI_API_KEY<\/code>\uff09\uff1a<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">ini<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-ini code-block-extension-codeShowNum\" lang=\"ini\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-attr\">OPENAI_API_KEY<\/span>=YOUR_OPENAI_API_KEY<\/span>\n<\/code><\/pre>\n<h2 data-id=\"heading-4\">\u7b2c\u4e8c\u6b65\uff1a\u7f16\u5199 API \u5ba2\u6237\u7aef<\/h2>\n<p>\u4e3a\u4e86\u4e0d\u66b4\u9732\u4f60\u7684 OpenAI key\uff0c\u6211\u4eec\u9700\u8981\u8981\u521b\u5efa\u4e00\u4e2a API \u7aef\u70b9\u6765\u66ff\u4ee3\u4ece\u6d4f\u89c8\u5668\u76f4\u63a5\u8bf7\u6c42 API\u3002\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u4f7f\u7528 <a href=\"https:\/\/link.juejin.cn?target=https%3A%2F%2Fnextjs.org%2Fdocs%2Fapi-routes%2Fintroduction\" target=\"_blank\" title=\"https:\/\/nextjs.org\/docs\/api-routes\/introduction\" ref=\"nofollow noopener noreferrer\" rel=\"noopener\">Next.js API \u8def\u7531<\/a>\u6765\u8bbe\u7f6e\u4f60\u7684\u7aef\u70b9\uff1a<\/p>\n<ol>\n<li>\u5728\u9879\u76ee\u4e2d\u7684 pages \u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a <code>api<\/code> \u7684\u65b0\u6587\u4ef6\u5939\u3002<\/li>\n<li>\u5728 <code>api<\/code> \u6587\u4ef6\u5939\u5185\uff0c\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a <code>createMessage.ts<\/code> \u7684\u65b0\u7684 TypeScript \u6587\u4ef6\u3002<\/li>\n<li>\u5728 <code>createMessage.ts<\/code> \u6587\u4ef6\u4e2d\uff0c\u6211\u4eec\u53ef\u4ee5\u4f7f\u7528 OpenAI SDK \u6216\u5411 OpenAI API \u53d1\u9001 HTTP \u8bf7\u6c42\uff0c\u4e3a\u6211\u4eec\u4e0e AI \u7684\u201c\u4f1a\u8bdd\u201d\u751f\u6210\u65b0\u6d88\u606f\u3002\u5728\u672c\u6559\u7a0b\u4e2d\u6211\u4eec\u5c06\u76f4\u63a5\u8c03\u7528 API\u3002<\/li>\n<\/ol>\n<p>\u4ee5\u4e0b\u662f\u6211\u4eec API \u8def\u7531\u7684\u4ee3\u7801\u3002<\/p>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">NextApiRequest<\/span>, <span class=\"hljs-title class_\">NextApiResponse<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'next'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title function_\">createMessage<\/span>(<span class=\"hljs-params\"><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\">  req: NextApiRequest,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\">  res: NextApiResponse<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">  <span class=\"hljs-keyword\">const<\/span> { messages } = req.<span class=\"hljs-property\">body<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">  <span class=\"hljs-keyword\">const<\/span> apiKey = process.<span class=\"hljs-property\">env<\/span>.<span class=\"hljs-property\">OPENAI_API_KEY<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">  <span class=\"hljs-keyword\">const<\/span> url = <span class=\"hljs-string\">'https:\/\/api.openai.com\/v1\/chat\/completions'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">  <span class=\"hljs-keyword\">const<\/span> body = <span class=\"hljs-title class_\">JSON<\/span>.<span class=\"hljs-title function_\">stringify<\/span>({<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">    messages,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">    <span class=\"hljs-attr\">model<\/span>: <span class=\"hljs-string\">'gpt-3.5-turbo'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\">    <span class=\"hljs-attr\">stream<\/span>: <span class=\"hljs-literal\">false<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">  })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\">  <span class=\"hljs-keyword\">try<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"18\">    <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-title function_\">fetch<\/span>(url, {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"19\">      <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">'POST'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"20\">      <span class=\"hljs-attr\">headers<\/span>: {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"21\">        <span class=\"hljs-string\">'Content-Type'<\/span>: <span class=\"hljs-string\">'application\/json'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"22\">        <span class=\"hljs-title class_\">Authorization<\/span>: <span class=\"hljs-string\">`Bearer <span class=\"hljs-subst\">${apiKey}<\/span>`<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"23\">      },<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"24\">      body,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"25\">    })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"26\">    <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">await<\/span> response.<span class=\"hljs-title function_\">json<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"27\">    res.<span class=\"hljs-title function_\">status<\/span>(<span class=\"hljs-number\">200<\/span>).<span class=\"hljs-title function_\">json<\/span>({ data })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"28\">  } <span class=\"hljs-keyword\">catch<\/span> (error) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"29\">    res.<span class=\"hljs-title function_\">status<\/span>(<span class=\"hljs-number\">500<\/span>).<span class=\"hljs-title function_\">json<\/span>({ <span class=\"hljs-attr\">error<\/span>: error.<span class=\"hljs-property\">message<\/span> })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"30\">  }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"31\">}<\/span>\n<\/code><\/pre>\n<p>\u5bf9\u4e8e\u8fd9\u4e2a\u4f8b\u5b50\uff0c\u6211\u4eec\u4f7f\u7528\u4e86 <code>gpt-3.5-turbo<\/code> \u6a21\u578b\uff0c\u56e0\u4e3a\u5728\u64b0\u5199\u672c\u6587\u7684\u65f6\u5019\u5b83\u662f\u53ef\u7528\u7684\u3002\u5982\u679c\u4f60\u60f3\u7528 GPT-4\uff0c\u4f60\u53ef\u4ee5\u5728\u5fc5\u8981\u7684\u65f6\u5019\u4fee\u6539\u8fd9\u4e2a\u503c\u3002<\/p>\n<p><code>messages<\/code> \u7684\u503c\u662f\u4e00\u4e2a\u6570\u7ec4\uff0c\u5b83\u5b58\u50a8\u4e86\u6211\u4eec\u4e0e AI \u57fa\u4e8e\u804a\u5929\u7684\u5bf9\u8bdd\u4e2d\u7684\u6d88\u606f\u3002\u6bcf\u4e2a\u6d88\u606f\u90fd\u5305\u542b\u4e00\u4e2a <code>role<\/code> \u548c <code>content<\/code>\u3002<code>role<\/code> \u53ef\u4ee5\u662f\u4ee5\u4e0b\u51e0\u79cd\uff1a<\/p>\n<ul>\n<li><strong>system<\/strong> \u8fd9\u662f\u53d1\u9001\u7ed9 AI \u7684\u521d\u59cb\u63d0\u793a\uff0c\u6307\u793a\u5b83\u5982\u4f55\u884c\u52a8\u3002\u4f8b\u5982\uff0c\u4f60\u53ef\u4ee5\u4f7f\u7528 &#8220;\u4f60\u662f ChatGPT\uff0c\u4e00\u4e2a OpenAI \u8bad\u7ec3\u7684\u8bed\u8a00\u6a21\u578b&#8221;\u3002\u6216 &#8220;\u4f60\u662f\u4e00\u4e2a\u4f7f\u7528\u5404\u79cd\u7f16\u7a0b\u8bed\u8a00\u548c\u5f00\u53d1\u5de5\u5177\u5f00\u53d1\u8f6f\u4ef6\u7a0b\u5e8f\u3001\u7f51\u9875\u5e94\u7528\u548c\u79fb\u52a8\u5e94\u7528\u7684\u8f6f\u4ef6\u5de5\u7a0b\u5e08&#8221;\u3002\u5c1d\u8bd5\u4e0d\u540c\u7684\u521d\u59cb\u6d88\u606f\u53ef\u4ee5\u5e2e\u52a9\u4f60\u5fae\u8c03 AI \u7684\u884c\u4e3a\u3002<\/li>\n<li><strong>user<\/strong> \u8fd9\u4ee3\u8868\u7528\u6237\u7684\u8f93\u5165\u3002\u4f8b\u5982\uff0c\u7528\u6237\u53ef\u4ee5\u95ee\uff0c\u201c\u4f60\u53ef\u4ee5\u63d0\u4f9b\u4e00\u4e2a JavaScript \u51fd\u6570\u6765\u83b7\u53d6\u5f53\u524d\u7684\u5929\u6c14\u5417\uff1f\u201d<\/li>\n<li><strong>assitant<\/strong> \u8fd9\u662f AI \u7684\u54cd\u5e94\uff0c\u5373 API \u7aef\u70b9\u8fd4\u56de\u7684\u6d88\u606f\u3002<\/li>\n<\/ul>\n<h2 data-id=\"heading-5\">\u7b2c\u4e09\u6b65\uff1a\u521b\u5efa\u6d88\u606f\u51fd\u6570<\/h2>\n<p>\u73b0\u5728\u7aef\u70b9\u5df2\u7ecf\u51c6\u5907\u597d\u8fde\u63a5 AI \u4e86\uff0c\u6211\u4eec\u53ef\u4ee5\u5f00\u59cb\u8bbe\u8ba1\u6211\u4eec\u7684\u7528\u6237\u754c\u9762\u6765\u4fc3\u8fdb\u4ea4\u4e92\u3002\u9996\u5148\uff0c\u6211\u4eec\u6765\u521b\u5efa <code>sendMessage<\/code> \u51fd\u6570\u3002\u5c31\u662f\u8fd9\u6837\uff1a<\/p>\n<ol>\n<li>\u5728 <code>utils<\/code> \u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e00\u4e2a\u65b0\u6587\u4ef6\uff0c\u540d\u4e3a <code>sendMessage.ts<\/code>\u3002<\/li>\n<li>\u5728 <code>sendMessage.ts<\/code> \u4e2d\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'openai'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">sendMessage<\/span> = <span class=\"hljs-keyword\">async<\/span> (<span class=\"hljs-params\">messages: ChatCompletionRequestMessage[]<\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\">  <span class=\"hljs-keyword\">try<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\">    <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-title function_\">fetch<\/span>(<span class=\"hljs-string\">'\/api\/createMessage'<\/span>, {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">      <span class=\"hljs-attr\">method<\/span>: <span class=\"hljs-string\">'POST'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">      <span class=\"hljs-attr\">headers<\/span>: {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">        <span class=\"hljs-string\">'Content-Type'<\/span>: <span class=\"hljs-string\">'application\/json'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">      },<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\">      <span class=\"hljs-attr\">body<\/span>: <span class=\"hljs-title class_\">JSON<\/span>.<span class=\"hljs-title function_\">stringify<\/span>({ messages }),<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">    })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">    <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">await<\/span> response.<span class=\"hljs-title function_\">json<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\">  } <span class=\"hljs-keyword\">catch<\/span> (error) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">    <span class=\"hljs-variable language_\">console<\/span>.<span class=\"hljs-title function_\">log<\/span>(error)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\">  }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\">}<\/span>\n<\/code><\/pre>\n<p>\u6709\u4e86\u8fd9\u4e2a\u51fd\u6570\uff0c\u4f60\u5c31\u53ef\u4ee5\u5728\u7528\u6237\u754c\u9762\u548c AI \u4e4b\u95f4\u901a\u8fc7 API \u7aef\u70b9\u5efa\u7acb\u6c9f\u901a\u4e86\u3002<\/p>\n<p>\u73b0\u5728\u8ba9\u6211\u8bbe\u7f6e\u5728 <code>useMessages<\/code> hook \u4e2d\u521b\u5efa\u65b0\u6d88\u606f\u7684\u903b\u8f91\u3002\u5728 <code>utils<\/code> \u6587\u4ef6\u5939\u91cc\uff0c\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a <code>useMessages.tsx<\/code> \u7684\u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/p>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> { useToast } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@apideck\/components'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'openai'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">import<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\">  <span class=\"hljs-title class_\">ReactNode<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\">  createContext,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">  useContext,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">  useEffect,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">  useState,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">} <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\"><span class=\"hljs-keyword\">import<\/span> { sendMessage } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'.\/sendMessage'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\"><span class=\"hljs-keyword\">interface<\/span> <span class=\"hljs-title class_\">ContextProps<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">  <span class=\"hljs-attr\">messages<\/span>: <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span>[]<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\">  <span class=\"hljs-attr\">addMessage<\/span>: <span class=\"hljs-function\">(<span class=\"hljs-params\">content: <span class=\"hljs-built_in\">string<\/span><\/span>) =&gt;<\/span> <span class=\"hljs-title class_\">Promise<\/span>&lt;<span class=\"hljs-built_in\">void<\/span>&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">  <span class=\"hljs-attr\">isLoadingAnswer<\/span>: <span class=\"hljs-built_in\">boolean<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"18\"><span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title class_\">ChatsContext<\/span> = createContext&lt;<span class=\"hljs-title class_\">Partial<\/span>&lt;<span class=\"hljs-title class_\">ContextProps<\/span>&gt;&gt;({})<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"19\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"20\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title function_\">MessagesProvider<\/span>(<span class=\"hljs-params\">{ children }: { children: ReactNode }<\/span>) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"21\">  <span class=\"hljs-keyword\">const<\/span> { addToast } = <span class=\"hljs-title function_\">useToast<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"22\">  <span class=\"hljs-keyword\">const<\/span> [messages, setMessages] = useState&lt;<span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span>[]&gt;([])<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"23\">  <span class=\"hljs-keyword\">const<\/span> [isLoadingAnswer, setIsLoadingAnswer] = <span class=\"hljs-title function_\">useState<\/span>(<span class=\"hljs-literal\">false<\/span>)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"24\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"25\">  <span class=\"hljs-title function_\">useEffect<\/span>(<span class=\"hljs-function\">() =&gt;<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"26\">    <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">initializeChat<\/span> = (<span class=\"hljs-params\"><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"27\">      <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-attr\">systemMessage<\/span>: <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span> = {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"28\">        <span class=\"hljs-attr\">role<\/span>: <span class=\"hljs-string\">'system'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"29\">        <span class=\"hljs-attr\">content<\/span>: <span class=\"hljs-string\">'You are ChatGPT, a large language model trained by OpenAI.'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"30\">      }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"31\">      <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-attr\">welcomeMessage<\/span>: <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span> = {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"32\">        <span class=\"hljs-attr\">role<\/span>: <span class=\"hljs-string\">'assistant'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"33\">        <span class=\"hljs-attr\">content<\/span>: <span class=\"hljs-string\">'Hi, How can I help you today?'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"34\">      }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"35\">      <span class=\"hljs-title function_\">setMessages<\/span>([systemMessage, welcomeMessage])<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"36\">    }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"37\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"38\">    <span class=\"hljs-comment\">\/\/ When no messages are present, we initialize the chat the system message and the welcome message<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"39\">    <span class=\"hljs-comment\">\/\/ We hide the system message from the user in the UI<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"40\">    <span class=\"hljs-keyword\">if<\/span> (!messages?.<span class=\"hljs-property\">length<\/span>) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"41\">      <span class=\"hljs-title function_\">initializeChat<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"42\">    }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"43\">  }, [messages?.<span class=\"hljs-property\">length<\/span>, setMessages])<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"44\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"45\">  <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">addMessage<\/span> = <span class=\"hljs-keyword\">async<\/span> (<span class=\"hljs-params\">content: <span class=\"hljs-built_in\">string<\/span><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"46\">    <span class=\"hljs-title function_\">setIsLoadingAnswer<\/span>(<span class=\"hljs-literal\">true<\/span>)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"47\">    <span class=\"hljs-keyword\">try<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"48\">      <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-attr\">newMessage<\/span>: <span class=\"hljs-title class_\">ChatCompletionRequestMessage<\/span> = {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"49\">        <span class=\"hljs-attr\">role<\/span>: <span class=\"hljs-string\">'user'<\/span>,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"50\">        content,<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"51\">      }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"52\">      <span class=\"hljs-keyword\">const<\/span> newMessages = [...messages, newMessage]<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"53\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"54\">      <span class=\"hljs-comment\">\/\/ Add the user message to the state so we can see it immediately<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"55\">      <span class=\"hljs-title function_\">setMessages<\/span>(newMessages)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"56\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"57\">      <span class=\"hljs-keyword\">const<\/span> { data } = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-title function_\">sendMessage<\/span>(newMessages)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"58\">      <span class=\"hljs-keyword\">const<\/span> reply = data.<span class=\"hljs-property\">choices<\/span>[<span class=\"hljs-number\">0<\/span>].<span class=\"hljs-property\">message<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"59\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"60\">      <span class=\"hljs-comment\">\/\/ Add the assistant message to the state<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"61\">      <span class=\"hljs-title function_\">setMessages<\/span>([...newMessages, reply])<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"62\">    } <span class=\"hljs-keyword\">catch<\/span> (error) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"63\">      <span class=\"hljs-comment\">\/\/ Show error when something goes wrong<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"64\">      <span class=\"hljs-title function_\">addToast<\/span>({ <span class=\"hljs-attr\">title<\/span>: <span class=\"hljs-string\">'An error occurred'<\/span>, <span class=\"hljs-attr\">type<\/span>: <span class=\"hljs-string\">'error'<\/span> })<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"65\">    } <span class=\"hljs-keyword\">finally<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"66\">      <span class=\"hljs-title function_\">setIsLoadingAnswer<\/span>(<span class=\"hljs-literal\">false<\/span>)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"67\">    }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"68\">  }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"69\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"70\">  <span class=\"hljs-keyword\">return<\/span> (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"71\">    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ChatsContext.Provider<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">messages<\/span>, <span class=\"hljs-attr\">addMessage<\/span>, <span class=\"hljs-attr\">isLoadingAnswer<\/span> }}&gt;<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"72\">      {children}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"73\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ChatsContext.Provider<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"74\">  )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"75\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"76\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"77\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">useMessages<\/span> = (<span class=\"hljs-params\"><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"78\">  <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-title function_\">useContext<\/span>(<span class=\"hljs-title class_\">ChatsContext<\/span>) <span class=\"hljs-keyword\">as<\/span> <span class=\"hljs-title class_\">ContextProps<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"79\">}<\/span>\n<\/code><\/pre>\n<h2 data-id=\"heading-6\">\u7b2c\u56db\u6b65\uff1a\u5b9e\u73b0\u6d88\u606f UI \u7ec4\u4ef6<\/h2>\n<p>\u8bbe\u7f6e\u597d\u6211\u4eec\u7684\u51fd\u6570\u4e4b\u540e\uff0c\u6211\u4eec\u73b0\u5728\u53ef\u4ee5\u8bbe\u8ba1 UI \u7ec4\u4ef6\uff0c\u8be5\u7ec4\u4ef6\u5c06\u4f7f\u7528\u8fd9\u4e9b\u51fd\u6570\u6765\u521b\u5efa\u4e00\u4e2a\u53ef\u4ea4\u4e92\u7684\u804a\u5929\u754c\u9762\u3002\u9075\u7167\u4ee5\u4e0b\u6b65\u9aa4\uff1a<\/p>\n<ol>\n<li>\u5728\u4f60\u9879\u76ee\u7684 <code>components<\/code> \u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e00\u4e2a\u540d\u53eb <code>MessageForm.tsx<\/code> \u7684\u65b0\u6587\u4ef6\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">Button<\/span>, <span class=\"hljs-title class_\">TextArea<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@apideck\/components'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><span class=\"hljs-keyword\">import<\/span> { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">import<\/span> { useMessages } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'utils\/useMessages'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\"><span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">MessageForm<\/span> = (<span class=\"hljs-params\"><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">  <span class=\"hljs-keyword\">const<\/span> [content, setContent] = <span class=\"hljs-title function_\">useState<\/span>(<span class=\"hljs-string\">''<\/span>)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">  <span class=\"hljs-keyword\">const<\/span> { addMessage } = <span class=\"hljs-title function_\">useMessages<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">  <span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">handleSubmit<\/span> = <span class=\"hljs-keyword\">async<\/span> (<span class=\"hljs-params\">e: <span class=\"hljs-built_in\">any<\/span><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\">    e?.<span class=\"hljs-title function_\">preventDefault<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">    <span class=\"hljs-title function_\">addMessage<\/span>(content)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">    <span class=\"hljs-title function_\">setContent<\/span>(<span class=\"hljs-string\">''<\/span>)<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">  }<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">  <span class=\"hljs-keyword\">return<\/span> (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\">    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span><\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\">      <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"relative mx-auto max-w-3xl rounded-t-xl\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"18\">      <span class=\"hljs-attr\">onSubmit<\/span>=<span class=\"hljs-string\">{handleSubmit}<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"19\">    &gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"20\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\" supports-backdrop-blur:bg-white\/95 h-[130px] rounded-t-xl border-t border-l border-r border-gray-200 border-gray-500\/10 bg-white p-5 backdrop-blur dark:border-gray-50\/[0.06]\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"21\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">htmlFor<\/span>=<span class=\"hljs-string\">\"content\"<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"sr-only\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"22\">          Your message<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"23\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"24\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">TextArea<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"25\">          <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"content\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"26\">          <span class=\"hljs-attr\">placeholder<\/span>=<span class=\"hljs-string\">\"Enter your message here...\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"27\">          <span class=\"hljs-attr\">rows<\/span>=<span class=\"hljs-string\">{3}<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"28\">          <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">{content}<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"29\">          <span class=\"hljs-attr\">autoFocus<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"30\">          <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"border-0 !p-3 text-gray-900 shadow-none ring-1 ring-gray-300\/40 backdrop-blur focus:outline-none focus:ring-gray-300\/80 dark:bg-gray-800\/80 dark:text-white dark:placeholder-gray-400 dark:ring-0\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"31\">          <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{(e:<\/span> <span class=\"hljs-attr\">any<\/span>) =&gt; setContent(e.target.value)}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"32\">        \/&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"33\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"absolute right-8 bottom-10\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"34\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"flex space-x-3\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"35\">            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Button<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span> <span class=\"hljs-attr\">size<\/span>=<span class=\"hljs-string\">\"small\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"36\">              Send<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"37\">              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">svg<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"38\">                <span class=\"hljs-attr\">xmlns<\/span>=<span class=\"hljs-string\">\"http:\/\/www.w3.org\/2000\/svg\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"39\">                <span class=\"hljs-attr\">fill<\/span>=<span class=\"hljs-string\">\"none\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"40\">                <span class=\"hljs-attr\">viewBox<\/span>=<span class=\"hljs-string\">\"0 0 24 24\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"41\">                <span class=\"hljs-attr\">strokeWidth<\/span>=<span class=\"hljs-string\">{1.5}<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"42\">                <span class=\"hljs-attr\">stroke<\/span>=<span class=\"hljs-string\">\"currentColor\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"43\">                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"ml-1 h-4 w-4\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"44\">              &gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"45\">                <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">path<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"46\">                  <span class=\"hljs-attr\">strokeLinecap<\/span>=<span class=\"hljs-string\">\"round\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"47\">                  <span class=\"hljs-attr\">strokeLinejoin<\/span>=<span class=\"hljs-string\">\"round\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"48\">                  <span class=\"hljs-attr\">d<\/span>=<span class=\"hljs-string\">\"M6 12L3.269 3.126A59.768 59.768 0 0121.485 12 59.77 59.77 0 013.27 20.876L5.999 12zm0 0h7.5\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"49\">                \/&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"50\">              <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">svg<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"51\">            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Button<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"52\">          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"53\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"54\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"55\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"56\">  )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"57\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"58\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"59\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-title class_\">MessageForm<\/span><\/span>\n<\/code><\/pre>\n<p>\u73b0\u5728\u6211\u4eec\u5df2\u7ecf\u8bbe\u7f6e\u597d\u4e86\u6d88\u606fUI\u7ec4\u4ef6\uff0c\u6211\u4eec\u9700\u8981\u518d\u521b\u5efa\u4e00\u4e2a\u7ec4\u4ef6\u6765\u6e32\u67d3\u6d88\u606f\u5217\u8868\u3002<\/p>\n<ol start=\"2\">\n<li>\u5728 <code>components<\/code> \u6587\u4ef6\u5939\u4e2d\u521b\u5efa\u4e00\u4e2a\u540d\u4e3a <code>MessageList.tsx<\/code> \u7684\u65b0\u6587\u4ef6\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u4ee3\u7801\uff1a<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> { useMessages } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'utils\/useMessages'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title function_\">MessagesList<\/span> = (<span class=\"hljs-params\"><\/span>) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\">  <span class=\"hljs-keyword\">const<\/span> { messages, isLoadingAnswer } = <span class=\"hljs-title function_\">useMessages<\/span>()<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">  <span class=\"hljs-keyword\">return<\/span> (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"mx-auto max-w-3xl pt-8\"<\/span>&gt;<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">      {messages?.map((message, i) =&gt; {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">        const isUser = message.role === 'user'<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\">        if (message.role === 'system') return null<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">        return (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">            <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">message-<\/span>${<span class=\"hljs-attr\">i<\/span>}`}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\">            <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">fade-up<\/span> <span class=\"hljs-attr\">mb-4<\/span> <span class=\"hljs-attr\">flex<\/span> ${<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">              <span class=\"hljs-attr\">isUser<\/span> ? '<span class=\"hljs-attr\">justify-end<\/span>' <span class=\"hljs-attr\">:<\/span> '<span class=\"hljs-attr\">justify-start<\/span>'<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\">            } ${<span class=\"hljs-attr\">i<\/span> === <span class=\"hljs-string\">1<\/span> ? '<span class=\"hljs-attr\">max-w-md<\/span>' <span class=\"hljs-attr\">:<\/span> ''}`}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\">            <span class=\"hljs-attr\">key<\/span>=<span class=\"hljs-string\">{message.content}<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"18\">          &gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"19\">            {!isUser &amp;&amp; (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"20\">              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"21\">                <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/www.teamsmart.ai\/next-assets\/team\/ai.jpg\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"22\">                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"h-9 w-9 rounded-full\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"23\">                <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"avatar\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"24\">              \/&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"25\">            )}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"26\">            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"27\">              <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">{{<\/span> <span class=\"hljs-attr\">maxWidth:<\/span> '<span class=\"hljs-attr\">calc<\/span>(<span class=\"hljs-attr\">100<\/span>% <span class=\"hljs-attr\">-<\/span> <span class=\"hljs-attr\">45px<\/span>)' }}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"28\">              <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">{<\/span>`<span class=\"hljs-attr\">group<\/span> <span class=\"hljs-attr\">relative<\/span> <span class=\"hljs-attr\">rounded-lg<\/span> <span class=\"hljs-attr\">px-3<\/span> <span class=\"hljs-attr\">py-2<\/span> ${<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"29\">                <span class=\"hljs-attr\">isUser<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"30\">                  ? '<span class=\"hljs-attr\">from-primary-700<\/span> <span class=\"hljs-attr\">to-primary-600<\/span> <span class=\"hljs-attr\">mr-2<\/span> <span class=\"hljs-attr\">bg-gradient-to-br<\/span> <span class=\"hljs-attr\">text-white<\/span>'<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"31\">                  <span class=\"hljs-attr\">:<\/span> '<span class=\"hljs-attr\">ml-2<\/span> <span class=\"hljs-attr\">bg-gray-200<\/span> <span class=\"hljs-attr\">text-gray-700<\/span> <span class=\"hljs-attr\">dark:bg-gray-800<\/span> <span class=\"hljs-attr\">dark:text-gray-200<\/span>'<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"32\">              }`}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"33\">            &gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"34\">              {message.content.trim()}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"35\">            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"36\">            {isUser &amp;&amp; (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"37\">              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"38\">                <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/www.teamsmart.ai\/next-assets\/profile-image.png\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"39\">                <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"h-9 w-9 cursor-pointer rounded-full\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"40\">                <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"avatar\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"41\">              \/&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"42\">            )}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"43\">          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"44\">        )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"45\">      })}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"46\">      {isLoadingAnswer &amp;&amp; (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"47\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"mb-4 flex justify-start\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"48\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"49\">            <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/www.teamsmart.ai\/next-assets\/team\/ai.jpg\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"50\">            <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"h-9 w-9 rounded-full\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"51\">            <span class=\"hljs-attr\">alt<\/span>=<span class=\"hljs-string\">\"avatar\"<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"52\">          \/&gt;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"53\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"loader relative ml-2 flex items-center justify-between space-x-1.5 rounded-full bg-gray-200 p-2.5 px-4 dark:bg-gray-800\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"54\">            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"block h-3 w-3 rounded-full\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"55\">            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"block h-3 w-3 rounded-full\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"56\">            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"block h-3 w-3 rounded-full\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"57\">          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"58\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"59\">      )}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"60\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"61\">  )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"62\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"63\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"64\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-title class_\">MessagesList<\/span><\/span>\n<\/code><\/pre>\n<p>\u6211\u4eec\u4e0d\u5e0c\u671b\u5c55\u793a\u521d\u59cb\u7cfb\u7edf\u6d88\u606f\uff0c\u56e0\u6b64\u5982\u679c <code>role<\/code> \u662f <code>system<\/code> \u7684\u8bdd\u6211\u4eec\u8fd4\u56de <code>null<\/code>\u3002\u63a5\u7740\uff0c\u6211\u4eec\u57fa\u4e8e <code>role<\/code> \u662f <code>assitant<\/code> \u6216 <code>user<\/code> \u6765\u8c03\u6574\u4e00\u4e0b\u6d88\u606f\u7684\u6837\u5f0f\u3002<\/p>\n<p>\u5f53\u6211\u4eec\u7b49\u5f85\u54cd\u5e94\u65f6\uff0c\u6211\u4eec\u9700\u8981\u5c55\u793a\u4e00\u4e2a\u52a0\u8f7d\u5143\u7d20\u3002\u4e3a\u4e86\u8ba9 <code>loader<\/code> \u5143\u7d20\u52a8\u8d77\u6765\uff0c\u6211\u4eec\u9700\u8981\u6dfb\u52a0\u4e00\u4e9b\u81ea\u5b9a\u4e49\u7684 CSS\u3002\u5728\u6837\u5f0f\u6587\u4ef6\u5939\u91cc\uff0c\u521b\u5efa\u4e00\u4e2a <code>globals.css<\/code> \u6587\u4ef6\u5e76\u6dfb\u52a0\u4ee5\u4e0b\u6837\u5f0f\uff1a<\/p>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">css<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-css code-block-extension-codeShowNum\" lang=\"css\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-selector-class\">.loader<\/span> <span class=\"hljs-selector-tag\">span<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\">  <span class=\"hljs-attribute\">animation-name<\/span>: bounce;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\">  <span class=\"hljs-attribute\">animation-duration<\/span>: <span class=\"hljs-number\">1.5s<\/span>;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\">  <span class=\"hljs-attribute\">animation-iteration-count<\/span>: infinite;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\">  <span class=\"hljs-attribute\">animation-timing-function<\/span>: ease-in-out;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\"><span class=\"hljs-selector-class\">.loader<\/span> <span class=\"hljs-selector-tag\">span<\/span><span class=\"hljs-selector-pseudo\">:nth-child<\/span>(<span class=\"hljs-number\">2<\/span>) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">  <span class=\"hljs-attribute\">animation-delay<\/span>: <span class=\"hljs-number\">50ms<\/span>;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\"><span class=\"hljs-selector-class\">.loader<\/span> <span class=\"hljs-selector-tag\">span<\/span><span class=\"hljs-selector-pseudo\">:nth-child<\/span>(<span class=\"hljs-number\">3<\/span>) {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">  <span class=\"hljs-attribute\">animation-delay<\/span>: <span class=\"hljs-number\">150ms<\/span>;<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">}<\/span>\n<\/code><\/pre>\n<p>\u786e\u4fdd\u5728 <code>_app.tsx<\/code> \u6587\u4ef6\u4e2d\u5bfc\u5165\u8fd9\u4e2a CSS \u6587\u4ef6\uff1a<\/p>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'styles\/globals.css'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-string\">'styles\/tailwind.css'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">ToastProvider<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'@apideck\/components'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">AppProps<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'next\/app'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title function_\">App<\/span>(<span class=\"hljs-params\">{ Component, pageProps }: AppProps<\/span>): <span class=\"hljs-variable constant_\">JSX<\/span>.<span class=\"hljs-property\">Element<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\">  <span class=\"hljs-keyword\">return<\/span> (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">ToastProvider<\/span>&gt;<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Component<\/span> {<span class=\"hljs-attr\">...pageProps<\/span>} \/&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">ToastProvider<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">  )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">}<\/span>\n<\/code><\/pre>\n<ol start=\"3\">\n<li>\u6211\u4eec\u5df2\u7ecf\u6784\u5efa\u597d\u4e86\u6d88\u606fUI\u7ec4\u4ef6\uff0c\u73b0\u5728\u53ef\u4ee5\u5728\u5e94\u7528\u7a0b\u5e8f\u4e2d\u4f7f\u7528\u5b83\u4eec\u4e86\u3002\u6253\u5f00 <code>pages<\/code> \u76ee\u5f55\u5e76\u6253\u5f00 <code>index.tsx<\/code>\u3002\u5728\u6b64\u6587\u4ef6\u4e2d\u79fb\u9664\u6837\u677f\u4ee3\u7801\u3002<\/li>\n<\/ol>\n<pre><\/div><div class=\"code-block-extension-headerRight\"><span class=\"code-block-extension-lang\">typescript<\/span><div class=\"code-block-extension-copyCodeBtn\">\u590d\u5236\u4ee3\u7801<\/div><\/div><\/div><code class=\"hljs language-typescript code-block-extension-codeShowNum\" lang=\"typescript\"><span class=\"code-block-extension-codeLine\" data-line-num=\"1\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-title class_\">Layout<\/span> <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'components\/Layout'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"2\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-title class_\">MessageForm<\/span> <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'components\/MessageForm'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"3\"><span class=\"hljs-keyword\">import<\/span> <span class=\"hljs-title class_\">MessagesList<\/span> <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'components\/MessageList'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"4\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">NextPage<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'next'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"5\"><span class=\"hljs-keyword\">import<\/span> { <span class=\"hljs-title class_\">MessagesProvider<\/span> } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'utils\/useMessages'<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"6\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"7\"><span class=\"hljs-keyword\">const<\/span> <span class=\"hljs-title class_\">IndexPage<\/span>: <span class=\"hljs-title class_\">NextPage<\/span> = <span class=\"hljs-function\">() =&gt;<\/span> {<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"8\">  <span class=\"hljs-keyword\">return<\/span> (<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"9\">    <span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MessagesProvider<\/span>&gt;<\/span><\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"10\">      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Layout<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"11\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MessagesList<\/span> \/&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"12\">        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> <span class=\"hljs-attr\">className<\/span>=<span class=\"hljs-string\">\"fixed bottom-0 right-0 left-0\"<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"13\">          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">MessageForm<\/span> \/&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"14\">        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"15\">      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Layout<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"16\">    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">MessagesProvider<\/span>&gt;<\/span><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"17\">  )<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"18\">}<\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"19\"><\/span>\n<span class=\"code-block-extension-codeLine\" data-line-num=\"20\"><span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-title class_\">IndexPage<\/span><\/span>\n<\/code><\/pre>\n<p>\u6211\u4eec\u5df2\u7ecf\u7528 <code>MessageProvider<\/code> \u5305\u88c5\u4e86\u7ec4\u4ef6\uff0c\u56e0\u6b64\u6211\u4eec\u53ef\u4ee5\u5728\u4e0d\u540c\u7ec4\u4ef6\u4e4b\u95f4\u5171\u4eab\u72b6\u6001\u3002\u6211\u4eec\u8fd8\u7ed9 <code>MessageForm<\/code> \u7ec4\u4ef6\u6dfb\u52a0\u4e86\u4e00\u4e2a div \u5bb9\u5668\uff0c\u56e0\u4e3a\u5b83\u88ab\u56fa\u5b9a\u5728\u4e86\u9875\u9762\u5e95\u90e8\u3002<\/p>\n<h2 data-id=\"heading-7\">\u7b2c\u4e94\u6b65\uff1a\u8fd0\u884c\u8fd9\u4e2a\u804a\u5929\u5e94\u7528\u7a0b\u5e8f<\/h2>\n<p>\u73b0\u5728\u6211\u4eec\u53ef\u4ee5\u8fd0\u884c\u8fd9\u4e2a\u804a\u5929\u7a0b\u5e8f\u4e86\u3002\u4f60\u53ef\u4ee5\u8fd9\u6837\u6d4b\u8bd5\u4f60\u7684 ChatGPT \u5e94\u7528\uff1a<\/p>\n<ol>\n<li>\u786e\u4fdd\u4f60\u7684\u5f00\u53d1\u670d\u52a1\u5df2\u8fd0\u884c\u3002\uff08<code>yarn dev<\/code>\uff09<\/li>\n<li>\u5728\u6d4f\u89c8\u5668\u4e2d\u6253\u5f00\u4f60\u7684\u5e94\u7528\u7a0b\u5e8f\u7684\u6839 URL\u3002\uff08<code>localhost:3000<\/code>\uff09<\/li>\n<li>\u4f60\u5e94\u8be5\u770b\u5230 UI \u5df2\u7ecf\u6e32\u67d3\u51fa\u6765\u3002\u5728\u5e95\u90e8\u7684\u6587\u672c\u6846\u4e2d\u8f93\u5165\u6d88\u606f\u5e76\u70b9\u51fb <em>Send<\/em>\u3002AI \u673a\u5668\u4eba\u5c06\u54cd\u5e94\u4f60\u7684\u6d88\u606f\u3002<\/li>\n<\/ol>\n<p>\u5b8c\u6210\u4ee3\u7801\u53ef\u4ee5\u5728<a href=\"https:\/\/link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Fjakeprins%2Fnextjs-chatgpt-tutorial\" target=\"_blank\" title=\"https:\/\/github.com\/jakeprins\/nextjs-chatgpt-tutorial\" ref=\"nofollow noopener noreferrer\" rel=\"noopener\">\u8fd9\u91cc<\/a>\u67e5\u770b\u3002<\/p>\n<p>\u539f\u6587\u8fde\u63a5\uff1a<a href=\"https:\/\/link.juejin.cn?target=https%3A%2F%2Fwww.jakeprins.com%2Fblog%2Fhow-to-create-a-chatgpt-application-using-next-js-and-the-openai-api\" target=\"_blank\" title=\"https:\/\/www.jakeprins.com\/blog\/how-to-create-a-chatgpt-application-using-next-js-and-the-openai-api\" ref=\"nofollow noopener noreferrer\" rel=\"noopener\">www.jakeprins.com\/blog\/how-to\u2026<\/a><\/p>\n<p>\u5168\u6587\u5b8c\u3002<\/p>","protected":false},"excerpt":{"rendered":"<p>\u4f7f\u7528 Next.js, TypeScript, TailwindCSS \u6784\u5efa ChatGPT \u5e94\u7528 \u5148\u51b3\u6761\u4ef6 \u672c\u673a\u5df2\u5b89\u88c5 Node.js \u548c npm \u5bf9 React \u548c TypeScript \u57fa\u672c\u4e86\u89e3<\/p>\n","protected":false},"author":1,"featured_media":2185,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"rank_math_title":"Next.js\u6253\u9020AI\u804a\u5929\u5e94\u7528\uff1a\u63a5\u5165ChatGPT - \u5948\u65af\u79d1\u6280\u793e\u533a","rank_math_description":"\u8fd9\u7bc7\u6280\u672f\u6559\u7a0b\u5c06\u6307\u5bfc\u4f60\u4f7f\u7528 Next.js, TypeScript \u548c Tailwind CSS \u6784\u5efa\u4e00\u4e2a\u7c7b\u4f3c ChatGPT \u7684\u804a\u5929\u5e94\u7528\uff0c\u5e76\u63a5\u5165 OpenAI API \u5b9e\u73b0 AI \u5bf9\u8bdd\u529f\u80fd\u3002","rank_math_focus_keyword":"Next.js, TypeScript, Tailwind CSS, ChatGPT, OpenAI API","views":"30","footnotes":""},"categories":[3],"tags":[127,128,129,136,126],"collection":[],"class_list":["post-1180","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fenlei2","tag-ai","tag-128","tag-129","tag-136","tag-gpt"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/posts\/1180","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/comments?post=1180"}],"version-history":[{"count":0,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/posts\/1180\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/media\/2185"}],"wp:attachment":[{"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/media?parent=1180"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/categories?post=1180"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/tags?post=1180"},{"taxonomy":"collection","embeddable":true,"href":"https:\/\/www.nicekj.com\/nicekj2024\/wp\/v2\/collection?post=1180"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}