Skip to content

第二章:大语言模型(LLM)基础 —— Agent 的大脑 ​

2.1 什么是大语言模型? ​

大语言模型(Large Language Model, LLM) 是 AI Agent 的核心引擎。简单理解:

LLM 就是一个超级"文字接龙"高手。你给它一段文字,它能预测接下来最合理的文字,而且它读过互联网上海量的文本,所以"接"得特别聪明。

对 JS 开发者的类比 ​

javascript
// LLM 的本质行为可以类比为:
function llm(input) {
  // 基于海量训练数据学到的"模式"
  // 预测最合理的输出
  return mostLikelyCompletion(input);
}

// 例如:
llm("JavaScript 是一种") 
// → "广泛使用的编程语言,主要用于Web开发..."

主流 LLM 一览(2025-2026) ​

模型厂商特点API 价格参考
GPT-5OpenAI最新旗舰,深度推理能力极强较高
GPT-5.3 InstantOpenAIGPT-5 系列轻量版,速度快中等
GPT-4oOpenAI综合能力强,性价比高中等
Claude Opus 4.6Anthropic当前最强推理+编码模型较高
Claude Sonnet 4Anthropic代码能力出色,速度与质量均衡中等
Gemini 2.5 ProGoogle多模态强,上下文超长中等
DeepSeek-V3DeepSeek性价比极高,中文优秀低
Qwen 2.5阿里中文优秀,可本地部署低/免费
Llama 3.3Meta开源,可本地部署免费

💡 模型更新很快:OpenAI 在 2025 年底发布了 GPT-5,Anthropic 的 Claude 已到 Opus 4.6 版本。选择模型时关注官方最新发布。

2.2 理解 LLM 的关键概念 ​

Token(令牌) ​

LLM 不是按"字"或"词"处理文本的,而是按 Token 处理。

javascript
// 英文大约 1 token ≈ 4 个字符 ≈ 0.75 个单词
"Hello, world!" → ["Hello", ",", " world", "!"]  // 4 tokens

// 中文大约 1 token ≈ 1-2 个汉字
"你好世界" → ["你好", "世界"]  // 约 2-4 tokens

为什么你需要关心 Token?

  • API 按 Token 计费(输入 + 输出)
  • 每个模型有 上下文窗口 限制(能处理的最大 Token 数)
模型上下文窗口
GPT-4o128K tokens
GPT-51M tokens
Claude Sonnet 4200K tokens
Claude Opus 4.6200K tokens
Gemini 2.5 Pro1M tokens

Temperature(温度) ​

控制输出的"创造性":

javascript
// temperature = 0:确定性输出,每次结果一样(适合 Agent 任务执行)
// temperature = 0.7:有一定随机性(适合创意写作)
// temperature = 1.0+:非常随机(适合头脑风暴)

const response = await openai.chat.completions.create({
  model: "gpt-4o",
  temperature: 0,  // Agent 场景推荐用 0 或很低的值
  messages: [{ role: "user", content: "你好" }]
});

System Prompt(系统提示词) ​

告诉 LLM "你是谁"、"你该怎么做":

javascript
const messages = [
  { 
    role: "system", 
    content: "你是一个专业的前端开发助手,精通 JavaScript 和 React。回答要简洁,给出代码示例。" 
  },
  { 
    role: "user", 
    content: "如何用 React 写一个计数器?" 
  }
];

消息角色 ​

LLM API 使用不同角色来组织对话:

javascript
const messages = [
  { role: "system", content: "..." },    // 系统设定(Agent 的"人设")
  { role: "user", content: "..." },      // 用户输入
  { role: "assistant", content: "..." }, // AI 的回复
  { role: "tool", content: "..." },      // 工具执行结果(Agent 场景)
];

2.3 动手实战:调用你的第一个 LLM API ​

方案一:使用 OpenAI API ​

1. 获取 API Key ​

  1. 访问 https://platform.openai.com/
  2. 注册/登录 → API Keys → Create new secret key
  3. 复制保存好(只显示一次)

💡 国内用户可以使用兼容 OpenAI 格式的服务:DeepSeek(api.deepseek.com)、智谱AI、阿里通义等

2. 创建项目 ​

