AI面试八股文-04_4-AI项目实战经验面试题

0 阅读17分钟

pdf版下载链:https://pan.quark.cn/s/9cc742e9c2a8

04 AI 项目实战:项目表达、成本优化与冷启动

难度: ⭐⭐⭐⭐⭐ 更新: 2026-10-12 考点: 项目描述、技术选型、难点突破、性能优化

真实性说明:本文中的公司名、流量、准确率、成本和提升比例是 STAR 回答的演示占位值,不是行业基准,也不能直接冒充个人经历。面试时只使用自己可解释、可复现的数据,并说明样本量、指标定义、评测集和时间窗口。

截至 2026-10 的项目表达原则

  1. 不再把 GPT-3.5/GPT-4 + LangChain 当“当前标准栈”;它们可作为历史项目背景,当前方案用 FAST_MODEL / STRONG_MODEL / REASONING_MODEL 等能力别名并通过评测路由。
  2. 优先讲系统边界:数据权限、索引更新、状态持久化、工具幂等、审批、可观测和回滚,而不是罗列框架名。
  3. reasoning/Agent 项目要说明完成条件、预算、工具验证和人工接管;不能用“模型会反思”代替可靠性设计。
  4. 时效性强的型号、价格和上下文从供应商官方文档读取并配置化,不写死在业务代码或面试材料中。

📋 目录

  1. RAG系统项目
  2. AI Agent项目
  3. LLM应用项目
  4. 多模态项目
  5. 优化类项目
  6. 项目回答技巧

一、RAG系统项目

图解:RAG 项目回答的工程主线

在这里插入图片描述

Q1: "请介绍一下你做过的RAG系统项目"

💡 STAR回答模板

S (Situation - 背景):

"我在xx公司负责开发一个企业级知识库问答系统,主要服务内部员工查询公司文档、政策、技术文档等。知识库包含5000+文档,总计200万字,涵盖HR、技术、产品等多个领域。"

T (Task - 任务):

"项目目标是实现:

  1. 准确率>85% (用户满意度)
  2. 平均响应时间<2秒
  3. 成本可控(月<$500)
  4. 支持中英文混合查询"

A (Action - 行动):

  1. 技术架构设计
# 技术栈选择
向量数据库: Qdrant (开源,支持混合检索)
Embedding候选: Qwen3-Embedding / BGE-M3 / 托管Embedding (用领域集实测)
LLM: FAST_MODEL + STRONG_MODEL (按任务评测路由)
编排: 供应商SDK + 显式工作流/状态机;需要持久状态时可选LangGraph等

# 核心流程
用户提问 → Query改写(补充上下文)
         → 混合检索(BM25 + 语义)
         → Rerank精排(BGE-Reranker)
         → 上下文压缩(LLMLingua)
         → LLM生成答案
         → 引用来源标注
  1. 关键优化点

(1) 分块策略优化

# 问题: 固定512 token分块效果差
# 原因: 切断了语义完整性

# 解决: 语义分块 + 重叠
from langchain.text_splitter import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,           # 略大,保留更多上下文
    chunk_overlap=200,        # 20%重叠,避免边界问题
    separators=["\n\n", "\n", "。", ".", " "],  # 优先按段落
)

# 效果: 召回率 68% → 79%

(2) 混合检索实现

def hybrid_search(query, top_k=20):
    # BM25检索
    bm25_results = bm25_retriever.search(query, k=top_k)

    # 向量检索
    vector_results = vector_db.search(
        embedding_model.encode(query),
        k=top_k
    )

    # RRF融合
    final_results = reciprocal_rank_fusion(
        [bm25_results, vector_results],
        k=60
    )

    return final_results[:10]  # 取top-10

# 效果: 召回率 79% → 87%

(3) Rerank精排

from sentence_transformers import CrossEncoder

# 示例候选;截至 2026-10 也应评测 Qwen3-Reranker / 托管 Rerank API
reranker = CrossEncoder(RERANKER_MODEL)

def rerank(query, candidates):
    # 计算query与每个candidate的相关性分数
    scores = reranker.predict([
        [query, doc.content] for doc in candidates
    ])

    # 按分数排序
    ranked = sorted(
        zip(candidates, scores),
        key=lambda x: x[1],
        reverse=True
    )

    return [doc for doc, _ in ranked[:5]]

# 效果: 精确率 73% → 89%

(4) 成本优化 - 语义缓存

from langchain.cache import RedisSemanticCache

# 相似问题直接返回缓存答案
cache = RedisSemanticCache(
    redis_url="redis://localhost:6379",
    embedding=embedding_model,
    score_threshold=0.85  # 相似度>0.85命中缓存
)

# 命中率和节省比例必须来自线上分桶统计

语义缓存键至少包含 tenant、ACL、知识库版本、Prompt/模型版本和时效标签;不能只按相似度跨用户复用答案。

R (Result - 结果):

