目 录CONTENT

文章目录

从后端工程师到 AI 工程师:我踩过的那些坑

PySuper
2026-01-17 / 0 评论 / 0 点赞 / 8 阅读 / 0 字
温馨提示:
所有牛逼的人都有一段苦逼的岁月。 但是你只要像SB一样去坚持,终将牛逼!!! ✊✊✊

一、思维转变:最难的不是技术

转型初期,我以为最大的挑战是学新东西。后来才发现,最难的是忘掉旧思维

1.1 从确定性到概率性

后端工程师的思维是确定性的:

# 后端思维:100% 确定
def get_user(user_id: int) -> User:
    user = db.query(User).filter(id == user_id).first()
    if user is None:
        raise UserNotFoundError()
    return user

同样的逻辑,在 AI 世界里是完全不同的:

# AI 思维:概率性结果
def classify_intent(user_message: str) -> str:
    response = llm.chat([
        {"role": "user", "content": f"分类: {user_message}"}
    ])
    # 同样的输入,可能每次输出不同
    # "今天天气怎么样" 可能被分类为:
    # - weather (80%)
    # - general (15%)
    # - schedule (5%)
    return parse_intent(response)

我的踩坑经历:曾经用传统单元测试的方式测试 Prompt,结果发现同一个测试用例跑 10 次有 3 次失败。一开始以为是 Prompt 问题,花了一周优化 Prompt,后来才发现这在 AI 系统里是正常现象

正确的做法

# 测试 AI 输出的分布,而不是单个结果
def test_intent_classification():
    """测试意图分类的稳定性"""
    test_cases = [
        "今天天气怎么样",
        "帮我订一个明天上午的会议",
        "查一下我的订单"
    ]
    
    results = defaultdict(list)
    
    # 每个用例跑 20 次
    for _ in range(20):
        for case in test_cases:
            intent = classify_intent(case)
            results[case].append(intent)
    
    # 检查主意图的一致性
    for case, intents in results.items():
        primary_intent = max(set(intents), key=intents.count)
        consistency = intents.count(primary_intent) / len(intents)
        
        # 一致性应该 > 90%,否则需要优化 Prompt
        assert consistency > 0.9, f"{case}: 一致性 {consistency} 过低"

1.2 从规则驱动到数据驱动

后端系统的逻辑是规则写死的

# 规则驱动:if-else 逻辑清晰
def calculate_discount(user: User, order: Order) -> float:
    if user.is_vip:
        if order.amount > 1000:
            return 0.2  # VIP + 大额 = 8折
        else:
            return 0.1  # VIP + 小额 = 9折
    else:
        if order.amount > 2000:
            return 0.05  # 普通 + 大额 = 95折
        else:
            return 0.0   # 普通 + 小额 = 不打折

AI 系统是数据驱动的,规则隐藏在模型参数里:

# 数据驱动:规则从数据中学习
class DiscountAgent:
    """折扣决策 Agent(不是写死的 if-else)"""
    
    def __init__(self, model, discount_history: List[DiscountCase]):
        # 通过示例学习折扣策略
        self.examples = discount_history
    
    def decide(self, user: User, order: Order) -> DiscountAgentOutput:
        prompt = f"""作为折扣决策专家,根据历史案例决定折扣力度。

历史案例:
{self._format_examples()}

当前用户:
- 会员等级: {user.level}
- 购买历史: {len(user.orders)} 单
- 投诉记录: {user.complaint_count} 次

当前订单:
- 金额: {order.amount}
- 商品类别: {order.category}
- 是否促销: {order.is_promotion}

请给出折扣建议,格式:
折扣比例: XX%
理由: XXX
"""
        
        return self.model.generate(prompt)

我的踩坑经历:刚开始做 AI 应用时,我本能地想用规则"兜底"——模型输出不可靠,那就加 if-else。结果代码越写越像传统的业务逻辑,AI 变成了"花式 if-else"的装饰器。

正确的做法:承认 AI 的不确定性,用工程手段处理(重试、ensemble、降级),而不是用规则覆盖。

二、技术栈扩展:需要补的课

从后端到 AI 工程师,技术栈扩展比我想象的大得多:

领域

后端工程师

AI 工程师

我的掌握程度

Python

⭐⭐⭐⭐⭐

⭐⭐⭐⭐⭐

已有

API 设计

⭐⭐⭐⭐⭐

⭐⭐⭐

已有

数据库

⭐⭐⭐⭐⭐

⭐⭐

需要补

容器化

⭐⭐⭐⭐

⭐⭐⭐⭐

已有

向量数据库

⭐⭐⭐

需要补

GPU 编程

⭐⭐

需要补

Prompt 工程

⭐⭐⭐⭐

需要学

模型微调

⭐⭐

需要学

MLOps

⭐⭐⭐

需要学

2.1 向量数据库:新的数据存储

向量数据库是 AI 时代的"新数据库",我一开始完全不理解它的价值。

我的踩坑:试图用 MySQL 的全文搜索替代向量检索,结果检索质量差到无法接受。

# ❌ 错误:用 MySQL 全文搜索做语义检索
def search_products_mysql(query: str) -> List[Product]:
    # 这种方式只能匹配关键词,无法理解语义
    # "想找一台跑机器学习快的电脑" 可能搜不到任何结果
    # 因为数据库里没有"机器学习"这个关键词
    products = db.query(Product).filter(
        Product.name.match(query) |
        Product.description.match(query)
    ).all()
    return products

# ✅ 正确:用向量数据库做语义检索
def search_products_vector(query: str) -> List[Product]:
    # 1. 把查询转成向量
    query_embedding = embedding_model.encode(query)
    
    # 2. 在向量数据库中检索
    results = vector_db.search(
        collection="products",
        query_vector=query_embedding,
        top_k=10
    )
    
    # 3. 返回相关产品
    return [Product.from_vector_result(r) for r in results]

2.2 GPU 编程:从零开始

作为后端工程师,我对 GPU 的了解仅限于"玩游戏用的显卡"。转型 AI 后发现,GPU 是 AI 的基础设施。

我的踩坑:第一次部署 vLLM 时,不知道需要 GPU,直接在普通服务器上跑,结果 CPU 推理慢到无法忍受。

# 检查服务器是否有 GPU
nvidia-smi

# 如果没有 GPU,需要使用云服务或更换服务器
# AWS: p3.2xlarge (Tesla V100)
# GCP: a2-highgpu-1g (A100)
# 阿里云: gn6v (V100)

2.3 Prompt 工程:新的编程范式

Prompt 工程是 AI 工程师的"新语言",但它跟传统编程完全不同:

# 传统编程:精确的指令
def add(a: int, b: int) -> int:
    return a + b

# Prompt 工程:模糊的指导
def classify_with_prompt(text: str) -> str:
    prompt = """
    请根据用户输入判断意图。
    
    # 注意
    - 这只是一个指导,不是硬性规则
    - 需要结合上下文理解
    - 如果不确定,请返回 "unknown"
    """
    # Prompt 的输出取决于模型理解,而不是代码逻辑

三、踩坑实录:五个刻骨铭心的教训

踩坑一:用传统 API 思维设计 LLM 接口

问题描述:我把 LLM 当成了普通的 REST API,用传统的接口设计思维来设计 AI 能力。

我的做法

# 传统 API 思维
class LLMService:
    def chat(self, user_input: str) -> str:
        """同步调用,直接返回结果"""
        response = openai.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": user_input}]
        )
        return response.choices[0].message.content
    
    def batch_process(self, inputs: List[str]) -> List[str]:
        """批量处理"""
        results = []
        for inp in inputs:
            # 串行调用,完全忽略 LLM 的特殊性
            results.append(self.chat(inp))
        return results

问题

  1. 超时问题:LLM 响应时间不确定,可能 1 秒也可能 60 秒

  2. 成本问题:没有预算控制,大流量直接破产

  3. 稳定性问题:API 有失败率,没有降级策略

  4. 一致性:同样的输入可能返回不同结果

正确的做法

