深度解析 simonw/llm 项目------12.2k Star、63 个版本迭代、50+ 插件生态,如何成为终端 AI 工具的事实标准。
项目概览
LLM 是由 Django 联合创始人、知名开源开发者 Simon Willison 创建的命令行工具和 Python 库,用于统一访问 OpenAI、Anthropic Claude、Google Gemini、Meta Llama 等数十种大语言模型。它不仅支持远程 API 调用,还支持通过插件在本地运行模型。
关键数据:
| 指标 | 数值 |
|---|---|
| GitHub Stars | 12,200+ |
| 最新版本 | 0.31(2026-04-24) |
| 累计发布版本 | 63 |
| 官方+社区插件 | 50+ |
| 支持模型数量 | 100+(含插件) |
| 代码语言 | Python 99.8% |
| 许可证 | Apache 2.0 |
核心设计理念
Unix 哲学在 AI 时代的回归
LLM 的设计根植于 Unix 哲学------做一件事并做好。它将"与语言模型交互"这个行为,抽象为一条可以在终端执行的命令:
bash
llm "Ten fun names for a pet pelican"
这行代码的背后是一个精心设计的统一抽象层。用户无需关心底层是 GPT-4o 还是 Claude 4 Opus,无需记忆不同的 API 签名和认证方式,只需要知道模型的名称。
微内核 + 插件架构
LLM 采用了类似操作系统微内核的设计------核心只负责命令行解析、密钥管理、SQLite 日志和插件加载,所有模型的具体实现都通过插件完成:
┌─────────────────────────────────────┐
│ LLM Core │
│ ┌──────────┐ ┌──────────────────┐ │
│ │ CLI 解析 │ │ 密钥管理 │ │
│ └──────────┘ └──────────────────┘ │
│ ┌──────────┐ ┌──────────────────┐ │
│ │SQLite 日志│ │ 插件加载器 │ │
│ └──────────┘ └──────────────────┘ │
└─────────────┬───────────────────────┘
│
┌─────────┼─────────┐
▼ ▼ ▼
┌────────┐┌────────┐┌────────┐
│llm- ││llm- ││llm- │
│openai ││anthropic││ollama │
└────────┘└────────┘└────────┘
这种架构带来了三个关键优势:
- 核心精简:基础安装只包含 OpenAI 模型支持,不引入不必要的依赖
- 按需扩展 :需要 Claude?
llm install llm-anthropic。需要本地模型?llm install llm-ollama - 社区驱动:任何人都可以编写插件来支持新的模型提供商
安装与快速上手
安装
支持多种安装方式,覆盖不同用户偏好:
bash
# pip
pip install llm
# Homebrew(macOS/Linux)
brew install llm
# pipx(隔离环境安装)
pipx install llm
# uv(Rust 实现的快速包管理器)
uv tool install llm
30 秒上手
bash
# 1. 设置 OpenAI API Key
llm keys set openai
# 粘贴你的 API Key
# 2. 执行一个提示词(默认使用 gpt-4o-mini)
llm "Ten fun names for a pet pelican"
# 3. 从图像中提取文本
llm "extract text" -a scanned-document.jpg
# 4. 用系统提示分析代码
cat myfile.py | llm -s "Explain this code"
# 5. 启动交互式聊天
llm chat -m gpt-4.1
接入其他模型
bash
# Google Gemini
llm install llm-gemini
llm keys set gemini
llm -m gemini-2.0-flash 'Tell me fun facts about Mountain View'
# Anthropic Claude
llm install llm-anthropic
llm keys set anthropic
llm -m claude-4-opus 'Impress me with wild facts about turnips'
# 本地模型(Ollama)
llm install llm-ollama
ollama pull llama3.2:latest
llm -m llama3.2:latest 'What is the capital of France?'
核心功能深度解析
1. 提示词执行与管道
LLM 最基础的能力是在命令行执行提示词,但它远不止于此。它天然适配 Unix 管道:
bash
# 将文件内容作为提示词输入
cat README.md | llm -s "Summarize this in 3 bullet points"
# 提取代码块
llm -x 'Python function to reverse a string'
# -x 参数自动提取响应中第一个 fenced code block
# 继续上一次对话
llm -c "Now do it in JavaScript"
# 使用模糊搜索指定模型(不需要记完整 ID)
llm -q gpt -q 4o "your prompt"
-x(--extract)和 --xl(--extract-last)参数是 LLM 的一个巧妙设计------在终端场景下,你往往只关心代码本身而非模型的解释文字,这两个参数直接提取响应中的代码块,省去了手动复制。
2. 模板系统:可复用的提示词
模板允许你保存和复用提示词配置,包括系统提示、模型选择、参数和工具:
bash
# 创建一个模板
llm -s "Translate to French" -m gpt-4.1-mini --save translate-fr
# 使用模板
llm -t translate-fr "Hello, how are you?"
# 模板支持变量
llm -s "Translate to $language" --save translate
llm -t translate -p language Spanish "Hello"
模板以 YAML 文件存储,结构清晰:
yaml
system: Translate to {$language}
model: gpt-4.1-mini
options:
temperature: 0.3
更强大的是,模板可以绑定工具和 Schema(下文详述),这意味着你可以创建"一键执行"的复杂工作流。
GitHub 模板共享 :通过 llm-templates-github 插件,你可以直接使用他人在 GitHub 上分享的模板:
bash
llm install llm-templates-github
llm -t gh:simonw/pelican-svg -m o3-mini
3. Fragments:长上下文组装器
Fragments 是 0.24 版本引入的关键特性,解决了长上下文场景下的提示词组装问题。它允许你从多个来源(URL、文件路径、数据库记录)组装一个长提示词,并且这些内容会在 SQLite 中去重存储:
bash
# 从 URL 加载内容作为上下文
llm -f https://llm.datasette.io/robots.txt 'explain this file'
# 组合多个来源
llm -f paper.pdf -f notes.md 'Compare these documents'
# 在聊天中使用
llm chat -f codebase/ 'Ask questions about this code'
Fragments 的真正威力在于插件生态。通过 register_fragment_loaders() 插件钩子,社区已经构建了丰富的片段加载器:
| 插件 | 用途 | 示例 |
|---|---|---|
| llm-video-frames | 视频转帧序列 | llm -f video-frames:video.mp4 |
| llm-fragments-github | 加载整个 GitHub 仓库 | llm -f github:simonw/files-to-prompt |
| llm-hacker-news | 导入 HN 对话 | llm -f hn:43615912 |
| llm-fragments-pypi | 加载 PyPI 包信息 | llm -f pypi:ruff |
| llm-fragments-pdf | PDF 转 Markdown | llm -f pdf:paper.pdf |
4. Schemas:结构化数据提取
0.23 版本引入的 Schema 功能是 LLM 最具实用价值的特性之一。它让大语言模型输出符合 JSON Schema 的结构化数据,而不是自由文本:
bash
# 使用简洁的 Schema DSL
llm --schema 'name, age int, bio' 'Describe a nice dog'
# 从新闻中提取人物
llm --schema 'name, title, organization, role' 'Extract people from this article' \
-f news-article.txt
# 生成数组
llm --schema 'name, age int, bio' --schema-multi 'Describe 3 nice dogs'
在 Python API 中,Schema 可以使用 Pydantic 模型:
python
import llm
from pydantic import BaseModel
class Dog(BaseModel):
name: str
age: int
model = llm.get_model("gpt-4o-mini")
response = model.prompt("Describe a nice dog", schema=Dog)
# 输出:{"name": "Buddy", "age": 3}
这把 LLM 从"聊天工具"提升为"数据处理管道"------你可以用它从非结构化文本中批量提取结构化数据,然后存入数据库、生成报表或触发下游工作流。
5. Tools:让模型调用外部工具
0.26 版本引入的 Tool 支持是 LLM 的一次重大进化。模型现在可以调用 Python 函数来完成它自身无法完成的任务:
命令行使用:
bash
# 内联定义工具
llm --functions '
def multiply(x: int, y: int) -> int:
"""Multiply two numbers."""
return x * y
' 'what is 34234 * 213345'
# 使用插件注册的工具
llm -T simple_eval 'What is 2^20?'
Python API------更强大的用法:
python
import llm
def multiply(x: int, y: int) -> int:
"""Multiply two numbers."""
return x * y
model = llm.get_model("gpt-4.1-mini")
# chain() 方法自动处理多轮工具调用
response = model.chain(
"What is 34234 * 213345?",
tools=[multiply],
)
print(response.text())
Toolbox 类------有状态的工具集合:
python
import llm
class Memory(llm.Toolbox):
_memory = None
def _get_memory(self):
if self._memory is None:
self._memory = {}
return self._memory
def set(self, key: str, value: str):
"Set something as a key"
self._get_memory()[key] = value
def get(self, key: str):
"Get something from a key"
return self._get_memory().get(key) or ""
model = llm.get_model("gpt-4.1-mini")
memory = Memory()
conversation = model.conversation(tools=[memory])
# 模型可以在多轮对话中使用 Memory 工具
print(conversation.chain("Set name to Simon").text())
print(conversation.chain("What is my name?").text())
工具调试钩子------对开发者至关重要的功能:
python
def before_call(tool, tool_call):
print(f"About to call {tool.name} with {tool_call.arguments}")
def after_call(tool, tool_call, tool_result):
print(f"{tool.name} returned {tool_result.output}")
response = model.chain(
"Complex question requiring tools",
tools=[multiply, search],
before_call=before_call,
after_call=after_call,
)
社区已构建了丰富的工具插件:
| 插件 | 功能 |
|---|---|
| llm-tools-simpleeval | 数学表达式计算 |
| llm-tools-quickjs | 沙箱化 JavaScript 执行 |
| llm-tools-sqlite | 只读 SQL 查询 |
| llm-tools-datasette | 查询远程 Datasette |
| llm-tools-exa | 网络搜索 |
| llm-tools-rag | 嵌入集合检索 |
6. Embeddings:向量嵌入与语义搜索
LLM 不仅是语言模型的客户端,还是一个完整的嵌入管理工具:
bash
# 生成单个嵌入
llm embed -m text-embedding-3-small -c "Hello world"
# 批量嵌入文件内容
llm embed-multi docs -m text-embedding-3-small \
--files docs/ '*.md' --store
# 语义相似度搜索
llm similar docs -c "machine learning"
Python API 同等强大:
python
import llm
model = llm.get_embedding_model("text-embedding-3-small")
# 生成嵌入向量
vector = model.embed("Hello world")
# 使用 Collection 进行批量管理
collection = llm.Collection("docs", model)
collection.embed("doc1", "Content of document 1")
collection.embed("doc2", "Content of document 2")
# 语义搜索
results = collection.similar("machine learning")
嵌入数据存储在 SQLite 中,配合 llm-sentence-transformers、llm-clip、llm-embed-jina 等插件,可以在本地构建完整的语义搜索系统。
7. SQLite 日志:完整的对话审计
LLM 默认将所有提示词和响应记录到本地 SQLite 数据库,这是一个被低估但极为重要的设计决策:
bash
# 查看最近的日志
llm logs
# 按模型过滤
llm logs -m gpt-4o
# 搜索日志
llm logs -q "pelican"
# 查看特定对话
llm logs --cid CONVERSATION_ID
# 导出 Schema 收集的结构化数据
llm logs --data --data-key name
# 查看 Token 使用量
llm logs -u
这个设计带来了几个重要的好处:
- 可审计性:每次 AI 调用都有记录,方便回顾和追溯
- 可分析性:可以统计不同模型的使用频率和 Token 消耗
- 可复现性:对话历史完整保存,可以随时回溯
- 与 Datasette 集成:通过 Datasette 可以在浏览器中可视化浏览所有日志
8. 多模态支持
从 0.17 版本开始,LLM 支持图片、音频、视频等多模态输入:
bash
# 图片(URL 或文件)
llm -m gpt-4o "describe this image" \
-a https://example.com/photo.jpg
llm -m gpt-4o-mini "extract text" -a scanned-document.jpg
# 多个附件
llm -m gpt-4o "compare these images" -a img1.jpg -a img2.jpg
# PDF
llm -m gpt-4o "summarize this document" -a report.pdf
Python API 同样支持:
python
model = llm.get_model("gpt-4o")
response = model.prompt(
"Describe these images",
attachments=[
llm.Attachment(path="pelican.jpg"),
llm.Attachment(url="https://example.com/photo.jpg"),
]
)
插件系统详解
插件钩子(Plugin Hooks)
LLM 的插件系统提供了六个核心钩子,覆盖了所有扩展场景:
| 钩子 | 用途 | 引入版本 |
|---|---|---|
register_commands(cli) |
添加新的 CLI 命令 | 早期 |
register_models(register) |
注册新的语言模型 | 早期 |
register_embedding_models(register) |
注册嵌入模型 | 早期 |
register_tools(register) |
注册工具函数 | 0.26 |
register_template_loaders(register) |
注册模板加载器 | 0.24 |
register_fragment_loaders(register) |
注册片段加载器 | 0.24 |
插件生态全景
本地模型插件:
| 插件 | 运行框架 | 平台 |
|---|---|---|
| llm-gguf | llama.cpp | 跨平台 |
| llm-mlx | Apple MLX | macOS |
| llm-ollama | Ollama | 跨平台 |
| llm-llamafile | llamafile | 跨平台 |
| llm-gpt4all | GPT4All | 跨平台 |
远程 API 插件:
覆盖了几乎所有主流模型提供商:Mistral、Gemini、Anthropic、Cohere、Perplexity、Groq、Fireworks、Together AI、DeepSeek、OpenRouter、Bedrock、xAI Grok 等。
如果某个 API 提供商兼容 OpenAI 接口格式,甚至不需要安装插件------只需在 extra-openai-models.yaml 中配置即可。
编写自己的插件:
LLM 的插件开发体验经过了精心打磨。以一个 Markov 链模型插件为例:
python
from llm import Model, register
class MarkovModel(Model):
model_id = "markov"
def execute(self, prompt, stream, response, conversation):
# 实现 execute 方法
text = build_markov_chain(prompt.prompt)
yield text
def register_models(register):
register(MarkovModel())
安装和测试:
bash
llm install -e .
llm -m markov "some input text"
Python API:超越 CLI 的编程接口
LLM 不仅是 CLI 工具,还是一个完整的 Python 库。这意味着你可以将其集成到任何 Python 应用中:
基础用法
python
import llm
# 获取模型
model = llm.get_model("gpt-4o-mini")
# 执行提示词(懒加载,直到调用 .text() 才真正执行)
response = model.prompt("Five surprising names for a pet pelican")
print(response.text())
# 流式输出
response = model.prompt("A poem about coding")
for chunk in response:
print(chunk, end="", flush=True)
异步支持
python
import llm
model = llm.get_async_model("gpt-4o")
# 异步执行
print(await model.prompt("Hello").text())
# 异步流式输出
async for chunk in model.prompt("Tell me a story"):
print(chunk, end="", flush=True)
对话管理
python
import llm
model = llm.get_model("gpt-4.1-mini")
conversation = model.conversation()
response1 = conversation.prompt("My name is Alice")
print(response1.text())
response2 = conversation.prompt("What is my name?")
# 模型知道你叫 Alice
print(response2.text())
Token 追踪与回调
python
import llm
model = llm.get_model("gpt-4o-mini")
response = model.prompt("A poem about a hippo")
# 注册完成回调(可以用于追踪 Token 使用量)
response.on_done(lambda r: print(r.usage()))
print(response.text())
# 输出:
# Usage(input=20, output=494, details={})
版本演进与关键里程碑
LLM 的版本迭代非常活跃,每个版本都引入了实质性功能:
| 版本 | 日期 | 核心特性 |
|---|---|---|
| 0.31 | 2026-04-24 | GPT-5.5 支持,文本详细度控制 |
| 0.30 | 2026-03-31 | 插件钩子增强,文档改进 |
| 0.29 | 2026-03-17 | GPT-5.4 系列模型 |
| 0.28 | 2025-12-12 | GPT-5.1/5.2,Python 3.10+ 要求 |
| 0.27 | 2025-08-11 | GPT-5 系列支持,模板可绑定工具 |
| 0.26 | 2025-05-27 | Tool 支持------里程碑版本 |
| 0.25 | 2025-05-04 | Fragment loader 支持附件,gpt-4.1/o3/o4-mini |
| 0.24 | 2025-04-07 | Fragments 与模板加载器------长上下文支持 |
| 0.23 | 2025-02-28 | Schema 支持------结构化数据提取 |
| 0.22 | 2025-02-16 | KeyModel/AsyncKeyModel,llm-mlx 插件 |
| 0.20 | 2025-01-22 | o1 模型,-x 代码块提取 |
| 0.19 | 2024-12-01 | Token 使用量追踪与日志 |
| 0.18 | 2024-11-17 | 异步模型支持 |
| 0.17 | 2024-10-29 | 多模态附件------图片/音频/视频 |
| 0.16 | 2024-09-12 | OpenAI 模型使用内部 key 机制 |
| 0.15 | 2024-07-18 | gpt-4o-mini 成为默认模型 |
| 0.14 | 2024-05-13 | GPT-4o 支持 |
从演进路线可以看出,LLM 的功能拓展遵循了一条清晰的路径:基础调用 → 模型覆盖 → 数据持久化 → 多模态 → 异步 → 结构化输出 → 工具调用 → 长上下文。每一步都建立在之前的基础上,形成了有机的功能体系。
设计亮点与工程思考
1. SQLite 作为一等公民
LLM 对 SQLite 的使用是一个值得学习的工程决策。SQLite 不需要服务器进程,数据就在用户本地的 logs.db 文件中。这意味着:
- 零运维成本------不需要安装和配置数据库
- 便携性------整个对话历史就是一个文件
- 可查询------用 SQL 查询你的 AI 使用记录
- 与 Datasette 天然集成------在浏览器中浏览和分析
2. 懒加载的响应设计
Python API 中的 Response 对象采用懒加载设计------调用 model.prompt() 不会立即执行请求,只有在调用 response.text() 时才真正触发。这个设计让流式输出和回调注册变得自然:
python
response = model.prompt("A poem")
response.on_done(lambda r: save_to_db(r)) # 注册回调
print(response.text()) # 执行请求 + 流式输出 + 触发回调
3. API Key 的多层管理
LLM 提供了三种 API Key 管理方式,覆盖不同安全需求:
llm keys set openai------加密存储到keys.json(文件权限 600)- 环境变量
OPENAI_API_KEY------CI/CD 和容器化场景 key=参数------Python API 编程场景
4. OpenAI 兼容模型的零插件接入
很多模型提供商(如 DeepSeek、vLLM、LocalAI)提供 OpenAI 兼容的 API。LLM 允许通过 extra-openai-models.yaml 配置这些模型,无需编写任何代码:
yaml
- model_id: deepseek-chat
model_name: deepseek-chat
api_base: "https://api.deepseek.com/v1"
api_key_name: deepseek
can_stream: true
vision: true
supports_schema: true
5. 对 Prompt Injection 的坦诚
与许多 AI 工具不同,LLM 在文档中明确警告了 Tool 使用场景下的 Prompt Injection 风险。这种坦诚的态度对于建立用户信任至关重要。
实战场景
场景一:代码审查管道
bash
# 在 CI/CD 中自动审查代码变更
git diff main | llm -s "Review this code change. Focus on:
1. Security vulnerabilities
2. Performance issues
3. Code style problems
Output as bullet points." -m gpt-4.1-mini
场景二:文档批量提取结构化数据
python
import llm, json, glob
model = llm.get_model("gpt-4.1-mini")
for file in glob.glob("contracts/*.txt"):
with open(file) as f:
content = f.read()
response = model.prompt(
f"Extract contract details from:\n{content}",
schema=llm.schema_dsl(
"party_a, party_b, value float, start_date, end_date, contract_type"
)
)
data = json.loads(response.text())
print(json.dumps(data, indent=2))
场景三:构建语义搜索系统
bash
# 1. 批量嵌入文档
llm embed-multi knowledge-base -m text-embedding-3-small \
--files docs/ '*.md' --store
# 2. 语义搜索
llm similar knowledge-base -c "how to configure authentication"
# 3. 结合 RAG 工具
llm install llm-tools-rag
llm -T rag "What does the documentation say about API keys?"
场景四:带工具的智能助手
python
import llm
def calculate(expression: str) -> str:
"""Evaluate a mathematical expression safely."""
import ast
try:
result = eval(compile(ast.parse(expression, mode='eval'), '', 'eval'))
return str(result)
except Exception as e:
return f"Error: {e}"
def search_docs(query: str) -> str:
"""Search the documentation for relevant information."""
# 自定义搜索逻辑
return search_internal_docs(query)
model = llm.get_model("gpt-4.1")
conversation = model.conversation(tools=[calculate, search_docs])
while True:
user_input = input("> ")
if user_input.lower() in ('exit', 'quit'):
break
response = conversation.chain(user_input)
print(response.text())
与同类工具对比
| 特性 | simonw/llm | LangChain | Ollama CLI | OpenAI CLI |
|---|---|---|---|---|
| 定位 | 通用 CLI + Python 库 | 应用开发框架 | 本地模型运行 | OpenAI 专属 |
| 多模型支持 | 100+(含插件) | 通过集成 | 仅本地模型 | 仅 OpenAI |
| 插件系统 | 成熟(6 个钩子) | 无(库级别扩展) | Modelfile | 无 |
| 对话日志 | SQLite 内置 | 需自行实现 | 无 | 无 |
| 结构化输出 | Schema DSL + Pydantic | 需 OutputParser | 无 | JSON Mode |
| 工具调用 | 内置 | Agent 框架 | 无 | Function Calling |
| 嵌入管理 | 内置 | 需 VectorStore | 无 | 无 |
| 本地模型 | 通过插件 | 通过集成 | 核心功能 | 无 |
| 学习曲线 | 低 | 高 | 低 | 低 |
LLM 的独特定位在于:它不是开发框架,而是开发者工具。你不需要学习复杂的 Agent 抽象、Chain 组装或者 Memory 管理------一条命令就能完成大部分工作,需要编程时也有简洁的 Python API。
局限与权衡
- 同步模型的阻塞问题 :虽然 0.18 版本引入了异步支持,但并非所有插件都实现了
AsyncModel,在异步上下文中使用同步模型仍会阻塞事件循环 - Token 计费追踪粒度有限 :虽然有
response.usage()和 SQLite 日志,但缺少按项目、按标签维度的成本聚合能力 - 没有内置的 Agent 编排 :LLM 提供了
model.chain()和Toolbox,但没有 LangChain 那样的 Agent 编排框架(如 ReAct、Plan-and-Execute) - Windows 体验弱于 Unix:管道、文件路径、终端交互在 Windows 上偶尔会遇到兼容性问题
- Schema 支持依赖模型能力:结构化输出需要模型本身支持,并非所有模型都能可靠地遵循 Schema
总结
simonw/llm 是一个在 AI 工具生态中占据独特位置的项目。它不是另一个 LangChain,也不是另一个 Ollama------它是连接终端和大语言模型之间最直接的那座桥梁。
三个层面的价值:
- 工具层面:一条命令访问任何模型,管道友好的输入输出,SQLite 完整审计
- 平台层面:成熟的插件系统、模板共享、Schema/Tool/Fragment 三大扩展机制
- 哲学层面:Unix 哲学在 AI 时代的实践------简单、可组合、可编程
如果你是经常在终端工作的开发者,如果你厌倦了在不同 AI 网页之间切换,如果你想用脚本自动化 AI 工作流------LLM 值得一试。
bash
pip install llm && llm keys set openai && llm "Why should developers use CLI tools for AI?"
参考链接: