soarli博客
type: channel
link: https://blog.soarli.top/
description: 欢迎来到soarli博客，是一个充满魔力的地方！
items: 非对称战争的胜利：8x RTX 4090 集群如何重构 AI 推理的算力逻辑
items: 权力、语言与愿景：五位历史级领导者的深度比较政治经济学报告
items: 从零构建现代化服务器：Docker + Compose + Nginx + HTTPS 全栈部署指南
items: Ubuntu SSH 安全加固与效率提升指南：从修改端口到密钥登录
items: 故障排查：Ollama 服务停止后显存不释放？教你三招彻底清理“僵尸显卡”
items: 如何榨干 8张 RTX 4090 算力？Ollama 高并发集群部署全记录
items: 本地大模型开发实战：手把手教你在 LangChain 和 LangGraph 中配置 Ollama
items: 通过 6 个 Python 案例，从 LangChain 进阶到 LangGraph
items: 从 LangChain 到 LangGraph：构建下一代 AI 应用的技术选型与架构演进
items: 解决 Open WebUI 非管理员用户无法看到模型的问题

非对称战争的胜利：8x RTX 4090 集群如何重构 AI 推理的算力逻辑
type: item
date: 2026-02-04T01:45:00+08:00
description: 在 AI 军备竞赛的当下，H100 是毫无疑问的“核武器”，但它昂贵、稀缺且受制于人。然而，近期在农大智能的实战验证中，一种“非正规军”的战术正在悄然改变游戏规则：8张 RTX 4090 构成的异构集群。这不仅仅是一次硬件的堆叠，更是一场关于算力成本、架构灵活性与工程极致的非对称战争。本文将深入剖析这套方案如何突破“无 NVLink”的物理封锁，并从“聚是一团火，散做满天星”的战术高度，解读其对 AI 行业的深远意义。一、 战略意义：打破“显存霸权”的第三条路长期以来，AI 从业者面临一个残酷的二选一：要么花天价买 H100 获得大显存，要么忍受消费级显卡的显存不足。农大智能通过 8x 4090 方案走出了第三条路。这套方案的核心意义在于：它剥离了“训练”与“推理”的强绑定关系。现状： 训练需要超高带宽（NVLink 是刚需），但推理更看重显存容量和吞吐量。突破： 既然推理对卡间通信不敏感，我们通过极高复杂度的软件工程（流水线并行与数据并行调度），将 8 张消费级显卡逻辑化为一台超级计算机。这标志着：顶级大模型的本地化部署，不再是巨头的特权。二、 战术形态：“聚散随心”的算力辩证法这套方案之所以被称为“算力怪兽”，是因为它在农大智能上实现了两种截然不同的战术形态的完美切换。这不仅是技术的胜利，更是调度哲学的体现。1. 聚是一团火：攻克“超大模型”的显存壁垒技术原理（模型并行 / Pipeline Parallelism）：系统将 8 张显卡的 24GB 显存进行物理级联，构建出 192GB 的超大显存池。模型被切分成 8 段，数据流像流水线一样流过每一张卡。核心价值：这是 H100 单卡（80GB）无法企及的领域。全量加载： 它可以让 Llama-3-70B (FP16) 这种需要 ~140GB 显存的巨型模型，在不进行任何有损量化的情况下全血运行。超长上下文： 在运行 DeepSeek-V3 或 Grok-1 量化版时，剩余的显存可以支持极长的 Context Window（上下文窗口），让模型能“记住”整本书的内容。意义： 让消费级硬件拥有了处理“企业级复杂任务”的能力。2. 散做满天星：吞吐量的“暴力美学”技术原理（数据并行 / Data Parallelism）：面对 7B/13B/20B 等中小型模型，系统瞬间解耦，化身为 8 个独立的推理节点。每个节点加载一个完整的模型副本，互不干扰。核心价值：QPS 翻倍： 相比于大卡切分，这种物理独立的并行方式没有任何资源争抢。QPS（每秒处理请求数）直接翻 8 倍。高并发承载： 在面对海量用户请求（如对外 API 服务）时，这套系统的吞吐量是惊人的。意义： 极大地降低了单位请求的边际成本，是商业化落地的最佳形态。三、 经济逻辑：1/5 成本下的“降维打击”如果说技术是骨架，那么成本效益（Cost-Efficiency）就是这套方案的灵魂。1. 算力账本的重构CAPEX（资本性支出）对比：8x 4090 集群： 硬件成本约 1.6 万美元（按 $2000/张计算）。1张 H100： 市场溢价往往超过 3 万美元，且经常处于缺货状态。OPEX（运营支出）优势：虽然 4090 能耗较高，但在纯推理场景下，通过 农大智能 的优化，其 FP16/Int8 的单位算力产出极高。2. 投资回报率 (ROI) 的奇点对于 AI 初创公司或高校实验室，用不到 2 万美元的成本，构建出理论吞吐量匹敌甚至超越 2-3 张 H100 的推理集群，意味着：产品上线的时间提前了。API 服务的定价可以比竞争对手更低。验证大模型想法的试错成本被极限压缩。四、 扩展与未来：从“工程折腾”到“标准基座”很多人认为 8x 4090 只是“土法炼钢”，但在农大智能看来，这是未来边缘计算与私有化部署的标准雏形。1. 供应链的“反脆弱性”H100 意味着极其脆弱的供应链（禁运、缺货、涨价）。而 4090 方案基于消费电子市场，随处可买、坏了即换。这种硬件的可获得性，构建了业务连续性的坚实护城河。2. 软件定义的算力该方案的成功落地，证明了软件优化可以弥补硬件短板。在没有 NVLink 的情况下，通过精细的 PCIe 通道管理、CPU 调度优化和显存页面管理，依然可以跑满 GPU 利用率。这为未来兼容更多型号的显卡（如 RTX 5090，或国产消费级显卡）铺平了道路。3. 应用场景的无限延展企业私有云： 并不是所有企业都需要训练模型，99% 的企业只需要推理。这套方案是企业内部知识库（RAG）的最佳载体。高校科研： 让每个实验室都拥有一台能跑 70B 模型的“超算”，彻底释放科研创造力。五、 结语8x RTX 4090 集群方案，不仅仅是一次硬件组装的胜利，更是“农大智能”对 AI 算力垄断的一次有力突围。它证明了：在…

权力、语言与愿景：五位历史级领导者的深度比较政治经济学报告
type: item
date: 2026-02-03T23:19:44+08:00
description: 本研究报告旨在构建一个跨越时空与领域的领导力分析框架，选取马云（数字时代的制度设计者）、温斯顿·丘吉尔（自由世界的战时捍卫者）、莫汉达斯·甘地（非暴力变革的圣徒）、巴拉克·奥巴马（理性主义的现代政治家）与阿道夫·希特勒（极权主义的破坏性煽动者）作为研究对象。这五位人物分别代表了商业、战争、社会运动、民主政治与独裁统治五个截然不同的维度。本报告将突破传统的传记式叙述，转而采用政治心理学、组织行为学及战略管理的交叉视角，深入剖析其领导力的底层逻辑、权力运作机制、危机应对模式以及话语体系构建。报告总计约一万五千字，旨在为当代个体在动荡环境下的自我成长与领导力修炼提供深层的行动指南。1. 绪论：领导力的多维光谱与核心变量领导力并非一种单一的特质，而是一个在特定历史情境下，通过愿景构建、资源动员与心理契约建立，从而通过他人达成目标的过程。当我们把马云、丘吉尔、甘地、奥巴马和希特勒置于同一分析平面时，我们实际上是在审视人类影响力的极限光谱：从商业生态的构建到国家机器的动员，从精神灵魂的净化到群体狂热的煽动。本报告将围绕三个核心变量展开深度论述：危机作为熔炉：领导力往往是在常态崩塌的瞬间被定义的。无论是2003年的非典危机、1940年的敦刻尔克大撤退，还是2008年的金融海啸，危机是检验领导者反脆弱能力的唯一试金石。语言作为杠杆：这五位人物无一例外都是语言大师。他们通过演讲、口号或布道，重新定义了现实，将个人的意志转化为集体的行动。制度与人的博弈：杰出的领导者不仅解决眼前的问题，更致力于留下（或摧毁）一套制度。马云的合伙人制度、甘地的真理之路、希特勒的领袖原则，都是对“组织如何运作”这一问题的不同回答。2. 马云：数字文明的布道者与制度设计师马云不仅是中国互联网经济的标志性人物，更是一位在商业文明中引入“教师型领导力”与复杂制度设计的战略家。他的领导力超越了单纯的财富创造，延伸至对商业基础设施的重构和对企业家精神的哲学思考。2.1 起源与底色：从西湖边的英语教师到互联网先知马云的早期经历为他独特的领导风格奠定了基础。作为一名英语教师，他并不具备传统技术极客的代码能力，也不具备传统商人的资本积累。这种“外行”身份迫使他必须发展出一种基于愿景驱动（Vision-Driven）而非能力驱动的领导模式。失败的馈赠与韧性的养成：马云早年的挫折——从考大学的屡次失败到求职肯德基被拒——塑造了他极高的逆商（AQ）。这种在被拒绝中保持乐观的能力，成为后来阿里巴巴“拥抱变化”价值观的心理根基 。互联网的启蒙瞬间：1995年在美国西雅图第一次接触互联网的经历，对马云而言是一次近乎宗教般的顿悟（Epiphany）。他意识到互联网将消除信息不对称，赋能中小企业。这一刻，他从一个单纯的创业者转变为一个“信仰者”。正是这种对未来的绝对确信，使他在面对早期团队的质疑时，能够展现出类似宗教领袖般的感召力 。2.2 危机中的反脆弱：2003年非典（SARS）的组织进化2003年的非典疫情是阿里巴巴发展史上的“至暗时刻”，也是马云领导力跃迁的关键节点。这一事件生动地展示了反脆弱（Antifragile）领导力的精髓：不仅在危机中生存，更在危机中进化。隔离中的战斗文化：当一名员工被确诊为疑似病例，导致阿里全员500多人被强制隔离时，公司面临业务停摆的灭顶之灾。马云通过电话和拨号上网，将分散在各家各户的员工编织成一张无形的网。他不仅没有让恐慌蔓延，反而通过高频的沟通（情感抚慰）和严格的纪律（业务连续性），将“隔离”异化为一次全员的“闭关修炼” 。淘宝的秘密诞生：在外界看来阿里陷入瘫痪之时，马云却在此时秘密启动了淘宝网项目。他敏锐地洞察到，非典导致线下交易受阻，正是培养用户线上交易习惯的千载难逢的时机。这种在战术防守（隔离）的同时进行战略进攻（推淘宝）的二元运作能力，是顶级战略家的标志。非典不仅没有击垮阿里，反而催生了阿里的“铁军精神”和C2C霸主地位，验证了“危中有机”的辩证法 。2.3 制度设计的巅峰：阿里巴巴合伙人制度深度解析马云最深远的商业遗产并非淘宝或支付宝，而是他为解决“创始人控制权”与“企业传承”矛盾而设计的阿里巴巴合伙人制度（Lakeside Partners）。超越股权的控制逻辑：在现代公司治理中，随着多轮融资，创始团队的股权必然被稀释。马云在持股比例降至个位数（上市时约8.9%甚至更低）的情况下，如何保持对庞大帝国的控制？他没有选择简单的AB股（双重股权结构），而是设计了更为复杂的合伙人制度。该制度规定，阿里巴巴的合伙人团队拥有提名董事会简单多数成员的专属权利。这意味着，无论软银或雅虎持有多少股份，只要合伙人团队保持团结，就能牢牢掌握公司的战略方向 。文化传承的制度化载体：马云设计该制度的核心逻辑不仅是控制，更是文化的传承。成为合伙人有着极高的门槛：必须在阿里工…

