OpenAI o3-mini:轻量级推理之王,STEM 领域新标杆!

Page content

OpenAI o3-mini:轻量级推理之王,STEM 领域新标杆! by 浮之静

lencx 浅思

从 AI 发展的现状来看,主要还是以辅助任务为主,虽说 Agent 的终极目标是自动化,但因大模型输出不可控,仍需介入人力来对其结果进行监督和修正。目前主流 AI 主要通过以下形式存在:

  • Web 网页:ChatGPT、Claude、Gemini、DeepSeek、豆包、千问、智谱等主流 AI 均是以在线网页为主的对话式聊天。

  • 系统应用:一般由官方提供,相较于网页版,额外提供了一些系统访问能力,可以用来执行更复杂任务(如本地文件读写、系统通知、与第三方应用协作等)。如果按平台划分,可分为 Windows、macOS、Linux、移动端等。如果按代码实现可分为套壳或原生应用。

    • 套壳应用:直接将网页打包成跨平台应用,不需要二次开发,也利于维护。但缺点也十分明显,不是体积过大,就是内存占用过多。常用跨平台打包框架有 Electron、Tauri 等。

    • 原生应用:使用特定平台框架或语言进行开发(如 Swift、Kotlin 等),虽增加了维护复杂性,但往往也会提供更好的性能支持和更复杂的系统调用能力。

  • 本地应用:为了满足特殊需求,一些用户会通过本地模型或第三方 API 来部署自己的服务。这算是比较极客的玩法了,特点是自由度更高,数据可控。至于需要交互的对话界面可通过 GitHub 找到,此领域也特卷,目前很多 AI 类开源项目都支持多模型 API 调用,以满足复杂的用户需求。

  • AI 编程:据我所知,AI 编程目前主要有两个方向。一种疯狂在卷本地 IDE(可以外挂 docs 等来提高编码准确性),另一种是疯狂卷在线 AI(用自然语言快速搭建网站)。

    • 本地 IDEGitHub Copilot[1]Cursor[2]Windsurf[3]Trae[4] 等。

    • 在线 AIv0[5]bolt.new[6]Replit AI[7] 等。

  • ...

而 o3-mini 的强大代码能力则让我看到了新可能,它是一种介于半应用和半编程的中间态,让编程小白可以通过自然语言描述快速生成一份本地可执行的代码片段(很适合做本地化小工具或批量任务处理脚本)。这或许就是未来个人的必备技能:

  • 能够将工作或生活中的部分任务抽离成需求描述给 AI,让其进行自动化处理,程序化处理似乎更准确(抽象描述需求的能力)。

  • 稍微懂点编程,可以搞定本地代码运行环境,处理一些常见编程错误(知道如何将错误信息发送给 AI,让其修复)。

  • ...

这里有一个小思考:代码片段、程序运行环境、以及 AI 之间存在一些关联,似乎可以通过一个应用来进行集中化管理,这或许就是 Noi 下一步要做的事情。

o3-mini

OpenAI 发布了 o3-mini[8],这是目前最具成本效益的推理模型(虽然价格依然高于 DeepSeek,但已远低于 o1 了。价格对比见文末附录),现已在 ChatGPTAPI 中提供。该模型于 2024 年 12 月首次预览,专为科学、数学和编程任务优化,同时具备 OpenAI o1-mini 的低成本和低延迟优势(目前模型选择中已经移除了 o1-mini)。o1 支持视觉推理但不支持联网搜索,o3-mini 支持联网搜索但不支持视觉。o1 目前仍是更广泛的常识推理模型,而 o3-mini 则为需要精度和速度的技术领域提供了专门的替代方案,大家可根据需要选择对应模型。

值得一提:迫于 DeepSeek 给到的压力,免费版目前可在消息输入框中选择 推理(Reason) 或重新生成响应来试用 OpenAI o3-mini,这是 ChatGPT 首次向免费用户提供推理模型。Plus、Team 用户使用量也从每天 50 次提升至 150 次,Pro 用户则可以无限使用 o3-mini、o3-mini-high(每月 $200 果然不是白花的),企业版将在 2 月份上线。