"项目上线后:

  • 准确率达到89% (超过目标85%)
  • P95响应时间1.8秒 (目标<2秒)
  • 月成本 **320∗∗(低于320**(低于 500 目标)
  • 日均处理**2000+**次查询
  • 用户满意度4.3/5

核心突破点:

  1. 混合检索+Rerank,召回率提升19%
  2. 语义缓存,成本降低35%
  3. 语义分块,召回率提升11%"

面试追问应对:

Q: "为什么选择Qdrant而不是Pinecone/Milvus?"

"我们对比了3个方案:

  • Pinecone: 云服务,易用但贵($70/月起)
  • Milvus: 功能强大但部署复杂,需要K8s
  • Qdrant: 开源免费,Docker部署简单,支持混合检索⭐

我们团队已有自托管能力,因此选择 Qdrant。自部署不等于成本为 0,还要计入计算、存储、备份、升级、告警和人力。"

Q: "遇到的最大难点是什么?怎么解决的?"

"最大难点是长文档检索不准。

问题现象:

  • 用户问'请假流程',检索到的chunk是'考勤制度第3章',但答案在第5章
  • 召回率只有68%

分析原因:

  • 固定512 token分块,切断了语义
  • 标题和正文分离,丢失了上下文

解决方案:

  1. 语义分块: 按段落/标题层级切分
  2. 增加chunk_overlap: 200 token重叠
  3. Parent-Child索引: 检索时返回父chunk

效果: 召回率68%→79%,提升16%"

Q: "如果让你重新设计,会怎么改进?"

"3个改进方向:

  1. 引入HyDE (假设性文档嵌入)
  • 当前: 直接用用户问题检索
  • 改进: 先让LLM生成假设答案,用假设答案检索
  • 验证: 在指代/短查询子集做消融,防止查询漂移
  1. 多路召回+学习排序
  • 当前: BM25 + Vector 两路
  • 改进: + 时间相关性 + 用户历史偏好
  • 预期: 个性化提升
  1. Fine-tune Embedding模型
  • 当前: 通用bge模型
  • 改进: 在企业文档上微调
  • 验证: 与更换基础模型、困难负例训练做同预算对比"

Q2: "RAG系统中遇到的召回率低问题,怎么解决的?"

图解:召回率低的排查路径

在这里插入图片描述

💡 答案要点

问题分析:

召回率低 = 相关文档没检索到

可能原因:
1. 分块策略不合理
2. Embedding模型不适配
3. 只用单一检索方式
4. Query表达不清晰

诊断步骤:

Step 1: 建立评估数据集

# 构建100条标准问答对
test_dataset = [
    {
        "question": "员工请假超过3天需要什么审批?",
        "ground_truth_docs": ["doc_123", "doc_456"],  # 应该检索到的文档ID
        "ideal_answer": "超过3天需要部门经理+HR审批"
    },
    # ... 100条
]

# 计算Recall@K
def evaluate_recall(retriever, dataset, k=5):
    total_recall = 0
    for item in dataset:
        retrieved = retriever.search(item["question"], k=k)
        retrieved_ids = [doc.id for doc in retrieved]

        # 计算召回了多少ground_truth
        hits = len(set(retrieved_ids) & set(item["ground_truth_docs"]))
        recall = hits / len(item["ground_truth_docs"])
        total_recall += recall

    return total_recall / len(dataset)

# 基线: Recall@5 = 0.68

Step 2: 逐项优化

(1) 优化分块 (+11% Recall)

# Before: 固定长度
splitter_old = RecursiveCharacterTextSplitter(chunk_size=512)

# After: 语义分块 + 元数据
from langchain.text_splitter import MarkdownTextSplitter

splitter_new = MarkdownTextSplitter(
    chunk_size=800,
    chunk_overlap=200,
    # 保留标题层级
    add_start_index=True
)

# 添加元数据
for chunk in chunks:
    chunk.metadata = {
        "source": doc.source,
        "title": extract_title(chunk),
        "section": extract_section(chunk),
        "page": chunk.page
    }

# Recall: 0.68 → 0.79 (+11%)

(2) 混合检索 (+8% Recall)

# Before: 只用向量检索
vector_results = vector_db.search(query)

# After: BM25 + Vector + RRF
def hybrid_retrieval(query, k=20):
    # BM25擅长关键词
    bm25_results = bm25.search(query, k=k)

    # Vector擅长语义
    vector_results = vector_db.search(
        embed(query), k=k
    )

    # RRF融合
    return rrf_fusion([bm25_results, vector_results], k=60)

# Recall: 0.79 → 0.87 (+8%)

(3) Query改写 (+5% Recall)

# Before: 直接用用户原始问题
query = "请假流程"  # 太简短,语义不明

# After: LLM扩展query
def expand_query(query):
    prompt = f"""
    原始问题: {query}

    请生成3个相关的扩展查询,帮助检索:
    1. 同义词替换
    2. 补充上下文
    3. 细化问题

    示例:
    原始: "请假流程"
    扩展:
    1. "员工请假审批流程"
    2. "如何申请休假"
    3. "请假需要哪些步骤"
    """

    expanded = llm.generate(prompt)
    return [query] + expanded  # 返回原始+扩展

# 用多个query检索,合并结果
all_results = []
for q in expand_query(query):
    all_results.extend(hybrid_retrieval(q, k=10))

# 去重+排序
final = deduplicate_and_rerank(all_results)

# Recall: 0.87 → 0.92 (+5%)

(4) Rerank精排 (+3% 保持top-5质量)

from sentence_transformers import CrossEncoder

reranker = CrossEncoder('BAAI/bge-reranker-large')

# 先召回20个候选
candidates = hybrid_retrieval(query, k=20)

# Rerank精选top-5
scores = reranker.predict([
    [query, doc.content] for doc in candidates
])

top5 = sorted(
    zip(candidates, scores),
    key=lambda x: x[1],
    reverse=True
)[:5]

# Precision@5: 0.73 → 0.89 (+16%)

最终效果:

优化路径:
基线 (0.68)
→ 语义分块 (0.79, +11%)
→ 混合检索 (0.87, +8%)
→ Query扩展 (0.92, +5%)
→ Rerank (精确率+16%)

总提升: Recall@5 从 68% → 92% (+24个百分点)

成本分析:

优化成本:
- 语义分块: 0 (只是代码改动)
- 混合检索: +100ms延迟, $0成本
- Query扩展: +$0.002/次 (LLM调用)
- Rerank: +200ms延迟, $0成本

投入产出比: 极高

面试话术:

"召回率低我会先建立带相关文档 ID 的评测集,按查询类型分桶,再分别对 chunk、混合检索、改写和 Rerank 做消融。报告 Recall@K/nDCG、P95 延迟和单次成本,并明确这些数字来自哪版语料和多少条样本。"


二、AI Agent项目

图解:Agent 项目系统结构

在这里插入图片描述

Q3: "介绍一下你做过的AI Agent项目"

💡 STAR回答模板

S (Situation):

"我在xx公司开发了一个客服Agent,自动处理用户咨询、订单查询、退换货等问题。原来完全靠人工,客服团队10人,日均处理500个工单,响应慢、成本高。"

T (Task):

"目标是:

  • 自动化率>70% (Agent独立解决)
  • 准确率>90%
  • 平均响应时间<10秒
  • 降低人力成本50%"

A (Action):

  1. Agent架构设计
用户输入 → 意图识别 → 工具路由 → 工具执行 → 结果整合 → 回复用户
               ↓
         [ReAct循环]
   Thought → Action → Observation → 继续或结束
  1. 工具设计
tools = [
    # 工具1: 订单查询
    {
        "name": "query_order",
        "description": "查询用户订单信息,需要订单号",
        "parameters": {
            "order_id": "string"
        },
        "function": query_order_from_db
    },

    # 工具2: 知识库检索
    {
        "name": "search_faq",
        "description": "搜索常见问题FAQ",
        "parameters": {
            "question": "string"
        },
        "function": search_rag_system
    },

    # 工具3: 退货流程
    {
        "name": "process_refund",
        "description": "处理退货申请,需要订单号和原因",
        "parameters": {
            "order_id": "string",
            "reason": "string"
        },
        "function": create_refund_ticket
    },

    # 工具4: 转人工
    {
        "name": "transfer_to_human",
        "description": "复杂问题转人工客服",
        "parameters": {},
        "function": create_human_ticket
    }
]
  1. 工具调用状态机(ReAct 是历史经典模式)
async def run_agent(request, max_steps=5):
    state = {"request": request, "tool_results": [], "steps": 0}

    while state["steps"] < max_steps:
        decision = await model.decide(
            state=state,
            tools=tool_schemas,
            output_schema=AgentDecision,
        )
        if decision.type == "final":
            return verify_and_render(decision.answer, state)

        authorized = policy_engine.authorize(
            user=request.user,
            tool=decision.tool,
            args=decision.arguments,
        )
        if not authorized:
            return transfer_to_human(reason="permission_denied")

        result = await execute_idempotently(
            decision.tool, decision.arguments, idempotency_key=request.id
        )
        state["tool_results"].append(sanitize_untrusted(result))
        state["steps"] += 1

    return transfer_to_human(reason="budget_exhausted")

不要求模型输出并存储原始 Thought。生产记录结构化决策、工具参数、授权结果、观察和最终依据,既可审计又避免把隐藏思维链当日志。

  1. 关键优化

(1) 意图识别提前

# 问题: 每次都从ReAct开始,浪费token

# 优化: 先快速分类
def classify_intent(query):
    prompt = f"""
    分类用户意图(只返回类别):
    1. order_query - 订单查询
    2. refund - 退换货
    3. faq - 常见问题
    4. other - 其他

    用户: {query}
    类别:
    """
    intent = fast_model.generate_structured(prompt, schema=Intent)
    return intent.strip()

# 根据意图直接调工具
intent = classify_intent(query)
if intent == "order_query":
    order_id = extract_order_id(query)
    result = query_order(order_id)
    # 省去ReAct推理,快速返回

# 效果: 延迟 8s → 2s, 成本 -60%

(2) 防止死循环

class SafeAgent:
    def __init__(self, max_iterations=5):
        self.max_iterations = max_iterations

    def run(self, query):
        iteration = 0
        while iteration < self.max_iterations:
            thought = self.think(query)
            action = self.act(thought)
            observation = self.execute(action)

            # 检查是否完成
            if self.is_done(observation):
                return observation

            iteration += 1

        # 超过最大迭代,转人工
        return self.transfer_to_human(query)

(3) 工具调用失败处理

def execute_tool_with_retry(tool, params, max_retries=3):
    for attempt in range(max_retries):
        try:
            result = tool.function(**params)
            return {"success": True, "data": result}

        except DatabaseTimeout:
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)  # 指数退避
                continue
            return {"success": False, "error": "数据库超时"}

        except InvalidParameter as e:
            # 参数错误不重试,让LLM修正
            return {
                "success": False,
                "error": f"参数错误: {str(e)}",
                "suggestion": "请检查并修正参数"
            }