从零构建现代化服务器：Docker + Compose + Nginx + HTTPS 全栈部署指南
type: item
date: 2026-02-03T14:07:44+08:00
description: 很多刚接触 Linux 服务器的朋友，在部署项目时都会经历三个阶段的痛苦：环境配置地狱：装 MySQL 缺库，装 Python 版本冲突，换台服务器又要重来一遍。端口裸奔：用户通过 http://IP:8080 访问，既丑陋又不安全。维护困难：服务挂了不知道，日志找不到，想要 HTTPS 却不会配证书。今天，我们将通过一套“工业级”的标准方案一次性解决所有问题。我们将使用 Docker 容器化应用，用 Docker Compose 编排服务，最后用 Nginx 做反向代理并配置 HTTPS。这是目前中小型互联网企业最主流的部署架构。📋 教程大纲架构总览：我们要做成什么样？基础建设：在 Ubuntu 上安装 Docker 全家桶容器编排：用 Compose 一键拉起 Web+数据库+缓存反向代理：安装 Nginx 接管流量安全加固：配置 HTTPS 证书与隐藏后端端口1. 架构总览：我们要做成什么样？在开始动手之前，先看懂这张架构图：Docker 容器群：这是“后厨”，负责运行你的代码（Web）、存数据（MySQL）、做缓存（Redis）。它们运行在独立的虚拟网络中。Nginx：这是“前台大堂经理”，运行在宿主机上，监听 80/443 端口。外界的所有请求必须先经过它。流程：用户访问域名 -> Nginx (处理 HTTPS 加密) -> 转发给 Docker (处理业务) -> 返回结果。2. 基础建设：在 Ubuntu 上安装 Docker 全家桶虽然 Ubuntu 源自带 Docker，但版本较老。我们使用官方脚本安装最新版。2.1 一键安装脚本复制以下命令在服务器终端执行：# 1. 卸载旧版本 sudo apt remove docker docker-engine docker.io containerd runc # 2. 安装基础工具 sudo apt update sudo apt install ca-certificates curl gnupg # 3. 添加官方密钥 sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg sudo chmod a+r /etc/apt/keyrings/docker.gpg # 4. 设置仓库源 echo \ "deb [arch="$(dpkg --print-architecture)" signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ "$(. /etc/os-release && echo "$VERSION_CODENAME")" stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # 5. 正式安装 sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin 2.2 关键配置：免 Sudo 运行把当前用户加入 Docker 用户组，这样运行命令就不需要每次都输 sudo 了。sudo usermod -aG docker $USER ⚠️ 注意： 执行完这步，请断开 SSH 连接并重新登录，否则不生效。3. 容器编排：用 Compose 一键拉起全栈环境我们要部署一套包含 Web 应用 + MySQL + Redis + phpMyAdmin 的完整环境。3.1 编写 Dockerfile (项目说明书)在你的项目根目录下，新建 Dockerfile，告诉 Docker 怎么打包你的代码（以 Python 为例）：FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt COPY . . EXPOSE 8000 CMD ["python", "app.py"] 3.2 编写 docker-compose.yml (指挥官)这是最核心的一步。在项目根目录新建 docker-compose.yml：version: '3.8' services: # --- 1. Web 应用 --- web: bui…

Ubuntu SSH 安全加固与效率提升指南：从修改端口到密钥登录
type: item
date: 2026-02-03T14:05:00+08:00
description: SSH 是我们管理服务器的“大门”。默认情况下，这扇门开在 22 号端口，并且使用密码锁。这意味着互联网上任何一个人都知道去哪里敲门，并且可以尝试无数把钥匙（暴力破解）。本教程将带你完成一次完整的 SSH 升级改造：换个隐蔽的门（改端口） -> 换把指纹锁（密钥登录） -> 门口安个自动炮塔（Fail2Ban） -> 给自己配个万能遥控器（SSH Config）。📋 目录现状诊断：查看当前 SSH 端口隐身术：安全修改 SSH 端口铁桶阵：配置密钥登录并禁用密码主动防御：安装 Fail2Ban 防止暴力破解极致效率：配置本地 SSH Config 秒连服务器1. 现状诊断：查看当前 SSH 端口在动刀之前，先确认现在的 SSH 跑在哪个端口上。方法 A：查看正在监听的进程（最准确）这能反映服务当前实际运行的状态：sudo ss -tulpn | grep ssh 查看输出中 0.0.0.0:22 冒号后面的数字，即为当前端口。方法 B：查看配置文件grep -i "Port" /etc/ssh/sshd_config 如果显示 #Port 22，说明使用的是默认端口 22。2. 隐身术：安全修改 SSH 端口修改默认端口可以避开绝大多数针对 22 端口的无脑扫描脚本。⚠️ 警告：在确认新端口能连接之前，千万不要关闭当前的终端窗口！否则一旦配置错误，你会被锁在服务器外面。步骤 2.1：备份并修改配置# 备份原配置 sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # 编辑配置 sudo nano /etc/ssh/sshd_config 找到 #Port 22，去掉 # 号，并将 22 改为一个不常用的端口（例如 2222 或 10086）：Port 2222保存退出：Ctrl+O -> Enter -> Ctrl+X。步骤 2.2：放行防火墙 (UFW) —— 最关键的一步如果开启了防火墙却忘了这一步，重启服务后你就进不去了。sudo ufw allow 2222/tcp 步骤 2.3：重启服务并验证sudo systemctl restart ssh 验证方法：保持当前窗口不动，新开一个终端窗口尝试连接：ssh -p 2222 用户名@服务器IP 如果连接成功，恭喜你，修改完成！你可以选择删除旧的 22 端口规则：sudo ufw delete allow 22/tcp。3. 铁桶阵：配置密钥登录并禁用密码密码可能被猜到，但密钥文件很难被偷走。这是提升安全性的质变一步。步骤 3.1：在本地电脑生成密钥在你的电脑（不是服务器）上运行：ssh-keygen -t rsa -b 4096 一路回车即可。这会在 ~/.ssh/ 下生成 id_rsa (私钥) 和 id_rsa.pub (公钥)。步骤 3.2：将公钥上传到服务器在你的电脑上运行：# 注意：如果刚才改了端口，这里要加 -p ssh-copy-id -p 2222 用户名@服务器IP 步骤 3.3：验证密钥登录尝试登录，确认是否还需要输入密码：ssh -p 2222 用户名@服务器IP 如果直接进去了，说明密钥配置成功。步骤 3.4：禁用密码登录既然有了钥匙，就封死密码登录的缺口。回到服务器编辑配置：sudo nano /etc/ssh/sshd_config 修改以下项：PubkeyAuthentication yes PasswordAuthentication no 重启 SSH 服务：sudo systemctl restart ssh。现在，没有密钥的人，连输入密码的机会都没有了。4. 主动防御：安装 Fail2Ban即使改了端口，执着的黑客可能还是会扫到你。Fail2Ban 可以监控日志，自动拉黑那些不断试错的 IP。步骤 4.1：安装sudo apt update sudo apt install fail2ban 步骤 4.2：配置复制一份配置文件副本：sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local sudo nano /etc/fail2ban/jail.local 在 [sshd] 部分，确保修改端口为你的新端口：[sshd] enabled = true port = 2222 <-- 这里一定要改成你的新端口！ bantime = 3600 # 封禁 1 小时 maxretry = 3 # 试错 3 次就封 步骤 4.3：启动sudo systemctl restart fail2ban sudo systemctl enable fail2ban 查看被封禁的 IP 列表（战果统计）：sudo fail2ban-client…

