从完全不懂AI到能独立开发AI应用,我只用了3个月。这篇文章分享我的学习路径和踩过的坑,帮你少走弯路。

开篇:为什么我要学AI应用开发?

去年年底,我在公司的一次技术分享会上被问到:"你们前端能不能做一个智能客服?"当时的我一脸懵逼——我知道ChatGPT很火,但怎么把它变成一个真正能用的产品?完全没有头绪。

作为一个写了10年前端的老程序员,我突然意识到一个问题:AI不再是遥不可及的"黑科技",它已经变成了一个工程问题。 而工程问题,正是我们开发者擅长解决的。

这篇文章,我想分享从零开始学习AI应用开发的完整路径。不是教你训练模型(那是算法工程师的活儿),而是教你如何用现成的AI能力,快速构建实际可用的应用

读完这篇文章,你将学到:

  • AI应用开发的核心概念和技术栈
  • 3个可以立即上手的实战项目
  • 我在英博云平台部署AI应用的真实经验
  • 新手最容易踩的5个坑以及解决方案

背景知识:AI应用开发到底在开发什么?

在深入之前,我们需要先搞清楚一个问题:AI应用开发和传统开发有什么区别?

传统开发 vs AI应用开发

用一个类比来说明:

对比项 传统开发 AI应用开发
逻辑来源 开发者编写的规则 模型"学习"出来的能力
输入输出 确定性的 概率性的(同样输入可能不同输出)
调试方式 断点、日志 Prompt调优、上下文管理
核心技能 编程语言、框架 Prompt工程、API调用、上下文设计

简单说,AI应用开发的核心是"调用"而不是"实现"。大模型已经具备了理解、推理、生成的能力,我们要做的是:

  1. 设计好输入(Prompt工程)
  2. 调用API获取结果
  3. 处理输出并呈现给用户

AI应用的技术架构

一个典型的AI应用架构是这样的:

┌─────────────────────────────────────────────────────────┐
│                      前端 (用户界面)                      │
│              Vue/React + 流式输出 + 消息展示              │
└─────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│                      后端 (业务逻辑)                      │
│        Prompt管理 + 上下文管理 + API调用 + 会话管理       │
└─────────────────────────────────────────────────────────┘
                            │
                            ▼
┌─────────────────────────────────────────────────────────┐
│                    AI服务 (大模型能力)                    │
│         OpenAI API / Claude API / 私有化部署模型          │
└─────────────────────────────────────────────────────────┘

对于前端开发者来说,这个架构其实很熟悉——不就是前后端分离吗?只不过后端多了一层AI服务的调用。

核心原理:AI应用开发的三个关键概念

1. Prompt工程:和AI"说话"的艺术

Prompt就是你给AI的指令。同样的问题,不同的Prompt会得到完全不同的结果。

一个糟糕的Prompt:

帮我写个代码

一个好的Prompt:

你是一个资深的JavaScript开发者。请帮我实现一个防抖函数,要求:
1. 支持立即执行模式
2. 支持取消功能
3. 使用TypeScript编写
4. 添加完整的类型注解

💡 经验分享:Prompt工程的本质是"减少歧义"。你给AI的上下文越清晰,它的输出就越符合预期。

2. 上下文管理:AI的"记忆"

大模型本身是"无状态"的——它不会记得上一轮对话说了什么。所谓的"记忆",其实是我们在每次请求时把历史对话一起发送给它。

// 这就是为什么每次请求都要带上历史消息
const messages = [
  { role: 'system', content: '你是一个helpful的助手' },
  { role: 'user', content: '什么是JavaScript?' },
  { role: 'assistant', content: 'JavaScript是一门编程语言...' },
  { role: 'user', content: '它和TypeScript有什么区别?' }  // 当前问题
];

这带来一个问题:上下文长度有限。 大多数模型有最大Token限制(比如GPT-4是8K或128K),超过限制就会报错。所以我们需要设计策略来管理上下文:

  • 滑动窗口:只保留最近N轮对话
  • 摘要压缩:用AI总结历史对话
  • 重要性筛选:保留关键信息,删除无关内容

3. 流式输出:提升用户体验的关键

如果你用过ChatGPT,会发现它的回复是"打字机"效果,一个字一个字出来。这不是为了好看,而是因为:

  1. AI生成需要时间,流式输出让用户不用等完整响应
  2. 用户可以实时看到生成内容,体验更好
  3. 如果生成内容不对,可以及时中断

前端实现流式输出的关键代码:

async function streamChat(prompt: string, onChunk: (text: string) => void) {
  const response = await fetch('/api/chat', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ prompt }),
  });

  const reader = response.body?.getReader();
  const decoder = new TextDecoder();

  while (true) {
    const { done, value } = await reader!.read();
    if (done) break;

    const chunk = decoder.decode(value);
    onChunk(chunk);  // 每收到一块数据就回调
  }
}

// 使用示例
let fullText = '';
await streamChat('写一首诗', (chunk) => {
  fullText += chunk;
  updateUI(fullText);  // 实时更新界面
});

实战代码:三个快速上手的AI项目

理论说了这么多,来点实际的。我整理了3个适合入门的项目,按难度递增排列。

项目1:智能翻译助手(难度:⭐)

这是最简单的入门项目,核心就是调用一次API。

// translate.ts
import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({
  apiKey: process.env.ANTHROPIC_API_KEY,
});

async function translate(text: string, targetLang: string): Promise<string> {
  const message = await client.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 1024,
    messages: [
      {
        role: 'user',
        content: `请将以下文本翻译成${targetLang},只返回翻译结果,不要解释:

${text}`
      }
    ]
  });

  // 提取文本内容
  const content = message.content[0];
  if (content.type === 'text') {
    return content.text;
  }
  throw new Error('Unexpected response type');
}

// 使用
const result = await translate('Hello, world!', '中文');
console.log(result);  // 你好,世界!

学习重点

  • 如何安装和配置AI SDK
  • 基本的API调用方式
  • Prompt的基本写法

项目2:代码Review助手(难度:⭐⭐)

这个项目需要处理更复杂的输入(代码片段),并输出结构化的结果。

// code-reviewer.ts
import Anthropic from '@anthropic-ai/sdk';

interface ReviewResult {
  score: number;
  issues: Array<{
    severity: 'error' | 'warning' | 'info';
    line?: number;
    message: string;
    suggestion: string;
  }>;
  summary: string;
}

async function reviewCode(code: string, language: string): Promise<ReviewResult> {
  const client = new Anthropic();

  const systemPrompt = `你是一个代码审查专家。请审查用户提供的${language}代码,并以JSON格式返回审查结果。

返回格式必须是:
{
  "score": 0-100的评分,
  "issues": [
    {
      "severity": "error" | "warning" | "info",
      "line": 行号(如果适用),
      "message": "问题描述",
      "suggestion": "修改建议"
    }
  ],
  "summary": "整体评价"
}

审查维度包括:代码规范、潜在bug、性能问题、安全隐患、可读性。`;

  const message = await client.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 2048,
    system: systemPrompt,
    messages: [
      {
        role: 'user',
        content: `请审查以下代码:\n\n\`\`\`${language}\n${code}\n\`\`\``
      }
    ]
  });

  const content = message.content[0];
  if (content.type === 'text') {
    // 从Markdown代码块中提取JSON
    const jsonMatch = content.text.match(/```json\n?([\s\S]*?)\n?```/);
    const jsonStr = jsonMatch ? jsonMatch[1] : content.text;
    return JSON.parse(jsonStr);
  }
  throw new Error('Unexpected response type');
}

// 使用示例
const code = `
function add(a, b) {
  return a + b
}
`;

const result = await reviewCode(code, 'javascript');
console.log(result);
// {
//   score: 70,
//   issues: [
//     { severity: 'warning', message: '缺少类型注解', suggestion: '使用TypeScript...' },
//     { severity: 'info', message: '缺少分号', suggestion: '建议添加分号...' }
//   ],
//   summary: '代码功能正确,但缺少类型安全和一些最佳实践...'
// }

学习重点

  • System Prompt的使用
  • 结构化输出的处理
  • JSON解析和错误处理

项目3:多轮对话机器人(难度:⭐⭐⭐)

这是一个完整的对话系统,需要管理会话状态和上下文。

// chatbot.ts
import Anthropic from '@anthropic-ai/sdk';

interface Message {
  role: 'user' | 'assistant';
  content: string;
}

class ChatBot {
  private client: Anthropic;
  private messages: Message[] = [];
  private systemPrompt: string;
  private maxContextLength = 10;  // 最多保留10轮对话

  constructor(systemPrompt: string) {
    this.client = new Anthropic();
    this.systemPrompt = systemPrompt;
  }

