Q: 你觉得RAG中最难的是什么?(文档切割喽)

A: 您提到了一个非常关键的点。确实,文档切割是RAG系统中至关重要且最具挑战性的环节之一,它直接决定了检索的上限,进而影响最终生成的质量。

除了切割,我认为另一个深层次的难点是检索器的优化与评估。具体来说:

  1. 文档切割的挑战:这不仅仅是简单的文本切分。难点在于如何保持语义的完整性。

    • 粒度问题:块太大,会引入噪声;块太小,会丢失关键上下文。例如,切割学术论文时,如何保证一个完整的研究方法或结论不被截断是一个难题。
    • 跨段落关联:有些关键信息分散在多个段落或章节中(比如论文中的“引言”和“结论”),简单的滑动窗口切割会破坏这种逻辑关联。
  2. 检索器的挑战:即使切割得很好,如何保证总能检索到最相关的内容同样困难。

    • 语义鸿沟:用户的查询用语和知识库中的专业术语可能存在差异,要求嵌入模型有极强的语义理解能力。
    • 复杂查询:对于涉及多跳推理、比较或总结性的复杂问题,简单的向量相似度检索往往不够,需要结合关键词检索、重排序等策略来优化。

在我的项目中,我通过递归分割法平衡块大小,并为每个块添加了元数据,并通过人工评估和优化检索召回率 来系统性地应对这些挑战。


Q: 你是怎么解决幻觉问题的?

A: 我采用了一个系统性、多层次的方案来综合治理幻觉问题,而不是依赖单一方法:

  1. 源头控制:在RAG的检索阶段,我优化了检索器,通过混合检索 和重排序 技术,确保提供给模型的上下文是高度相关和准确的,从源头上减少模型“编造”的机会。

  2. 过程约束:在生成阶段,我进行了精细的提示词工程。我的系统提示词中会明确指令:“严格根据提供的上下文回答问题,如果上下文没有提及,请直接说明‘根据已知信息无法回答该问题’”。这为模型的行为划定了清晰的边界。

  3. 后处理验证:在可能的情况下,我会设计引用机制,要求模型在生成答案时标明其依据的来源文本块。这样不仅方便用户验证,也为后续的评估和迭代提供了依据。

  4. 模型选型:在我的本地部署方案中,我选择了在遵循指令和拒绝回答方面表现较好的模型,如Qwen-Chat系列,它们对于超出知识范围的问题通常能更好地做出“不知道”的响应。

总结来说,解决幻觉是一个从检索、生成到后处理的端到端优化过程,核心思想是让模型“有据可依”并“言出有据”。


Q: 微调(Fine-tuning)和RAG的区别是啥?

A: 这是一个非常核心的问题。微调和RAG是两种互补但思路截然不同的技术,它们的区别可以从以下几个维度理解:

维度RAG微调
核心功能知识注入与增强事实一致性。像一个学生开卷考试,随时可以去查阅参考书(知识库)。能力迁移与风格学习。像一个学生通过大量练习,形成了某种固定的思维模式或技能。
作用机制通过检索外部知识并将其作为上下文提供给模型,来影响模型的输出。通过更新模型内部的权重参数,来改变模型本身的行为。
知识存储知识存储在外部向量数据库中,与模型分离。知识被内化到模型的参数中。
更新灵活性高。知识库可以随时、低成本地增删改查,实时更新。低。更新知识需要重新训练或增量训练,成本高、周期长。
主要适用场景1. 处理实时性、动态性强的知识。
2. 解决模型的事实性“幻觉”问题。
3. 需要
追溯答案来源
的场景。
1. 学习特定的语言风格、格式。
2. 掌握特定的复杂推理模式或任务流程。
3. 适应特定的专业领域术语体系。

一个形象的比喻是:RAG是给模型一本随时可以翻阅的《操作手册》,而微调是培养一个具有特定工作习惯的《老师傅》。

在实际应用中,两者并非互斥。对于企业级应用,最强大的架构往往是 “RAG + 微调” 的结合:用微调让模型更好地理解和遵循我们领域的指令格式,同时用RAG为它提供最新、最准确的专业知识。


好的,这是一份针对您提供的第二轮面试问题清单的详细解答,涵盖了系统设计、八股文和个人问题,旨在全面展示您的技术实力和职业素养。


系统设计

Q: 短链系统?
A: 一个高性能短链系统的核心是 “将长网址映射到一个简短的键,并通过重定向提供服务”。

  1. 核心流程:
    • 生成:接受长URL,通过分布式ID生成器(如Snowflake)或Hash(如MurmurHash,冲突后拼接)生成一个唯一短键。
    • 存储:使用K-V数据库(如Redis缓存热点,MySQL/HBase持久化)存储 短键 -> 长URL 的映射。
    • 重定向:用户访问短链,服务端通过302 Found重定向到长URL,利于统计和缓存控制。
  2. 关键设计:
    • 高并发:使用Redis缓存热点短链,抵挡读流量洪峰。
    • ID生成器:必须分布式、高可用,避免单点瓶颈和冲突。

