Guides
We0Model
用模型卡片与 provider 配置封装 LangChain chat model 的运行时模型对象。
概览
We0Model 是 SDK 在运行时真正使用的模型对象。它把两层信息绑在一起:
ModelCard:声明式的模型卡片,描述模型 id、能力上限、默认采样参数与 SDK 选项。chat_model:由LlmFactory根据卡片实例化出的 LangChainBaseChatModel。
模型不直接构造。常规链路是先用 ProviderCard 描述一个 provider 及其下挂模型,再通过 provider.find_model(...) 取到 ModelCard,最后交给 LlmFactory.create_model(...) 得到 We0Model,传入 We0Agent。
最小定义顺序
第一步定义 provider 和模型卡片:
import os
from we0agent.domain.models.model import We0Model, ModelCard, ProviderCard
from we0agent.sdk.langchain.llm.llm_factory import LlmFactory
provider = ProviderCard(
id="openai",
name="OpenAI",
family="openai",
api_key=os.environ["OPENAI_API_KEY"],
models=[
ModelCard(
id="gpt-5.4-mini",
name="GPT-5.4 Mini",
context=400_000,
max_tokens=128_000,
temperature=1.0,
),
],
)
第二步取出模型卡片并构造运行时 We0Model:
card = provider.find_model("gpt-5.4-mini")
model: We0Model = LlmFactory.create_model(card)得到的 model 即可直接传给 We0Agent(参见 We0Agent)。
agent = We0Agent(
name="assistant",
model=model,
system_prompt=system_prompt,
)ModelCard
ModelCard 是一张声明式模型卡片,描述单个模型的标识、能力与默认参数。它本身不持有 provider 配置,而是通过 provider 属性回指所属的 ProviderCard(由 ProviderCard 在初始化时自动绑定)。
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
id | str | 是 | — | 模型标识,会作为底层 SDK 的 model 参数下发。 |
name | str | 是 | — | 模型展示名称。 |
max_tokens | int | None | 否 | None | 模型默认最大输出 token 数。 |
context | int | None | 否 | None | 模型上下文窗口大小。 |
temperature | float | None | 否 | None | 模型默认温度参数。 |
enabled | bool | 否 | True | 模型是否启用。 |
headers | dict[str, str] | 否 | {} | 模型默认请求头。 |
options | JsonObject | 否 | {} | 透传给底层 SDK 的默认选项,会以 **options 展开进 chat model 构造。 |
provider 是只读属性,返回绑定的 ProviderCard(未绑定时为 None)。一般不需要手动设置——把 ModelCard 放进 ProviderCard.models 后会自动回填。
options 是 provider 专属的逃生口。它直接展开进对应 LangChain chat model 的构造参数,因此具体可用键取决于 provider family(如 OpenAI 的 reasoning、Anthropic 的 thinking、Google 的 thinking_budget、DeepSeek 的 reasoning_effort)。
ModelCard(
id="claude-sonnet-4-6",
name="Claude Sonnet 4.6",
context=1_000_000,
max_tokens=64_000,
temperature=1.0,
options={
"effort": "high",
"thinking": {"type": "enabled", "budget_tokens": 56_000},
},
)ProviderCard
ProviderCard 描述一个模型 provider 及其下挂的模型列表。它持有连接信息(base_url / api_key)与 family 归属,并负责把自身回填到每个 ModelCard.provider。
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
id | str | 是 | — | provider 标识。 |
name | str | 是 | — | provider 展示名称。 |
family | str | 是 | — | provider 家族标识,决定底层 chat model 类型,取值见下表。 |
base_url | str | None | 否 | None | provider 基础地址,可指向自建网关或兼容端点。 |
api_key | str | None | 否 | None | provider API 密钥。 |
enabled | bool | 否 | True | provider 是否启用。 |
models | list[ModelCard] | 否 | [] | provider 下挂的模型列表。 |
初始化行为与约束
family必须是受支持的模型家族,否则在构造时直接抛出KeyError。支持的 family 取值来自 LangChain 内置 provider 列表,本 SDK 当前实现了下表四种。- 构造完成后,列表里的每个
ModelCard都会被自动绑定到该 provider(model.provider回指self),无需手动设置。
| family | 底层 chat model | 依赖包 |
|---|---|---|
openai | ChatOpenAI | langchain_openai |
anthropic | ChatAnthropic | langchain_anthropic |
google_genai | ChatGoogleGenerativeAI | langchain_google_genai |
deepseek | EnhancedChatDeepSeek | langchain_deepseek |
注意:
family是家族标识,与id是两个概念。id可以自定义(例如"my-openai-gateway"),但family必须落在受支持取值上。Google provider 的 family 是google_genai,不是
find_model
find_model(model_id) 按 ModelCard.id 在 models 中查找模型卡片,命中即返回;未命中抛出 KeyError。
card = provider.find_model("gpt-5.4-mini") # 命中返回 ModelCard
provider.find_model("does-not-exist") # 抛出 KeyErrorWe0Model
We0Model 是运行时模型对象,由 LlmFactory.create_model(...) 产出,包含两个字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
card | ModelCard | 是 | 当前运行时模型对应的模型卡片。 |
chat_model | BaseChatModel | 是 | 当前运行时实际使用的 LangChain chat model 实例。 |
它在卡片之上提供了一组便捷属性:
| 属性 | 类型 | 说明 |
|---|---|---|
id | str | 等价于 card.id。 |
name | str | 等价于 card.name。 |
provider | ProviderCard | None | 等价于 card.provider。 |
profile | ModelProfile | None | 底层 chat model 的能力画像。 |
context_window | int | 解析后的上下文窗口大小,见下方解析规则。 |
max_output_tokens | int | 解析后的最大输出 token 数,见下方解析规则。 |
能力解析规则
context_window 与 max_output_tokens 不是简单读字段,而是带回退逻辑:
context_window:优先取card.context(需> 0);否则回退到profile["max_input_tokens"](需为正整数);两者都缺失时抛出ValueError。max_output_tokens:优先取card.max_tokens(需> 0);否则回退到profile["max_output_tokens"](需为正整数);两者都缺失时抛出ValueError。
易错点:如果模型卡片没有显式填写
context/max_tokens,且底层profile也未声明对应能力,访问这两个属性会直接抛ValueError。建议在ModelCard上显式声明能力上限,避免运行期才暴露问题。
LlmFactory
LlmFactory 负责把 ModelCard 实例化为可调用的模型。两个静态方法:
| 方法 | 返回 | 说明 |
|---|---|---|
create_chat_model(model_card) | BaseChatModel | 按 provider family 构造底层 LangChain chat model。 |
create_model(model_card) | We0Model | 在 create_chat_model 之上封装出运行时 We0Model。 |
create_chat_model
create_chat_model 读取 model_card.provider,按 family 分派到对应的 LangChain chat model:
- provider 为
None时抛出ValueError(卡片未绑定 provider)。 - family 不在受支持取值内时抛出
ValueError(不受支持的 family)。
构造各 chat model 时统一应用以下约定:
max_retries=0:工厂层不做重试,重试与错误恢复交由上层引擎处理。model_card.options以**options展开进构造参数,作为 provider 专属能力的逃生口。- OpenAI / Anthropic / DeepSeek 设置
stream_usage=True,以便在流式过程中拿到 usage 统计。
各 family 的参数映射如下:
| family | model 参数 | 输出上限参数 | api_key 处理 | base_url |
|---|---|---|---|---|
openai | model | max_completion_tokens | api_key | base_url |
anthropic | model_name | max_tokens_to_sample | api_key(转为 SecretStr) | base_url |
google_genai | model | max_output_tokens | google_api_key | — |
deepseek | model | max_tokens | api_key | — |
注意:
google_genai与deepseek的工厂实现不接收base_url,即便ProviderCard.base_url有值也不会被传入。temperature在四种 family 下都会从model_card.temperature透传。
create_model
create_model 是常规入口。它先调用 create_chat_model 得到底层模型,再封装为 We0Model:
from we0agent.sdk.langchain.llm.llm_factory import LlmFactory
model = LlmFactory.create_model(card)
# 等价于:
# We0Model(card=card, chat_model=LlmFactory.create_chat_model(card))端到端示例
下面把 provider 声明、模型构造、agent 装配串起来:
import os
from we0agent.domain.models.model import We0Model, ModelCard, ProviderCard
from we0agent.sdk.langchain.llm.llm_factory import LlmFactory
def create_anthropic_model(model_id: str = "claude-sonnet-4-6") -> We0Model:
provider = ProviderCard(
id="anthropic",
name="Anthropic",
family="anthropic",
api_key=os.environ["ANTHROPIC_API_KEY"],
models=[
ModelCard(
id="claude-sonnet-4-6",
name="Claude Sonnet 4.6",
context=1_000_000,
max_tokens=64_000,
temperature=1.0,
options={
"effort": "high",
"thinking": {"type": "enabled", "budget_tokens": 56_000},
},
),
],
)
# find_model 命中后交给工厂;未命中会抛 KeyError
return LlmFactory.create_model(provider.find_model(model_id))
model = create_anthropic_model()
print(model.id, model.context_window, model.max_output_tokens)构造好的 We0Model 即可作为 We0Agent(model=...) 的入参。模型如何参与流式调用、prompt caching 与结构化输出,参见 Streaming 与 SystemPrompt。