# AI-native 接口设计
class LLMService:
    def __init__(self, config: LLMConfig):
        self.config = config
        self.cache = SemanticCache(...)  # 语义缓存
        self.budget_tracker = BudgetTracker(...)
        self.circuit_breaker = CircuitBreaker(...)
    
    async def chat(
        self,
        user_input: str,
        context: Dict = None,
        timeout: float = 30.0
    ) -> LLMResponse:
        """异步调用,带完整错误处理"""
        
        # 1. 检查缓存(70% 请求可以命中)
        cached = await self.cache.get(user_input)
        if cached:
            return LLMResponse(content=cached, source="cache")
        
        # 2. 检查预算
        if not self.budget_tracker.check():
            return LLMResponse(
                content="服务暂时不可用,请稍后重试",
                source="budget_limit"
            )
        
        # 3. 带超时和重试的调用
        try:
            response = await asyncio.wait_for(
                self._call_llm(user_input, context),
                timeout=timeout
            )
        except asyncio.TimeoutError:
            # 超时降级
            return self._degrade_response(user_input)
        except Exception as e:
            # 熔断保护
            if self.circuit_breaker.is_open():
                return self._fallback_response()
            raise
        
        # 4. 更新缓存和预算
        await self.cache.set(user_input, response.content)
        self.budget_tracker.record(response.usage)
        
        return response
    
    async def batch_chat(
        self,
        inputs: List[str],
        max_concurrency: int = 5
    ) -> List[LLMResponse]:
        """带并发控制的批量处理"""
        semaphore = asyncio.Semaphore(max_concurrency)
        
        async def bounded_call(inp: str) -> LLMResponse:
            async with semaphore:
                return await self.chat(inp)
        
        # 并发执行,充分利用 API 能力
        return await asyncio.gather(*[bounded_call(i) for i in inputs])

踩坑二:忽略成本管理

问题描述:作为后端工程师,我对"API 调用成本"完全没有概念。

我的教训:一个周末的自动化测试,烧掉了 2000 美元的 API 费用。

# ❌ 危险的做法:无限调用
def process_all_feedback():
    """处理所有用户反馈"""
    feedbacks = get_all_feedbacks()  # 假设有 100 万条
    
    results = []
    for fb in feedbacks:
        # 每条反馈都调用 LLM
        # 100万条 × $0.01 = $10,000
        result = llm.analyze(fb.content)
        results.append(result)
    
    return results

# ✅ 安全的做法:批量 + 预算控制
def process_all_feedback_safe():
    """带预算控制的批处理"""
    feedbacks = get_all_feedbacks()
    
    # 分批处理
    BATCH_SIZE = 100
    DAILY_BUDGET = 100  # 每天最多 $100
    
    total_cost = 0
    results = []
    
    for i in range(0, len(feedbacks), BATCH_SIZE):
        batch = feedbacks[i:i + BATCH_SIZE]
        
        # 检查预算
        batch_cost = estimate_cost(batch)
        if total_cost + batch_cost > DAILY_BUDGET:
            print(f"预算已达上限,停止处理")
            break
        
        # 批量处理(减少 API 调用次数)
        batch_result = await llm.batch_analyze(batch)
        results.extend(batch_result)
        total_cost += batch_result.cost
    
    return results

def estimate_cost(batch: List[Feedback]) -> float:
    """估算成本"""
    # 假设平均每个反馈 500 tokens
    avg_tokens = 500
    input_price = 0.001  # $0.001 / 1K tokens
    output_price = 0.003  # $0.003 / 1K tokens
    
    total_input = len(batch) * avg_tokens
    total_output = len(batch) * avg_tokens * 0.5  # 输出通常是输入的一半
    
    return (total_input * input_price + total_output * output_price) / 1000

成本监控配置

# config/cost_control.yaml
cost_control:
  daily_budget: 100.0          # 每日预算 $100
  monthly_budget: 2000.0       # 每月预算 $2000
  alert_threshold: 0.8         # 80% 时报警
  emergency_stop: 0.95        # 95% 时自动停止
  
  rate_limits:
    per_minute: 60             # 每分钟最多 60 次调用
    per_hour: 1000             # 每小时最多 1000 次
    per_day: 10000             # 每天最多 10000 次
  
  cache:
    enabled: true
    hit_target: 0.5           # 目标缓存命中率 50%
  
  model_routing:
    # 根据任务复杂度选择模型
    simple:
      - qwen2.5-3b              # 简单任务用小模型
    complex:
      - gpt-4o                  # 复杂任务用大模型

踩坑三:不做评测就上线

问题描述:Prompt 调好了,测试了几个 case 感觉不错,直接上线。结果用户一用,问题百出。

我的教训:用户说 AI "答非所问",我看了日志才发现 AI 把负面反馈识别成了正面。

# ❌ 错误:拍脑袋测试
def test_sentiment():
    test_cases = [
        "这个产品太棒了",  # 正面
        "质量太差了",       # 负面
    ]
    
    for case in test_cases:
        result = sentiment_analysis(case)
        print(f"{case} -> {result}")
    
    # 只测试了 2 个 case,就觉得没问题了
    # 实际上漏掉了大量边界情况

# ✅ 正确:系统性评测
class SentimentEvaluator:
    """情感分析评测器"""
    
    def __init__(self):
        self.test_suite = self._build_test_suite()
    
    def _build_test_suite(self) -> List[TestCase]:
        """构建测试套件"""
        return [
            # 明确情感
            TestCase("这个产品太棒了", "positive", "明确正面"),
            TestCase("质量太差了", "negative", "明确负面"),
            TestCase("一般般吧", "neutral", "中性"),
            
            # 讽刺
            TestCase("哇,你可真是个好产品啊", "negative", "讽刺"),
            TestCase("太棒了,又坏了", "negative", "讽刺"),
            
            # 双重否定
            TestCase("不是不好", "positive", "双重否定"),
            TestCase("我觉得不差", "positive", "双重否定"),
            
            # 混合情感
            TestCase("质量很好但是价格太贵", "mixed", "混合"),
            
            # 边界
            TestCase("", "unknown", "空输入"),
            TestCase("哈哈哈哈", "positive", "无情感词"),
            TestCase("F**k", "negative", "纯脏话"),
            
            # 领域特定
            TestCase("等了3天还没到", "negative", "物流投诉"),
            TestCase("客服态度恶劣", "negative", "服务投诉"),
        ]
    
    def evaluate(self, model) -> EvaluationResult:
        """全面评测"""
        results = []
        
        for case in self.test_suite:
            predicted = model.predict(case.input)
            is_correct = predicted == case.expected
            
            results.append({
                "input": case.input,
                "expected": case.expected,
                "predicted": predicted,
                "correct": is_correct,
                "category": case.category
            })
        
        # 分维度统计
        by_category = defaultdict(lambda: {"correct": 0, "total": 0})
        for r in results:
            by_category[r["category"]]["total"] += 1
            if r["correct"]:
                by_category[r["category"]]["correct"] += 1
        
        category_accuracy = {
            cat: data["correct"] / data["total"]
            for cat, data in by_category.items()
        }
        
        overall = sum(r["correct"] for r in results) / len(results)
        
        return EvaluationResult(
            overall_accuracy=overall,
            category_accuracy=category_accuracy,
            failed_cases=[r for r in results if not r["correct"]],
            recommendation=self._get_recommendation(overall, category_accuracy)
        )
    
    def _get_recommendation(self, overall, category_accuracy) -> str:
        if overall < 0.9:
            return "❌ 不建议上线,需要优化"
        if category_accuracy.get("讽刺", 0) < 0.8:
            return "⚠️ 上线后需重点监控讽刺检测"
        return "✅ 可以上线,建议持续监控"

踩坑四:Prompt 管理混乱

问题描述:Prompt 散落在代码各处,改一个 Prompt 要找半天,还容易改出问题。

我的教训:改了一个"通用" Prompt,结果影响了 5 个不同功能的输出格式。

# ❌ 混乱的 Prompt 管理
class ChatBot:
    def __init__(self):
        # Prompt 散落在代码里
        pass
    
    def handle_intent_classification(self, text):
        prompt = """请分类用户意图:..."""  # 这里一个 Prompt
        return self.llm.chat(prompt)
    
    def handle_sentiment(self, text):
        prompt = """请分析情感:..."""  # 另一个 Prompt
        return self.llm.chat(prompt)
    
    def handle_entity_extraction(self, text):
        prompt = """请提取实体:..."""  # 又一个 Prompt
        return self.llm.chat(prompt)