Q: 分布式锁的设计?
A: 分布式锁用于在分布式系统中互斥地访问共享资源。

  1. 基于Redis:使用 SET lock_key random_value NX PX 30000 命令(NX表示不存在才设置,PX设置超时时间),value需为随机值,确保只能由加锁者解锁。配合Lua脚本保证解锁的原子性。
  2. 基于ZooKeeper:创建临时有序节点,最小节点的客户端获得锁。通过Watch机制,当前一个节点被删除时自动唤醒后续客户端,实现公平锁。
  3. 核心考量:
    • 互斥性:同一时刻只有一个客户端能持有锁。
    • 死锁预防:锁必须有超时时间。
    • 容错性:Redis异步复制可能导致锁丢失,ZooKeeper的CP模型更可靠。

Q: 给你一部长篇小说,怎么做文档切割?
A: 目标是保持情节和语义的完整性。

  1. 策略:采用 “按章节粗切 + 递归细切” 的混合策略。
  2. 步骤:
    • 第一级切割:利用明显的章节标记(如“第一章”、“Chapter 1”)将小说切割成大的章节块。这是最自然的语义边界。
    • 第二级切割:对于过长的章节,使用 RecursiveCharacterTextSplitter,优先按“段落 -> 句子 -> 逗号”的层级进行递归分割,并设置重叠窗口(如200字),确保上下文衔接。
  3. 增强:为每个文本块添加丰富的元数据,如 {chapter: "第三章", character: "张三、李四"},便于后续检索时提供更多上下文。

Q: 怎么做到论文翻译,并且格式尽可能和原来的统一?
A: 这是一个格式保持和内容转换并重的任务。

  1. 文档解析与结构提取:使用专业的解析库(如PyMuPDF for PDF, python-docx for Word)将原始文档解构为样式树,识别出标题、正文、图表、参考文献等元素及其格式(字体、大小、位置)。
  2. 分内容类型翻译:
    • 文本翻译:将提取出的纯文本按块(如段落)送入大模型,指令中强调“您是专业学术翻译,请准确翻译以下内容,保留专业术语”。
    • 非文本元素:图表内的文字需要OCR提取后单独翻译再贴回。
  3. 文档重建:按照第一步提取的样式树,将翻译后的文本“填充”回对应的样式结构中,生成目标语言文档。大模型在翻译时,可以要求它输出与原文格式标记对应的内容(如Markdown),以简化重建过程。

Q: 游戏社区客服助手设计。如何绑定游戏黑话,如何利用好公司内部的文档?
A: 核心是构建一个领域知识增强的RAG系统。

  1. 系统设计:
    • 知识库:将公司内部的游戏攻略、版本更新日志、常见问题、客服手册等文档向量化存储。
    • 问答引擎:用户提问时,系统从知识库中检索相关信息,并连同问题一起送给大模型生成回答。
  2. 绑定游戏黑话:
    • 构建同义词库:创建一个“黑话-官方术语”的映射表(如“搓招 -> 技能连招”)。
    • 查询扩展/重写:在检索前,利用同义词库或一个小模型,将用户查询中的黑话替换或扩展为官方术语,提升检索命中率。
  3. 利用内部文档:
    • 将内部文档作为RAG系统的唯一可信知识源,确保回答的准确性。
    • 对文档进行版本管理,确保助手回答与当前游戏版本一致。

Q: 结合线上问题快速定位项目工程代码有问题的地方?
A: 这是一个典型的可观测性问题。

  1. 链路追踪:集成APM工具,为每个请求生成唯一TraceID,串联起经过的所有微服务。出错时,通过TraceID快速定位到故障服务和方法。
  2. 日志聚合:将分布式系统的日志集中收集到平台。根据错误信息、时间戳和TraceID,检索出相关的错误日志和上下文。
  3. 指标监控:监控系统的QPS、延迟、错误率。当收到告警时,结合指标异常的时间点和链路、日志信息,三角定位出问题的根本原因。
  4. 代码层面:在关键逻辑处增加详细的日志和指标埋点。

