
OpenAI回归开源:gpt-oss-120b和gpt-oss-20b完整指南 原创
本文将向你介绍OpenAI新发布的两个开源模型--gpt-oss-120b和gpt-oss-20b,它们的特点,以及在何种场景下该使用哪个模型。
近期,OpenAI发布了两个开源的大语言模型(LLM)--gpt-oss-120b和gpt-oss-20b。它们是自GPT-2以来,由OpenAI第一个公开许可的LLM。其旨在创建最好、最先进的、供推理和工具使用的模型。通过开源gpt-oss,OpenAI允许人们在Apache 2.0的范围内,自由地使用和适配。当然,这两种模式也考虑了专业个性化,以及定制到本地和上下文任务的民主化方法。
在本文指南中,我们将介绍如何获取gpt-oss-120b和gpt-oss-20b服务,以及在何种场景下使用哪个模型。
gpt-oss的特别之处
OpenAI本次新开源的模型是自GPT-2以来最强大的公共模型。其先进之处主要体现在:
- 开放的Apache 2.0许可证:gpt-oss的各种模型不但完全开源,并且是根据Apache 2.0许可证提供授权的。这意味着,它们没有任何copyleft限制,开发人员可以将其用于研究或商业产品,且无需许可费或源代码义务。
- 可配置的推理水平:gpt-oss独特的功能在于用户可以轻松地将模型的推理能力配置为:低、中或高。这是速度与“思考”深度的权衡。使用“浅推理”和“深度推理”分别会让模型在回答之前进行少量与深度的“思考”。
- 全思考链(Chain-of-Thought)访问:与许多封闭模型不同,gpt-oss展示了其内部推理。它有一个默认的分析输出,即推理步骤通道,以指向最终答案通道。用户和开发人员可以检查或过滤输出部分,以调试或信任模型的推理。
- 原生代理功能:gpt-oss模型建立在代理工作流之上。它们是为遵循指令而构建的,而且在“思考”中使用了工具的原生支持。
模型概述和架构
这两个gpt-oss模型都基于Transformer网络,采用了专家混合(Mixture-of-Experts,MoE)设计。在MoE中,只有完整参数(即“专家”)的子集才对于每个输入的token有效,从而减少了计算。我们来看一组数字:
- gpt-oss-120b的总参数量为1170亿个(36层)。它使用了128个专家子网络,每个token都有4个活跃的专家,也就是说每个token能生成51亿个活跃参数。
- gpt-oss-20b的总参数量为210亿个(24层),它有32个专家(4个活跃),每个token产生约36亿个活跃参数。同时,该架构还包括了一些高级功能,例如:所有注意力层(attention layer)都使用旋转位置嵌入(Rotary Positional Embeddings,RoPE)来处理过长的上下文(最多128,000个token),以便注意力本身在全局滑动窗口和128 token的滑动窗口之间交替进行。该设计类似于GPT-3。
此外,这些模型使用了大小为8的分组多查询注意力,以节省内存,同时也保持了快速推理能力。由于其激活函数是SwiGLU,因此所有专家权重都被量化为4位的MXFP4格式,以允许大型模型适配80GB GPU,让小型模型适配16GB,而不会造成重大的准确性损失。
下表总结了其核心规格参数:
模型 | 层 | 总参数 | 活跃参数/token | 专家(总计/活跃) | 上下文 |
gpt-oss-120b | 36 | 117B | 5.1B | 128 / 4 | 128K |
gpt-oss-20b | 24 | 21B | 36B | 32/4 | 128K |
技术规格和许可
- 硬件要求:gpt-oss-120b需要高端GPU(约80-100 GB VRAM),并在单个80 GB A100/H100级GPU或多GPU的设置上运行。而gpt-oss-20b相对较轻,即使在笔记本电脑或苹果Silicon上也能以约16 GB VRAM运行。同时,这两种型号都支持128K token的上下文,非常适合冗长的文档,以及密集型计算。
- 量化和性能:这两种型号都使用4位的MXFP4作为默认值,其有助于减少内存的使用,并加快推理速度。当然,如果没有兼容的硬件,它们会回落到16位,并且需要约48 GB供给gpt-oss-20b。此外,使用FlashAttention等可选的高级内核,也可以进一步提高计算速度。
- 许可证和使用:基于Apache 2.0发布,这两种型号都可以被自由地使用、修改和分发,甚至用于商业用途,而无版权或代码共享的要求,更无API费用或许可证限制。
技术规格 | gpt-oss-120b | gpt-oss-20b |
总参数 | 1170亿 | 210亿 |
每个token的活跃参数 | 51亿 | 36亿 |
架构 | 带有128专家的MoE(4个活跃/token) | 带有32专家的MoE(4个活跃/token) |
Transformer块 | 36层 | 24层 |
上下文窗口 | 128,000个token | 128,000个token |
内存要求 | 80 GB(适合单个H100 GPU) | 16GB |
安装和设置过程
下面我们来看看如何上手使用gpt-oss:
Hugging Face Transformers:请安装其最新的库,并直接加载模型。以下安装命令是必要的先决条件:
pip install --upgrade accelerate transformers
以下代码可从Hugging Face hub处下载所需的模型。
from transformers import AutoTokenizer, AutoModelForCausalLM
tokenizer = AutoTokenizer.from_pretrained("openai/gpt-oss-20b")
model = AutoModelForCausalLM.from_pretrained(
"openai/gpt-oss-20b", device_map="auto", torch_dtype="auto")
下载模型后,你可以使用以下方式进行测试:
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain why the sky is blue."}
]
inputs = tokenizer.apply_chat_template(
messages, add_generation_prompt=True, return_tensors="pt"
).to(model.device)
outputs = model.generate(**inputs, max_new_tokens=200)
print(tokenizer.decode(outputs[0]))
此设置可从OpenAI指南中获得,并在任何GPU上运行。为了在NVIDIA A100/H100卡上获得最佳速度,请安装triton内核,以使用MXFP4;否则该模型将会在内部使用16位。
vLLM:对于高吞吐量或多GPU服务,你可以使用vLLM库。OpenAI在2x H100s上可以实现,你可以使用以下命令安装vLLM:
pip install vllm
接着你可以通过以下命令启动服务器:
vllm serve openai/gpt-oss-120b --tensor-parallel-size 2
或者在Python中,使用:
from vllm import LLM
llm = LLM("openai/gpt-oss-120b", tensor_parallel_size=2)
output = llm.generate("San Francisco is a")
print(output)
这其实是在Hopper GPU上使用优化的注意力内核。
Ollama(Mac/Windows上的本地):Ollama是本地聊天服务器的turnkey。安装Ollama后,只需运行:
ollama pull gpt-oss:20b
ollama run gpt-oss:20b
这将下载(量化)模型并启动用户聊天界面。Ollama会默认自动应用“harmony”格式的聊天模板。你也可以通过API调用它。例如,使用Python和OpenAI SDK指向Ollama的终端:
from openai import OpenAI
client = OpenAI(base_url="http://localhost:11434/v1", api_key="ollama")
response = client.chat.completions.create(
model="gpt-oss:20b",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Explain what MXFP4 quantization is."}
]
)
print(response.choices[0].message.content)
它会像官方API一样,将提示词发送给本地gpt-oss模型。
Llama.cpp(CPU/ARM):提供预构建的GGUF版本(例如,ggml-org/GPT-Oss-120b-GGUF on Hugging Face)。安装llama.cpp后,你可以在本地构建服务模型:
# macOS:
brew install llama.cpp
# Start a local HTTP server for inference:
llama-server -hf ggml-org/gpt-oss-120b-GGUF -c 0 -fa --jinja --reasoning-format none
然后以相同的格式将聊天消息发送到http://localhost:8080。此选项允许在具有JIT或Vulkan支持的CPU或GPU-agnostic的环境中运行。
总体而言,gpt-oss模型可以与最常见的框架一起使用。上述方法(如:Transformers、vLLM、Ollama、llama.cpp)涵盖了桌面和服务器设置。你也可以进行混合配置。例如,运行一个用于快速推理的设置(如:在GPU上的vLLM)和另一个用于设备测试的设置(如:Ollama或llama.cpp)。
实际操作演示部分
任务 1:推理任务
提示词:选择与第三个术语相关的选项,就像第二个术语与第一个术语相关的方式一样。
IVORY : ZWSPJ :: CREAM : ?
- NFDQB
- SNFDB
- DSFCN
- BQDZL
import os
os.environ['HF_TOKEN'] = 'HF_TOKEN'
from openai import OpenAI
client = OpenAI(
base_url="https://router.huggingface.co/v1",
api_key=os.environ["HF_TOKEN"],
)
completion = client.chat.completions.create(
model="openai/GPT-Oss-20b", # openai/GPT-Oss-120b Change to use 120b model
messages=[
{
"role": "user",
"content": """Select the option that is related to the third term in the same way as the second term is related to the first term.
IVORY : ZWSPJ :: CREAM : ?
A. NFDQB
B. SNFDB
C. DSFCN
D. BQDZL
"""
}
],
)
# Check if there's content in the main content field
if completion.choices[0].message.content:
print("Content:", completion.choices[0].message.content)
else:
# If content is None, check reasoning_content
print("Reasoning Content:", completion.choices[0].message.reasoning_content)
# For Markdown display in Jupyter
from IPython.display import display, Markdown
# Display the actual content that exists
content_to_display = (completion.choices[0].message.content or
completion.choices[0].message.reasoning_content or
"No content available")
gpt-oss-120b的响应为:
Content: **Answer: C. DSFCN**
1
Answer: C. DSFCN
display (Markdown (content_to_display))
gpt-oss-20b的回应为:
display (Markdown (content_to_display))
→ Letters of CREAM: C=3, R=18, E=5, A=1, M=13.
Option A: NFDQB: N=14, F=6, D=4, Q=17, B=2. Differences: +11, -12, -1, +16, -11? Let's compute: 3->14 diff +11.
18->6 diff -12 or +14 mod 26. 5->4 diff -1. 1->17 diff +16. 13->2 diff -11 or +15 mod 26.
Option B: SNFDB: S=19, N=14, F=6, D=4, B=2. Diffs: +16, -4, +1, +3, -11? Actually 1->? Wait 1 is A -> D=4 diff +3. 13->2 diff -11.
Option C: DSFCN: D=4, S=19, F=6, C=3, N=14. Diffs: +1, -4? 18->19 +1? Wait from R=18 to S=19 diff +1. 5->6 +1. 1->3 +2. 13->14 +1. So diff pattern from CREAM: +1, +1, +1, +2, +1? Hmm.
Option D: BQDZL: B=2, Q=17, D=4, Z=26, L=12. Diffs: -1? 3->2-1. 18->17 - 1. 5->4 -1. 1->26 -? 1->26 diff+25 or
1 but need wrap: 1 to 26 is -1 mod 26? Actually 26-1=25; but shift -1? 13->12 -1. So pattern differences:
1,-1,-1,-1,-1. That looks like constant shift -1. Wait check: A-> difference of -1? But from A to Z one position back yields Z. So -1 shift for each letter.
But CREAM to BQDZL: C(3)->B(2) diff -1; R(18)->Q(17) diff -1; E(5)->D(4) diff -1; A(1)->Z(26) diff -1; M(13)-
>L(12) diff -1. Yep exactly each letter minus 1 circularly. So mapping from IVORY to ZWSPJ: Let's check if shift is also -1 for all letters? IVORY: I(9)->Z(26) diff -? 9-1=8 which is H, not Z. So not -1. Let's try shift +? but maybe we mis-evaluated earlier differences incorrectly? Let's compute mapping of letters of IVORY to ZWSPJ if shift is +? compute 9 > 26: difference +17. 22 ->23: +1. 15 ->19: +4. 18->16: -2. 25->10: -15 or +11. So not constant.
But mapping for CREAM to BQDZL is constant -1. Could that be the same rule that applied to IVORY? Let's see if maybe we mis-check: maybe we should shift each letter of IVORY +? to get ZWSPJ. Check if shift is maybe +10?
9+10=19 -> S, not Z. Maybe shift is +? maybe it's variable: first letter shift by +17, second +1, etc. Might correspond to the positions of C and D? Maybe shift pattern equal to letters of "IRIS"? Hard.
But maybe we mis-evaluated mapping: Let's just brute force compute if there's any simple transformation for
IVORY to ZWSPJ that could also apply to CREAM making one of options. Because four options: NFDOB (option
A) etc. Maybe only one will match a pattern that also holds for IVORY->ZWSPJ.
Maybe we need to deduce mapping from the two words: find the key that transforms first to second. Could be a Caesar shift based on some rule like shift each letter by number of letters same as preceding letter's position difference? For example: I shift by something, produce Z. Let's see I->Z: difference 17. Maybe shift equals difference between l's position in alphabet and length of word? 9-5=4? Not 17. difference between number of letters before I? No.
Maybe mapping uses the second word's letters as "reference" like "Z" is the 26th letter which equals sum of I (9) +
V 22) + 0(15) + R18) + Y25) = 9+22+15+18+25=89; 89 mod 26 = 11? not 26.
比较分析
gpt-oss-120B正确地识别了类比中的相关模式,并通过深思熟虑的推理选择了选项C。因为它有条不紊地解释了单词对之间的字符转换,因此获得了正确的映射。另一方面,gpt-oss-20B未能在此任务上产生任何结果,则可能是因为输出token的限制,也就揭示了输出长度的局限性,以及计算效率的低下。总体而言,gpt-oss-120B能够更好地管理符号推理,具有更多的控制和准确性。可见,对于此类涉及到语言类比的推理任务而言,gpt-oss-120B比gpt-oss-20B更可靠。
任务2:代码生成
提示词:给定两个大小分别为m和n的排序数组nums1和nums2,返回两个排序数组的中位数。
在C++中,总体运行时复杂度应该是O(log(m+n))。
示例1:
输入:nums1 = [1,3],nums2 = [2]
输出:2.00000
解释:合并数组=[1,2,3],中位数为2。
示例2:
输入:nums1 = [1,2],nums2 = [3,4]
输出:2.50000
解释:合并数组=[1,2,3,4],中位数为(2 + 3)/2 = 2.5。
约束:
nums1.length==m
nums2.length==n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i],nums2[i] <= 106
import os
from openai import OpenAI
client = OpenAI(
base_url="https://router.huggingface.co/v1",
api_key=os.environ["HF_TOKEN"],
)
completion = client.chat.completions.create(
model="openai/GPT-Oss-120b", # openai/GPT-Oss-20b change to use 20b model
messages=[
{
"role": "user",
"content": """Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n)) in C++.
Example 1:
Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.
Example 2:
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.
Constraints:
nums1.length == m
nums2.length == n
0 <= m <= 1000
0 <= n <= 1000
1 <= m + n <= 2000
-106 <= nums1[i], nums2[i] <= 106
"""
}
],
)
# Check if there's content in the main content field
if completion.choices[0].message.content:
print("Content:", completion.choices[0].message.content)
else:
# If content is None, check reasoning_content
print("Reasoning Content:", completion.choices[0].message.reasoning_content)
# For Markdown display in Jupyter
from IPython.display import display, Markdown
# Display the actual content that exists
content_to_display = (completion.choices[0].message.content or
completion.choices[0].message.reasoning_content or
"No content available")
gpt-oss-120b的响应为:
include <bits/stdc++.h>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(const vector<int>& nums1,
const vector<int>& nums2) {
// Let A be the shorter array.
const vector<int>* A = &nums1;
const vector<int>* B = &nums2;
if (A->size() > B->size()) swap(A, B); // now |A| ≤ |B|
int m = A->size();
int n = B->size();
int total = m + n;
int half = (total + 1) / 2; // size of left part
int low = 0, high = m; // we search over number of elements taken from A
while (low <= high) {
int i = (low + high) / 2; // elements from A on the left side
int j = half - i; // must come from B
// Edge handling: use infinities for out‑of‑range indices
int a_left = (i == 0 ? INT_MIN : (*A)[i - 1]);
int a_right = (i == m ? INT_MAX : (*A)[i]);
int b_left = (j == 0 ? INT_MIN : (*B)[j - 1]);
int b_right = (j == n ? INT_MAX : (*B)[j]);
if (a_left > b_right) { // i too large
high = i - 1;
} else if (b_left > a_right) { // i too small
low = i + 1;
} else { // correct split
int max_left = max(a_left, b_left);
if (total % 2 == 1) // odd
return static_cast<double>(max_left);
int min_right = min(a_right, b_right);
return (max_left + min_right) / 2.0;
}
}
// The code never reaches here because the constraints guarantee at least one element.
return 0.0;
}
};
/* Example usage
int main() {
Solution s;
vector<int> a = {1, 3};
vector<int> b = {2};
cout << fixed << setprecision(5) << s.findMedianSortedArrays(a, b) << endl; // 2.00000
a = {1,2};
b = {3,4};
cout << fixed << setprecision(5) << s.findMedianSortedArrays(a, b) << endl; // 2.50000
}
gpt-oss-20b的响应为
# Reference Implementation (C++17)
include <bits/stdc++.h>
using namespace std;
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1,
vector<int>& nums2) {
// Ensure nums1 is the shorter array
if (nums1.size() > nums2.size())
return findMedianSortedArrays(nums2, nums1);
int m = nums1.size();
int n = nums2.size();
int low = 0, high = m;
int halfLen = (m + n + 1) / 2; // size of left part
while (low <= high) {
int i = (low + high) / 2; // partition in nums1
int j = halfLen - i; // partition in nums2
// i too small - must move right
if (i < m && nums2[j-1] > nums1[i])
low = i + 1;
// i too big - must move left
else if (i > 0 && nums1[i-1] > nums2[j])
high = i - 1;
else {
// correct partition found
int maxLeft;
if (i == 0)
maxLeft = nums2[j-1];
else if (j == 0)
maxLeft = nums1[i-1];
else
maxLeft = max(nums1[i-1], nums2[j-1]);
// odd total, median is maxLeft
if ((m + n) % 2 == 1)
return static_cast<double>(maxLeft);
// even total, need minRight as well
int minRight;
if (i == m)
minRight = nums2[j];
else if (j == n)
minRight = nums1[i];
else
minRight = min(nums1[i], nums2[j]);
return (maxLeft + minRight) / 2.0;
}
}
// Should never reach here for valid input
return 0.0;
}
};
/* Example usage:
int main() {
Solution s;
vector<int> a = {1, 3};
vector<int> b = {2};
cout << fixed << setprecision(5) << s.findMedianSortedArrays(a, b) << endl; // 2.00000
}
比较分析
gpt-oss-120B准确地完成了类比,选择了选项C,并通过成功地识别字母替换模式,显示了强有力的理由。该模型在处理字母振荡的转变和跟踪事物之间的关系方面,显示了良好的推理。与之对比,gpt-oss-20B甚至无法完成任务。该模型超过了输出token的限制,没有返回答案。这表明gpt-oss-20B在资源使用或处理提示方面效率低下。总体而言,gpt-oss-120B在结构推理任务中表现得更好,这使得它比gpt-oss-20B更擅长与符号类比相关的任务。
模型选择指南
在120B和20B模型之间如何进行选择,完全取决于项目需求或我们正在处理的任务。通常:
- gpt-oss-120b:是一种大功率模型,可将其用于较为困难的推理任务、复杂的代码生成、数学问题解决或特定领域的问答。它的性能接近OpenAI的o4-mini模型。因此,它需要一个具有80GB以上 VRAM的大型GPU来运行,并且能在视分步推理至关重要的基准和长形式(long-form)任务中表现出色。
- gpt-oss-20b:是一个针对效率优化的“苦干”模型。在许多基准测试中,它与OpenAI的o3-mini的质量相匹配,但可以在单个16GB VRAM上运行。当你需要快速的设备响应助手、低延迟聊天机器人、或使用网络搜索、及Python调用的工具时,请选择20B。它非常适合概念验证、移动/边缘应用、或硬件受限的场景使用。在许多情况下,20B模型的回答已足够好。例如,它在某项困难的数学竞赛任务中的得分约为96%,几乎与120B相当。
性能基准和比较
在标准化基准方面,OpenAI的各个gpt-oss可以共享结果。目前,120B模型正在不断迭代。它在艰难的推理和知识任务上的得分已高于20B模型,虽然目前两者仍各有千秋。
基准 | gpt-oss-120b | gpt-oss-20b | 开放AI o3 | OpenAI o4-mini |
MMLU | 90.0 | 85.3 | 93.4 | 93.0 |
GPQA Diamond | 80.1 | 71.5 | 83.3 | 81.4 |
Humanity’s Last Exam | 19.0 | 17.3 | 24.9 | 17.7 |
AIME 2024 | 96.6 | 96.0 | 95.2 | 98.7 |
AIME 2025 | 97.9 | 98.7 | 98.4 | 99.5 |
基准 | gpt-oss-120b | gpt-oss-20b | 开放AI o3 | OpenAI o4-mini |
MMLU | 90.0 | 85.3 | 93.4 | 93.0 |
GPQA Diamond | 80.1 | 71.5 | 83.3 | 81.4 |
Humanity’s Last Exam | 19.0 | 17.3 | 24.9 | 17.7 |
AIME 2024 | 96.6 | 96.0 | 95.2 | 98.7 |
AIME 2025 | 97.9 | 98.7 | 98.4 | 99.5 |
来源:ChatGPT
来源:ChatGPT
用例和应用
以下是gpt-oss的一些典型用例场景:
- 内容生成和重写:生成或重写文章、故事或营销文案。gpt-oss模型可以在写作前描述他们的思维过程,并帮助作家和记者创建更好的内容。
- 辅导和教育:可以演示描述概念的不同方式,一步一步地解决问题,并为教育应用或辅导工具和医学提供反馈。
- 代码生成:可以很好地生成代码、调试代码或解释代码。gpt-oss模型也可以在内部运行工具,允许它们辅助开发任务或作为编码助手提供帮助。
- 研究协助:可以总结文档,回答特定领域的问题,并分析数据。gpt-oss的模型也可以针对法律、医学或科学等特定研究领域进行微调。
- 自主代理:启用并使用工具构建带有自主代理的机器人。这些机器人可以浏览网页、调用API或运行代码。它们便捷地与代理框架集成,以构建更复杂的基于步骤的工作流。
小结
综上所述,在OpenAI发布的两个开源模型gpt-oss-120b和gpt-oss-20b中,120B模型全面表现优秀,特别是在:生成更清晰的内容,解决更难的问题,编写更好的代码,并更快地适应研究和自主任务等方面。当然,其短板在于资源利用强度较高,给本地部署带来了一定挑战。
译者介绍
陈峻(Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验。
原文标题:OpenAI Returns to Open Source: A Complete Guide to gpt-oss-120b and gpt-oss-20b,作者:Vipin Vashisth
