> ## Documentation Index
> Fetch the complete documentation index at: https://simplellmfunc.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# LLM 即函数

> 为什么将 LLM 调用视为类型化 Python 函数会改变一切

# LLM 即函数

SimpleLLMFunc 的核心洞察：LLM 调用应该与 Python 函数调用无法区分。

## 现有方案的问题

大多数 LLM 框架在你和模型之间引入了新的抽象：

* **链式框架**让你以链接步骤的方式思考，每一步通过框架定义的协议向下一步传递数据
* **图框架**让你定义节点和边，通过可视化 DAG 路由数据
* **Agent 框架**将 LLM 隐藏在一个管理自身状态的"代理"抽象背后

所有这些都在你的意图和模型之间放置了一层框架特定的概念。你在学习框架的词汇，而不是直接表达你的任务。

## 函数模型

在 SimpleLLMFunc 中，LLM 调用就是函数调用：

```python theme={null}
@llm_function(llm_interface=llm)
async def extract_entities(text: str) -> list[Entity]:
    """从文本中提取命名实体。包括人物、组织和地点类型。"""
    pass
```

这是一个完整的、可运行的程序。这个函数：

* 有**名称** — `extract_entities`
* 有**类型化参数** — `text: str`
* 有**类型化返回值** — `list[Entity]`
* 有**文档字符串**描述行为 — 这就是提示词
* 是**可等待的** — `await extract_entities("...")`
* 是**可组合的** — 从其他函数调用它、传递它、测试它

没有"链"，没有"节点"，没有"Agent 对象"。只有函数。

## 你获得什么

### 边界处的类型安全

返回类型注解是一个契约。框架确保 LLM 输出被解析为你声明的类型——否则抛出明确的错误。不需要手动 JSON 解析，不会"有时模型返回字符串而不是对象"。

```python theme={null}
class Analysis(BaseModel):
    sentiment: Literal["positive", "negative", "neutral"]
    confidence: float = Field(ge=0.0, le=1.0)
    reasoning: str

result: Analysis = await analyze(text)  # 类型检查，结构保证
```

### 可组合性

函数天然可组合。用普通 Python 构建复杂管道：

```python theme={null}
async def full_pipeline(document: str) -> Report:
    entities = await extract_entities(document)
    summary = await summarize(document)
    sentiment = await analyze_sentiment(document)
    return Report(entities=entities, summary=summary, sentiment=sentiment)
```

不需要框架 DSL。不需要链定义。只是函数调用函数。

### 可测试性

像任何其他函数一样 mock 它：

```python theme={null}
async def test_pipeline():
    with mock.patch("my_module.extract_entities") as mock_extract:
        mock_extract.return_value = [Entity(name="Alice", type="person")]
        result = await full_pipeline("Alice went to Paris.")
        assert result.entities[0].name == "Alice"
```

### IDE 支持

你的 IDE 已经知道如何处理异步函数、类型注解和文档字符串。自动补全、跳转到定义、内联文档——全部免费。

## 扩展：LLM 即 Agent

`@llm_chat` 将函数模型扩展到多轮 Agent。Agent 仍然只是一个函数——它接受输入，返回输出。区别在于它可以使用工具并维护对话状态：

```python theme={null}
@llm_chat(llm_interface=llm, toolkit=[search, calculate], stream=True)
async def research_agent(question: str, history: list | None = None):
    """研究问题，使用可用工具。引用你的来源。"""
    pass
```

相同的函数接口。相同的可组合性。但现在函数可以在内部跨多个步骤推理（ReAct 循环），使用工具，并流式传输结果。

## 关键洞察

框架的工作是让"我想调用 LLM"和"我调用了一个 Python 函数"之间的差距尽可能接近零。其他一切——上下文管理、工具执行、类型解析——都是实现细节，你可以忽略它们直到需要自定义。

当你确实需要自定义时，[上下文模型](/zh/context/overview)给你完全的控制。但默认就是：写一个函数。
