【SpringAi最新版入门(二)】

搭建可视化页面

在resource中新建一个文件夹static,创建index.html,要注意的是文件夹必须是static,否则springboot无法加载index.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Spring AI 聊天助手</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
        }

        body {
            background-color: #f5f7fa;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            padding: 20px;
        }

        .chat-container {
            width: 100%;
            max-width: 800px;
            background: white;
            border-radius: 16px;
            box-shadow: 0 8px 30px rgba(0, 0, 0, 0.08);
            overflow: hidden;
            display: flex;
            flex-direction: column;
        }

        .chat-header {
            background-color: #6366f1;
            color: white;
            padding: 20px;
            text-align: center;
            font-size: 18px;
            font-weight: 600;
        }

        .chat-body {
            flex: 1;
            padding: 24px;
            min-height: 500px;
            max-height: 700px;
            overflow-y: auto;
            background: #fafbfc;
        }

        .message-bubble {
            background: white;
            padding: 16px 20px;
            border-radius: 14px;
            box-shadow: 0 2px 6px rgba(0, 0, 0, 0.04);
            line-height: 1.7;
            font-size: 15px;
            color: #333;
            white-space: pre-wrap;
            word-break: break-word;
            border: 1px solid #eee;
        }

        .loading {
            color: #6366f1;
            font-style: italic;
            margin-top: 10px;
            animation: fade 1.5s infinite;
        }

        @keyframes fade {
            0%, 100% { opacity: 0.5; }
            50% { opacity: 1; }
        }

        .chat-footer {
            padding: 16px 20px;
            border-top: 1px solid #eee;
            display: flex;
            gap: 12px;
        }

        #promptInput {
            flex: 1;
            padding: 14px 18px;
            border: 1px solid #ddd;
            border-radius: 12px;
            outline: none;
            font-size: 15px;
            transition: border 0.2s;
        }

        #promptInput:focus {
            border-color: #6366f1;
        }

        #sendBtn {
            padding: 14px 24px;
            background: #6366f1;
            color: white;
            border: none;
            border-radius: 12px;
            font-weight: 500;
            cursor: pointer;
            transition: background 0.2s;
        }

        #sendBtn:hover {
            background: #4f46e5;
        }

        #sendBtn:disabled {
            background: #a5b4fc;
            cursor: not-allowed;
        }
    </style>
</head>
<body>

<div class="chat-container">
    <div class="chat-header">Spring AI 智能助手</div>
    <div class="chat-body" id="response"></div>
    <div class="chat-footer">
        <input type="text" id="promptInput" placeholder="请输入你的问题......" autocomplete="off">
        <button id="sendBtn">发送</button>
    </div>
</div>

<script>
    const responseEl = document.getElementById('response');
    const sendBtn = document.getElementById('sendBtn');
    const promptInput = document.getElementById('promptInput');

    let eventSource = null;

    // 发送问题
    function sendMessage() {
        const prompt = promptInput.value.trim();
        if (!prompt) return;

        // 清空界面 & 禁用按钮
        responseEl.innerHTML = '<div class="loading">AI 思考中,请稍候......</div>';
        sendBtn.disabled = true;
        promptInput.disabled = true;

        // 关闭旧连接
        if (eventSource) eventSource.close();

        // 创建新连接
        eventSource = new EventSource(`http://localhost:8080/ai/chat?prompt=${encodeURIComponent(prompt)}`);

        let fullText = '';
        eventSource.onmessage = function (event) {
            fullText += event.data;
            responseEl.innerHTML = `<div class="message-bubble">${fullText}</div>`;
        };

        eventSource.onerror = function () {
            responseEl.innerHTML += '<div style="color:red;">连接断开。。。</div>';
            closeConnection();
        };

        eventSource.onopen = function () {
            responseEl.innerHTML = '<div class="loading">正在接收回复......</div>';
        };
    }

    function closeConnection() {
        if (eventSource) eventSource.close();
        sendBtn.disabled = false;
        promptInput.disabled = false;
        promptInput.value = '';
        eventSource = null;
    }

    // 绑定事件
    sendBtn.addEventListener('click', sendMessage);
    promptInput.addEventListener('keydown', e => e.key === 'Enter' && sendMessage());
</script>

</body>
</html>

启动springboot后访问浏览器,效果展示

流式输出

修改之前的chat函数:

java 复制代码
 @GetMapping("/chat")
    public Flux<String> chat(@RequestParam String prompt) {
        return chatClient.prompt(prompt).stream().content();
    }

去浏览器测试,

那么ai在返回结果时就可以一个词一个词的输出了,极大的增强了用户的体验,而不是像之前一样输出所有文字后在返回给用户。

记忆化

到目前为止,ai其实只能记录我们的一次对话,无法获取之前对话的内容。我们可以配置chatclient来解决这个问题:

java 复制代码
@Bean
    public ChatClient chatClient(OllamaChatModel model) {
        return ChatClient.builder(model)
                .defaultAdvisors(MessageChatMemoryAdvisor.builder(MessageWindowChatMemory.builder()
                        .maxMessages(10) //最大记忆的对话次数
                        .build())
                        .conversationId("use") //会话id
                        .build())
                .build();
    }

可以看到我们为chatclint配置了defaultAdvisors,在advisor中我们可以配置MessageWindowChatMemory从而实现记忆功能。

相关推荐
万少3 分钟前
用腻了 WorkBuddy 的默认界面?这个开源小工具给它换上了毛玻璃
前端·javascript·后端
fuquxiaoguang1 小时前
中间件的“价值重估”:传统同质化竞争终结,AI智能编排时代开启
人工智能·中间件
To_OC2 小时前
LC 15 三数之和:双指针不难,难的是把去重做对
javascript·算法·leetcode
触底反弹2 小时前
🔥 前端也能玩转 AI 流式输出!从二进制流到打字机效果,一篇讲透
javascript·人工智能·node.js
腾渊信息科技公司2 小时前
工业数据运维痛点根治方案:基于AI Agent的产线自动化台账系统落地
运维·人工智能·自动化·个人开发·ai编程
西安老张(AIGC&ComfyUI)2 小时前
第030章:ComfyUI视频制作LTX-2.3模型文生视频工作流详解(三)
人工智能·aigc·comfyui
胡萝卜术3 小时前
深度重构:Agent Skills——从 Prompt 工程到能力工程
javascript·架构·github
苦猿的大模型日记3 小时前
Day25 | 模型量化横评 GPTQ vs AWQ vs GGUF vs INT8——同一个 Qwen3-8B 压四遍,谁还活着
人工智能
benchmark_cc3 小时前
如何用 Python + QuantDash 快速构建高胜率“配对交易(Pairs Trading)”策略?
开发语言·人工智能·python·pandas·量化交易·quantdash
深海鱼肝油ya3 小时前
小说自动生成系统(二)
人工智能·大模型·agent·智能体·自动化编程·小说生成系统