大模型应用的运行原理:Token、上下文、采样、成本与工程边界

调用一次大模型 API 很简单:提交消息,等待模型返回文本。真正困难的是解释下面这些现象:为什么相同问题会得到不同答案,为什么上下文越长反而越容易遗漏信息,为什么流式输出能显著改善体验,以及为什么一个看起来很便宜的请求在多轮对话中会迅速变贵。

这些现象并不是 API 的偶然行为,而是由大模型的生成机制决定的。本文从一次请求的完整生命周期出发,建立一套可以直接用于系统设计、故障分析和成本治理的技术模型。

一、一次模型调用究竟发生了什么

一个典型请求会经过六个阶段:

flowchart LR A[应用组装消息] --> B[Tokenizer 分词] B --> C[模型前向计算] C --> D[得到下一词概率] D --> E[采样一个 Token] E --> F{是否结束} F -- 否 --> C F -- 是 --> G[返回完整结果]

模型并不是一次性写出整段答案。它每轮只做一件事:根据当前上下文,计算词表中每个 Token 成为"下一个 Token"的可能性,再从中选出一个。新 Token 会追加到上下文,参与下一轮计算,直到生成结束标记或达到长度上限。

因此,一段 500 Token 的回答,至少经历了约 500 次自回归生成。流式接口只是把已经生成的片段尽快交给客户端,并没有改变模型逐 Token 生成的本质。

在工程上,一次调用还包含模型之外的链路:

  • 应用层负责身份、权限、会话、输入校验和输出渲染;
  • 上下文层负责系统指令、历史消息、检索结果和工具结果的编排;
  • 模型层负责概率推断,而不是事实查询或事务提交;
  • 工具与数据层提供模型参数中没有的实时知识和确定性能力;
  • 观测层记录延迟、Token、成本、检索证据、工具轨迹和错误类型。

把这些职责混在一个 Prompt 里,通常就是系统从 Demo 走向生产时开始失控的原因。

二、Token 是模型真正处理的单位

模型看到的不是字符、单词或 JavaScript 字符串,而是一串整数 ID。Tokenizer 会把输入转换成 Token 序列:

text 复制代码
原始文本 -> 子词或字节片段 -> Token ID -> 向量表示

现代模型常使用 BPE、Unigram 或它们的变体。以 BPE 的直觉为例:先把文本拆成很小的单元,再反复合并语料中高频相邻片段。常见词可能只占一个 Token,罕见词会被拆成多个 Token。

这会带来三个重要后果。

1. 字符数不能准确代表成本

同样长度的中文、英文、代码、Base64 或随机 ID,Token 数可能差异很大。下面只能作为直觉,不能作为计费依据:

text 复制代码
一段自然英文       通常能以常见子词压缩
中文与混合语言     取决于词表覆盖率
代码与 JSON        标点、缩进、标识符都会占 Token
随机串和 Base64    重复模式少,往往更昂贵

可靠做法是在发送请求前使用对应模型的 tokenizer 估算,而不是用 text.length。

2. 截断必须按 Token 进行

如果系统按字符截断,既无法精确控制窗口,也可能把代码块、JSON、UTF-8 字节或检索段落截断在不可解析的位置。正确顺序是:先按业务边界分段,再计算 Token,最后按预算选择完整片段。

3. Tokenizer 也是模型契约的一部分

更换模型时,即使 Prompt 完全相同,Token 数、边界和成本也可能变化。因此模型迁移测试不能只比较回答质量,还应记录:

  • 输入和输出 Token 数;
  • 长文本截断位置;
  • 结构化输出稳定性;
  • 首 Token 延迟与生成速度;
  • 相同评估集上的单位成功成本。

4. 字节级 Token 会影响流式解码

部分 tokenizer 会退化到字节级表示。一个中文字符或 Emoji 的 UTF-8 字节可能落在多个 Token 中,而模型服务返回的网络分块又可能继续切断 Token 对应的字节序列。因此下面的做法并不安全:

ts 复制代码
// 错误示例:每个分块单独解码,可能产生替换字符 �
const text = new TextDecoder().decode(chunk);

应复用同一个 TextDecoder,让它保留未完成的多字节序列:

ts 复制代码
const decoder = new TextDecoder("utf-8", { fatal: false });
let text = "";

for await (const chunk of byteStream) {
  text += decoder.decode(chunk, { stream: true });
}

