use-local-llm:React Hooks 用于实际本地运行的 AI

发布: (2026年3月12日 GMT+8 05:08)
9 分钟阅读
原文: Dev.to

Source: Dev.to

Cover image for use-local-llm: React Hooks for AI That Actually Work Locally

Pooya Golchian

你终于让本地 LLM 运行起来了。你拉取模型,用 curl 测试,效果非常好。但当你尝试把它集成到 React 应用时,却碰壁了。

大家普遍使用的工具默认你是从服务器调用 OpenAI 或 Anthropic,它们并不期望你直接在浏览器中访问 localhost:11434。即使可以,它们也会强迫你去构建 API 路由、添加后端,从而让原型变得复杂。

我一直遇到这种挫败感,于是创建了 use-local-llm —— 一个专注于一件事的库:在浏览器中直接从本地模型流式获取 AI 响应,无需后端。

Source:

为什么现有工具不适用

你可能会认为可以直接使用 Vercel AI SDK。它是 React + AI 的标准:设计良好、文档齐全、经受过实战考验。

但它并不是为你想要做的事情而构建的。

Vercel AI SDK 需要一个 API 层。你的 React 应用 POST 到一个 Next.js 服务器,然后服务器调用 LLM 并把流式结果返回。这在使用 OpenAI 或 Anthropic 的生产应用中是合理的——你需要后端来处理身份验证、费用跟踪和安全性。

当 LLM 已经在 localhost:11434 本地运行时,这个服务器只会增加阻力:需要编写更多代码、增加延迟、为快速原型带来更多复杂性。

我想要的很简单: 一个直接与本地模型通信的单一 React hook。没有中间人。没有 API 路由。只有 React 与正在运行的 LLM。

Browser → fetch() → localhost:11434 → streaming tokens back

这就是完整的架构。没有中介。

工作原理

use-local-llm 为你提供 React Hook,直接在浏览器中从本地 LLM 流式获取响应。无需 API 路由。无需后端。只需一个 Hook 和你正在运行的模型。

一个 Hook,全部搞定。

function Chat() {
  const { messages, send, isStreaming } = useOllama("gemma3:1b");

  return (
    <>
      {messages.map((m, i) => (
        <p key={i}>
          <strong>{m.role}:</strong> {m.content}
        </p>
      ))}
      <button onClick={() => send("Hello!")} disabled={isStreaming}>
        {isStreaming ? "Generating…" : "Send"}
      </button>
    </>
  );
}

这就是一个完整的流式聊天界面。消息历史?已处理。流式状态?已处理。中途停止生成?已处理。所有复杂性都已封装在 Hook 中。

没有 /api/chat 路由。没有 Next.js。没有后端配置。只有 React,发挥它的最佳特性。

与任何本地 LLM 配合使用

无论你使用的是 Ollama、LM Studio、llama.cpp,还是任何兼容 OpenAI 的服务器,它都能直接工作:

const ollama = useLocalLLM({ endpoint: "http://localhost:11434", model: "gemma3:1b" });
const lmStudio = useLocalLLM({ endpoint: "http://localhost:1234", model: "local-model" });
const llamaCpp = useLocalLLM({ endpoint: "http://localhost:8080", model: "model" });

后端会根据端口自动检测。每种实现都使用其原生的流式协议,因此无论你选择哪种工具,都能获得最佳性能。

高级:逐标记控制

需要细粒度的控制吗?在流式传输时捕获每个标记:

function Writer() {
  const { output, generate, isStreaming } = useStreamCompletion({
    endpoint: "http://localhost:11434",
    model: "gemma3:1b",
    onToken: (token) => console.log("Token:", token),
  });

  return (
    <>
      <pre>{output}</pre>
      <button onClick={() => generate("Write a haiku about React")}>
        生成
      </button>
    </>
  );
}

发现可用模型

让您的用户在无需手动配置的情况下从可用模型中进行选择:

function ModelPicker() {
  const { models, isLoading } = useModelList();

  return (
    <select disabled={isLoading}>
      {models.map((m) => (
        <option key={m.name} value={m.name}>
          {m.name}
        </option>
      ))}
    </select>
  );
}

对比