R (Result):

"项目上线3个月后:

  • 自动化率达到78% (超过目标70%)
  • 准确率92% (目标90%)
  • 平均响应时间3.5秒 (目标<10秒)
  • 人力成本降低65% (5个客服缩减到2个)
  • 用户满意度4.2/5 → 4.6/5

关键成果:

  • 日均自动处理390个工单(总500个)
  • 人工客服只处理110个复杂问题
  • 夜间无人值守,24小时服务"

面试追问应对:

Q: "Agent出错怎么办?"

"3层防护:

  1. 意图识别层: 提前分类,简单问题直接返回,不走Agent
  2. 迭代限制层: 最多5次工具调用,超过转人工
  3. 异常捕获层: 工具调用失败重试3次,失败则转人工

实际上线后,Agent失败率<3%,都能优雅降级到人工。"

Q: "如何评估Agent质量?"

"4个维度:

  1. 自动化率: 成功独立解决的比例 (78%)
  2. 准确率: 人工抽查100条,答案正确的比例 (92%)
  3. 用户满意度: 对话结束后评分 (4.6/5)
  4. 工具调用效率: 平均调用次数 (1.8次,目标<3)

每周生成评估报告,发现问题及时调整Prompt。"


三、成本优化项目

Q4: "你的项目如何降低成本的?具体优化了什么?"

图解:AI 项目降本三板斧

在这里插入图片描述

💡 STAR回答模板

S (Situation):

"我们的 AI 客服系统每月模型 API 成本高达 $8,000,主要来自所有请求都调用高成本强模型。老板要求在不降低用户体验的前提下,把成本降低 50%。"

T (Task):

"目标:

  • 月成本从 8,000降到8,000 降到 4,000(降低 50%)
  • 用户满意度不低于当前4.2/5
  • 响应速度不超过3秒"

A (Action):

优化路径1: Token使用优化 (-35%成本)

  1. 上下文压缩