  async chat(userMessage: string): Promise<string> {
    // 添加用户消息
    this.messages.push({ role: 'user', content: userMessage });

    // 控制上下文长度
    if (this.messages.length > this.maxContextLength * 2) {
      this.messages = this.messages.slice(-this.maxContextLength * 2);
    }

    // 调用API
    const response = await this.client.messages.create({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 1024,
      system: this.systemPrompt,
      messages: this.messages,
    });

    const content = response.content[0];
    if (content.type !== 'text') {
      throw new Error('Unexpected response type');
    }

    const assistantMessage = content.text;

    // 保存助手回复
    this.messages.push({ role: 'assistant', content: assistantMessage });

    return assistantMessage;
  }

  // 流式对话
  async *streamChat(userMessage: string): AsyncGenerator<string> {
    this.messages.push({ role: 'user', content: userMessage });

    if (this.messages.length > this.maxContextLength * 2) {
      this.messages = this.messages.slice(-this.maxContextLength * 2);
    }

    const stream = this.client.messages.stream({
      model: 'claude-sonnet-4-20250514',
      max_tokens: 1024,
      system: this.systemPrompt,
      messages: this.messages,
    });

    let fullResponse = '';

    for await (const event of stream) {
      if (event.type === 'content_block_delta' && event.delta.type === 'text_delta') {
        fullResponse += event.delta.text;
        yield event.delta.text;
      }
    }

    this.messages.push({ role: 'assistant', content: fullResponse });
  }

  clearHistory(): void {
    this.messages = [];
  }

  getHistory(): Message[] {
    return [...this.messages];
  }
}

// 使用示例
const bot = new ChatBot('你是一个友好的编程助手,专门帮助前端开发者解决问题。');

// 普通对话
const reply1 = await bot.chat('什么是React Hooks?');
console.log(reply1);

const reply2 = await bot.chat('给我一个useState的例子');
console.log(reply2);  // AI会记得上下文,知道在讨论React Hooks

// 流式对话
process.stdout.write('AI: ');
for await (const chunk of bot.streamChat('再给我一个useEffect的例子')) {
  process.stdout.write(chunk);
}
console.log();

学习重点

  • 会话状态管理
  • 上下文长度控制
  • 流式API的使用
  • 面向对象的封装

英博云部署实战

代码写好了,怎么部署呢?我在英博云平台上部署过几个AI应用,分享一下实际经验。

为什么选择英博云?

作为一个前端开发者,我在选择AI部署平台时考虑几个因素:

  1. 简单易用:不想搞复杂的Docker和K8s配置
  2. 成本可控:按量付费,初期成本低
  3. 性能稳定:API延迟要低,不能卡顿

英博云平台在这几方面都做得不错,特别是它提供的一站式AI部署服务,对于不熟悉运维的前端开发者很友好。

部署步骤

  1. 准备Node.js项目
# 项目结构
my-ai-app/
├── src/
│   ├── index.ts       # 入口文件
│   └── chatbot.ts     # 聊天机器人实现
├── package.json
├── tsconfig.json
└── .env.example
  1. 配置环境变量
# .env.example
ANTHROPIC_API_KEY=your-api-key
PORT=3000
  1. 创建简单的HTTP服务
// src/index.ts
import express from 'express';
import cors from 'cors';
import { ChatBot } from './chatbot';

const app = express();
app.use(cors());
app.use(express.json());

// 会话存储(生产环境建议用Redis)
const sessions = new Map<string, ChatBot>();

app.post('/api/chat', async (req, res) => {
  const { sessionId, message, systemPrompt } = req.body;

  // 获取或创建会话
  let bot = sessions.get(sessionId);
  if (!bot) {
    bot = new ChatBot(systemPrompt || '你是一个友好的AI助手');
    sessions.set(sessionId, bot);
  }

  try {
    // 设置流式响应
    res.setHeader('Content-Type', 'text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    for await (const chunk of bot.streamChat(message)) {
      res.write(`data: ${JSON.stringify({ text: chunk })}\n\n`);
    }

    res.write('data: [DONE]\n\n');
    res.end();
  } catch (error) {
    console.error('Chat error:', error);
    res.status(500).json({ error: 'Internal server error' });
  }
});

app.post('/api/clear', (req, res) => {
  const { sessionId } = req.body;
  const bot = sessions.get(sessionId);
  if (bot) {
    bot.clearHistory();
  }
  res.json({ success: true });
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});
  1. 在英博云上部署

英博云平台创建应用后,通过Git推送或者直接上传代码包即可完成部署。平台会自动检测Node.js项目并安装依赖。

踩坑经验

部署过程中我遇到了几个问题:

坑1:环境变量没生效

解决:在英博云控制台的"环境变量"中配置,不要写在代码里

坑2:冷启动太慢