# ✅ 集中的 Prompt 管理
# config/prompts.yaml
prompts:
  intent_classification:
    template: |
      分析用户消息的意图,可选类别:
      - search: 需要搜索
      - order: 需要下单
      - query: 需要查询
      - complaint: 投诉
      - general: 一般对话
      
      用户消息: {input}
      
      只返回一个词。
    
    config:
      model: gpt-4o-mini
      temperature: 0
      max_tokens: 50
    
    examples:
      - input: "帮我查一下订单"
        output: "query"
      - input: "太差了,垃圾产品"
        output: "complaint"
  
  sentiment_analysis:
    template: |
      分析用户反馈的情感倾向:
      - positive: 正面
      - negative: 负面
      - neutral: 中性
      
      用户反馈: {input}
    config:
      model: gpt-4o-mini
      temperature: 0
# prompts/manager.py
"""Prompt 管理器"""
from pathlib import Path
import yaml
from typing import Dict, Optional
from dataclasses import dataclass
import hashlib

@dataclass
class PromptConfig:
    """Prompt 配置"""
    template: str
    config: Dict
    examples: list = None
    version: str = "1.0.0"

class PromptManager:
    """Prompt 管理器"""
    
    def __init__(self, config_path: str):
        self.config_path = Path(config_path)
        self.prompts: Dict[str, PromptConfig] = {}
        self._load()
        
        # Prompt 版本控制
        self.version_history: Dict[str, list] = {}
    
    def _load(self):
        """加载 Prompt 配置"""
        with open(self.config_path) as f:
            data = yaml.safe_load(f)
        
        for name, config in data.get("prompts", {}).items():
            self.prompts[name] = PromptConfig(
                template=config["template"],
                config=config.get("config", {}),
                examples=config.get("examples"),
                version=config.get("version", "1.0.0")
            )
    
    def render(self, name: str, **kwargs) -> tuple[str, Dict]:
        """渲染 Prompt"""
        if name not in self.prompts:
            raise ValueError(f"Prompt not found: {name}")
        
        prompt = self.prompts[name]
        
        # 填充变量
        rendered = prompt.template.format(**kwargs)
        
        # 添加 few-shot examples
        if prompt.examples:
            examples_text = "\n".join(
                f"示例: {e['input']} -> {e['output']}"
                for e in prompt.examples
            )
            rendered = f"{examples_text}\n\n{rendered}"
        
        return rendered, prompt.config
    
    def update(self, name: str, new_template: str, version: str = None):
        """更新 Prompt(带版本记录)"""
        if name not in self.prompts:
            raise ValueError(f"Prompt not found: {name}")
        
        old_prompt = self.prompts[name]
        
        # 记录历史
        if name not in self.version_history:
            self.version_history[name] = []
        
        self.version_history[name].append({
            "version": old_prompt.version,
            "template": old_prompt.template,
            "hash": hashlib.md5(old_prompt.template.encode()).hexdigest()
        })
        
        # 更新
        self.prompts[name] = PromptConfig(
            template=new_template,
            config=old_prompt.config,
            examples=old_prompt.examples,
            version=version or self._increment_version(old_prompt.version)
        )
        
        # 保存
        self._save()
    
    def _increment_version(self, version: str) -> str:
        """版本号递增"""
        parts = version.split(".")
        parts[-1] = str(int(parts[-1]) + 1)
        return ".".join(parts)
    
    def _save(self):
        """保存配置"""
        data = {
            "prompts": {
                name: {
                    "template": p.template,
                    "config": p.config,
                    "examples": p.examples,
                    "version": p.version
                }
                for name, p in self.prompts.items()
            }
        }
        
        with open(self.config_path, "w") as f:
            yaml.dump(data, f, allow_unicode=True)

踩坑五:忽视可观测性

问题描述:AI 系统上线后,用户说"不好用",但我看日志完全不知道哪里出了问题。