# Before: 直接把检索到的5个文档全传给LLM
docs = retriever.search(query, k=5)
context = "\n\n".join([doc.content for doc in docs])
# 平均输入: 3500 tokens

prompt = f"""
基于以下文档回答问题:

{context}  # ← 很多无关内容

问题: {query}
"""

# After: LLMLingua压缩上下文
from llmlingua import PromptCompressor

compressor = PromptCompressor()

compressed = compressor.compress_prompt(
    context,
    instruction="保留回答问题所需的关键信息",
    target_token=1000,  # 目标压缩到1000 tokens
    condition_compare=True,
    reorder_context="sort"  # 相关性排序
)

# 压缩后平均: 950 tokens
# Token减少: (3500-950)/3500 = 73%
# 成本节省: 输入token成本 -73%

效果数据:

压缩前: 平均3500 input tokens
压缩后: 平均950 input tokens
准确率: 89% → 87% (下降2%,可接受)
成本节省: $2800/月 (-35%)
  1. 会话历史管理
class ConversationManager:
    def __init__(self, max_history=3):
        self.history = []
        self.summary = ""

    def add_turn(self, user_msg, assistant_msg):
        self.history.append({
            "user": user_msg,
            "assistant": assistant_msg
        })

        # 超过3轮,摘要最早的一轮
        if len(self.history) > 3:
            old_turn = self.history.pop(0)

            # 使用经过摘要评测的低成本模型;具体模型 ID 由配置中心管理
            turn_summary = fast_model.summarize(
                f"用户: {old_turn['user']}\n助手: {old_turn['assistant']}"
            )

            self.summary += turn_summary + "\n"

    def get_context(self):
        # 上下文 = 历史摘要 + 最近3轮完整对话
        context = []

        if self.summary:
            context.append(f"历史对话摘要:\n{self.summary}")

        for turn in self.history:
            context.append(f"用户: {turn['user']}")
            context.append(f"助手: {turn['assistant']}")

        return "\n".join(context)

# 效果
# Before: 10轮对话 = 10轮完整历史(约5000 tokens)
# After: 10轮对话 = 摘要(200 tokens) + 最近3轮(1500 tokens)
# Token节省: 70%

优化路径2: 模型路由 (-25%成本)

原理: 简单问题用便宜模型,复杂问题用贵模型

class ModelRouter:
    def __init__(self):
        # 分类器: 判断问题复杂度
        self.classifier = fasttext.load_model("complexity_classifier.bin")

        # 使用能力别名,不把快速变化的供应商型号和价格写死在业务代码中
        self.fast_model = "FAST_MODEL"
        self.strong_model = "STRONG_MODEL"

    def route(self, query):
        # 分类: simple / medium / complex
        complexity = self.classifier.predict(query)[0][0]

        if complexity == "simple":
            # 60%的问题是简单问题
            # 例: "营业时间?", "怎么退货?"
            return self.fast_model

        elif complexity == "medium":
            # 中等任务先试快速模型
            response = llm_pool[self.fast_model].generate(query)

            # 通过验证器、规则或校准置信度决定是否升级到强模型
            if self.is_uncertain(response):
                return self.strong_model
            else:
                return self.fast_model

        else:  # complex
            # 复杂问题直接使用强模型
            # 例: "对比3款产品的性价比"
            return self.strong_model

    def is_uncertain(self, response):
        # 检测不确定的标志
        uncertain_phrases = [
            "我不确定",
            "可能是",
            "这取决于",
            "抱歉,我无法"
        ]
        return any(phrase in response for phrase in uncertain_phrases)

# 使用
router = ModelRouter()
model = router.route(user_query)
response = llm_pool[model].generate(query)

# 生产评估:
# - 统计 FAST_MODEL / STRONG_MODEL 的请求占比与升级率
# - 比较任务成功率、P95 延迟和单位成功任务成本
# - 模型、价格或流量分布变化后重新校准路由阈值

优化路径3: 语义缓存 (-30%成本)

原理: 相似问题直接返回缓存,不调API

from langchain.cache import RedisSemanticCache
from langchain.embeddings import OpenAIEmbeddings

class SemanticCache:
    def __init__(self):
        self.redis_client = Redis(host='localhost', port=6379)
        self.embedding_model = OpenAIEmbeddings()
        self.similarity_threshold = 0.85

    def get(self, query):
        """检查缓存"""
        # 1. 计算query的embedding
        query_embedding = self.embedding_model.embed_query(query)

        # 2. 从Redis向量搜索相似query
        similar = self.redis_client.search(
            query_vector=query_embedding,
            k=1,
            similarity_threshold=self.similarity_threshold
        )

        if similar:
            # 命中缓存
            cached_query, cached_response = similar[0]
            print(f"缓存命中: '{query}' ≈ '{cached_query}'")
            return cached_response

        return None

    def set(self, query, response, ttl=86400):
        """存入缓存"""
        query_embedding = self.embedding_model.embed_query(query)

        self.redis_client.set(
            key=query,
            value=response,
            embedding=query_embedding,
            ttl=ttl  # 24小时过期
        )

# 使用
cache = SemanticCache()

def answer_question(query):
    # 先查缓存
    cached = cache.get(query)
    if cached:
        return cached

    # 缓存未命中,调用LLM
    response = llm.generate(query)

    # 存入缓存
    cache.set(query, response)

    return response

# 示例缓存命中:
# Query1: "怎么退货?"
# Query2: "如何申请退款?" ← 相似度0.91,命中缓存
# Query3: "退货流程是什么?" ← 相似度0.88,命中缓存

# 效果数据:
# 缓存命中率: 35%
# 成本节省: 35% API调用
# 延迟降低: 2.5s → 0.1s (缓存响应)

缓存策略优化:

# 问题: 不是所有问题都适合缓存
# 例: "今天天气怎么样?" - 答案每天变化