text += decoder.decode(); // 刷出解码器内部剩余字节

这说明应用看到的三种边界并不相同:

text 复制代码
模型 Token 边界 ≠ UTF-8 字符边界 ≠ HTTP 网络分块边界

流协议只能在自己的事件边界上解析 JSON,Markdown 只能在累计文本上解析语法,不能假设一次 read() 就对应一个完整 Token、字符或事件。

三、下一 Token 概率是怎样产生的

模型对词表中每个候选 Token 输出一个未归一化分数,称为 logit。Softmax 把这些分数转换成概率:
P(xi)= e zi/T ∑je zj/T P(x_i) = \frac{e^{z_i / T}}{\sum_j e^{z_j / T}} P(xi)=∑jezj/Tezi/T

其中:

  • zi z_i zi 是候选 Token 的 logit;
  • TT T 是 temperature;
  • P(xi) P(x_i) P(xi) 是采样概率。

假设三个候选 Token 的 logits 是 [3, 2, 1]。当温度较低时,最大值会更加突出,输出更稳定;温度升高时,概率分布变平,低概率候选更容易被选中。

严格地说,上式要求 T>0T>0 T>0。API 中的 temperature=0 通常表示采用贪心或接近贪心的实现,并不是把 0 直接代入分母。

需要注意:temperature 不会让模型"知道更多",它只改变已有概率分布的形状。知识问答提高温度通常不会减少事实错误,只会让错误表达得更多样。

Greedy、Top-k 与 Top-p

常见解码策略并不等价:

  • Greedy:总是选择概率最高的 Token,可复现性较好,但可能出现机械重复或局部最优;
  • Top-k:只保留概率最高的 k 个候选,再重新归一化;
  • Top-p:从高到低累加概率,只保留累计概率达到 p 的最小候选集合;
  • 随机采样:按过滤后的概率抽取,能提高多样性,也引入不确定性。

Top-p 的候选数量会随分布变化:模型很确定时集合可能只有几个 Token;模型不确定时集合会自动扩大。这也是它比固定 Top-k 更适合通用生成的原因之一。

生产系统应根据任务设置采样参数,而不是全站共用一组配置:

任务 建议倾向 原因
分类、抽取、路由 低温度、严格 Schema 需要稳定和可验证
事实问答 低温度、带证据 多样性价值低
摘要 中低温度 兼顾忠实度与表达
创意写作 中高温度 允许探索更多候选

即使 temperature 为 0,也不应把模型调用理解为严格确定性函数。并行计算、服务端模型版本、量化方式和供应商实现都可能造成细微差异。真正需要幂等的业务,必须在应用层实现幂等,而不能依赖模型每次返回相同文本。

用熵观察模型到底有多犹豫

概率分布的熵可以描述下一步选择的不确定性:
H(P)=−∑iP(xi)log⁡P(xi)H(P) = -\sum_i P(x_i)\log P(x_i) H(P)=−i∑P(xi)logP(xi)

当一个 Token 的概率接近 1 时,熵较低,说明模型对下一步较确定;当很多候选概率接近时,熵较高,说明模型存在多条可能路径。温度升高通常会让分布更平、熵更高。

供应商未必暴露完整 logits,但这个概念仍然有工程意义:创意任务允许高熵输出,分类和工具参数则应尽量降低不确定性,并通过枚举、Schema、候选约束和业务校验把输出空间收紧。

不要把模型给出的 confidence 字段直接当作统计置信度。它通常也是模型生成的文本,没有经过校准。若业务需要概率意义上的置信度,应在标注集上比较预测分数与真实正确率,并使用可靠性图、ECE 等方法做校准。

四、Transformer 为什么需要上下文窗口

Transformer 会把每个 Token 转换成向量,并通过自注意力计算不同位置之间的关系。单个注意力头的核心形式可以写成:
Attention(Q,K,V)=softmax ( QKT dk ) VAttention(Q, K, V) = softmax\left(\frac{QK^T}{\sqrt{d_k}}\right)V Attention(Q,K,V)=softmax(dk QKT)V

直觉上,Query 表示当前位置想找什么,Key 表示每个位置能被怎样匹配,Value 表示匹配后实际取回的信息。 QKTQK^T QKT 会产生一个"每个位置关注其他位置"的矩阵。

