开发者教案 · Developer Lesson

LM Studio 本地 LLM
API 与 SDK 全景图

把你的电脑变成一台私有的推理服务器。本教案系统梳理 LM Studio 官方开发者文档:从启动本地服务、REST API、OpenAI / Anthropic 兼容端点,到工具调用、结构化输出与 MCP 集成。

目标读者 · 全栈 / Agent 开发者 本地端口 · localhost:1234 三种 SDK · REST / Python / TypeScript 来源 · lmstudio.ai/docs/developer
01

总览:你能用 LM Studio 搭什么

LM Studio 把本地下载的开源模型(GGUF / MLX)包装成一个跑在 localhost 上的推理服务器。任何能发 HTTP 请求的代码——或现成的 OpenAI / Anthropic 客户端——都能直接连上它,无需把数据发往云端。

核心能力地图

Chat
对话与文本生成

支持 token 流式输出,构建本地聊天应用与生成流程。

Agents
工具调用 + MCP

连接函数、MCP 服务器,完全在本机运行 Agent 工作流。

JSON
结构化输出

用 JSON Schema 强约束模型输出,生成可校验的类型化结果。

Vectors
嵌入与分词

生成 embeddings、检查 token,搭建检索 / 索引管线。

Models
模型管理

加载、下载、列出模型,掌控内存中可用的实例。

四种接入方式(同一个服务器,多种"门面")