class SmartCache:
    def should_cache(self, query, response):
        """判断是否应该缓存"""

        # 1. 静态知识问题 → 缓存
        static_patterns = [
            r".*是什么",
            r".*的定义",
            r".*怎么.*",  # 流程类
        ]

        if any(re.match(p, query) for p in static_patterns):
            return True, 86400*7  # 缓存7天

        # 2. 实时数据问题 → 不缓存
        dynamic_patterns = [
            r".*今天.*",
            r".*现在.*",
            r".*最新.*",
        ]

        if any(re.match(p, query) for p in dynamic_patterns):
            return False, 0

        # 3. 订单查询 → 短时缓存
        if "订单" in query and re.search(r"\d{6,}", query):
            return True, 300  # 缓存5分钟

        # 4. 默认: 缓存24小时
        return True, 86400

R (Result):

"经过3个月优化:

  • 月成本从 8,000降到∗∗8,000 降到 **3,600**(降低 55%,超过目标)
  • 用户满意度4.2/5 → 4.4/5 (提升!)
  • P95响应时间2.8s → 1.2s (更快!)

成本拆解:

  • Token压缩: -$2800 (-35%)
  • 模型路由: -$2000 (-25%)
  • 语义缓存: -$2400 (-30%)
  • 总节省: -$4400 (实际有重叠,最终-55%)

关键insight:

  1. 35%缓存命中率带来最大收益
  2. 简单任务优先使用经评测达标的快速模型
  3. 上下文压缩73%,准确率只降2%"

面试追问应对:

Q: "语义缓存会不会返回过时信息?"

"我们做了3层防护:

  1. TTL分级: 静态知识7天,实时数据不缓存,订单5分钟
  2. 缓存失效机制: 产品价格变动时,主动清除相关缓存
  3. 用户反馈: 每个缓存答案底部显示'生成于X分钟前',用户可点击'重新生成'

实测过时率<1%,用户投诉0。"

Q: "模型路由的分类器怎么训练的?"

"我们用FastText训练:

  1. 数据标注: 人工标注1000条历史问题为simple/medium/complex
  2. 特征: 问题长度、实体数量、是否有比较词('对比','哪个更')
  3. 训练: FastText 3分钟训练完,准确率89%
  4. 持续学习: 每周用新数据增量训练

路由器低置信度、验证器不通过或任务风险较高时会升级到强模型;兜底逻辑必须通过离线评测和线上灰度验证。"

Q: "Token压缩会不会丢失关键信息?"

"我们做了评估:

  1. AB测试: 200条问题,人工评分压缩前后答案质量
  2. 结果: 压缩到1000 token时,质量从4.5/5降到4.4/5,损失2%
  3. 阈值选择: 我们用target_token=1000作为最优平衡点

LLMLingua的reorder_context='sort'会把最相关的内容放前面,LLM优先看到,所以质量损失小。"


四、数据与冷启动项目

Q5: "新产品上线,没有数据怎么办?如何冷启动?"

图解:冷启动数据闭环

在这里插入图片描述

💡 STAR回答模板

S (Situation):

"我们要上线一个新的AI写作助手,但完全没有用户数据,也没有用户反馈来优化模型。产品经理要求1个月内上线MVP,并在3个月内达到用户留存率30%。"

T (Task):

"挑战:

  • 没有用户历史数据
  • 没有标注数据训练个性化模型
  • 不知道用户真实需求
  • 预算有限,无法大规模标注"

A (Action):

策略1: 利用开源数据 + 合成数据

开源数据作为基础

# 1. 收集开源写作数据集
datasets = [
    "tatsu-lab/alpaca",           # 52K指令数据
    "Anthropic/hh-rlhf",          # 人类偏好数据
    "OpenAssistant/oasst1",       # 多轮对话
    "BELLE-2M-CN",                # 中文指令200万
]

# 2. 过滤与写作相关的数据
from datasets import load_dataset

all_data = []
for dataset_name in datasets:
    ds = load_dataset(dataset_name)

    # 过滤: 只保留写作相关
    writing_keywords = ["写", "撰写", "文章", "博客", "邮件", "报告"]

    filtered = ds.filter(
        lambda x: any(kw in x["instruction"] for kw in writing_keywords)
    )

    all_data.extend(filtered)

# 得到约8万条写作相关数据
print(f"收集到 {len(all_data)} 条写作数据")

合成数据补充

# 用经过评测的强模型生成领域特定训练数据
def generate_synthetic_data(seed_examples, num_samples=1000):
    """
    基于种子数据,让 STRONG_MODEL 生成相似的训练样本
    """
    synthetic_data = []

    for _ in range(num_samples):
        # 随机选3个种子示例
        examples = random.sample(seed_examples, 3)

        prompt = f"""
        参考以下写作任务示例:

        示例1:
        指令: {examples[0]["instruction"]}
        输出: {examples[0]["output"]}

        示例2:
        指令: {examples[1]["instruction"]}
        输出: {examples[1]["output"]}

        示例3:
        指令: {examples[2]["instruction"]}
        输出: {examples[2]["output"]}

        请生成1个类似的写作任务和对应的高质量输出。
        要求:
        1. 指令多样化(商业邮件、技术文档、营销文案等)
        2. 输出长度200-500字
        3. 语言流畅专业

        JSON格式输出。
        """

        response = gpt4.generate(prompt, response_format="json")
        synthetic_data.append(response)

    return synthetic_data

# 生成5000条合成数据
synthetic = generate_synthetic_data(all_data[:100], num_samples=5000)

# 总训练数据 = 8万开源 + 5千合成 = 8.5万

效果:

  • 成本: $150(示例:强模型生成 5K 样本,需替换为真实账单)
  • 时间: 2天
  • 质量: 人工抽查100条,合格率92%

策略2: 引导式数据收集

产品设计嵌入数据收集

