纯JS完成CHATGPT流式输出

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Chat with OpenAI</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 600px;
            margin: 50px auto;
        }
        #input-section, #history-section {
            margin-bottom: 20px;
        }
        #output {
            padding: 10px;
            background-color: #f1f1f1;
            min-height: 50px;
            margin-top: 10px;
            white-space: pre-wrap;
        }
        #history {
            padding: 10px;
            background-color: #f9f9f9;
            margin-top: 20px;
            border: 1px solid #ddd;
        }
    </style>
</head>
<body>
    <h2>Chat with OpenAI</h2>
    <div id="input-section">
        <input type="text" id="user-input" placeholder="Type your question..." style="width: 80%;">
        <button onclick="sendMessage()">Send</button>
    </div>
    <div id="output"></div>
    <div id="history-section">
        <h3>Chat History</h3>
        <div id="history"></div>
    </div>

    <script>
        //JS部分详见下面
    </script>
</body>
</html>

完成比较简陋,需要的自己美化界面。流式输出,存储本地列表。

javascript 复制代码
        const API_KEY = '';  // 替换为你的OpenAI API密钥
		const API_URL = '';

        // 获取并展示本地历史记录
        function loadHistory() {
            const historyContainer = document.getElementById('history');
            const chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || [];
            historyContainer.innerHTML = '';
            chatHistory.forEach(entry => {
                const question = document.createElement('p');
                question.textContent = `Q: ${entry.question}`;
                const answer = document.createElement('p');
                answer.textContent = `A: ${entry.answer}`;
                historyContainer.appendChild(question);
                historyContainer.appendChild(answer);
                historyContainer.appendChild(document.createElement('hr'));
            });
        }

        // 发送用户问题并流式获取答案
       async function sendMessage() {
           const userInput = document.getElementById('user-input').value;
           if (!userInput) return;
       
           document.getElementById('output').textContent = 'Thinking...';
           document.getElementById('user-input').value = '';
       
           try {
               const response = await fetch(API_URL, {
                   method: "POST",
                   headers: {
                       "Content-Type": "application/json",
                       "Authorization": `Bearer ${API_KEY}`
                   },
                   body: JSON.stringify({
                       model: "gpt-3.5-turbo",
                       messages: [{"role": "user", "content": userInput}],
                       stream: true
                   })
               });
       
               const reader = response.body.getReader();
               const decoder = new TextDecoder("utf-8");
               let responseText = '';
               document.getElementById('output').textContent = '';
       
               while (true) {
                   const { done, value } = await reader.read();
                   if (done) break;
                   
                   // 将流返回的数据块转为文本
                   const chunk = decoder.decode(value, { stream: true });
                   
                   // 解析流返回的JSON字符串
                   const lines = chunk.trim().split("\n");
                   for (const line of lines) {
                       if (line.startsWith("data:")) {
                           const jsonStr = line.replace("data: ", "").trim();
                           if (jsonStr !== "[DONE]") {
                               const parsedData = JSON.parse(jsonStr);
                               const content = parsedData.choices[0].delta.content || '';
                               responseText += content;
                               document.getElementById('output').textContent = responseText;
                           }
                       }
                   }
               }
       
               saveToHistory(userInput, responseText);
           } catch (error) {
               document.getElementById('output').textContent = 'Error: ' + error.message;
           }
       }

        // 保存对话记录到localStorage
        function saveToHistory(question, answer) {
            const chatHistory = JSON.parse(localStorage.getItem('chatHistory')) || [];
            chatHistory.push({ question, answer });
            localStorage.setItem('chatHistory', JSON.stringify(chatHistory));
            loadHistory();
        }

        // 初次加载历史记录
        loadHistory();
相关推荐
仿生狮子2 小时前
OpenAI 攻下千禧年难题之后,开发者似乎无动于衷
前端·数学·vibecoding
夏幻灵6 小时前
JavaScript this 面试:五种绑定规则、优先级与常见面试陷阱
开发语言·javascript·面试
Lvan的前端笔记6 小时前
docker:每个前端项目一个 Nginx 容器还是只有一个Nginx容器
前端·nginx·docker
三天不学习6 小时前
Egg.js 4 突然爆火,原因是否归结于AI 原生落地需求爆发?
前端·javascript·全栈·egg.js
xcs194057 小时前
前端 vue 的前端页面debugger 进不去
前端·javascript·vue.js
明月_清风8 小时前
Deno 终局来了:从挑战 Node 到被 Cloudflare 收编
前端·后端·node.js
云上先途18 小时前
AI搜索排名优化,需要重点布局哪些关键词和内容形式?
人工智能·chatgpt
Csvn9 小时前
框架性能优化
前端
回眸&啤酒鸭10 小时前
【回眸】OpenSwarm 多智能体协作系统实战指南
大数据·前端·人工智能
用户693717500138411 小时前
2026,程序员的时代拐点到了
android·前端·后端