故障排查：Ollama 服务停止后显存不释放？教你三招彻底清理“僵尸显卡”
type: item
date: 2026-02-03T04:56:00+08:00
description: 💥 案发现场在搭建 8x RTX 4090 的 Ollama 高并发集群时，我编写了脚本来启动多个实例。然而在调试过程中，当我试图停止脚本或重启服务时，遇到了一个让人血压升高的现象：并没有任何模型在跑，但 nvidia-smi 显示 8 张显卡依然被塞得满满当当！+---------------------------------------------------------------------------------------+ | NVIDIA-SMI 535.129.03 Driver Version: 535.129.03 CUDA Version: 12.2 | |-----------------------------------------+----------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | |=========================================+======================+======================| | 0 NVIDIA GeForce RTX 4090 Off | 00000000:19:00.0 Off | Off | | 31°C P0 30W / 450W | 18292MiB / 24564MiB | 0% Default | |-----------------------------------------+----------------------+----------------------+ | 1 NVIDIA GeForce RTX 4090 Off | 00000000:1A:00.0 Off | Off | | 30°C P0 28W / 450W | 18292MiB / 24564MiB | 0% Default | | ... (以此类推，8张卡全红) | +---------------------------------------------------------------------------------------+ 症状总结：高显存占用：每张卡都被占了约 18GB（正好是 Gemma-27B 模型的显存量）。零算力利用：GPU-Util 为 0%，说明进程虽然占着坑，但没在干活。杀不掉：尝试普通的 kill 命令无效，显存依然不释放。🕵️‍♂️ 原因分析这是典型的 “僵尸进程” (Zombie/Orphan Processes) 问题。当你强制终止（Ctrl+C）一个 Shell 脚本时，有时候只能杀掉脚本本身（父进程），而脚本启动的 Ollama 子进程（实际上是底层的 llama_runner）并没有收到退出信号，或者因为程序内部卡死（Deadlock）而忽略了普通的终止信号（SIGTERM）。这些“孤儿”会继续霸占着显存不肯走，导致你无法启动新的服务，甚至导致 OOM（显存溢出）错误。🛠️ 解决方案：从温柔到暴力针对这种情况，我们有三层手段来处理。方案一：精准狙击（推荐）如果你只想清理卡住的集群实例，但想保留那个默认的 11434 全局服务，不要用 killall。# 1. 查找所有 ollama serve 进程 ps -ef | grep "ollama serve" # 2. 排除掉全局服务(11434)，杀掉其他的 # awk '{print $2}' 提取进程ID (PID) # xargs kill -9 传递给 kill 命令执行强制查杀 ps -ef | grep "ollama serve" | grep -v "11434" | awk '{print $2}' | xargs kill -9 关键点：必须使用 -9 参数。普通的 kill 发送的是 SIGTERM（请你退出），卡死的进程听不见；-9 发送的是 SIGKILL（强制处决），由操作系统内核直接把进程干掉，不容反驳。方案二：按硬件查杀（最直观）如果你不知道是哪个进程在捣乱，只知道显卡被占用了，可以直接问显卡驱动：“谁在用我的显卡？”1. 查看占用者：# -v 显示详细信息 sudo fuser -v /dev/nvidia* 你会看到一串 PID，这就证实了确实有残留进程。2. 核弹清理（慎用）：这条命令会杀掉所有正在使用 NVIDIA 显卡的进程。如果你的服务器上还有别的人在跑训练，慎…