# 方法1: 首次使用引导
def onboarding_flow(user):
    """新用户注册时收集偏好"""

    # Step 1: 写作场景偏好
    scenes = show_options([
        "商业邮件",
        "技术文档",
        "营销文案",
        "学术论文",
        "社交媒体",
        "创意故事"
    ])
    user.preferences["scenes"] = scenes

    # Step 2: 风格偏好
    styles = show_options([
        "正式专业",
        "轻松幽默",
        "简洁直接",
        "详细严谨"
    ])
    user.preferences["styles"] = styles

    # Step 3: 示例任务
    example_task = "请帮我写一封感谢邮件给合作伙伴"
    ai_draft = generate_draft(example_task)

    # 让用户评分和编辑
    rating = user.rate(ai_draft, scale=5)
    edited = user.edit(ai_draft)

    # 收集首次反馈数据
    save_feedback({
        "task": example_task,
        "draft": ai_draft,
        "rating": rating,
        "edited_version": edited,
        "user_id": user.id
    })

    return user.preferences

# 方法2: 轻量级反馈机制
def show_output_with_feedback(output):
    """每次输出都收集反馈"""

    display(output)

    # 一键反馈(不打断流程)
    feedback_ui = """
    这个答案有用吗? 👍 👎
    [复制] [重新生成] [编辑优化]
    """

    user_action = wait_for_action()

    if user_action == "thumbs_up":
        log_positive_feedback(output)
    elif user_action == "thumbs_down":
        # 追问原因
        reason = ask_reason([
            "不够专业",
            "太啰嗦",
            "偏离主题",
            "其他"
        ])
        log_negative_feedback(output, reason)
    elif user_action == "edit":
        edited = user_edit(output)
        # 收集对比数据: AI版 vs 用户优化版
        log_edit_data(original=output, edited=edited)

数据飞轮启动

Week 1: 100个种子用户
   ↓ 每人平均使用5次
   ↓ 收集500条反馈

Week 2: 用500条反馈微调模型v1.1
   ↓ 质量提升,吸引300新用户
   ↓ 收集2000条反馈

Week 3: 用2500条反馈微调模型v1.2
   ↓ 质量再提升,吸引1000新用户
   ↓ 收集8000条反馈

Week 4: 数据飞轮加速旋转

策略3: 主动学习优化标注

问题: 8.5万数据全部人工标注成本太高

解决: 主动学习,只标注最有价值的数据

class ActiveLearningAnnotator:
    def __init__(self, unlabeled_data, budget=1000):
        self.unlabeled_pool = unlabeled_data
        self.labeled_data = []
        self.budget = budget
        self.model = None

    def run(self):
        # Step 1: 随机标注100条作为种子
        seed_samples = random.sample(self.unlabeled_pool, 100)
        self.labeled_data = self.manual_annotate(seed_samples)
        self.unlabeled_pool = [x for x in self.unlabeled_pool if x not in seed_samples]

        # Step 2: 训练初始模型
        self.model = train_model(self.labeled_data)

        # Step 3: 主动学习循环
        while len(self.labeled_data) < self.budget:
            # 找出模型最不确定的样本
            uncertain_samples = self.select_uncertain_samples(k=50)

            # 人工标注这50条
            newly_labeled = self.manual_annotate(uncertain_samples)

            # 加入训练集
            self.labeled_data.extend(newly_labeled)

            # 重新训练
            self.model = train_model(self.labeled_data)

            print(f"已标注: {len(self.labeled_data)}/{self.budget}")

        return self.model

    def select_uncertain_samples(self, k=50):
        """选择最不确定的样本"""
        uncertainties = []

        for sample in self.unlabeled_pool[:5000]:  # 从pool中抽5000条评估
            # 模型预测
            probs = self.model.predict_proba(sample["instruction"])

            # 计算不确定性(熵)
            entropy = -sum(p * np.log(p) for p in probs if p > 0)

            uncertainties.append((sample, entropy))

        # 按不确定性排序,取top-k
        uncertainties.sort(key=lambda x: x[1], reverse=True)

        return [x[0] for x in uncertainties[:k]]

    def manual_annotate(self, samples):
        """人工标注"""
        labeled = []
        for sample in samples:
            # 调用标注平台API
            label = annotation_platform.annotate(
                task=sample["instruction"],
                annotator_id="expert_001"
            )

            sample["label"] = label
            labeled.append(sample)

        return labeled

# 使用主动学习
al = ActiveLearningAnnotator(unlabeled_data=all_data, budget=1000)
optimized_model = al.run()

# 效果对比:
# 随机标注1000条: 准确率75%
# 主动学习标注1000条: 准确率82% (+7%)
# 相当于随机标注1500条的效果,节省33%标注成本

策略4: 用户分群 + AB测试

解决冷启动时不知道用户需求的问题

class ColdStartUserSegmentation:
    def __init__(self):
        self.segments = {
            "business": {
                "keywords": ["商业", "邮件", "报告", "合同"],
                "model_config": {"temperature": 0.3, "style": "formal"}
            },
            "creative": {
                "keywords": ["故事", "小说", "剧本", "创意"],
                "model_config": {"temperature": 0.9, "style": "creative"}
            },
            "tech": {
                "keywords": ["技术", "文档", "API", "代码"],
                "model_config": {"temperature": 0.5, "style": "technical"}
            }
        }

    def assign_segment(self, user_first_query):
        """根据首次查询分群"""
        query = user_first_query.lower()

        for segment_name, config in self.segments.items():
            if any(kw in query for kw in config["keywords"]):
                return segment_name, config["model_config"]

        # 默认分配到"通用"群
        return "general", {"temperature": 0.7, "style": "balanced"}

    def ab_test_variants(self, segment):
        """每个分群内AB测试不同模型配置"""
        variants = {
            "A": {"model": "gpt-3.5-turbo", "prompt_template": "template_v1"},
            "B": {"model": "gpt-4", "prompt_template": "template_v1"},
            "C": {"model": "gpt-3.5-turbo", "prompt_template": "template_v2"}
        }

        # 随机分配
        variant = random.choice(["A", "B", "C"])
        return variants[variant]

# 使用
segmenter = ColdStartUserSegmentation()

