第01阶段:AI应用基础与 OpenAI 入门
先看懂 AI 应用的工作流程,再完成第一次 API 调用,最后学会写清楚提示词。
进入学习函数做统计,AI 做解释和建议,组合成一个学习助手。
本课项目:AI学习管家
学习重点:数据分析、函数协作、学习建议。工具重点:Function Calling + JSON。
页面里加入 OpenAI、Node.js、Python 和 JSON 图标,帮助学生把 AI 能力、后端调用、脚本实验和结构化输出放在同一条学习路线里理解。
先用阶段卡片看清大方向,再用周课卡片进入具体项目。每节课都保留理论、例子、Node.js、Python、练习和自测,学生可以直接按卡片推进。
先看懂 AI 应用的工作流程,再完成第一次 API 调用,最后学会写清楚提示词。
进入学习AI 不只要会说话,还要按固定格式交答案,这样程序才能稳定处理。
进入学习AI 负责理解语言,函数负责精确计算;两者配合,结果更可靠。
进入学习把图片也交给 AI 看,再让它用清楚的文字或 JSON 结果回答。
进入学习需要最新消息时查网页;需要班级资料时查文件。先找资料,再回答。
进入学习把 AI 能力做成网页:前端收集输入,后端保护密钥,页面展示结果。
进入学习Agent 会按步骤完成任务,但你要给它工具、边界、检查规则和预算意识。
进入学习把前面学过的提示词、JSON、函数、检索、网页和安全设计合在一个作品里。
进入学习成绩里的平均分、最高分、最低分要用函数算;学习建议可以让 AI 用更温和的话说出来。
理论不是背概念,而是帮你判断项目为什么这样设计。下面这些规则会在代码里反复出现。
这一课的项目是“AI学习管家”,重点是“数据分析、函数协作、学习建议”。你可以把它当成一个小实验:先给它一个清楚输入,再观察代码里哪些地方用到了 Function Calling + JSON。课堂里我们不会一上来就追求复杂功能,而是先把最小版本做出来。最小版本跑通以后,你再改输入、改提示词、改输出格式,变化就会看得很清楚。
这几课开始让 AI 和函数合作。模型听懂人的话,函数做确定的事。这样的分工很像课堂小组:一个同学负责读题,一个同学负责计算。
本课有一条很实用的学习线索:先问“用户到底给了什么”,再问“程序希望拿到什么”。比如你可以试这些输入:数学72,英语88,科学64;语文90,数学91,英语89;数学45,英语80,科学78。这些输入故意有简单的,也有容易出问题的。正常输入能帮你确认功能;短输入、空输入、奇怪输入能帮你发现系统边界。
写代码时建议你分三轮。第一轮只跑通官方调用,不加自己的想法;第二轮把输入换成自己的例子,看看结果是否还合理;第三轮才开始改结构,比如增加字段、加错误提示、做网页交互。这个顺序有点慢,但很稳。真正浪费时间的不是慢,而是一下子改太多,最后不知道错在哪里。
不要让模型负责精确计算。它可以解释过程,但平均分、面积、乘法结果应该由函数给出。
理论部分要和代码一起看。比如“输入契约”不是一个漂亮词,它在代码里就是长度检查、必填字段、表单校验;“输出契约”也不是空话,它在代码里就是 JSON Schema、固定字段或页面渲染规则。你每写一行检查代码,都是在告诉系统:什么结果可以接受,什么结果需要退回去重新处理。
课堂里可以把同桌当成第一个用户。你把项目跑给同桌看,让对方换一个输入,观察系统会不会乱。很多问题都是别人随手一试才出现的,比如输入太短、问题太模糊、连续点击按钮、图片看不清。能处理这些小麻烦,作品就会从“我电脑上能跑”变成“别人也能用”。
最后做复盘时,不要只写“我学会了调用 API”。可以写得更具体:我学会了怎样限制输入,怎样让输出固定,怎样判断结果不可靠,怎样把报错变成用户看得懂的提示。这样的复盘有用,因为下一课你真的会再次用到它。
先把例子看懂,再动手写代码。你不需要一次记住所有概念,先能说清楚“输入是什么、输出是什么、程序要检查什么”。
数学 72,英语 88,科学 64。
{
"average": 74.7,
"best_subject": "英语",
"weak_subject": "科学"
}
科学是目前最需要照顾的科目。今天先复习 20 分钟错题,再做 3 道同类题。
下面同时给出 Node.js 和 Python 两套完整最小实现。先任选一种原样跑通,再改输入、改提示词、改输出格式。
import OpenAI from "openai";
const client = new OpenAI();
const MODEL = process.env.OPENAI_MODEL || "gpt-5.5";
const tools = [
{
type: "function",
name: "analyze_scores",
description: "分析学生各科成绩,返回平均分、强项和弱项。",
parameters: {
type: "object",
properties: {
scores: {
type: "array",
items: {
type: "object",
properties: {
subject: { type: "string" },
score: { type: "number" },
},
required: ["subject", "score"],
additionalProperties: false,
},
},
},
required: ["scores"],
additionalProperties: false,
},
strict: true,
},
];
function analyzeScores(scores) {
const total = scores.reduce((sum, item) => sum + item.score, 0);
const average = Number((total / scores.length).toFixed(1));
const sorted = [...scores].sort((a, b) => a.score - b.score);
return {
average,
weak_subject: sorted[0].subject,
best_subject: sorted[sorted.length - 1].subject,
};
}
let input = [
{ role: "user", content: "数学72,英语88,科学64。请帮我分析,并给今天的复习建议。" },
];
let response = await client.responses.create({ model: MODEL, input, tools });
input.push(...response.output);
for (const item of response.output) {
if (item.type !== "function_call") continue;
if (item.name === "analyze_scores") {
const args = JSON.parse(item.arguments);
const result = analyzeScores(args.scores);
input.push({
type: "function_call_output",
call_id: item.call_id,
output: JSON.stringify(result),
});
}
}
response = await client.responses.create({
model: MODEL,
input,
tools,
instructions: "根据函数结果给建议。语气鼓励,建议要具体,每条不超过 25 字。",
});
console.log(response.output_text);
from openai import OpenAI
import json
import os
client = OpenAI()
MODEL = os.getenv("OPENAI_MODEL", "gpt-5.5")
tools = [
{
"type": "function",
"name": "analyze_scores",
"description": "分析学生各科成绩,返回平均分、强项和弱项。",
"parameters": {
"type": "object",
"properties": {
"scores": {
"type": "array",
"items": {
"type": "object",
"properties": {
"subject": {"type": "string"},
"score": {"type": "number"},
},
"required": ["subject", "score"],
"additionalProperties": False,
},
}
},
"required": ["scores"],
"additionalProperties": False,
},
"strict": True,
}
]
def analyze_scores(scores):
total = sum(item["score"] for item in scores)
average = round(total / len(scores), 1)
sorted_scores = sorted(scores, key=lambda item: item["score"])
return {
"average": average,
"weak_subject": sorted_scores[0]["subject"],
"best_subject": sorted_scores[-1]["subject"],
}
input_items = [
{"role": "user", "content": "数学72,英语88,科学64。请帮我分析,并给今天的复习建议。"}
]
response = client.responses.create(model=MODEL, input=input_items, tools=tools)
input_items += response.output
for item in response.output:
if item.type != "function_call":
continue
if item.name == "analyze_scores":
args = json.loads(item.arguments)
result = analyze_scores(args["scores"])
input_items.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": json.dumps(result, ensure_ascii=False),
})
response = client.responses.create(
model=MODEL,
input=input_items,
tools=tools,
instructions="根据函数结果给建议。语气鼓励,建议要具体,每条不超过 25 字。",
)
print(response.output_text)