如何榨干 8张 RTX 4090 算力？Ollama 高并发集群部署全记录
type: item
date: 2026-02-03T04:45:00+08:00
description: 🚀 背景与痛点最近在部署一台拥有 8 张 NVIDIA RTX 4090 的高性能服务器时，我遇到了一个典型的“算力浪费”问题。场景复现：使用 Ollama 运行 Gemma 27B 模型。一张 4090 (24GB 显存) 绰绰有余。然而，当大量并发请求涌入时，通过 nvidia-smi或gpustat -i 观察发现了一个尴尬的现象：“一核有难，七核围观” —— 只有 GPU 0 显存爆满、拼命工作，而 GPU 1 到 GPU 7 却全程空闲，FPS（每秒生成token数）惨不忍睹。🧐 原因深度分析这是由 Ollama（基于 llama.cpp）默认的调度策略决定的：优先单卡加载：如果单张显卡能装下模型，Ollama 为了减少 PCIe 通信延迟，会优先将模型完整加载到一张卡上，而不是拆分。缺乏自动数据并行：Ollama 原生不支持“检测到高并发，自动在空闲显卡上启动副本”。它擅长 模型并行（大模型切分到多卡），而不支持 数据并行（多卡跑多份副本）。结论：为了让 8 张卡同时处理请求，我们需要手动构建 “多实例 + 负载均衡” 架构。🛠️ 解决方案架构我们采用 Nginx + 多 Ollama 实例 的方案，架构逻辑如下：后端层：启动 8 个独立的 Ollama 进程，分别绑定 GPU 0 - 7，监听 11534 - 11541 端口。网关层：使用 Nginx 作为统一反向代理，负责鉴权（IP 白名单）和智能负载均衡。优化层：配置显存自动释放策略，并解决 Root 权限下的路径映射问题。第一步：编写集群启动脚本我们需要一个脚本来批量启动 8 个进程，并注入显卡隔离、模型路径等环境变量。创建脚本 start_cluster.sh：#!/bin/bash # ================= ⚙️ 配置区域 ================= # 1. 模型存储路径 (关键) # 官方安装的 Ollama 模型通常在系统目录，而非 Root 目录。 # 必须显式指定，否则会报 "model not found"。 MODEL_PATH="/usr/share/ollama/.ollama/models" # 2. 起始端口 (避开默认的 11434) BASE_PORT=11534 # 3. 显存驻留策略 # "15s" 表示无请求 15秒后自动释放显存 (默认是5分钟) # 既能应对突发并发，又能让显卡在空闲时降温节能 KEEP_ALIVE="15s" # =========================================== echo "🚀 正在启动 Ollama 多卡负载均衡集群..." echo "📂 模型路径: $MODEL_PATH" echo "⏱️ 显存策略: $KEEP_ALIVE" # 循环启动 8 个实例 (对应 GPU 0-7) for i in {0..7}; do CURRENT_PORT=$((BASE_PORT + i)) # 核心原理： # CUDA_VISIBLE_DEVICES=$i : 显卡隔离，让该进程只能看到第 i 张卡 # OLLAMA_MODELS=$MODEL_PATH : 强制指向系统公共模型库 # OLLAMA_HOST=127.0.0.1:... : 绑定本地回环，拒绝外部直连 CUDA_VISIBLE_DEVICES=$i \ OLLAMA_MODELS=$MODEL_PATH \ OLLAMA_HOST=127.0.0.1:$CURRENT_PORT \ OLLAMA_KEEP_ALIVE=$KEEP_ALIVE \ nohup ollama serve > ollama_gpu_$i.log 2>&1 & echo " ✅ 实例 $i (GPU $i) 已启动 | 端口: $CURRENT_PORT" done echo "🎉 集群启动完毕！" ⚠️ 避坑指南：如果你以 root 身份运行脚本，Ollama 默认会去 /root/.ollama 找模型。如果你之前是用普通用户或官方脚本安装的，模型其实在 /usr/share/ollama。如果不加 OLLAMA_MODELS 变量，百分百报错。第二步：配置 Nginx 负载均衡Nginx 的作用不仅仅是分发，关键在于 流式输出支持 和 智能调度。修改 Nginx 配置文件（通常位于 /etc/nginx/nginx.conf 或 conf.d/ 下）：http { # 1. 定义负载均衡组 (Upstream) upstream ollama_gpu_cluster { # 🔥 核心策略：最少连接 (least_conn) # 相比轮询(Round Robin)，它能将新请求发给当前"最闲"的显…

本地大模型开发实战：手把手教你在 LangChain 和 LangGraph 中配置 Ollama
type: item
date: 2026-02-02T00:45:48+08:00
description: 引言：为什么要本地运行 LLM？随着 Llama 3、Mistral 和 Qwen 等开源模型越来越强，很多开发者开始寻找替代 OpenAI API 的方案。本地运行 LLM 不仅完全免费，还能保护数据隐私，且不受速率限制（Rate Limit）。而在本地运行方案中，Ollama 凭借其极致的易用性成为了事实上的标准。今天，我们将深入探讨如何将 Ollama 接入目前最强大的两个编排框架：LangChain（用于构建基础应用）和 LangGraph（用于构建复杂的 Stateful Agent）。🚀 准备工作在开始写代码之前，我们需要确保环境就绪。安装 Ollama： 前往 Ollama 官网 下载安装包。安装完成后，在终端拉取一个模型（以 Llama 3 为例）：ollama pull llama3确保终端能运行 ollama list 并看到模型。安装 Python 依赖： 我们将使用 LangChain 官方最新的集成库 langchain-ollama（比旧版的 community 库更稳定）：pip install langchain-ollama langgraph第一部分：LangChain 基础配置在 LangChain 中，核心组件是 ChatOllama。它适配了标准的 Chat Model 接口，支持 System/User 消息格式。1. 基础对话与流式输出本地模型相比云端 API，速度可能会稍慢，因此流式输出 (Streaming) 对于用户体验至关重要。from langchain_ollama import ChatOllama from langchain_core.messages import HumanMessage, SystemMessage # 初始化模型 # base_url 默认是 localhost:11434，Docker 用户需注意修改 llm = ChatOllama( model="llama3", temperature=0, ) print("--- 基础调用 ---") messages = [ SystemMessage(content="你是一个精通 Python 的技术专家。"), HumanMessage(content="用一句话解释什么是递归。") ] print(llm.invoke(messages).content) print("\n--- 流式输出 (提升体验) ---") for chunk in llm.stream("写一个快速排序的 Python 函数"): print(chunk.content, end="", flush=True)2. 配置嵌入模型 (Embeddings)如果你在做 RAG（知识库问答），千万不要用 llama3 做嵌入，效果不好且慢。推荐使用专门的嵌入模型，如 nomic-embed-text。ollama pull nomic-embed-textfrom langchain_ollama import OllamaEmbeddings embeddings = OllamaEmbeddings(model="nomic-embed-text") vector = embeddings.embed_query("LangChain 是一个很棒的框架") print(f"向量生成成功，维度: {len(vector)}")第二部分：LangGraph 进阶配置LangGraph 的核心是图（Graph）和状态（State）。我们需要将 Ollama 封装在图的节点（Node）中。实战：构建一个带有记忆的本地聊天机器人这个例子展示了如何让 Ollama 记住上下文。from typing import Annotated from typing_extensions import TypedDict from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langchain_ollama import ChatOllama from langchain_core.messages import BaseMessage # 1. 定义状态：使用 add_messages 自动追加历史记录 class State(TypedDict): messages: Annotated[list[BaseMessage], add_messages] # 2. 初始化模型 llm = ChatOllama(model="llama3", temperature=0.5) …