我的教训:一个复杂的 Agent 工作流,某一步出错了,但日志里只有最终结果,没有中间过程。

# ❌ 缺少可观测性
class Agent:
    def run(self, user_input: str):
        # 黑盒执行,出问题完全不知道哪一步出错
        intent = self.classify_intent(user_input)
        entities = self.extract_entities(user_input)
        response = self.generate(intent, entities)
        return response

# ✅ 完整可观测性
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor

class ObservableAgent:
    """可观测的 Agent"""
    
    def __init__(self):
        # 设置 tracing
        self.tracer = trace.get_tracer(__name__)
        
        # 记录每个步骤的输入输出
        self.step_logs: List[StepLog] = []
    
    def run(self, user_input: str):
        with self.tracer.start_as_current_span("agent_run") as span:
            # 添加上下文
            span.set_attribute("user_input.length", len(user_input))
            span.set_attribute("user_input.preview", user_input[:100])
            
            try:
                # 步骤 1:意图分类
                with self.tracer.start_as_current_span("intent_classification"):
                    span = trace.get_current_span()
                    span.set_attribute("step", "intent_classification")
                    
                    intent = self.classify_intent(user_input)
                    
                    span.set_attribute("intent.result", intent)
                    span.set_attribute("intent.confidence", intent.get("confidence", 0))
                    
                    self.step_logs.append(StepLog(
                        step="intent_classification",
                        input=user_input,
                        output=intent,
                        duration_ms=0,  # 计算实际耗时
                        status="success"
                    ))
                
                # 步骤 2:实体提取
                with self.tracer.start_as_current_span("entity_extraction"):
                    span = trace.get_current_span()
                    span.set_attribute("step", "entity_extraction")
                    
                    entities = self.extract_entities(user_input)
                    
                    span.set_attribute("entities.count", len(entities))
                    span.set_attribute("entities.types", list(entities.keys()))
                    
                    self.step_logs.append(StepLog(
                        step="entity_extraction",
                        input=user_input,
                        output=entities,
                        duration_ms=0,
                        status="success"
                    ))
                
                # 步骤 3:响应生成
                with self.tracer.start_as_current_span("response_generation"):
                    span = trace.get_current_span()
                    span.set_attribute("step", "response_generation")
                    
                    response = self.generate(intent, entities)
                    
                    span.set_attribute("response.length", len(response))
                    span.set_attribute("response.tokens_used", response.usage.total_tokens)
                    
                    self.step_logs.append(StepLog(
                        step="response_generation",
                        input={"intent": intent, "entities": entities},
                        output=response.content,
                        duration_ms=0,
                        status="success"
                    ))
                
                span.set_attribute("result.success", True)
                return response
                
            except Exception as e:
                span.set_attribute("result.success", False)
                span.set_attribute("error.type", type(e).__name__)
                span.set_attribute("error.message", str(e))
                
                self.step_logs.append(StepLog(
                    step="unknown",
                    input=user_input,
                    output=None,
                    duration_ms=0,
                    status="failed",
                    error=str(e)
                ))
                
                raise
# config/observability.yaml
observability:
  tracing:
    enabled: true
    exporter: jaeger           # jaeger / zipkin / otlp
    sampling_rate: 1.0          # 全量采样(调试时)
    # sampling_rate: 0.1       # 采样 10%(生产时)
  
  metrics:
    enabled: true
    interval_seconds: 10
      
    custom_metrics:
      - name: llm_request_duration
        type: histogram
        buckets: [0.1, 0.5, 1, 2, 5, 10, 30]
      
      - name: llm_token_usage
        type: counter
        labels: [model, type]
      
      - name: llm_cache_hit_rate
        type: gauge
      
      - name: agent_step_duration
        type: histogram
        labels: [step_name]
  
  logging:
    enabled: true
    level: INFO
    
    structured: true            # JSON 格式日志
    
    masks:                     # 敏感字段脱敏
      - user_id
      - phone
      - email
      - token

四、转型路线图

基于我的踩坑经历,总结一条相对平稳的转型路线:

┌─────────────────────────────────────────────────────────────────┐
│                      AI 工程师转型路线图                         │
│                                                                 │
│  第一阶段:LLM Ops (1-2个月)                                    │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • Prompt 工程基础                                       │   │
│  │ • API 调用(OpenAI、Claude、本地模型)                   │   │
│  │ • 基本可观测性(日志、metrics)                          │   │
│  │ • 语义缓存                                               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           ↓                                     │
│  第二阶段:AI Infra (2-3个月)                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • vLLM / Ollama 部署                                     │   │
│  │ • 向量数据库(Milvus / Qdrant)                          │   │
│  │ • 模型选型与评测                                         │   │
│  │ • GPU 基础                                               │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           ↓                                     │
│  第三阶段:Agent 工程化 (2-3个月)                                │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • LangGraph / Agent 框架                                 │   │
│  │ • RAG 工程化                                             │   │
│  │ • 工具调用设计                                           │   │
│  │ • 复杂工作流编排                                         │   │
│  └─────────────────────────────────────────────────────────┘   │
│                           ↓                                     │
│  第四阶段:高级能力 (持续学习)                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │ • 模型微调(LoRA / QLoRA)                               │   │
│  │ • Agent 内存管理                                         │   │
│  │ • 多模态应用                                             │   │
│  │ • AI 安全与合规                                          │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

4.1 每日学习计划

时间

内容

资源

30 分钟

阅读 AI 工程化博客/论文

PySuper, Lil'Log, The Batch

1 小时

动手实践小项目

GitHub examples

30 分钟

复盘当天踩坑

个人 wiki

周末

深入学习一个主题

Coursera, deeplearning.ai

4.2 关键里程碑

  1. 第一个可用的 AI 应用(第 1 周):一个简单的 Chatbot

  2. 第一个 RAG 应用(第 2 周):文档问答系统

  3. 第一个 Agent 应用(第 1 个月):带工具调用的 Agent

  4. 第一个生产项目(第 3 个月):完整上线一个 AI 功能

  5. 第一个生产系统(第 6 个月):多个 AI 功能的统一平台

五、给后来者的建议

5.1 技术层面

  1. 不要忽视基础:Python、API 设计、数据库这些基础能力依然重要

  2. 动手最重要:看 10 篇教程不如做 1 个小项目

  3. 保持谦逊:AI 发展太快,今天的正确可能明天就过时

  4. 关注工程化:模型能力固然重要,但工程能力决定你能不能把它用好

5.2 心态层面

  1. 接受不确定性:AI 系统的输出本身就是不确定的,要学会与之共处

  2. 拥抱变化:AI 领域的工具和最佳实践还在快速迭代

  3. 保持耐心:转型需要时间,不要期望一周就能成为专家

  4. 记录成长:写博客、记笔记,这是你回顾和分享的基础

5.3 职业层面

  1. 找到自己的定位:不是每个人都要成为 Prompt 工程专家或 AI Infra 专家

  2. 与业务结合:纯技术很难体现价值,要找到 AI 与业务的结合点

  3. 建立影响力:分享你的经验,这会加速你的成长

  4. 持续学习:AI 领域的学习永远不会停止

总结

从后端工程师到 AI 工程师,这一年我踩的坑比过去五年后端生涯加起来都多。但我从不后悔这个选择。

最大的收获

  1. 思维升级:从确定性思维到概率性思维,从规则驱动到数据驱动

  2. 技术广度:向量数据库、GPU 编程、Prompt 工程... 技术栈大幅扩展

  3. 影响力提升:从"写接口的"到"做 AI 系统的",价值定位完全不同

最痛的教训

  1. AI 系统不是传统系统的简单升级,需要全新的工程思维

  2. 成本控制和可观测性比技术本身更重要

  3. 没有评测就没有优化,没有优化就没有改进

如果你也在考虑转型,希望我的经历能给你一些参考。AI 工程化是一条充满挑战但也充满机遇的路,走下去,你会发现一个全新的世界。


相关阅读

  • 第32篇:AI 工程化的三层架构:模型层 / 平台层 / 应用层

  • 第31篇:vLLM 0.20.0 生产部署实战

  • 第34篇:2026 年 AI 工程化:我们到了哪里,还要走多远

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区