def handle_new_user(user):
    # 首次查询
    first_query = user.get_first_query()

    # 分群
    segment, config = segmenter.assign_segment(first_query)
    user.segment = segment

    # AB测试
    variant = segmenter.ab_test_variants(segment)
    user.variant = variant

    # 用对应配置生成
    output = generate_with_config(
        query=first_query,
        **config,
        **variant
    )

    # 记录实验数据
    log_experiment({
        "user_id": user.id,
        "segment": segment,
        "variant": variant,
        "satisfaction": user.rate(output)
    })

# 2周后分析AB测试结果
# Business分群: Variant B (STRONG_MODEL + template_v1) 满意度最高
# Creative分群: Variant C (FAST_MODEL + template_v2) 单位成功任务成本最低
# Tech分群: Variant A 效果相当,选最便宜的

R (Result):

"1个月MVP上线,3个月数据:

  • 累计用户: 3500人
  • 日活留存: 35% (超过目标30%)
  • 收集数据: 18000条用户交互
  • 模型迭代: v1.0 → v1.5 (5次微调)
  • 用户满意度: 3.2/5 → 4.1/5

成本控制:

  • 开源数据: $0
  • 合成数据: $150(示例,需替换为真实模型和账单)
  • 主动学习标注: **3,000∗∗(1,000条×3,000**(1,000 条 × 3/条)
  • 总成本: **3,150∗∗(远低于全量标注约3,150**(远低于全量标注约 250,000)

关键成功因素:

  1. 产品设计嵌入数据收集,用户无感提供反馈
  2. 主动学习节省67%标注成本
  3. AB测试快速找到每个分群的最优配置
  4. 数据飞轮2周开始加速,用户增长带来数据增长"

面试追问应对:

Q: "合成数据质量怎么保证?"

"三层质量控制:

  1. Prompt 工程:给 STRONG_MODEL 提供 3 个高质量示例并限制输出 schema
  2. 自动过滤: 用规则过滤明显低质量数据(长度<50字,重复率>30%)
  3. 人工抽检: 每生成500条抽检50条,合格率<90%就调整Prompt

最终5000条合成数据,人工抽查100条,合格率92%,与开源数据质量相当。"

Q: "主动学习如何选择'最不确定'的样本?"

"我们用熵值(Entropy)衡量不确定性:

# 模型预测概率分布
probs = [0.4, 0.35, 0.25]  # 3个类别

# 计算熵
entropy = -sum(p * log(p) for p in probs)
# = 1.57 (高熵 = 不确定)

# 对比:确定的预测
probs2 = [0.9, 0.05, 0.05]
entropy2 = 0.47 (低熵 = 确定)

选熵值最高的样本标注,因为这些样本最能帮助模型区分边界,性价比最高。实测主动学习1000条,效果等于随机1500条。"


五、项目回答技巧

回答框架: STAR法则

S (Situation) - 项目背景 (20秒)

  • 公司/团队规模
  • 业务场景
  • 遇到的问题

T (Task) - 任务目标 (20秒)

  • 具体指标(量化)
  • 技术要求
  • 时间限制

A (Action) - 具体行动 (60秒) ⭐核心

  • 技术选型 + 理由
  • 架构设计
  • 关键优化点
  • 遇到的坑 + 解决方案

R (Result) - 最终结果 (20秒)

  • 量化数据(对比)
  • 业务价值
  • 技术亮点

通用话术模板

项目介绍:

"我在xx公司负责**[项目名],主要解决[业务痛点]。技术栈选用[核心技术],实现了[核心功能]。最终[关键指标]从[优化前]提升到[优化后],[业务价值]**。"

技术选型:

"我们对比了**[方案A]和[方案B],最终选择[方案B],主要因为[核心优势]。虽然[方案A]在[某方面]更好,但考虑到[实际约束],[方案B]**更适合。"

难点突破:

"最大的难点是**[具体问题]。表现是[现象],分析发现原因是[根因]。我们尝试了[方案1],但[问题]。最终用[最终方案]解决,效果是[数据对比]**。"

如果重新设计:

"如果重新设计,我会改进3点:


📝 速记卡片

项目类型核心考点回答重点
RAG系统召回率/准确率混合检索+Rerank+语义分块
AI Agent自动化率/鲁棒性ReAct+工具设计+失败处理
成本优化成本降低比例语义缓存+模型路由+Token压缩
冷启动数据收集/留存率开源数据+合成数据+主动学习

面试万能公式

项目 = 业务价值 + 技术亮点 + 量化数据

业务价值: 解决了什么问题,带来什么收益
技术亮点: 用了什么技术,为什么这么选
量化数据: 从x提升到y,提升了z%

上一模块: RAG系统 下一模块: Transformer架构


返回目录 →


六、大厂项目架构设计(2026 新增)

Q6: 如果让你设计一个企业级AI客服系统,你会怎么设计?

图解:企业级 AI 客服架构

在这里插入图片描述

💡 答案要点(STAR框架)

S(背景): 1000万用户,日活100万,需要7×24小时智能客服

T(任务): 设计一个能处理咨询、售后、投诉等多场景的AI客服系统

A(行动)——四层架构设计:

┌─────────────────────────────────────────────────────┐
│  接入层:多渠道统一接入                              │
│  微信/APP/网页/电话 → 统一消息格式                  │
└──────────────────┬──────────────────────────────────┘
                   ↓
┌──────────────────────────────────────────────────┐
│  路由层:意图识别 + 路由分发                       │
│  LLM 判断意图 → 转人工/知识库/工单系统             │
└──────────────────┬─────────────────────────────────┘
                   ↓
┌──────────────────────────────────────────────────┐
│  能力层:多Agent协作                               │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐         │
│  │ 知识库Agent│ │ 订单Agent │ │ 投诉Agent │         │
│  └──────────┘ └──────────┘ └──────────┘         │
└──────────────────┬─────────────────────────────────┘
                   ↓
┌──────────────────────────────────────────────────┐
│  数据层:会话记忆 + 知识库 + 工单系统               │
└──────────────────────────────────────────────────┘

关键设计点:

# 意图识别 + 路由
def route(query, session_history):
    intent = llm.judge(f"""
    判断用户意图:
    1=咨询 2=下单 3=售后 4=投诉 5=转人工
    问题:{query}
    历史:{session_history[-3:]}
    """)

    if intent == 5 or contains_sensitive词(query):
        return "human_agent"  # 转人工
    elif intent == 1:
        return "knowledge_agent"
    elif intent == 2:
        return "order_agent"
    # ...

# 多轮对话记忆
class ConversationMemory:
    def __init__(self, max_turns=10):
        self.history = []
        self.max_turns = max_turns

    def add(self, role, content):
        self.history.append({"role": role, "content": content})
        if len(self.history) > self.max_turns * 2:
            # 压缩:保留关键信息
            self.history = self.summarize_and_compress()

R(结果): 客服响应时间从30s→2s,问题解决率85%,人工客服工作量减少60%

Q7: 你如何设计一个多模态RAG系统(图文检索)?

💡 答案要点

多模态RAG架构:

用户上传图片 + 文字问题
         ↓
┌──────────────────────────────────────────┐
│  多模态 Encoder:                        │
│  - 图片 → CLIP 视觉编码 → 向量          │
│  - 文字 → CLIP 文本编码 → 向量          │
│  - 图+文 → 融合向量                     │
└──────────────────┬─────────────────────┘
                   ↓
┌──────────────────────────────────────────┐
│  跨模态检索:                            │
│  用户图 vs 文档图:相似度匹配            │
│  用户问题 vs 文档图:图文跨模态匹配      │
└──────────────────┬─────────────────────┘
                   ↓
┌──────────────────────────────────────────┐
│  多模态生成:                            │
│  LLaVA 等 VLM 基于图片 + 检索结果生成   │
└──────────────────────────────────────────┘

关键实现代码:

from sentence_transformers import CLIPModel
import torch

class MultimodalRAG:
    def __init__(self):
        self.model = CLIPModel.from_pretrained("openai/clip-vit-base-patch32")

    def encode_image(self, image):
        with torch.no_grad():
            image_features = self.model.get_image_features(image)
        return image_features.numpy()

    def encode_text(self, text):
        with torch.no_grad():
            text_features = self.model.get_text_features(text)
        return text_features.numpy()

    def crossmodal_search(self, query_image, query_text, doc_images, top_k=5):
        # 编码
        img_emb = self.encode_image(query_image)
        text_emb = self.encode_text(query_text)

        # 融合:图片和文字各50%
        fused_query = 0.5 * img_emb + 0.5 * text_emb

        # 在文档图片中检索
        similarities = []
        for doc_img in doc_images:
            doc_emb = self.encode_image(doc_img)
            sim = cosine_similarity(fused_query, doc_emb)
            similarities.append(sim)

        return sorted(zip(doc_images, similarities), key=lambda x: -x[1])[:top_k]

面试话术:

"多模态RAG的核心是跨模态对齐。我用CLIP做图片和文字的联合编码空间,用户的图片和文字问题都映射到同一个向量空间,直接做相似度匹配。文档端也用CLIP处理产品图片,建立图片向量库。检索时,用户的图+文query和文档图片做跨模态检索,精准找到相关图片。生成阶段用LLaVA读图回答。实测图文混合查询的准确率比纯文字检索提升了35%。"

Q8: 如何设计一个企业级AI Agent平台(类似Coze/Dify)?

💡 答案要点

平台核心架构:

┌─────────────────────────────────────────────────────────┐
│  用户层:可视化编排 / API 调用                          │
└──────────────────────┬──────────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────┐
│  编排层:工作流设计器                                  │
│  - 节点:LLM节点 / 知识库节点 / API节点 / 条件节点    │
│  - 边:数据流 / 条件流                               │
│  - 输出:DSL(领域特定语言)配置文件                  │
└──────────────────────┬───────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────┐
│  运行时层:工作流引擎                                  │
│  - 执行节点 → 收集输出 → 路由到下一节点             │
│  - 支持条件分支 / 循环 / 并行                        │
└──────────────────────┬───────────────────────────────┘
                       ↓
┌──────────────────────────────────────────────────────┐
│  能力层:工具生态                                     │
│  - 内置工具:知识库 / SQL / API / Webhook            │
│  - MCP 集成:扩展工具生态                            │
└──────────────────────────────────────────────────────┘

DSL 工作流配置示例:

workflow:
  name: "智能客服"
  version: "1.0"

  nodes:
    - id: "intent"
      type: "llm"
      model: "qwen2.5-14b"
      prompt: "判断用户意图:咨询/下单/售后/投诉"
      output: "user_intent"

    - id: "route"
      type: "condition"
      branches:
        - condition: "{{user_intent}} == '咨询'"
          next: "knowledge_base"
        - condition: "{{user_intent}} == '下单'"
          next: "order_agent"
        - condition: "{{user_intent}} == '售后'"
          next: "after_sales"
        default: "human_agent"

    - id: "knowledge_base"
      type: "rag"
      knowledge_id: "product_knowledge"
      top_k: 5
      output: "rag_result"

    - id: "after_sales"
      type: "api"
      url: "https://api.company.com/order/track"
      params: "{{order_id}}"
      output: "tracking_info"

  edges:
    - from: "intent"
      to: "route"
    - from: "route"
      to: "knowledge_base"
    # ...

  output:
    format: "markdown"
    stream: true

面试话术:

"企业级Agent平台的核心是'编排即服务'。我用DSL描述工作流,节点类型包括LLM、知识库、API、HTTP、代码执行等。工作流引擎解析DSL,按拓扑顺序执行节点,支持条件分支、并行、循环。编排层提供可视化画布,用户拖拖拽拽就能搭工作流,生成的DSL存到数据库,运行时引擎执行。平台还接入了MCP协议,工具生态可以无限扩展。"