刚刚 Sam 爆了一个小彩蛋(压力给到,OpenAI 也开始卖力了):还有一个 o3-mini 的好东西即将推出——我觉得我们把最好的留到了最后!

模型特性

  • 专注 STEM 领域:数学、科学、编程能力突出,性能超越 OpenAI o1-mini,并在部分任务上匹敌 OpenAI o1。

  • 支持开发者:支持函数调用(Function calling[9]结构化输出(Structured Outputs[10]开发者消息(Developer Messages[11] 等,可直接用于生产环境。

  • 三种推理模式

    • 低推理(low):优先速度,适合简单任务。

    • 中等推理(medium):默认模型,平衡准确性和速度,等效 OpenAI o1。

    • 高推理(high):更强推理能力,适合复杂任务(如编程、逻辑处理等)。

  • 改进搜索:o3-mini 可与搜索配合,查找带有相关链接的最新答案,这是 OpenAI 集成搜索功能到推理模型中的早期原型。

注:o1 模型不支持的搜索功能现已在 o3-mini 中获得支持。

性能提升

  • 数学(AIME 2024):o3-mini(高推理)达到 87.3% 准确率,比前代模型大幅提升。低推理模式接近 o1-mini,中等推理模式接近 o1,高推理模式超越 o1。

  • 博士级科学测试(GPQA Diamond):o3-mini(高推理)在生物、化学、物理测试中达 79.7%,在较少的推理工作量下,性能媲美 o1(78.0%)。

  • 编程竞赛(Codeforces):o3-mini(高推理)在 Codeforces 竞赛编程中达 2130 Elo,比 o1-mini(1650) 高出多个级别。

  • 软件工程(SWE-bench):o3-mini(高推理)在 SWE-bench 任务中达到 49.3%,超过所有已发布模型。

  • 更快响应速度:相较于 o1-mini,o3-mini(中等推理)平均快 24%,首个 token 延迟降低 2500ms,整体响应时间更短(7.7s vs 10.16s)。

  • ...

安全性

采用审议对齐deliberative alignment[12])训练策略(即在回答用户问题前,训练模型推理人类编写的安全规范),确保更强的安全性,在越狱(Jailbreak)测试中优于 GPT-4o。

案例分享

上面扯了那么多,对普通人而言并不直观。为了更好的感受 o3-mini,我测试了一些 prompt,感兴趣的朋友可以动手尝试(以下示例均为一次提问直出效果,无需多次迭代)。关于测试 prompt 的一些小技巧:

  • 请在单个文件中实现代码

  • 尽量不要使用依赖

案例

贪吃蛇

📌 Prompt

V1: create a snake game, where snakes compete with each other.

翻译:创建一个贪吃蛇游戏,让它们相互竞争。

V2: add score tracking, a pause button, and a restart button.

翻译:添加分数跟踪、暂停按钮和重启按钮。

可将以下代码保存在本地,通过 python 命令运行。

import pygame
import random
import sys

# --- Game Settings ---
GRID_SIZE = 20 # Size (in pixels) of each grid cell
GRID_WIDTH = 30 # Number of cells horizontally
GRID_HEIGHT = 30 # Number of cells vertically

WINDOW_WIDTH = GRID_WIDTH * GRID_SIZE
WINDOW_HEIGHT = GRID_HEIGHT * GRID_SIZE

FPS = 10 # Game speed (frames per second)

# --- Colors ---
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
YELLOW = (255, 255, 0)
GRAY = (100, 100, 100)

# --- Directions ---
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)

# --- Snake Class ---
class Snake:
def __init__(self, start_pos, color):
self.body = [start_pos] # The snake is a list of (x,y) positions
self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
self.color = color
self.alive = True
self.score = 0

def get_head(self):
return self.body[0]

def move(self, grow=False):
"""Advance the snake one step in its current direction.
If grow is True, the snake’s tail is not removed."""

if not self.alive:
return
head_x, head_y = self.get_head()
dx, dy = self.direction
new_head = (head_x + dx, head_y + dy)
self.body.insert(0, new_head)
if not grow:
self.body.pop()

def set_direction(self, new_direction):
"""Set a new direction for the snake. Prevent reversing if length > 1."""
if len(self.body) > 1:
cur_dx, cur_dy = self.direction
# Prevent 180° turn:
if (cur_dx * -1, cur_dy * -1) == new_direction:
return
self.direction = new_direction

def is_direction_safe(self, direction, snakes):
"""Check if moving in the given direction would cause an immediate collision."""
head_x, head_y = self.get_head()
dx, dy = direction
new_head = (head_x + dx, head_y + dy)
# Check board boundaries
if not (0 <= new_head[0] < GRID_WIDTH and 0 <= new_head[1] < GRID_HEIGHT):
return False
# Check collision with any snake’s body (including self)
for snake in snakes:
if new_head in snake.body:
return False
return True

def update_ai(self, food_list, snakes):
"""Simple AI: choose a direction that moves toward the closest food.
If that direction isn’t safe, try the other options."""

if not food_list:
return

head = self.get_head()
# Find the food item with the smallest Manhattan distance:
closest_food = min(food_list, key=lambda f: abs(f[0]-head[0]) + abs(f[1]-head[1]))
dx = closest_food[0] - head[0]
dy = closest_food[1] - head[1]

# Build a prioritized list of directions toward the food:
possible_directions = []
if dx > 0:
possible_directions.append(RIGHT)
elif dx < 0:
possible_directions.append(LEFT)
if dy > 0:
possible_directions.append(DOWN)
elif dy < 0:
possible_directions.append(UP)
# Append the remaining directions:
for d in [UP, DOWN, LEFT, RIGHT]:
if d not in possible_directions:
possible_directions.append(d)

# Choose the first safe direction:
for d in possible_directions:
if self.is_direction_safe(d, snakes):
self.set_direction(d)
return

# If no “preferred” direction is safe, pick any safe direction:
safe_dirs = [d for d in [UP, DOWN, LEFT, RIGHT] if self.is_direction_safe(d, snakes)]
if safe_dirs:
self.set_direction(random.choice(safe_dirs))
# Otherwise, no safe move is available; the snake will collide soon.

# --- Game Class ---
class Game:
def __init__(self):
pygame.init()
self.screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption("Autonomous Snake Competition")
self.clock = pygame.time.Clock()
self.font = pygame.font.SysFont(None, 24)
self.init_game_state()

def init_game_state(self):
"""Initialize or reset the game state (snakes, food, pause flag)."""
# Create several snakes with different starting positions and colors:
self.snakes = []
colors = [GREEN, BLUE, YELLOW, RED]
starting_positions = [
(5, 5),
(GRID_WIDTH - 6, GRID_HEIGHT - 6),
(5, GRID_HEIGHT - 6),
(GRID_WIDTH - 6, 5)
]
for i in range(len(colors)):
self.snakes.append(Snake(starting_positions[i], colors[i]))

self.food_list = []
self.spawn_food(count=5) # Start with 5 food items

# Game control flags
self.paused = False

def reset(self):
"""Restart the game by reinitializing the game state."""
self.init_game_state()

def spawn_food(self, count=1):
"""Spawn the given number of food items."""
for _ in range(count):
self.add_food()

def add_food(self):
"""Place a food item at a random empty cell."""
while True:
pos = (random.randint(0, GRID_WIDTH - 1), random.randint(0, GRID_HEIGHT - 1))
# Ensure no snake occupies this cell and it isn’t already food
collision = any(pos in snake.body for snake in self.snakes) or pos in self.food_list
if not collision:
self.food_list.append(pos)
break

def draw_scores(self):
"""Render the score for each snake on the screen."""
y_offset = 5
for i, snake in enumerate(self.snakes):
status = "Alive" if snake.alive else "Dead"
text_str = f"Snake {i+1} Score: {snake.score} ({status})"
text = self.font.render(text_str, True, WHITE)
self.screen.blit(text, (5, y_offset))
y_offset += 20

def draw_instructions(self):
"""Display instructions for pausing and restarting."""
instructions = "Press 'P' to pause/resume, 'R' to restart"
text = self.font.render(instructions, True, WHITE)
self.screen.blit(text, (5, WINDOW_HEIGHT - 25))

def run(self):
running = True
while running:
self.clock.tick(FPS)

# --- Event Handling ---
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_p:
self.paused = not self.paused
elif event.key == pygame.K_r:
self.reset()

if not self.paused:
# Update AI for each alive snake
alive_snakes = [snake for snake in self.snakes if snake.alive]
random.shuffle(alive_snakes)
for snake in alive_snakes:
snake.update_ai(self.food_list, self.snakes)

# Move each snake and check for collisions
for snake in alive_snakes:
if not snake.alive:
continue
head_before = snake.get_head()
new_head = (head_before[0] + snake.direction[0], head_before[1] + snake.direction[1])

# Check wall collisions
if not (0 <= new_head[0] < GRID_WIDTH and 0 <= new_head[1] < GRID_HEIGHT):
snake.alive = False
continue

# Check collisions with any snake’s body (using the current board state)
collision = False
for other in self.snakes:
if new_head in other.body:
collision = True
break
if collision:
snake.alive = False
continue

# Check if food is at the new head position:
if new_head in self.food_list:
snake.move(grow=True)
snake.score += 1
self.food_list.remove(new_head)
self.add_food() # Replace the eaten food
else:
snake.move(grow=False)

# --- Rendering ---
self.screen.fill(BLACK)

# Draw food items
for food in self.food_list:
rect = pygame.Rect(food[0] * GRID_SIZE, food[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE)
pygame.draw.rect(self.screen, RED, rect)

# Draw each snake
for snake in self.snakes:
color = snake.color if snake.alive else GRAY
for segment in snake.body:
rect = pygame.Rect(segment[0] * GRID_SIZE, segment[1] * GRID_SIZE, GRID_SIZE, GRID_SIZE)
pygame.draw.rect(self.screen, color, rect)

# Draw the scoreboard and instructions
self.draw_scores()
self.draw_instructions()

# If paused, overlay a pause message
if self.paused:
pause_text = self.font.render("Paused", True, WHITE)
text_rect = pause_text.get_rect(center=(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2))
self.screen.blit(pause_text, text_rect)

pygame.display.flip()

pygame.quit()
# --- Final Score Display ---
print("\n--- Final Scores ---")
for i, snake in enumerate(self.snakes):
status = "Alive" if snake.alive else "Dead"
print(f"Snake {i + 1} ({snake.color}): Score = {snake.score} ({status})")

# --- Run the Game ---
if __name__ == "__main__":
game = Game()
game.run()

彩球碰撞

📌 Prompt

Create a p5.js script that generates 100 colorful balls bouncing inside a slowly rotating sphere. Each ball should leave a fading trail, and collisions with the sphere boundary should trigger a particle effect scaled by collision strength. Ensure accurate collision detection so the balls remain within the sphere.

翻译:创建一个 p5.js 脚本,生成 100 个彩色球,它们在缓慢旋转的球体内弹跳。每个球都应留下一条逐渐消失的轨迹,与球体边界的碰撞应触发按碰撞强度缩放的粒子效果。确保准确的碰撞检测,使球保持在球体内。

可将代码粘贴于 p5.js 在线编辑器中查看效果:https://editor.p5js.org

// Global settings
let sphereRadius = 300; // Radius of the enclosing sphere
let numBalls = 100; // How many balls to create
let balls = []; // Array to store Ball objects
let particles = []; // Array to store Particle objects
let angle = 0; // Global rotation angle

function setup() {
createCanvas(windowWidth, windowHeight, WEBGL);
// Create the bouncing balls
for (let i = 0; i < numBalls; i++) {
balls.push(new Ball());
}
}

function draw() {
background(0);

// Slowly rotate the whole scene
angle += 0.005;
rotateY(angle);
rotateX(angle * 0.3);

// Draw the transparent sphere boundary (wireframe-like)
stroke(255, 150);
noFill();
strokeWeight(2);
sphere(sphereRadius);

// Update and draw each ball
for (let ball of balls) {
ball.update();
ball.draw();
}

// Update and draw all particles (from collisions)
for (let i = particles.length - 1; i >= 0; i--) {
particles[i].update();
particles[i].draw();
if (particles[i].lifespan <= 0) {
particles.splice(i, 1);
}
}
}

function windowResized() {
resizeCanvas(windowWidth, windowHeight);
}

// ─────────────────────────────────────────────────────────────
// Ball class: Each ball has a position, velocity, color, size,
// and it remembers a short trail of past positions for the fading tail.
// ─────────────────────────────────────────────────────────────
class Ball {
constructor() {
// Give the ball a random radius between 5 and 15
this.radius = random(5, 15);
// Start at a random point inside the sphere (keeping enough room)
let r = random(0, sphereRadius - this.radius);
this.pos = p5.Vector.random3D().mult(r);
// Set a random 3D velocity
this.vel = p5.Vector.random3D().mult(random(1, 3));
// Pick a random bright color
this.color = color(random(50, 255), random(50, 255), random(50, 255));
// For storing recent positions to draw the trail
this.trail = [];
this.maxTrailLength = 20;
}

update() {
// Record the current position for the trail
this.trail.push(this.pos.copy());
if (this.trail.length > this.maxTrailLength) {
this.trail.shift();
}

// Move the ball
this.pos.add(this.vel);

// Collision detection with the inner wall of the sphere:
// If the ball (including its own radius) goes past the boundary...
let distFromCenter = this.pos.mag();
if (distFromCenter + this.radius > sphereRadius) {
// Compute the normal at the collision point (pointing outward)
let normal = this.pos.copy().normalize();
// Calculate how far the ball is beyond the allowed boundary
let penetration = (distFromCenter + this.radius) - sphereRadius;

// Reflect the velocity along the normal direction:
// v' = v - 2 (v·n) n
let dot = this.vel.dot(normal);
if (dot > 0) { // only reflect if moving outward
this.vel.sub(p5.Vector.mult(normal, 2 * dot));
}

// Reposition the ball so it sits exactly inside the sphere
this.pos = normal.mult(sphereRadius - this.radius);

// Trigger a particle burst whose intensity depends on the collision strength.
// Here, we use the absolute value of the normal component of velocity.
let collisionStrength = abs(dot);
// Decide the number of particles (between 5 and 20)
let numParticles = constrain(floor(collisionStrength * 5), 5, 20);
for (let i = 0; i < numParticles; i++) {
particles.push(new Particle(this.pos.copy(), this.color, collisionStrength));
}
}
}

draw() {
// Draw the ball itself
noStroke();
fill(this.color);
push();
translate(this.pos.x, this.pos.y, this.pos.z);
sphere(this.radius);
pop();

// Draw the trail as a series of line segments that gradually become more opaque.
// (Old segments are more transparent.)
for (let i = 0; i < this.trail.length - 1; i++) {
// Map the segment index to an alpha value (0 for the oldest, 255 for the newest)
let alpha = map(i, 0, this.trail.length - 1, 0, 255);
stroke(red(this.color), green(this.color), blue(this.color), alpha);
strokeWeight(2);
let pos1 = this.trail[i];
let pos2 = this.trail[i + 1];
line(pos1.x, pos1.y, pos1.z, pos2.x, pos2.y, pos2.z);
}
}
}

// ─────────────────────────────────────────────────────────────
// Particle class: Each particle emerges from a collision.
// It starts at the collision point, moves with a bit of randomness (and damping),
// and fades out (its lifespan decreases) until it is removed.
// ─────────────────────────────────────────────────────────────
class Particle {
constructor(position, ballColor, collisionStrength) {
this.pos = position.copy();
// Use the collision point’s outward normal and add a bit of random direction
let normal = position.copy().normalize();
this.vel = p5.Vector.add(normal, p5.Vector.random3D().mult(0.5))
.mult(random(1, collisionStrength * 3));
this.lifespan = 255; // This value is used to fade the particle
this.size = random(2, 5);
this.color = ballColor;
}

update() {
this.pos.add(this.vel);
// Apply a damping so the particles slow down
this.vel.mult(0.95);
// Reduce lifespan (fading effect)
this.lifespan -= 5;
}

draw() {
noStroke();
fill(red(this.color), green(this.color), blue(this.color), this.lifespan);
push();
translate(this.pos.x, this.pos.y, this.pos.z);
sphere(this.size);
pop();
}
}

海浪

📌 Prompt

create a visually interesting shader that can run in twigl-dot-app make it like the ocean in a storm...

翻译:创建一个可以在 twigl-dot-app 中运行的视觉上有趣的着色器,使其像暴风雨中的海洋一样…

make it even more interesting

翻译:让它变得更加有趣

可将代码粘贴于 twigl 在线编辑器中查看效果:https://twigl.app

#ifdef GL_ES
precision mediump float;
#endif

uniform float time;
uniform vec2 resolution;

// ---------------------------------------------------------------------------
// Basic noise functions
// ---------------------------------------------------------------------------

// A simple 2D hash function
float hash(vec2 p) {
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
}

// Basic 2D noise (value noise)
float noise(vec2 p) {
vec2 i = floor(p);
vec2 f = fract(p);

float a = hash(i);
float b = hash(i + vec2(1.0, 0.0));
float c = hash(i + vec2(0.0, 1.0));
float d = hash(i + vec2(1.0, 1.0));

// Smooth interpolation
vec2 u = f * f * (3.0 - 2.0 * f);

return mix(a, b, u.x) +
(c - a) * u.y * (1.0 - u.x) +
(d - b) * u.x * u.y;
}

// Fractal Brownian Motion (fbm) for layered noise
float fbm(vec2 p) {
float total = 0.0;
float amplitude = 0.5;
for (int i = 0; i < 6; i++) {
total += amplitude * noise(p);
p *= 2.0;
amplitude *= 0.5;
}
return total;
}

// ---------------------------------------------------------------------------
// Main Shader – Enhanced Stormy Ocean
// ---------------------------------------------------------------------------
void main() {
// Normalize and center coordinates (preserving aspect ratio)
vec2 uv = (gl_FragCoord.xy - 0.5 * resolution.xy) / resolution.y;

// -- Swirling Vortex Distortion --
// Create a vortex-like swirl near the center to simulate turbulent eddies.
vec2 diff = uv;
float dist = length(diff);
// The rotation angle is modulated by an exponential falloff so the swirl is stronger near the center.
float angle = atan(diff.y, diff.x) + 0.3 * exp(-dist * 3.0) * sin(time * 1.5);
vec2 uvSwirl = vec2(cos(angle), sin(angle)) * dist;

// -- Base Wave Layers --
// Combine a sine wave with layered fbm noise to create dynamic, multi-scale waves.
float wave1 = sin(uvSwirl.x * 8.0 + time * 2.0);
float wave2 = fbm(uvSwirl * 3.0 - time * 0.5);
float wave3 = fbm(uvSwirl * 10.0 + time * 1.2);
float combinedWaves = wave1 * 0.4 + wave2 * 0.4 + wave3 * 0.2;

// -- Fine Ripple Distortion --
// Add a secondary, high-frequency ripple to the coordinates for extra surface detail.
vec2 ripple = vec2(fbm(uvSwirl * 20.0 + time), fbm(uvSwirl * 20.0 - time));
vec2 uvRipple = uvSwirl + ripple * 0.02;

// Recompute fine wave details with the rippled coordinates.
float detail = fbm(uvRipple * 15.0 - time);

// -- Foam Generation --
// Create foam by thresholding the combined wave height and fine details.
float foam = smoothstep(0.5, 0.7, combinedWaves + detail);

// -- Water Color and Gradient --
// Base water color: a deep blue that lightens toward the top.
vec3 waterColor = mix(vec3(0.0, 0.03, 0.1), vec3(0.0, 0.1, 0.3), uv.y + 0.5);
// Foam color: bright, frothy white-blue.
vec3 foamColor = vec3(0.9, 0.9, 1.0);
// Mix water and foam colors based on foam intensity.
vec3 color = mix(waterColor, foamColor, foam);

// -- Specular Highlights --
// Enhance the wave crests with subtle highlights.
float specular = smoothstep(0.6, 0.8, combinedWaves);
color += specular * vec3(0.3, 0.3, 0.35);

// -- Dramatic Lightning Flashes --
// Generate a random pulse value. Occasionally, when the value is very high,
// we simulate a lightning flash by blending the scene toward white.
float lightningPulse = fract(sin(time * 20.0) * 43758.5453123);
float lightning = smoothstep(0.98, 1.0, lightningPulse);
color = mix(color, vec3(1.0), lightning * 0.8);

// -- Additional High-Frequency Variation --
// Introduce extra subtle rippling from high-frequency noise to mimic tiny droplets and disturbances.
float smallRipples = fbm(uvRipple * 50.0 + time * 5.0);
color *= mix(0.9, 1.1, smallRipples);

// -- Gamma Correction --
color = pow(color, vec3(0.4545));

gl_FragColor = vec4(color, 1.0);
}

常见问题

如果未明确 AI 使用某种编程语言实现功能,它一般会首选 Python 作为实现语言,JavaScript 也是 AI 常用语言(主要得益于丰富的 NPM 生态)。所以这里推荐在操作系统中预安装 Python[13]Node.js[14] 环境,方便执行 AI 生成的代码片段。

  • uv[15]:是一款超高速的 Python 包和项目管理器,由 Rust 编写,可替代 pip、pip-tools、pipx、poetry 等多个工具,速度比 pip 快 10-100 倍。它支持 Python 版本管理、应用安装、脚本运行,并提供高效的项目管理功能,包括通用锁定文件和 Cargo 风格的工作区。uv 兼容 pip 接口,节省磁盘空间,并可直接通过 curl 或 pip 安装,无需预装 Rust 或 Python,适用于 macOS、Linux 和 Windows。

  • nvm[16]:Node.js 版本管理工具,替代品有 fnm[17],由 Rust 编写。

uv 和 nvm 可根据需要选择性安装,它们只是帮你优雅管理项目的工具,并不是代码执行的必须品。在案例贪吃蛇中,ChatGPT 给出的代码为 Python,以下给出了运行步骤以供参考:

创建虚拟环境

使用 uv 来创建一个 Python 虚拟环境(隔离项目依赖,避免不同项目之间的冲突):

# 3.11 为 python 版本,可根据需要自行切换
uv venv --python 3.11

激活虚拟环境

source .venv/bin/activate

安装依赖

uv pip install pygame

pygame[18]:是一组专为游戏开发设计的 Python 模块,构建于优秀的 SDL(Simple DirectMedia Layer[19])库之上。这使得开发者可以使用 Python 语言创建功能完备的游戏和多媒体程序。Pygame 高度可移植,可在几乎所有平台和操作系统上运行。

运行脚本

python snake.py

附录

价格:DeepSeek vs OpenAI

OpenAI o* 系列模型价格高于 DeepSeek,如果想使用最具性价比的 API,DeepSeek 仍是不错选择。o3-mini 在保持与 o1 类似推理质量的情况下,价格远低于 o1。如果你的应用正在使用 o1 模型做推理任务,则可以考虑切换至 o3 系列了。

References

[1]

GitHub Copilot: https://github.com/features/copilot

[2]

Cursor: https://www.cursor.com

[3]

Windsurf: https://codeium.com

[4]

Trae: https://www.trae.ai

[5]

v0: https://v0.dev

[6]

bolt.new: https://bolt.new

[7]

Replit AI: https://replit.com/ai

[8]

o3-mini: https://openai.com/index/openai-o3-mini

[9]

Function calling: https://platform.openai.com/docs/guides/function-calling

[10]

Structured Outputs: https://platform.openai.com/docs/guides/structured-outputs

[11]

Developer Messages: https://platform.openai.com/docs/guides/text-generation#building-prompts

[12]

deliberative alignment: https://openai.com/index/deliberative-alignment

[13]

Python: https://python.org

[14]

Node.js: https://nodejs.org

[15]

uv: https://github.com/astral-sh/uv

[16]

nvm: https://github.com/nvm-sh/nvm

[17]

fnm: https://github.com/Schniz/fnm

[18]

pygame: https://github.com/pygame/pygame

[19]

Simple DirectMedia Layer: https://www.libsdl.org


原文链接