解决:开启"预热"功能,保持至少1个实例常驻

坑3:流式响应被中断

解决:检查Nginx配置,需要关闭proxy_buffering

新手最容易踩的5个坑

总结一下我在学习AI应用开发过程中踩过的坑:

坑1:Prompt写得太模糊

错误示范

帮我处理一下这个数据

正确做法

请将以下JSON数据转换为CSV格式。
要求:
1. 第一行是表头
2. 日期格式统一为YYYY-MM-DD
3. 数值保留两位小数

数据:
{...}

坑2:忽视Token限制

每次请求都有Token限制,超过限制会报错。新手经常把整个文件都塞进去。

解决方案

  • 预估Token数量(粗略规则:1个中文字≈2 tokens,1个英文单词≈1-2 tokens)
  • 对长文本进行分块处理
  • 使用滑动窗口管理上下文
  • 调用API前检查输入长度
// 简单的Token估算(适用于大多数场景)
function estimateTokens(text: string): number {
  // 中文字符数 * 2 + 英文单词数
  const chineseChars = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
  const englishWords = text.replace(/[\u4e00-\u9fa5]/g, '').split(/\s+/).filter(Boolean).length;
  return chineseChars * 2 + englishWords;
}

// 使用前检查
const inputText = '你的长文本...';
const estimatedTokens = estimateTokens(inputText);
if (estimatedTokens > 8000) {
  console.warn('输入可能过长,考虑分块处理');
}

💡 不同模型的Token计算方式略有不同。OpenAI模型可以用tiktoken库精确计算,Claude模型可以用@anthropic-ai/tokenizer。但在实际开发中,上面的估算方法对于大多数场景已经够用。

坑3:没有处理API错误

AI API可能因为各种原因失败:限流、超时、服务器错误。

// 辅助函数:延迟执行
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// 带重试的安全调用
async function safeCall<T>(fn: () => Promise<T>, retries = 3): Promise<T> {
  for (let i = 0; i < retries; i++) {
    try {
      return await fn();
    } catch (error: any) {
      if (error.status === 429) {
        // 限流,等待后重试(指数退避)
        await sleep(Math.pow(2, i) * 1000);
        continue;
      }
      throw error;
    }
  }
  throw new Error('Max retries exceeded');
}

// 使用示例
const result = await safeCall(() => client.messages.create({
  model: 'claude-sonnet-4-20250514',
  max_tokens: 1024,
  messages: [{ role: 'user', content: '你好' }]
}));

坑4:过度依赖AI输出

AI的输出不是100%可靠的,可能有:

  • 格式不符合预期
  • 内容不准确(幻觉)
  • 输出被截断

解决方案

  • 始终做输出验证
  • 对关键信息做二次确认
  • 设置合理的max_tokens

坑5:忽视成本控制

API调用是收费的,不注意可能很快烧光预算。

建议

  • 使用cheaper的模型处理简单任务
  • 缓存重复请求的结果
  • 设置每日/每月用量上限
  • 监控token使用量
class CostTracker {
  private totalTokens = 0;
  private dailyLimit = 100000;

  track(inputTokens: number, outputTokens: number) {
    this.totalTokens += inputTokens + outputTokens;
    if (this.totalTokens > this.dailyLimit) {
      throw new Error('Daily token limit exceeded');
    }
  }
}

总结与建议

回顾这3个月的学习历程,我最大的感受是:AI应用开发比想象中简单,但也比想象中有深度。

核心收获

  1. Prompt工程是核心技能:写好Prompt比写代码更重要
  2. 工程化思维依然适用:错误处理、性能优化、成本控制一样重要
  3. 前端技能很有优势:流式输出、用户体验优化是我们的强项
  4. 实战是最好的老师:看100篇文章不如动手写一个项目

给前端开发者的建议

  1. 从简单项目开始:先做个翻译工具或写作助手,建立信心
  2. 学好Prompt工程:推荐看Anthropic和OpenAI的官方Prompt指南
  3. 关注新工具和框架:LangChain、Vercel AI SDK等都值得研究
  4. 加入社区:多看别人的项目和实践,避免重复踩坑
  5. 保持耐心:AI技术迭代很快,但基础原理是稳定的

后续学习计划

接下来我打算深入学习:

  • RAG(检索增强生成):让AI能够使用企业内部知识
  • Agent开发:让AI能够调用工具、完成复杂任务
  • 微调和本地部署:在英博云平台尝试部署开源模型

如果你对这些话题感兴趣,欢迎关注我的后续文章!

参考资源


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