功能Vercel AI SDKuse‑local‑llm
目标云端大模型(OpenAI、Anthropic…)本地大模型(Ollama、LM Studio、llama.cpp
架构客户端 → 服务器 → 云 API客户端 → 直接本地大模型
是否需要后端
设置时间10 分钟以上大约 2 分钟
包大小~50 KB以上2.8 KB(gzip压缩后)
依赖多个零(仅 React)
隐私数据会离开你的机器永不离开你的机器

根据你的使用场景选择工具。如果在生产环境中调用 OpenAI,请使用 Vercel AI SDK。如果在本地进行原型开发或优先考虑隐私,请使用 use‑local‑llm

Source:

为什么这样构建

零依赖(总计 2.8 KB)

整个包 gzipped 后只有 2.8 KB。运行时没有任何依赖——只需要把 React 作为 peer 依赖。

这有什么意义?你的原型应该能够瞬间安装,并且永远不会与项目中的其他内容产生冲突。没有依赖冲突,没有版本不匹配,没有冗余。

也可在 React 之外使用

核心流式函数(streamChat()streamGenerate())是 async generator,能够在任何环境下工作——React、Vue、原生 JS、Node.js 脚本。React 应用可以使用 hooks,其他场景直接使用 generator。

const stream = streamChat({
  endpoint: "http://localhost:11434",
  model: "gemma3:1b",
  messages: [{ role: "user", content: "Hello" }],
});

for await (const chunk of stream) {
  process.stdout.write(chunk.content);
}

AbortController 集成

每个流都可以立即取消。用户主动中止不会触发错误状态,因为中止生成是正常的用户操作,而非错误。

完整的 TypeScript 支持

所有内容都有严格的类型定义。你可以获得 IDE 自动补全、类型安全以及每个函数的清晰契约:

import type {
  Backend,        // "ollama" | "lmstudio" | "llamacpp" | "openai-compatible"
  ChatMessage,    // { role: "system" | "user" | "assistant", content: string }
  StreamChunk,    // { content: string, done: boolean, model?: string }
  LocalModel,     // { name, size?, modifiedAt?, digest? }
} from "use-local-llm";

架构

┌─────────────────────────────────────────────────┐
│               Your React App                    │
│                                                 │
│               useOllama("gemma3:1b")           │
│                     │                           │
│                     ▼                           │
│   useLocalLLM({ endpoint, model, ... })         │
│                     │                           │
│                     ▼                           │
│   streamChat() / streamGenerate()               │
│                     │   async generators        │
│                     ▼                           │
│   parseStreamChunk()                             │
│                     │   NDJSON + SSE parser    │
│                     ▼                           │
│   fetch() + ReadableStream                       │
└─────────┬───────────────────────────────────────┘
          │ HTTP (no server in between)          │
          ▼                                      │
   ┌─────────────────────┐                      │
   │  Ollama    :11434   │                      │
   │  LM Studio :1234   │                      │
   │  llama.cpp :8080   │                      │
   └─────────────────────┘

每一层都可以独立测试。hooks 基于纯函数构建,能够在任何地方运行。

何时使用 use‑local‑llm

适用场景

  • 🚀 Rapid prototyping – 在 2 分钟内让你的 React 应用开始流式 AI,而不是 20 分钟。
  • 🔒 Privacy‑first apps – 数据永不离开你的机器。没有云端 API 调用。没有追踪。
  • 🏢 Enterprise / offline – 能在空气隔离的网络和断网环境中运行。
  • 🎓 Learning – 在没有服务器样板代码的情况下,了解 LLM 流式工作原理。
  • Small footprint – 当捆绑体积和依赖项很重要时。

如下情况请跳过此库

  • 你在生产环境中使用 OpenAI、Anthropic 或其他云端 API。
  • 需要服务器端的身份验证、日志记录或限流。
  • 你的应用已经因其他原因使用了 Vercel AI SDK。

开始构建

步骤 1 – 安装库

npm install use-local-llm

步骤 2 – 启动本地 LLM

ollama serve

步骤 3 – 在你的 React 应用中流式传输 AI

(请参见上面的示例。)

完成。无需 API 路由。无需服务器配置。AI 在浏览器中流式传输,耗时不到 2 分钟。

Learn More

0 浏览
Back to Blog

相关文章

阅读更多 »