通过 6 个 Python 案例，从 LangChain 进阶到 LangGraph
type: item
date: 2026-02-02T00:33:59+08:00
description: 引言在 2024 年的 AI 开发浪潮中，开发者往往面临两个阶段的挑战：入门阶段： 如何把大模型（LLM）接入应用？（使用 LangChain）进阶阶段： 如何构建能够自我纠错、多轮思考的智能体（Agent）？（使用 LangGraph）本文将通过 6 个循序渐进的 Python 代码案例，带你从最基础的“线性链”一步步进阶到复杂的“状态机图”。第一部分：LangChain —— 线性流水线的艺术核心理念： Chain（链）。输入 -> 步骤A -> 步骤B -> 输出。 适用场景： 一次性问答、文档总结、简单数据处理。案例 1：Hello World (LCEL 基础)这是 LangChain 最经典的原子结构：Prompt + Model + Parser。 使用 LCEL (LangChain Expression Language) 的管道符 |，我们可以像搭积木一样组装逻辑。from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # 1. 定义组件 prompt = ChatPromptTemplate.from_template("用幽默的语气解释：什么是 {topic}") model = ChatOpenAI(model="gpt-3.5-turbo") parser = StrOutputParser() # 把复杂的对象转成纯字符串 # 2. 组装链条 chain = prompt | model | parser # 3. 运行 print(chain.invoke({"topic": "量子力学"}))💡 核心点： | 符号让数据像水流一样流过每个组件，无需写繁琐的函数调用。案例 2：顺序链 (Sequential Chain)当任务需要分步完成时，上一步的输出就是下一步的输入。 场景： 给产品取名 -> 根据名字写广告语。from langchain_core.runnables import RunnablePassthrough # 第一步：取名 name_chain = ( ChatPromptTemplate.from_template("为生产 {product} 的公司取一个酷名字") | ChatOpenAI() | StrOutputParser() ) # 第二步：写标语 (接收上一步生成的 company_name) slogan_chain = ( ChatPromptTemplate.from_template("为 {company_name} 写一句广告语") | ChatOpenAI() | StrOutputParser() ) # 串联：输入 -> 算出名字 -> 传给写标语链 full_chain = {"company_name": name_chain} | slogan_chain print(full_chain.invoke({"product": "彩虹袜子"}))💡 核心点： LangChain 自动处理了变量的传递，将复杂的逻辑拆解为简单的积木。案例 3：最小 RAG (检索增强生成)这是目前最主流的应用。让 AI “外挂”一个私有知识库。from langchain_community.vectorstores import FAISS from langchain_openai import OpenAIEmbeddings from langchain_text_splitters import CharacterTextSplitter # 1. 模拟私有数据 text = "云朵公司规定：周五下午提供无限量奶茶，禁止在办公室吃螺蛳粉。" vectorstore = FAISS.from_documents( CharacterTextSplitter().create_documents([text]), OpenAIEmbeddings() ) retriever = vectorstore.as_retriever() # 2. 构建 RAG 链 template = "基于已知信息回答：{context}。问题：{question}" rag_chain = ( {"context": retriever, "question": RunnablePassthrough()} | ChatPromptTemplate.from_template(template) | ChatOpenAI(…

