为了账号安全,请及时绑定邮箱和手机立即绑定

使用Next.js和Tailwind创建简单的流式OpenAI聊天应用(2024)

标签:
Node.js React

我使用了_v0_达到某个目标,发现我需要了解很多。希望这能帮助你在2024年。需要注意的是,有一段代码已不再支持,所以这最终将无法使用 :-(。趁现在还能用,赶紧试试吧!

这让我花了一点时间才搞定,但确实让我感到非常满足。

用v0

我用v0版本创建了大部分应用。但我用了GitHub Copilot来修复了很多地方。我也需要用很多自己的知识来修复它。它现在可以运行了 :)-

先决条件

这会对你有所帮助,你可以跟着我在这里手动设置一个简单shadcn项目的过程:https://medium.com/@johnmaeda/shadcn-with-nextjs-tailwind-yarn-on-macos-2024-75cb85491e97

那么,让我们开始吧

如果你能按顺序顺利完成这些,那你可真是走运。

首先,使用 yarn create next-app . --tailwind --typescript --eslint 创建一个新的 Next.js 应用程序,同时包含 Tailwind CSS、TypeScript 和 ESLint 支持。

然后,使用 npx shadcn@latest init 安装最新版本的 shadcn 并初始化。

接着,使用 npx shadcn@latest add button input card scroll-area 添加按钮、输入框、卡片和滚动区域组件。

之后,通过 yarn add ai 安装 AI 相关的库。

最后,通过 yarn add zod 安装 zod 库来处理数据验证。

我们需要编辑这些文件。

你的 app/layout.tsx 文件

    import Link from 'next/link'
    import { Inter } from 'next/font/google'
    import './globals.css'
    import { cn } from "@/lib/utils"

    const inter = Inter({ subsets: ['latin'] })

    export const metadata = {
      title: '标题',
      description: '描述',
    }

    export default function RootLayout({ children }: { children: React.ReactNode }) {
      return (
        <html lang="zh-CN">
          <body className={cn(inter.className, "bg-background")}>
            <div className="flex h-屏幕">
              <nav className="w-64 bg-card text-card-foreground shadow-lg fixed h-full overflow-y-auto">
                <div className="p-4">
                  <h1 className="text-2xl font-bold mb-4">聊天应用程序</h1>
                  <ul className="space-y-2">
                    <li>
                      <Link href="/" className="text-primary hover:underline">
                        首页
                      </Link>
                    </li>
                    <li>
                      <Link href="/chat" className="text-primary hover:underline">
                        聊天室
                      </Link>
                    </li>
                    <li>
                      <Link href="/docs" className="text-primary hover:underline">
                        文档
                      </Link>
                    </li>
                  </ul>
                </div>
              </nav>
              <main className="flex-1 p-4 overflow-auto ml-64">
                {children}
              </main>
            </div>
          </body>
        </html>
      )
    }

你的 app/page.tsx (即你的应用页面文件)

    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"  
    import Link from "next/link"  

    export default function Home() {  
      return (  
        <Card className="max-w-2xl mx-auto">  
          <CardHeader>  
            <CardTitle>欢迎来到简单的聊天应用页面</CardTitle>  
          </CardHeader>  
          <CardContent>  
            <p className="mb-4">  
              这是一个使用OpenAI生成回复的简单聊天应用程序。  
            </p>  
            <p>  
              转到<Link href="/chat" className="text-primary hover:underline">聊天</Link>页面开始对话,  
              或访问<Link href="/docs" className="text-primary hover:underline">文档</Link>页面,了解更多信息。  
            </p>  
          </CardContent>  
        </Card>  
      )  
    }
创建一些新文件和目录