当序列长度为 nn n 时,标准注意力矩阵包含 n2n^2 n2 个位置关系。虽然现代模型会使用 FlashAttention、分组查询注意力、滑动窗口注意力等优化,但长上下文依然会显著增加显存、计算和延迟。

上下文窗口是工作区,不是长期记忆

上下文窗口包含的通常是:

text 复制代码
系统指令
+ 开发者规则
+ 当前用户输入
+ 历史消息
+ 检索文档
+ 工具参数与结果
+ 模型输出预算

可以把预算写成:
Btotal = Binstruction + Bhistory + Bretrieval + Btools + Boutput B_{total} = B_{instruction} + B_{history} + B_{retrieval} + B_{tools} + B_{output} Btotal=Binstruction+Bhistory+Bretrieval+Btools+Boutput

任何一部分增长,都会挤压其他部分。一个支持 128K 上下文的模型,并不意味着应该塞满 128K;更长的输入会带来更高成本、更长首 Token 延迟,以及重要信息被噪声淹没的风险。

Lost in the Middle 与上下文腐化

模型对上下文中不同位置的利用并不均匀。关键证据位于超长上下文中部时,可能不如开头或结尾稳定;加入大量相似但无关的材料,还会让注意力在多个候选之间分散。

因此上下文工程的目标不是"放进去最多的信息",而是"在预算内放入完成当前任务所需的最小充分信息"。

五、API 通常是无状态的,记忆来自应用

多数大模型 API 不会自动记住上一次请求。所谓多轮对话,通常是应用在每次调用时重新发送必要历史:

sequenceDiagram participant U as 用户 participant A as 应用 participant M as 模型 U->>A: 第三轮问题 A->>A: 选择历史 摘要 记忆 A->>M: 重新提交本轮完整上下文 M-->>A: 新回答 A->>A: 保存消息与更新摘要 A-->>U: 流式展示

这解释了为什么对话轮数增加时成本会不断上升。如果每次都携带所有历史,第 ii i 轮的输入包含前 i−1i-1 i−1 轮内容,总输入量会接近二次增长。

假设每轮用户输入 200 Token、模型输出 400 Token,忽略系统指令:

text 复制代码
第 1 轮输入:200
第 2 轮输入:200 + 400 + 200 = 800
第 3 轮输入:200 + 400 + 200 + 400 + 200 = 1400
...

10 轮对话不是只支付 10 次单轮成本。应用需要组合使用:

  • 最近消息滑动窗口;
  • 旧历史结构化摘要;
  • 用户偏好的长期记忆;
  • 按当前问题检索相关往事;
  • 对不可丢失的业务状态使用数据库,而不是自然语言摘要。

KV Cache 与 Prompt Cache 不是同一件事

模型生成时会复用此前 Token 的 Key/Value 表示,这称为 KV Cache,它避免每生成一个 Token 都重新计算整个前缀。KV Cache 主要发生在一次生成内部,也会占用随上下文增长的显存。

部分供应商提供 Prompt Cache:当多个请求共享相同前缀时,服务端可以复用前缀计算,并对命中的 Token 提供更低价格或更低延迟。要提高命中率,应把稳定内容放前面,把动态内容放后面:

text 复制代码
稳定系统指令 -> 稳定工具定义 -> 稳定知识前缀 -> 动态历史 -> 当前问题

如果在前缀中加入时间戳、随机 ID 或频繁变化的用户数据,会导致后续完全相同的规则也无法命中缓存。

Prefill 与 Decode 是两种不同的计算阶段

一次生成可以拆成:

text 复制代码
Prefill:并行处理全部输入 Token,建立每层 KV Cache
Decode:每轮生成一个新 Token,并把新的 K/V 追加到缓存

输入很长时,Prefill 主导 TTFT;输出很长时,串行 Decode 主导总耗时。优化时必须先判断瓶颈属于哪一段:

现象 更可能的瓶颈 优先手段
首字很慢,生成后速度正常 Prefill 或排队 减少输入、缓存稳定前缀
首字正常,后续输出很慢 Decode 限制输出、换高吞吐模型
工具之间停顿很长 外部 I/O 并行只读工具、超时与缓存
并发升高后全部变慢 排队或显存压力 限流、批处理、容量扩展