接入方式适用场景标识
LM Studio REST API原生能力:有状态对话、模型管理、MCP,附带丰富统计信息/api/v1/*
OpenAI 兼容端点复用现有 OpenAI 客户端,仅改 base URL 即可迁移/v1/*
Anthropic 兼容端点复用 Claude 风格 Messages API 流程/v1/messages
官方 SDKlmstudio-js(TS)与 lmstudio-pythonnpm / pip
💡

教学要点:这四种方式访问的是同一个本地服务器。REST API 是"原生方言"(功能最全),OpenAI / Anthropic 端点是"兼容方言"(迁移最省事)。先理解这一点,后面所有章节就串起来了。

02

第一步:启动本地服务器

所有 API 调用的前提,是先让 LM Studio 的服务器跑起来。两种方式任选其一。

方式 A · 图形界面

打开 LM Studio,进入左侧的 Developer(开发者) 标签页,把左上角的 "Start server" 开关打开即可。

方式 B · 命令行 CLI(lms)

terminalbash
# 启动服务器(默认端口 1234)
lms server start

# 也可以指定端口
lms server start --port 1234

启动后,服务默认监听 http://localhost:1234

📦

如果还没装 lms CLI,运行 npx lmstudio install-cli 安装。如果还没下载模型,可用 lms get ibm/granite-4-micro 拉取一个轻量模型来练手。

03

三分钟快速上手

同一个"自我介绍"请求,用三种语言各写一遍。感受不同接入方式的形态差异。

TypeScript · lmstudio-js

install & runtypescript
// npm install @lmstudio/sdk
import { LMStudioClient } from "@lmstudio/sdk";

const client = new LMStudioClient();
const model  = await client.llm.model("openai/gpt-oss-20b");
const result = await model.respond("Who are you, and what can you do?");

console.info(result.content);

Python · lmstudio-python

install & runpython
# pip install lmstudio
import lmstudio as lms

with lms.Client() as client:
    model  = client.llm.model("openai/gpt-oss-20b")
    result = model.respond("Who are you, and what can you do?")
    print(result)

HTTP · LM Studio REST API

curlbash
curl http://localhost:1234/api/v1/chat \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -d '{
    "model": "openai/gpt-oss-20b",
    "input": "Who are you, and what can you do?"
  }'
🎯

观察:三种方式都只需要 model + 一句话输入。REST 的字段叫 input(注意不是 OpenAI 的 messages),这是 LM Studio 原生 API 的特征。

04

身份认证:API Token

默认情况下,本地服务器不要求认证——因为它只监听本机。但你可以开启 Token 认证以增强安全性(尤其是要在局域网内共享,或使用本地 MCP 插件时)。

📌

API Token 功能需要 LM Studio 0.4.0 或更新版本

  1. 开启认证开关

    进入 Developer 页 → Server Settings,打开 "Require authentication" 开关。开启后,所有经 REST / Python SDK / TypeScript SDK 的请求都必须带有效 Token。

  2. 创建 Token

    点击 Manage Tokens → Create Token,给它起个名字并选择权限。创建后立即复制保存——令牌只会显示这一次。

  3. 配置权限

    在 Token 列表里点 Edit 可随时修改名称与权限范围(可创建多个不同权限的 Token)。

  4. 在请求中携带

    把 Token 放进 HTTP 头:Authorization: Bearer $LM_API_TOKEN

带 Token 的请求bash
curl -X POST http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "model": "ibm/granite-4-micro", "input": "Open lmstudio.ai" }'
⚠️

注意:使用本地配置的 MCP 插件(来自 mcp.json)时,必须通过 Authorization 头进行 Token 认证。

05

REST API 核心:有状态对话

LM Studio 的 /api/v1/chat 端点默认是有状态的。这意味着你不必在每次请求里重发整段历史——服务器会自动存储并管理上下文。这是它区别于无状态 OpenAI 接口的关键设计。

工作机制

发送对话请求时,LM Studio 把会话存进一个 chat thread,并在响应里返回一个 response_id。在后续请求里带上它,对话即可延续。

第 1 轮请求input: "My favorite color is blue."
服务器返回response_id: resp_abc123…
第 2 轮请求带上 previous_response_id
input: "What color did I mention?"
模型记得上文"Blue." + 新的 response_id

开启新对话

新会话bash
curl http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ibm/granite-4-micro",
    "input": "My favorite color is blue."
  }'
响应json
{
  "model_instance_id": "ibm/granite-4-micro",
  "output": [
    { "type": "message", "content": "That's great! Blue is a beautiful color…" }
  ],
  "response_id": "resp_abc123xyz…"
}

延续对话

延续会话bash
curl http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ibm/granite-4-micro",
    "input": "What color did I just mention?",
    "previous_response_id": "resp_abc123xyz…"
  }'

关闭存储(无状态模式)

不想存对话?把 store 设为 false,响应就不会带 response_id。适合一次性请求。

无状态bash
curl http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "model": "ibm/granite-4-micro", "input": "Tell me a joke.", "store": false }'
🌿

进阶:每个 response_id 都是会话中一个唯一的"锚点"。指向不同的历史 response_id,就能从该点分叉(branch)出不同的对话支线。

06

chat 端点字段详解

POST /api/v1/chat —— 这是 REST API 的主力端点。下面拆解它的请求体和响应结构。

常用请求字段

字段类型说明
modelstring模型唯一标识。若未加载会自动加载
inputstring | array发给模型的消息,可为纯文本,也可为含 text / image 的对象数组
system_promptstring设定模型行为的系统消息
integrationsarray本次请求启用的集成(插件、临时 MCP 服务器等)
streamboolean是否经 SSE 流式输出,默认 false
temperaturenumber随机性 [0,1],0 为确定性输出
top_p / top_k / min_pnumber采样控制参数
repeat_penaltynumber重复惩罚,1 为不惩罚
max_output_tokensinteger最大生成 token 数
reasoningenumoff|low|medium|high|on,需模型支持
context_lengthinteger上下文 token 数。使用 MCP 时建议调大
storeboolean是否存储会话,默认 true
previous_response_idstring要续接的响应 ID,须以 resp_ 开头

响应里的 output 数组

响应的 output 是一个数组,每个元素可能是以下几种类型之一——这让你能完整还原模型的"思考—调用工具—回答"全过程:

type含义
message模型的文本消息
tool_call模型发起的工具调用(含 tool 名、arguments、output、provider_info)
reasoning模型的推理内容
invalid_tool_call无效工具调用(工具名错误或参数错误)

stats:性能与用量统计

每次响应都附带一个 stats 对象,这是 LM Studio REST API 相比兼容端点的一大优势:

stats 示例json
"stats": {
  "input_tokens": 646,
  "total_output_tokens": 586,
  "reasoning_output_tokens": 0,
  "tokens_per_second": 29.75,            // 生成速度
  "time_to_first_token_seconds": 1.088,    // 首 token 延迟 (TTFT)
  "model_load_time_seconds": 2.656          // 仅当本次需加载模型时出现
}

多模态:发送图片

input 写成对象数组,加入 type: "image" 项,用 base64 data URL 传图:

图像输入结构json
"input": [
  { "type": "message", "content": "What's in this image?" },
  { "type": "image",   "data_url": "data:image/jpeg;base64,…" }
]
07

OpenAI 兼容端点:零成本迁移

如果你已经有用 OpenAI SDK 写的代码,迁移到本地只需要改一行——把 base_url 指向 LM Studio。其余代码原封不动。

支持的端点

端点方法用途
/v1/modelsGET列出模型
/v1/responsesPOSTResponses API(支持 Codex)
/v1/chat/completionsPOSTChat Completions(主力)
/v1/embeddingsPOST生成嵌入向量
/v1/completionsPOST文本补全(Legacy)

Python:只改 base_url

openai 客户端python
from openai import OpenAI

client = OpenAI(
    base_url="http://localhost:1234/v1",   # 唯一改动
    api_key="lm-studio"                      # 任意占位符即可
)
# …其余代码与调用 OpenAI 完全相同…

cURL:把域名一换

diffbash
- curl https://api.openai.com/v1/chat/completions \
+ curl http://localhost:1234/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{
      "model": "在此填入 LM Studio 的模型标识",
      "messages": [{"role": "user", "content": "Say this is a test!"}],
      "temperature": 0.7
   }'
🔌

Codex 支持:因为 LM Studio 实现了 OpenAI 风格的 POST /v1/responses 端点,所以 Codex 可以直接接上本地模型工作。

🅰️

另有 Anthropic 兼容:除 OpenAI 外,LM Studio 还提供 Anthropic 兼容的 Messages 端点,让 Claude 风格的请求流程也能直接打到本地服务器。

08

结构化输出:用 Schema 锁死格式

通过给 /v1/chat/completions 传一份 JSON Schema,可强制模型输出符合该 schema 的合法 JSON。格式与 OpenAI 的 Structured Output API 一致,因此 OpenAI SDK 可直接复用。

Python 示例:生成虚构角色

structured-output.pypython
from openai import OpenAI
import json

client = OpenAI(base_url="http://localhost:1234/v1", api_key="lm-studio")

character_schema = {
    "type": "json_schema",
    "json_schema": {
        "name": "characters",
        "schema": {
            "type": "object",
            "properties": {
                "characters": {
                    "type": "array",
                    "items": {
                        "type": "object",
                        "properties": {
                            "name":        {"type": "string"},
                            "occupation":  {"type": "string"},
                            "personality": {"type": "string"},
                            "background":  {"type": "string"}
                        },
                        "required": ["name","occupation","personality","background"]
                    },
                    "minItems": 1
                }
            },
            "required": ["characters"]
        }
    }
}

response = client.chat.completions.create(
    model="your-model",
    messages=[{"role":"user","content":"Create 1-3 fictional characters"}],
    response_format=character_schema,
)

# content 是 JSON 字符串,需要自行解析
results = json.loads(response.choices[0].message.content)
print(json.dumps(results, indent=2))
⚠️

重要:并非所有模型都支持结构化输出,尤其是 7B 参数以下的小模型。不确定时请查看模型卡片 README。返回结果在 choices[0].message.content 中以字符串形式给出,需自行 parse 成 JSON 对象。

底层引擎

  • GGUF 模型:使用 llama.cpp 基于语法(grammar)的采样 API。
  • MLX 模型:使用 Outlines 实现(开源于 lmstudio-ai/mlx-engine)。
09

工具调用 Tool Use:让模型行动起来

工具调用让 LLM 能"请求"调用外部函数与 API。务必记住一句话:模型本身不能执行任何代码,它只能输出文本——由你的代码解析这段文本、执行函数、再把结果喂回模型。

什么是工具调用?三步循环

  1. LLM 输出文本,请求调用某个函数;
  2. 你的代码真正执行这个函数;
  3. 你的代码把执行结果反馈回 LLM,由它生成最终回答。

完整流程图

SETUP提供 LLM + 工具列表
获取用户输入
用 messages 提示 LLM
↓ 需要工具吗?
YES解析工具调用 → 执行 → 把结果加入 messages
NO直接正常回答用户
↺ 带着工具结果再次提示模型(这次不再给工具)

工具定义长什么样

工具以函数定义数组的形式放进请求体的 tools 字段,格式与 OpenAI Function Calling 一致:

tools 定义json
[
  {
    "type": "function",
    "function": {
      "name": "get_delivery_date",
      "description": "Get the delivery date for a customer's order",
      "parameters": {
        "type": "object",
        "properties": { "order_id": { "type": "string" } },
        "required": ["order_id"]
      }
    }
  }
]

这个列表会按模型的 chat template 被注入到 system prompt 里。当模型决定调用工具时,LM Studio 会把它解析进响应的 choices[0].message.tool_calls,并把 finish_reason 设为 "tool_calls"

多轮示例:核心模式

multi-turn-example.py(节选)python
# 1) 第一次调用,带上 tools
response = client.chat.completions.create(model=model, messages=messages, tools=tools)

# 2) 解析模型请求的工具调用,执行真实函数
tool_call = response.choices[0].message.tool_calls[0]
arguments = json.loads(tool_call.function.arguments)
delivery_date = get_delivery_date(arguments["order_id"])

# 3) 把"助手的工具调用"和"工具结果"都追加进 messages
messages.append({"role":"assistant", "tool_calls":[…]})
messages.append({
    "role": "tool",
    "content": json.dumps({"delivery_date": delivery_date}),
    "tool_call_id": tool_call.id
})

# 4) 再次调用(这次不带 tools),拿到自然语言最终回答
final = client.chat.completions.create(model=model, messages=messages)
print(final.choices[0].message.content)
# → "Your order #1017 is scheduled for delivery on November 19, 2024…"

原生 vs. 默认 支持

在 LM Studio 中,所有模型都至少支持某种程度的工具调用,但分两个级别:

Native 原生
带 🔨 锤子徽章

模型本身经过工具调用训练(chat template 支持),且 LM Studio 支持其工具格式。表现更好。例:Qwen、Llama-3.1/3.2、Mistral。

Default 默认
兜底方案

模型未经训练或 LM Studio 暂不支持其格式时,用自定义 system prompt 与默认调用格式兜底,并将 tool 角色消息转为 user 角色。效果因模型而异。

🔍

排错技巧:运行 lms log stream 查看实时日志,就能看到工具列表是如何被注入 prompt、以及模型输出的原始格式。如果小模型输出格式不正确,LM Studio 就无法解析出 tool_calls——这是定位问题的好线索。

流式工具调用

stream=true 时,工具调用会分块(chunk)传来:函数名与参数分散在多个 chunk.choices[0].delta.tool_calls 里,需要你累加拼接成完整的函数签名后再执行。

10

MCP 集成:把外部能力插进对话

/api/v1/chatintegrations 字段里,可以让模型直接与 MCP(Model Context Protocol)服务器交互。有两种接法。

① 临时 MCP 服务器(ephemeral_mcp)

无需预先配置,直接在请求里"即用即定义"一个远程 MCP 服务器:

ephemeral MCPbash
curl http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ibm/granite-4-micro",
    "input": "What is the top trending model on hugging face?",
    "integrations": [
      {
        "type": "ephemeral_mcp",
        "server_label": "huggingface",
        "server_url": "https://huggingface.co/mcp",
        "allowed_tools": ["model_search"]
      }
    ],
    "context_length": 8000
  }'

② 本地插件(plugin,来自 mcp.json)

引用你已在 mcp.json 里配置好的 MCP 插件,ID 形如 mcp/<server_label>。例如 Playwright 浏览器自动化:

local pluginbash
curl http://localhost:1234/api/v1/chat \
  -H "Authorization: Bearer $LM_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ibm/granite-4-micro",
    "input": "Open lmstudio.ai",
    "integrations": [
      { "type": "plugin", "id": "mcp/playwright", "allowed_tools": ["browser_navigate"] }
    ],
    "context_length": 8000
  }'
integration 类型关键字段认证要求
ephemeral_mcpserver_label · server_url · allowed_tools · headers远程,按需
pluginid(如 mcp/playwright)· allowed_tools必须用 Token 认证
🧰

组合使用:一个请求里可以同时挂多个 integration——比如一边用 HuggingFace MCP 搜模型、一边用 Playwright 插件打开网页。allowed_tools 用来收窄模型可调用的工具范围,不填则允许该服务器的全部工具。MCP 场景建议把 context_length 调大。

11

headless 部署:服务器 / CI 上跑 llmster

llmster 是 LM Studio 的核心打包成的守护进程(daemon),可在服务器、云实例或 CI 上独立运行,不依赖图形界面

安装

Mac / Linuxbash
curl -fsSL https://lmstudio.ai/install.sh | bash
Windows (PowerShell)powershell
irm https://lmstudio.ai/install.ps1 | iex

基本用法

lms 常用命令bash
lms daemon up          # 启动守护进程
lms get <model>        # 下载模型
lms server start       # 启动本地服务器
lms chat               # 打开交互式会话
lms load               # 加载一个模型进内存
lms log stream         # 查看实时日志(排错神器)
🖥️

官方文档另有专题介绍如何用 systemctl 把 llmster 设为 Linux 开机自启任务,以及 Idle TTL(空闲自动卸载)与 Auto-Evict 等内存管理特性,适合长期运行的服务部署。

12

速查表 & 教学小结

端点速查

端点方法说明
/api/v1/chatPOST原生对话,有状态,支持 MCP
/api/v1/modelsGET列出你的模型(含 LLM 与嵌入模型)
/api/v1/models/loadPOST加载模型
/api/v1/models/downloadPOST下载模型(返回 job_id)
/api/v1/models/download/status/{job_id}GET查询下载进度
/api/v1/models/unloadPOST卸载模型
/v1/chat/completionsPOSTOpenAI 兼容 · 工具调用 / 结构化输出主力
/v1/responsesPOSTOpenAI 兼容 · Responses(Codex)
/v1/embeddingsPOSTOpenAI 兼容 · 嵌入
/v1/messagesPOSTAnthropic 兼容 · Messages

三条核心心法

心法 ①
一个服务器,多种方言

REST 功能最全且有状态;OpenAI / Anthropic 端点为兼容迁移而生。按需选门面。

心法 ②
模型只会说话,不会做事

工具调用的本质是"模型请求 → 你执行 → 喂回结果"的循环。代码是真正的行动者。

心法 ③
本地优先,数据不出门

认证、MCP、headless 部署共同支撑一个完全私有、可上生产的本地推理栈。

给学习者的实践路线

  1. 跑通第一个请求

    lms server startlms get ibm/granite-4-micro → 用 curl 发一句 chat。

  2. 体会有状态对话

    连续两轮,用 previous_response_id 让模型"记住"你说过的话。

  3. 迁移一个 OpenAI 脚本

    把现有 OpenAI 代码的 base_url 改成本地,验证零改动迁移。

  4. 实现一次工具调用

    照着多轮示例,让模型调用你写的本地函数并拿回最终自然语言回答。

  5. 挂一个 MCP

    ephemeral_mcp 接 HuggingFace,或本地 Playwright 插件做浏览器自动化。

📚

延伸阅读(官方):Streaming events(SSE 流式事件)、Embeddings、Idle TTL & Auto-Evict、Serve on Local Network、API Changelog、以及 lmstudio-js / lmstudio-python 两套 SDK 的完整文档。