给个人博客装上“大脑”:用 Spring Boot + LangChain4j 实现全知全能的 Ops Copilot

0 阅读5分钟

给个人博客装上“大脑”:用 Spring Boot + LangChain4j 实现全知全能的 Ops Copilot

参加 #人工智能创作者签约季# 活动

在 AI 时代,作为一个爱折腾的程序员,我一直在思考:大模型除了能帮我们写代码,能不能帮我们“管服务器”?

以前,管理个人博客往往意味着繁琐的流程:

  • 博客图片需要一张张压缩上传到云存储。
  • 服务器内存满了要 SSH 连上去排查日志。
  • 忘了某个数据库容器的启动端口,还要翻查 docker-compose.yml

为了彻底解放双手,我在重构最近的个人博客(Next.js + Spring Boot 前后端分离项目)时,索性把大模型作为 Agent 接入了系统的后台管理中

经过几个周末的填坑,我终于实现了一个能够自动化管理服务器、执行命令行、上传文件、管理文章状态的 “Ops Copilot(运维副驾驶)”。

写下这篇文章,除了分享这个项目的架构和实现思路,也想和大家一起探讨 AI Agent 在日常 DevOps 场景中的无限潜力!🔥


🏗️ 整体架构设计:从 “瞎聊” 到 “干实事”

要做一个能管服务器的 AI,核心在于 LLM 必须具备 Tool Calling(工具调用)能力。它不能只停留在回答你“如何清理 Linux 日存”,而是能在你下达指令后,自动调用 SSH 工具去执行 rm -rf (当然需要二次确认😅)。

我选择了 Java + Spring Boot + LangChain4j 作为大模型后端基座,前端使用 Next.js 16 + Server-Sent Events (SSE) 实现流式交互。

整体的对话和执行流如下:

sequenceDiagram
    participant User as 👨‍💻 用户 (Admin UI)
    participant NextJS as 🌐 Next.js (前端代理)
    participant Spring as 🚀 Spring Boot (业务后端)
    participant LLM as 🧠 大模型 (DeepSeek/GPT-4)
    participant Linux as 🖥️ 宿主机服务器

    User->>NextJS: 1. "帮我查一下 docker 运行状态"
    NextJS->>Spring: 2. 发起 SSE SSE 连接请求
    Spring->>LLM: 3. 带着 System Prompt 和 Tools 列表请求大模型
    LLM-->>Spring: 4. 大模型决定调用 `executeSshCommand` 工具
    Spring->>NextJS: 5. [流式返回] 推送 Tool Call 事件前端展示状态
    Spring->>Linux: 6. JSch 建立 SSH 连接并执行 `docker ps`
    Linux-->>Spring: 7. 返回终端执行结果
    Spring->>LLM: 8. 将终端日志交还给大模型分析
    LLM-->>Spring: 9. 大模型生成易读的总结文本
    Spring->>NextJS: 10. [流式返回] 将 Markdown 字幕逐字推送给用户
    NextJS-->>User: 11. 渲染最终结果并断开连接

正如你所见,这不仅仅是一个聊天框,而是真实连接了宿主机环境的控制台


🛠️ 后端基座:Spring Boot 拥抱 LangChain4j

很多人提起 AI 应用开发第一反应是 Python + LangChain。但如果你和我一样,是后端 Java 体系的老面孔,LangChain4j 绝对是不二之选。

在这个项目中,我们不需要写一堆底层的 API 封装代码,只需要利用 LangChain4j 提供的 @Tool 注解和声明式 AI Service,就能光速构建 Agent。

1. 声明式配置 AI Agent

通过 @AiService 注解,注入系统的预设人格和上下文。这种接口化的写法非常 Spring 风格,优雅且易于测试:

@AiService
public interface OpsCopilotService {

    @SystemMessage({
        "你是系统高级运维副驾驶 (Ops Copilot)。",
        "你有能力通过提供的工具执行系统级操作,包括文件管理、SSH 命令执行等。",
        "在执行破坏性命令(如 rm -rf 等)之前,必须先询问用户确认。",
        "不要随意暴露服务器的底层密码或密钥信息。"
    })
    TokenStream chat(@MemoryId String sessionId, @UserMessage String userMessage);
}