Q: 有很多结构化和非结构化数据,怎么分析,再怎么得出我要的结论?
A: 采用数据湖仓一体的思路进行融合分析。

  1. 数据集成与存储:
    • 结构化数据:存入数据仓库。
    • 非结构化数据:存入数据湖。对其中的文本、图片等进行处理,提取特征或信息,生成结构化/向量化表示,再同步到数仓。
  2. 分析阶段:
    • 描述性分析:使用SQL对结构化数据进行聚合统计,了解“发生了什么”。
    • 探索性分析:对于非结构化数据,可以使用Embedding和聚类分析,发现隐藏的模式或主题。
    • 关联分析:将结构化数据(如用户画像)与非结构化数据的分析结果(如用户评论的情感倾向)进行关联,回答“为什么发生”。
  3. 得出结论:通过上述步骤,形成从宏观统计到微观案例的完整证据链,支撑业务决策。

八股

Q: go的内存分配策略、GMP、GC?
A:

  • 内存分配:采用分级分配策略。每个线程有本地缓存,小对象从mcache获取,不足时从全局mcentral和mheap申请,减少全局锁竞争。
  • GMP:
    • G:Goroutine,轻量级用户态线程。
    • M:Machine,对应内核线程,真正执行者。
    • P:Processor,调度上下文,管理G队列。
    • 工作流程:P维护一个本地G队列。M需要绑定P来执行G。当G阻塞时,M会与P解绑,新建或唤醒一个M来执行P队列中其他G。
  • GC:Go采用三色标记清除法,并发标记,并行清除,尽可能减少STW时间。

Q: python 的内存分配策略、GC?
A:

  • 内存分配:私有堆管理。小整数和短字符串有缓存池。为减轻碎片问题,使用了分级分配器。
  • GC:以引用计数为主,缺点是无法解决循环引用。因此,补充了一个分代回收的垃圾收集器,专门处理循环引用问题。

Q: redis 用过那些?mget 底层什么实现的?zset怎么实现的?
A:

  • 常用数据结构:String, List, Hash, Set, Zset, Stream等。
  • MGET实现:在Redis集群中,如果key分布在不同的节点上,MGET命令需要客户端或代理进行键的哈希标签匹配,或者在各个节点上分别获取后再聚合,并非原子操作。单实例下是原子操作。
  • Zset实现:采用 跳跃表 + 哈希表 的混合数据结构。
    • 跳跃表:支持按分数范围快速查询和排序。
    • 哈希表:支持按成员名快速查找对应分数。O(1)时间复杂度。

Q: mysql 索引怎么设计最好?
A: 这是一个权衡艺术,但有几个核心原则:

  1. 覆盖索引:尽可能让索引包含所有查询字段,避免回表。
  2. 最左前缀原则:联合索引的左侧列必须被使用。
  3. 选择高选择性字段:区分度高的字段(如ID)建索引效果更好。
  4. 避免过度索引:索引会降低写速度并占用空间。
  5. 考虑排序和分组:ORDER BY和GROUP BY的字段适合建索引。

Q: 数据库隔离级别?mvcc是怎么实现的?
A:

  • 隔离级别:读未提交 -> 读已提交 -> 可重复读 -> 串行化。
  • MVCC实现:通过版本链和ReadView实现。
    • 每行数据有隐藏的trx_id字段,标记创建和删除它的事务ID。
    • 在可重复读级别下,事务开始时生成一个ReadView,记录了当前活跃事务ID列表。通过比较数据行的trx_id与ReadView,来判断该行数据对该事务是否可见,从而实现非阻塞的一致性读。

Q: 分布式锁是什么实现的?
A: (此问题前面已详细回答,可简要概括)常用三种:

  1. Redis:SET NX PX + Lua脚本解锁。
  2. ZooKeeper:创建临时有序节点,监听前序节点。
  3. etcd:基于租约的KV操作。

Q: kafka的reblance 是什么?会产生那些问题?怎么保证数据不丢?
A:

  • Rebalance:当消费者组内消费者数量发生变化时,Kafka会重新分配分区给存活的消费者。
  • 问题:
    • 全局暂停:在Rebalance期间,所有消费者都会停止消费,造成消费停滞。
    • 重复消费:如果Rebalance发生在提交偏移量之前,可能导致消息被重复消费。
  • 保证数据不丢:
    • 生产者端:设置 acks=all,确保消息被所有ISR副本确认。
    • Broker端:设置 min.insync.replicas,保证至少有一定数量的副本存活。
    • 消费者端:在消息被业务逻辑成功处理后再手动提交偏移量。

Q: fastapi 设计原理?
A: FastAPI是一个基于Python类型提示的现代Web框架。

  1. 依赖注入系统:自动解析和处理请求参数、依赖关系。
  2. 基于Pydantic:利用类型提示进行数据验证和序列化,开发高效且可靠。
  3. 异步支持:原生支持async/await,能够轻松构建高性能的异步Web服务。
  4. 自动生成API文档:根据代码和类型提示,自动生成交互式OpenAPI文档。