bash
mkdir my-first-agent && cd my-first-agent
npm init -y
npm install openai

3. 编写代码 ​

javascript
// chat.mjs
import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY, // 从环境变量读取,不要硬编码!
  // 如果使用 DeepSeek,取消下面的注释:
  // baseURL: 'https://api.deepseek.com/v1',
});

async function chat(userMessage) {
  const response = await openai.chat.completions.create({
    model: 'gpt-4o',  // 或 'deepseek-chat'
    temperature: 0,
    messages: [
      { 
        role: 'system', 
        content: '你是一个友好的编程助手,擅长用简洁的方式解释技术概念。' 
      },
      { 
        role: 'user', 
        content: userMessage 
      }
    ],
  });

  return response.choices[0].message.content;
}

// 运行
const answer = await chat('用一句话解释什么是闭包?');
console.log(answer);

4. 运行 ​

bash
# 设置环境变量(Windows PowerShell)
$env:OPENAI_API_KEY="sk-your-key-here"

# 运行
node chat.mjs

方案二:使用 Ollama 本地运行(免费) ​

如果暂时没有 API Key,可以用 Ollama 在本地运行开源模型:

1. 安装 Ollama ​

从 https://ollama.com/ 下载安装。

2. 拉取模型 ​

bash
# 拉取 Qwen 2.5(中文好,体积适中)
ollama pull qwen2.5

# 或者拉取更小的模型(低配电脑)
ollama pull qwen2.5:3b

3. 编写代码 ​

Ollama 兼容 OpenAI API 格式,只需改 baseURL:

javascript
// chat-local.mjs
import OpenAI from 'openai';

const openai = new OpenAI({
  baseURL: 'http://localhost:11434/v1', // Ollama 本地地址
  apiKey: 'ollama', // Ollama 不需要真实 key,随便填
});

async function chat(userMessage) {
  const response = await openai.chat.completions.create({
    model: 'qwen2.5',
    temperature: 0,
    messages: [
      { role: 'system', content: '你是一个友好的编程助手。' },
      { role: 'user', content: userMessage }
    ],
  });

  return response.choices[0].message.content;
}

const answer = await chat('JavaScript 中 == 和 === 有什么区别?');
console.log(answer);

2.4 流式输出(Streaming) ​

聊天应用中,用户不想等 AI 全部生成完再看到结果,而是希望"打字机效果"逐字显示。这就是 Streaming(流式输出):

javascript
// stream.mjs
import OpenAI from 'openai';

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

async function chatStream(userMessage) {
  const stream = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: [
      { role: 'system', content: '你是一个编程助手。' },
      { role: 'user', content: userMessage }
    ],
    stream: true, // 开启流式输出
  });

  // 逐块处理
  for await (const chunk of stream) {
    const content = chunk.choices[0]?.delta?.content || '';
    process.stdout.write(content); // 逐字打印,不换行
  }
  console.log(); // 最后换行
}

await chatStream('用 JavaScript 实现快速排序,并解释原理');

💡 Electron 应用中,流式输出特别重要。你可以通过 IPC 将 stream 的每个 chunk 发送到渲染进程,实现流畅的打字效果。第 10 章会详细实现。

2.5 多轮对话 ​

AI Agent 需要维护对话历史,实现多轮对话:

javascript
// multi-turn.mjs
import OpenAI from 'openai';
import * as readline from 'readline';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

// 对话历史(这就是最简单的"记忆")
const messages = [
  { role: 'system', content: '你是一个 JavaScript 专家。回答简洁明了。' }
];

async function chat(userMessage) {
  // 将用户消息加入历史
  messages.push({ role: 'user', content: userMessage });

  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    messages: messages, // 传入完整对话历史
  });

  const assistantMessage = response.choices[0].message.content;
  
  // 将 AI 回复也加入历史
  messages.push({ role: 'assistant', content: assistantMessage });

  return assistantMessage;
}

// 简单的命令行交互
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

function askQuestion() {
  rl.question('你: ', async (input) => {
    if (input.toLowerCase() === 'exit') {
      rl.close();
      return;
    }
    const answer = await chat(input);
    console.log(`AI: ${answer}\n`);
    askQuestion();
  });
}

console.log('开始对话(输入 exit 退出):\n');
askQuestion();

运行后你可以这样对话:

你: 什么是 Promise?
AI: Promise 是 JS 中处理异步操作的对象...

你: 那 async/await 呢?
AI: async/await 是 Promise 的语法糖...(它记住了上文在讨论异步)

你: 给我一个结合两者的例子
AI: (它记住了在讨论 Promise 和 async/await)...

2.6 API 调用最佳实践 ​

错误处理 ​

javascript
async function safeChatCall(messages) {
  try {
    const response = await openai.chat.completions.create({
      model: 'gpt-4o',
      messages,
    });
    return response.choices[0].message.content;
  } catch (error) {
    if (error.status === 429) {
      // 速率限制 - 等待后重试
      console.log('请求太频繁,等待后重试...');
      await new Promise(r => setTimeout(r, 5000));
      return safeChatCall(messages); // 重试
    }
    if (error.status === 401) {
      throw new Error('API Key 无效,请检查配置');
    }
    throw error;
  }
}

安全准则 ​

javascript
// ❌ 绝对不要这样做
const openai = new OpenAI({
  apiKey: 'sk-abc123...',  // 硬编码 API Key
});

// ✅ 正确做法:从环境变量读取
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

// ✅ Electron 应用中:使用 .env 文件 + dotenv
// npm install dotenv
import 'dotenv/config';
// 然后在 .env 文件中:OPENAI_API_KEY=sk-xxx
// .env 文件加入 .gitignore !

控制成本 ​

javascript
// 1. 限制 max_tokens(最大输出长度)
const response = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages,
  max_tokens: 1000,  // 限制输出不超过 1000 tokens
});

// 2. 使用更便宜的模型处理简单任务
// 简单任务用 gpt-4o-mini,复杂任务再用 gpt-4o

// 3. 监控用量
const usage = response.usage;
console.log(`本次消耗: 输入 ${usage.prompt_tokens} + 输出 ${usage.completion_tokens} = ${usage.total_tokens} tokens`);

2.7 结构化输出(JSON Mode) ​

Agent 开发中经常需要 LLM 输出结构化数据(JSON),而不是自然语言:

javascript
// structured-output.mjs
import OpenAI from 'openai';

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });

async function extractInfo(text) {
  const response = await openai.chat.completions.create({
    model: 'gpt-4o',
    response_format: { type: 'json_object' }, // 强制 JSON 输出
    messages: [
      {
        role: 'system',
        content: `你是一个信息提取助手。将用户输入的文本提取为以下 JSON 格式:
{
  "name": "人名",
  "action": "做了什么",
  "time": "什么时候",
  "location": "在哪里"
}
缺少的信息填 null。`
      },
      {
        role: 'user',
        content: text
      }
    ],
  });

  return JSON.parse(response.choices[0].message.content);
}

const info = await extractInfo('张三昨天在公司写了一份报告');
console.log(info);
// { name: "张三", action: "写了一份报告", time: "昨天", location: "公司" }

💡 结构化输出是 Agent 开发的基础能力。在后面的 Function Calling 和工具调用中会大量使用。

2.8 小结 ​

本章你学到了:

  • ✅ LLM 的基本概念:Token、Temperature、上下文窗口
  • ✅ 消息角色:system、user、assistant、tool
  • ✅ 使用 OpenAI SDK 调用 API(也适用于 DeepSeek 等兼容服务)
  • ✅ 使用 Ollama 本地运行模型(免费方案)
  • ✅ 流式输出(Streaming)
  • ✅ 多轮对话与对话历史管理
  • ✅ API 安全和成本控制
  • ✅ 结构化输出(JSON Mode)

练习 ​

  1. 尝试用 OpenAI SDK 或 Ollama 运行本章的代码示例
  2. 修改 system prompt,让 AI 扮演不同角色(前端专家、产品经理、测试工程师)
  3. 实现一个简单的多轮对话 CLI 工具

下一章我们将深入学习提示词工程(Prompt Engineering),掌握与 LLM 高效沟通的技巧——这是开发高质量 Agent 的关键能力。

📖本文阅读--次|📊全站访问--次|👥访客--人