从 LangChain 到 LangGraph：构建下一代 AI 应用的技术选型与架构演进
type: item
date: 2026-02-02T00:21:53+08:00
description: 引言：AI 应用开发的“下半场”在大语言模型（LLM）应用开发的初期，我们都在做“填空题”：把 Prompt 发给模型，拿回结果。但在 2024 年之后的“下半场”，重点已经从简单的问答（Chatbot）*转向了*能够解决复杂任务的智能体（Agent）。在这个转折点上，开发者面临着两个核心问题：工具选型： Python 的 LangChain 是标准，但 Java 团队该何去何从？架构升级： 为什么线性的“Chain”不够用了？“Graph”到底解决了什么问题？本文将深度解析 LangChain 与 LangChain4j 的生态差异，并结合三大真实业务场景，探讨为何“非线性控制流”是构建高可用 Agent 的必经之路。一、 工具对决：LangChain (Python) vs. LangChain4j (Java)在 LLM 开发领域，Python 是“原住民”，而 Java 是“企业级霸主”。两者的选择不仅仅是语言之争，更是应用场景之争。维度LangChain (Python)LangChain4j (Java)定位行业标准与实验田企业级落地的桥梁生态速度日更，新论文特性秒级跟进稳健，跟随 Python 版核心特性开发体验动态灵活，适合快速原型 (MVP)强类型安全，适合大型系统维护杀手锏LangGraph (复杂的图编排)AiServices (声明式接口调用)选型建议： 如果你需要最新的 AI 架构（如多智能体协作）且团队熟悉 Python，选 LangChain；如果你身处银行、电商等 Java 核心业务环境，需要系统稳定性和 Spring Boot 集成，选 LangChain4j。二、 场景大爆发：非线性流程（Graph）到底能干什么？很多开发者会有疑问：“我用线性的 Chain 挺好的，为什么要引入复杂的 Graph？”线性的 Chain 就像一个只会按说明书做事的实习生，一步步做到底，遇到错误就卡死。非线性的 Graph 就像一个有经验的项目经理，懂得分流、检查、重做和请示领导。为了让你秒懂，我们来看三个真实的业务场景对比：场景 1：智能客服与退款流程 (Human-in-the-loop)任务： 用户要求退款。❌ 线性做法 (Chain)：用户说“我要退款” -> AI 判断意图 -> AI 调用退款接口 -> 灾难发生：用户退款了 100 万，系统直接自动批准了。✅ 非线性做法 (Graph)：这里引入了 条件分支 (Branching) 和 人工介入 (Checkpoint)。意图识别： 确认用户要退款。金额判断（分支节点）：如果金额 < 50元： 走“自动批准”路径 -> 调用接口 -> 结束。如果金额 > 50元： 走“人工审核”路径。人工审核（暂停/等待）： 系统暂停运行，发送工单给人类经理。经理操作： 经理点击“同意”。恢复运行： 系统从暂停处苏醒 -> 调用退款接口 -> 发送通知。场景 2：企业数据库查询助手 (Self-Correction)任务： 老板问：“上个季度销售额最高的三个产品是什么？”（Text-to-SQL）❌ 线性做法 (Chain)：LLM 生成 SQL -> 在数据库执行 -> 报错！（可能是字段名写错了） -> 任务失败，返回“查询出错，请稍后再试”。✅ 非线性做法 (Graph)：这里引入了 循环 (Cycle)。生成： LLM 初次生成 SQL。执行： 尝试在数据库运行。判断（分支）：成功： 返回数据。失败： 捕获错误信息（例如 "Column 'sales' does not exist"）。修正（回环）： 将错误信息 + 原 SQL 一起扔回给 LLM，让它反思。重试： LLM 生成修正后的 SQL -> 跳回第 2 步再次执行。价值： 这种“写错了改一下再试”的能力，是人类的基本素质，但在 AI 系统中需要通过 Graph 显式定义。场景 3：多角色内容创作 (Multi-Agent Collaboration)任务： 写一篇高质量的技术博客。❌ 线性做法 (Chain)：Prompt：“请写一篇关于 Java 的博客” -> LLM 生成一篇平平无奇的文章 -> 结束。✅ 非线性做法 (Graph)：这里引入了 状态共享 (State) 和 多角色协作。角色 A（作家）： 根据主题写初稿，存入全局状态 (State)。角色 B（主编）： 读取初稿，提出修改意见（例如：“语气太生硬，需要加点幽默感”），更新状态。判断： 主编满意吗？不满意： 跳回角色 A，让作家根据意见修改。满意： 走“排版发布”路径。循环： 这个过程可能循环 2-3 次，直到产出完美文章。三、 技术深挖：Corrective RAG (CRAG)理解了上面的业务场景，我们再看一个技术上的经…

解决 Open WebUI 非管理员用户无法看到模型的问题
type: item
date: 2026-02-01T20:45:00+08:00
description: 用管理员权限登录Open WebUI并按照图示操作：到这里其他人就能看到允许可见的模型了：