Q: go 中 net/http 如何处理的tcp粘包问题
A: Go的net/http库本身不处理TCP粘包问题。TCP粘包/拆包是传输层的问题,需要在应用层协议解决。HTTP协议本身通过 Content-Length 头部或 Transfer-Encoding: chunked 来明确界定每个请求/响应的边界。net/http库会严格按照HTTP协议规范来解析请求和构造响应,从而正确地处理粘包后的数据流。

Q: http2 是什么?比http1.1有什么优势?
A:

  • HTTP/2:是HTTP协议的第二个主要版本。
  • 优势:
    1. 二进制分帧:解析更高效,错误更少。
    2. 多路复用:一个TCP连接上可以并行交错多个请求和响应,解决了HTTP/1.1的队头阻塞问题。
    3. 头部压缩:使用HPACK算法压缩头部,减少开销。
    4. 服务器推送:服务器可以主动向客户端推送资源。

Q: Linux 网络性能调优的方式?
A:

  1. 调整内核参数:修改/etc/sysctl.conf,如增大net.core.somaxconn,调整net.ipv4.tcp_tw_reuse等。
  2. 中断亲和性:将网卡中断绑定到特定的CPU核心,减少上下文切换。
  3. 使用更高效的网络模式:如io_uring。
  4. 协议栈优化:针对特定场景调整TCP拥塞控制算法等。

Q: 如何定位Linux中的pid、端口号等等?
A:

  • ps -aux | grep [进程名]:查找进程PID。
  • netstat -tunlp | grep [端口号] 或 ss -tunlp | grep [端口号]:查找占用某端口的进程PID。
  • lsof -i :[端口号]:同上,功能强大。
  • cat /proc/[PID]/status:查看指定PID进程的详细信息。

个人

Q: 在每个项目的里的角色是什么?承担那些工作?
A: (请根据您的实际情况回答,以下是模板)
“在[项目A]中,我作为核心开发工程师,主要负责了[系统架构设计、核心模块开发与落地]。具体承担了[例如:RAG管道搭建、Agent逻辑实现、模型本地化部署与优化]等工作。
在[项目B]中,我作为项目负责人,主导了[技术选型、任务拆分与分配、进度管理和对外沟通],并亲自攻克了[某个技术难点]。”

Q: 项目是几个人在做?
A: (请根据实际情况回答)例如:“大部分项目是2-5人的小团队协作开发,这要求每个成员都需要有很强的独立负责能力和沟通协作精神。”

Q: 为什么离职、每次离职的原因是什么?
A: (这是一个关键问题,务必保持积极、正向)

  • 切忌:抱怨前公司、前领导、前同事。
  • 标准答案框架:“我在上一家公司度过了非常充实的时光,也成长了很多。我离开主要是出于对个人职业发展的规划,希望能够在[您当前应聘公司的领域,如‘大模型应用落地’]这个方向上深入钻研,并承担更核心的挑战。我非常看好贵公司在这个领域的布局和技术实力,所以非常期待能加入这里。”

Q: 平常怎么学习的?
A:

  1. 系统性输入:定期阅读顶级会议论文、技术博客和开源项目源码。
  2. 动手实践:将学到的理论通过个人项目或为公司搭建技术原型进行验证。
  3. 总结输出:写技术博客、在内部做技术分享,通过教来促进学。
  4. 社区交流:参与技术社区讨论,了解业界最佳实践和面临的共同挑战。

Q: 怎么接触到大模型的最新进展的?
A:

  1. 论文平台:每日浏览arXiv,关注NLP和AI顶会。
  2. 信息聚合:关注Hugging Face、LangChain等官网博客,以及一些优质的技术资讯账号和 Newsletter。
  3. 开源社区:关注GitHub上主流模型和框架的更新。
  4. 实践社群:参与相关的技术社群和线下活动,与同行交流。

Q: 对大模型将来的应用发展有什么看法?
A: (结合之前的回答,可补充)我认为会朝着 “深度垂直化、智能体化、多模态化” 的方向发展。大模型会从“什么都懂一点”的通才,转变为深入各行各业、能自主完成复杂任务的“专家”和“数字员工”。应用开发的焦点也会从单纯调API,转向构建稳定、可靠、能闭环解决实际业务问题的智能系统。

Q: 你将来的职业规划是什么?
A: (表达稳定性和成长性)
“短期来看,我希望能够深入理解贵公司的业务和技术栈,尽快融入团队,在‘大模型应用工程化’这个方向上成为团队值得信赖的专家,为业务创造实实在在的价值。
中长期,我希望能够跟随公司和行业的发展,不仅在技术上持续深耕,也希望能培养自己的跨领域能力和架构视野,未来有机会承担更重要的技术设计或团队管理职责,为公司更核心的业务做出贡献。”

更多推荐