2. 赋予 AI 灵魂:工具箱 (Tools)

大模型本身是不联网、不能碰磁盘的。我们要手动把“操作系统的手脚”给它接上。

这是我实现的一个 SSH 远程命令执行工具。只要给方法加上 @Tool 并且认真写好描述参数,大模型就能在需要时精准调用:

@Component
public class SshTools {
    
    @Tool("执行宿主机 Linux Bash 命令,常用于查看系统状态、操作 docker 等。")
    public String executeSshCommand(
        @P("需要执行的 Linux 命令语句,不要包含危险的 rm -rf 等指令") String command
    ) {
        log.info("【Ops Copilot】准备执行远程命令: {}", command);
        
        // 伪代码:这里利用 com.jcraft.jsch 实现远程 SSH 执行并捕获输出
        String output = jschService.exec(command);
        return output;
    }
}

💡 Tip: 大模型极其依赖 @Tool 和参数上面的描述文字(@P)。你把这个描述当成给新员工写的岗位 S.O.P 手册就行,越详细,模型调用的错误率越低。


🌐 前端展现:Next.js + SSE 的流式魅力

想要好的用户体验,“打字机效果”是跑不掉的。但更复杂的是,我们不仅要展示文本,要在 AI "正在思考""正在执行脚本""执行完成" 这几个状态间来回切换。

由于管理后台 (personal-blog-admin) 是用 Next.js 16 (App Router) 写的,我通过原生的 fetch 结合 ReadableStream 实现了多态事件的流式接收 (Server-Sent Events)。

我定义了这几种事件:

  • message: 常规文本输出
  • tool_call: 触发了服务器脚本操作(前端会打开一个伪终端窗口,打出“正在执行:xxx”)
  • ops_log: 真正的终端日志(剥离 ANSI 转义码高亮显示)
  • done: 流结束

在前端,自定义了 useOpsStream Hook 来解析这种混合事件:

// 解析自定义的混合 SSE 流数据块
const processChunk = (chunk: string) => {
    const lines = chunk.split('\n');
    for (const line of lines) {
        if (!line.trim()) continue;
        
        try {
            const data = JSON.parse(line);
            switch(data.type) {
                case 'message':
                    updateChat(data.content);
                    break;
                case 'tool_call':
                    showTerminalEffect(data.toolName, data.args);
                    break;
                case 'ops_log':
                    appendTerminalLog(data.log);
                    break;
                case 'done':
                    finishStream();
                    break;
            }
        } catch (e) {
            console.error("解析流式数据失败", e);
        }
    }
}

前端 UI 最终呈现出了一种极客风格的双窗口模式:左侧是和 AI 聊天的窗口,右侧是一个嵌入的 Terminal 终端。AI 的每一步操作都会在右侧终端中刷出真实的执行日志,非常有赛博朋克的快感! Ops_Copilot_Screenshot.png

🚀 开源与踩坑总结

把大模型引入到 CRUD 项目里,让我真切地体会到了开发范式的转变:未来,我们的系统将越来越多地从 "API 驱动" 变成 "Agent 驱动"

这个项目已经完全开源,分为 3 个仓库(后端、前端、管理端)。如果你想自己搭一套带 AI Agent 的高颜值博客,或者想白嫖一套开箱即用的代码学习 Spring Boot + LangChain4j,非常欢迎来看看!

👉 GitHub: personal-blog-backend(求个✨Star!写得头秃)

踩坑贴士

  1. 流式传输的跨域坑:前端使用 Nginx 代理或者 Next.js rewrites 时,经常会把 SSE 的 chunk 给合并缓存了,导致打字机效果失效(变成一坨坨直接崩出来)。记得在后端 Controller 和网关层加上强力的 Header Cache-Control: no-cache
  2. 大模型 Token 上限:让大模型执行 tail -n 100 或者 docker logs 的时候,如果日志太长,返回给大模型上下文直接爆掉超载。必须要加最大字数截断!

科技永远在发展,不拥抱 AI 迟早会被淘汰。与其抵触它,不如让它成为替我们干脏活累活的 Copilot 吧!

欢迎在评论区交流,大家平时还有哪些工作希望用 Agent 自动化的?👇