你的 app/api/chat/route.ts (没错,是 .ts 而不是 .tsx

    import OpenAI from 'openai';  
    import { NextResponse } from 'next/server';  
    import { OpenAIStream, StreamingTextResponse } from 'ai'  

    const openai = new OpenAI({  
      apiKey: process.env.OPENAI_API_KEY,  
    });  

    export async function POST(req: Request) {  
      const { messages } = await req.json();  

      try {  
        const response = await openai.chat.completions.create({  
          model: 'gpt-3.5-turbo',  
          stream: true,  
          messages,  
        });  

        const stream = OpenAIStream(response)  
        // 创建一个新的流响应对象
        return new StreamingTextResponse(stream);  
      } catch (error) {  
        console.error(`请求处理中出现错误: ${error}`);  
        return NextResponse.json({ error: '请求处理中出现错误。' }, { status: 500 });  
      }  
    }

注意,你会收到两个已弃用函数的警告。不用担心,不过现在还是能用的。

你的 app/chat/page.tsx 文件

    'use client'  

    import { useChat } from 'ai/react'  
    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"  
    import { ScrollArea } from "@/components/ui/scroll-area"  
    import { Input } from "@/components/ui/input"  
    import { Button } from "@/components/ui/button"  

    export default function Chat() {  
      const { messages, input, handleInputChange, handleSubmit } = useChat({  
        api: '/api/chat',  
      })  

      const customHandleSubmit = async (e: React.FormEvent) => {  
        e.preventDefault();  
        await handleSubmit(e); // 调用 useChat 的 handleSubmit 函数  
      }  

      return (  
        <Card className="w-full max-w-2xl mx-auto">  
          <CardHeader>  
            <CardTitle>和 AI 聊天</CardTitle>  
          </CardHeader>  
          <CardContent>  
            <ScrollArea className="h-[60vh] mb-4 p-4 border rounded">  
              {messages.map((message, index) => (  
                <div key={index} className={`mb-4 ${message.role === 'user' ? 'text-right' : 'text-left'}`}>  
                  <span className={`inline-block p-2 rounded-lg ${message.role === 'user' ? 'bg-primary text-primary-foreground' : 'bg-muted'}`}>  
                    {message.content}  
                  </span>  
                </div>  
              ))}  
            </ScrollArea>  
            <form onSubmit={customHandleSubmit} className="flex space-x-2">  
              <Input  
                type="text"  
                value={input}  
                onChange={handleInputChange}  
                placeholder="输入消息..."  
                className="flex-1"  
              />  
              <Button type="submit">发送消息</Button>  
            </form>  
          </CardContent>  
        </Card>  
      )  
    }

app/docs/page.tsx 文件中

    import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"  

    export default function Docs() {  
      return (  
        <Card className="max-w-2xl mx-auto">  
          <CardHeader>  
            <CardTitle>文档</CardTitle>  
          </CardHeader>  
          <CardContent>  
            <h2 className="text-2xl font-semibold mb-2">如何使用聊天应用</h2>  
            <ol className="list-decimal list-inside mb-4 space-y-2">  
              <li>进入聊天页面</li>  
              <li>在输入框中输入您的消息</li>  
              <li>按回车键或点击发送按钮发送消息</li>  
              <li>等待AI回复</li>  
              <li>继续您的聊天</li>  
            </ol>  
            <p>  
              聊天应用使用OpenAI的GPT模型来生成回复,对话实时处理,提供互动体验。  
            </p>  
          </CardContent>  
        </Card>  
      )  
    }
咱们就跑啊跑啊跑

在你运行之前,你需要先将你的OAI key添加到你的环境中。这样可以临时完成此操作。

    export OPENAI_API_KEY=sk-your-key-blah-blah-blah # 设置你的OpenAI API密钥

你准备好了,那就去做吧。

    yarn dev

这将给你一种你一直梦想的流式聊天体验,让你感觉自己也是酷炫的人。

这都应该正常运行了,但愿你够幸运。

下一步

这就够了,是我想要达到的地方。希望你也达到!祝你好运!代码库在这里(https://github.com/aji-ai/v0shadcn-nextjs-chat)。——JM

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

举报

0/150
提交
取消