KV Cache 的占用会随层数、序列长度和并发数线性增长。忽略对齐与实现差异,一个使用 GQA/MQA 的近似公式是:
Memor yKV ≈2⋅L⋅N⋅ Hkv ⋅D⋅BMemory_{KV} \approx 2 \cdot L \cdot N \cdot H_{kv} \cdot D \cdot B MemoryKV≈2⋅L⋅N⋅Hkv⋅D⋅B

其中 LL L 是层数, NN N 是当前序列长度, Hkv H_{kv} Hkv 是 KV 头数, DD D 是每个头的维度, BB B 是每个元素的字节数;前面的 2 分别代表 Key 和 Value。批量与并发还会继续乘上对应序列数。

例如 L=32L=32 L=32、 N=32,768N=32{,}768 N=32,768、 Hkv =8 H_{kv}=8 Hkv=8、 D=128D=128 D=128、BF16 每元素 2 字节,仅一条序列的 KV Cache 就约为:
2×32×32768×8×128×2≈4 GiB2 \times 32 \times 32768 \times 8 \times 128 \times 2 \approx 4\,\text{GiB} 2×32×32768×8×128×2≈4GiB

这个估算解释了为什么"模型支持超长上下文"和"系统能以低成本承载大量超长并发"是两回事。GQA 与 MQA 通过减少 KV 头数降低缓存占用,但不会让上下文成本消失。

六、幻觉不是一个单一故障

模型的目标是生成"在当前上下文下概率合理的后续文本",不是执行数据库中的真值查询。所谓幻觉至少可以拆成四类:

类型 根因 典型治理方式
参数知识错误 模型记忆过时或模糊 RAG、实时工具、要求引用
上下文遗漏 证据未召回或被截断 检索评估、上下文预算
指令冲突 多层规则含义不一致 明确优先级、Prompt 回归
推理与计算错误 概率生成不等于精确计算 代码执行、计算器、规则引擎

"请不要编造"只能提供弱约束。更可靠的系统会把不确定性显式设计进协议:

json 复制代码
{
  "answer": "无法从当前资料确认",
  "status": "insufficient_evidence",
  "citations": [],
  "confidence": 0.21
}

然后由服务端验证:引用是否真实存在、引用片段是否支持结论、低于阈值时是否触发拒答或人工确认。

七、结构化输出为什么比解析自然语言可靠

如果下游程序需要使用模型结果,不要从一段自然语言里用正则表达式"捞字段"。应该提供 JSON Schema 或等价约束,并在服务端再次校验:

ts 复制代码
import { z } from "zod";

const TicketResult = z.object({
  category: z.enum(["billing", "account", "bug", "other"]),
  urgency: z.enum(["low", "medium", "high"]),
  reason: z.string().max(300),
});

const parsed = TicketResult.safeParse(modelOutput);
if (!parsed.success) {
  // 记录失败原因,可选择修复调用或受控重试
}

Schema 约束解决的是"形状正确",不保证"语义正确"。例如 urgency: high 可以通过校验,但仍可能分错。完整链路要分三层验证:

  1. 语法层:是否是合法 JSON;
  2. 结构层:字段、枚举、长度是否符合 Schema;
  3. 业务层:字段组合是否满足业务规则,是否有证据支持。

工具调用也是结构化输出的一种。模型只负责提出"调用什么工具、参数是什么";权限判断、参数校验、幂等、超时与审计必须由应用执行。

八、Embedding 为什么能用于语义检索

生成模型输出 Token,Embedding 模型则把一段文本映射为高维向量。语义相近的文本,其向量方向通常更接近。常用的余弦相似度为:
cos(θ)= A⋅B∥A∥∥B∥ cos(\theta) = \frac{A \cdot B}{\lVert A \rVert \lVert B \rVert} cos(θ)=∥A∥∥B∥A⋅B

向量检索的一般流程是:

text 复制代码
文档切分 -> 计算文档向量 -> 写入向量索引
用户问题 -> 计算查询向量 -> 近邻搜索 -> 返回候选片段

但向量相似并不等于事实相关。精确型号、错误码、专有名词和版本号常常更适合关键词检索。因此生产级 RAG 通常结合:

  • 向量召回,覆盖语义改写;
  • BM25 或倒排索引,命中精确词项;
  • 元数据过滤,限定租户、权限、时间和文档类型;
  • Rerank,对候选进行更精细的相关性排序。

Embedding 还存在版本契约:更换模型后,新旧向量通常不能直接比较,需要重建索引或采用双写迁移。

九、延迟应该拆开看

用户感知到的总延迟可以近似拆成:
Ttotal = Tnetwork + Tqueue + Tprefill + Tdecode + Ttools T_{total} = T_{network} + T_{queue} + T_{prefill} + T_{decode} + T_{tools} Ttotal=Tnetwork+Tqueue+Tprefill+Tdecode+Ttools

  • 网络与排队:请求到达供应商及等待算力;
  • Prefill:处理输入上下文,输入越长通常越慢;
  • Decode:逐 Token 生成输出;
  • 工具时间:搜索、数据库或第三方接口调用。

至少要分别记录:

  • TTFT:发出请求到收到第一个 Token;
  • TPS:稳定生成阶段每秒输出 Token 数;
  • 总耗时:从请求开始到完成;
  • 工具耗时:每次外部调用的独立 Span。

流式输出主要改善"多久看到第一个字",并不会缩短模型完成全部生成的时间。若 TTFT 很高,应检查输入长度、排队和代理缓冲;若 TTFT 正常但总耗时高,应检查输出长度、模型生成速度和工具调用。

十、成本要按完整调用链计算

单次模型成本通常可以近似写成:
C= Tin Pin + Tout Pout + Ccache + Ctools C = T_{in}P_{in} + T_{out}P_{out} + C_{cache} + C_{tools} C=TinPin+ToutPout+Ccache+Ctools

其中 TT T 是 Token 数, PP P 是单位 Token 价格。Agent 与 RAG 系统中,还要加上改写、Embedding、Rerank、工具结果总结、失败重试等隐性调用。

真正有价值的指标不是"每次调用多少钱",而是:
CostPerSuccess=总成本成功完成且通过质量门槛的任务数CostPerSuccess = \frac{总成本}{成功完成且通过质量门槛的任务数} CostPerSuccess=成功完成且通过质量门槛的任务数总成本

一个便宜但经常失败、需要多次重试的小模型,单位成功成本可能高于一次完成任务的强模型。

常见优化顺序是:

  1. 删除无关上下文和重复工具描述;
  2. 限制输出长度,避免模型重复复述输入;
  3. 对稳定前缀使用缓存;
  4. 让规则、分类器或搜索引擎完成确定性工作;
  5. 按任务难度做模型路由;
  6. 最后才考虑用更小模型替换。

算一笔多阶段调用的完整成本

假设一次 RAG 请求包含四个计费阶段:

阶段 输入 Token 输出 Token 调用次数
Query 改写 800 80 1
Rerank 取决于候选总长度 少量分数 1
最终生成 6,000 900 1
失败修复 6,900 300 发生时 1

若只统计最终生成,就会漏掉改写、Rerank 和失败修复。设阶段 ii i 的调用次数为 ni n_i ni,输入输出价格为 Pin,i P_{in,i} Pin,i、 Pout,i P_{out,i} Pout,i,完整成本应写成:
Crequest =∑ini( Tin,i Pin,i + Tout,i Pout,i )+ Cinfra C_{request}=\sum_i n_i(T_{in,i}P_{in,i}+T_{out,i}P_{out,i})+C_{infra} Crequest=i∑ni(Tin,iPin,i+Tout,iPout,i)+Cinfra

C_infra 还包括向量数据库、搜索、对象存储、GPU 工具和观测平台。缓存命中不能直接从 Token 中删除,而应按供应商的缓存读写价格分别计费。对比方案时固定同一批任务,最终比较 P95 延迟、成功率和 CostPerSuccess,否则"单价更低"没有决策意义。

十一、模型路由应该由任务特征驱动

模型选型不能只看公开榜单。应用实际需要的是一个受约束的多目标优化:

text 复制代码
质量达到阈值
+ 延迟满足体验要求
+ 单位成功成本可接受
+ 支持所需上下文、工具和结构化输出
+ 数据与合规条件满足

可以为请求建立简单的复杂度特征:

ts 复制代码
type RouteInput = {
  inputTokens: number;
  needsTools: boolean;
  needsVision: boolean;
  strictJson: boolean;
  risk: "low" | "medium" | "high";
};

function routeModel(x: RouteInput) {
  if (x.needsVision) return "vision-model";
  if (x.risk === "high" || x.needsTools) return "strong-model";
  if (x.inputTokens < 2000 && x.strictJson) return "small-fast-model";
  return "general-model";
}

这只是路由入口。生产系统还需要使用真实评估集验证每个分支,并记录路由选择、回退原因和最终结果。模型版本升级时先跑离线回归,再做小流量灰度,而不是直接替换全量流量。

十二、可观测性必须覆盖输入、轨迹与结果

只记录 HTTP 200 无法解释 AI 系统是否真的工作。一次请求至少应形成如下 Trace:

text 复制代码
request_id
├─ context_build:各部分 Token 数、截断与缓存命中
├─ retrieval:查询、过滤条件、候选与分数
├─ model_call:模型版本、参数、TTFT、输入输出 Token
├─ tool_call:工具名、参数摘要、耗时、重试与结果
├─ validation:Schema 与业务校验结果
└─ response:完成状态、引用、用户反馈与总成本

日志中不要直接保存密钥、完整个人信息或敏感文档。可观测性和数据最小化并不冲突:可以记录哈希、长度、类型、脱敏摘要、引用 ID 和错误码,把原始内容放在受控存储中。

建议同时维护四类指标:

  • 质量:正确率、引用支持率、拒答准确率、工具成功率;
  • 性能:TTFT、TPS、P50/P95/P99 总延迟;
  • 成本:每请求 Token、缓存命中率、单位成功成本;
  • 安全:越权拦截、提示词注入命中、敏感输出与人工审批率。

十三、从机制推导出的工程原则

理解运行原理后,许多最佳实践不再是需要背诵的规则,而是自然结论:

  1. 模型是概率组件,所以关键结果必须验证;
  2. API 通常无状态,所以记忆必须由应用显式管理;
  3. 上下文有限且昂贵,所以要检索、压缩和按预算组装;
  4. 模型不拥有业务权限,所以工具执行必须经过应用授权;
  5. 流式输出只是传输策略,所以仍要处理取消、断线和半成品状态;
  6. 模型知识存在边界,所以实时事实应来自检索和工具;
  7. 单次成功不代表稳定,所以每次改动都要经过固定评估集。

十四、小结

一个大模型应用不是"界面加一个模型 API",而是概率模型与确定性软件系统的组合。模型负责理解、生成和提出候选动作;应用负责上下文、事实、权限、事务、验证与观测。

真正需要掌握的因果链是:

text 复制代码
逐 Token 概率生成
-> 输出不确定且延迟与长度相关
-> 需要流式传输、结构校验与评估

有限上下文与注意力成本
-> 历史不能无限追加
-> 需要摘要、检索、缓存与预算控制

模型没有实时事实和业务权限
-> 需要 RAG 与工具
-> 需要引用、授权、幂等与审计

当系统设计可以从这些机制推导出来,而不是依赖零散 Prompt 技巧时,大模型能力才真正变成可维护、可测量、可上线的软件能力。

参考资料

  • Vaswani 等:《Attention Is All You Need》
  • Sennrich 等:《Neural Machine Translation of Rare Words with Subword Units》
  • OpenAI:《Tokenizer 与 Prompt Caching 相关文档》
  • Anthropic:《Context Engineering 与 Long Context 相关文档》
  • Stanford CRFM:《Foundation Model Transparency 与评估资料》
相关推荐
乱世军军1 小时前
安装最新版本
人工智能
海边捡石子1 小时前
向量、图谱还是文件:Agent 记忆怎么选
人工智能·llm·agent
tiger从容淡定是人生1 小时前
从 Gemini 的任务示例出发:AI 能否从知识中推导工作流?
java·人工智能·aigc·知识图谱·创业创新·零知识证明
向哆哆1 小时前
外墙裂缝目标检测数据集:6,000+张图像 | 目标检测
人工智能·目标检测·计算机视觉
鶴哥只手遮天1 小时前
第 06 章 SQLite 持久化契约与数据模型
人工智能·开源
suliqiang1 小时前
AI 编程新范式:Vibe、Agentic 与 Spec 实战指南
人工智能·ai编程·ai-native
武子康1 小时前
LingBot-World 能连续生成一小时,为什么回到原地仍可能变样?
人工智能·llm·agent
AIGCmagic社区1 小时前
多模态Jev专题:OmniMed-Jev多标签可靠误差降到原来的1/126
人工智能·aigc·jev模型
鶴哥只手遮天1 小时前
第 16 章 模型与 Provider 抽象层
人工智能·开源