RAG的原理,大概是怎么一个过程,怎么做的切片
RAG是通过“向量检索 + 上下文增强”,让大模型基于外部知识生成答案的架构。核心流程是:文档切片、向量化存储、查询时检索相关片段,再拼接上下文让模型生成结果,其中切片策略直接决定检索效果。
模型幻觉是因为什么引起?应该怎么处理?
模型幻觉的本质原因是大语言模型是基于概率生成文本,而不具备真实的事实校验能力。当模型缺乏相关知识或上下文不足时,会生成看似合理但错误的内容。 解决方案通常从多层面入手,包括通过RAG引入外部知识、优化检索质量、加强Prompt约束、降低生成随机性,以及在工程上增加结果校验和工具调用机制,从而系统性降低幻觉问题。
拷打项目,每一个细节都会细问,甚至挖坑。比如说文生图用Redis做积分扣除是怎么扣的? 先把积分拿出来再扣除吗?
不会先把积分查出来再单独扣,因为这在并发场景下不是原子操作,可能导致超扣。 我们会用 Redis Lua 脚本,把“判断余额、扣减积分、记录幂等 requestId”放在同一个原子操作里完成。 扣成功后再创建文生图任务并调用模型。如果模型调用失败,会基于积分流水做幂等补偿退款,避免重复扣或者重复退。
算法题-二叉树的前序遍历
javaclass Solution { public List<Integer> preorderTraversal(TreeNode root) { // 用来存储最终结果(前序遍历的节点值) List<Integer> res = new ArrayList<>(); // 调用递归函数,从根节点开始遍历 dfs(root, res); // 返回结果 return res; } /** * 深度优先遍历(DFS) * @param node 当前访问的节点 * @param res 存储结果的集合(引用传递) */ private void dfs(TreeNode node, List<Integer> res) { // ===== 1. 递归终止条件 ===== // 如果当前节点为空,说明已经到叶子节点的下一层,直接返回 if (node == null) return; // ===== 2. 处理当前节点(前序的位置)===== // 前序遍历:根 -> 左 -> 右 // 所以在“进入节点时”就处理(加入结果) res.add(node.val); // ===== 3. 递归遍历左子树 ===== dfs(node.left, res); // ===== 4. 递归遍历右子树 ===== dfs(node.right, res); } }
前序遍历 根 → 左 → 右
中序遍历 左 → 根 → 右
后序遍历 左 → 右 → 跟
如何防止Agent陷入死循环
为了防止Agent陷入死循环,通常会从多层面进行控制。首先在控制层设置最大执行步数和超时机制作为兜底;其次在Prompt中明确终止条件,避免模型重复调用工具;同时在工具层增加调用去重和次数限制;在工程上可以引入状态机或workflow控制执行流程;最后通过结果判断和fallback机制,在异常情况下及时终止任务,从而整体保证Agent执行的稳定性。
RAG中为什么除了向量检索还要用BM25
在RAG中,向量检索和BM25通常会结合使用。向量检索擅长语义匹配,可以找到表达不同但含义相近的内容,但对关键词、数字和精确信息不敏感;而BM25基于关键词匹配,能够很好地处理API名称、ID等精确查询,但缺乏语义理解能力。因此通过Hybrid Search将两者结合,可以同时提升召回率和准确性,是实际工程中的常见做法。
线程池的核心参数有哪些
corePoolSize 核心线程数 maximumPoolSize 最大线程数 keepAliveTime 空闲线程存活时间 unit 时间单位 workQueue 任务队列 threadFactory 线程工厂 handler 拒绝策略
JVM回收算法
如何编写prompt
你是一名【角色】。
我现在的背景是:【背景】。
请你帮我完成:【任务】。
要求:
1. 【要求一】
2. 【要求二】
3. 【要求三】
输出格式:
1. 先给结论;
2. 再详细解释;
3. 举例说明;
4. 最后总结。用过openclaw吗,和其他ai的区别是 职业规划
接口和抽象类有什么区别?
接口(自上而下):
我们知晓某一行为,于是基于这些行为约束定义了接口
一些类需要有这些行为,因此实现对应的接口
先约定接口,再实现
抽象类(自下而上):
我们写了很多类,发现它们之间有共性,有很多代码可以复用
因此将公共逻辑封装成一个抽象类,减少代码冗余
先有一些类,才抽象了共同父类
Java中volatile关键字的作用是什么?
volatile是 Java 中用于修饰变量的关键字,主要作用是保证变量在多线程之间的可见性,并禁止指令重排序。它可以保证一个线程修改变量后,其他线程能立即看到最新值,也可以防止 JVM 或 CPU 对相关指令进行重排序。但是volatile不能保证复合操作的原子性,例如count++仍然不是线程安全的。如果需要保证原子性,需要使用synchronized、Lock或AtomicInteger等工具。volatile的底层实现是什么?
volatile的底层主要依赖 Java 内存模型和内存屏障实现。被volatile修饰的变量,在写操作时会把修改刷新到主内存,在读操作时会从主内存重新读取。JVM 会在 volatile 读写前后插入内存屏障,禁止特定类型的指令重排序。MySQL的事务隔离级别有哪些?
读未提交,事务a可以读取到事务b未提交的数据,会出现脏读现象
读已提交,事务a可以读取到事务b已经提交的数据,会出现不可重复读现象,前后多次读取,数据不一致
可重复读,事务a可以读取到相同的数据,可能会出现幻读现象,前后多次读取,数据前后总量不一致
串行化,最高级别的隔离等级
MySQL的默认事务隔离级别是什么?
可重复读
MySQL默认选择可重复读事务隔离级别的原因?
可重复读级别避免了脏读和不可重复读,以及绝大部分的幻读(不可完全避免)
使用了MVCC,使得并发性高
因为mysql为了兼容早期binlog的statement格式,这种格式会记录先提交的事务,但是在主库里面事务内部sql的执行顺序和提交顺序可能不一样,会导致主从不一致。而可重复读级别有间隙锁和临键锁,避免了这种情况
Cookie和session有什么区别
Cookie是存储在浏览器端的小型数据文件,主要是保存用户状态信息 Session是存储器服务端的数据文件,保存用户在服务器上的状 态信息,每个Session都有对应的Session ID,通过Cookie的方式存储在浏览器端,下次访问使用Session ID的方式获取对应的Session Token是一种加密字符串,用于身份验证和授权,认证后,服务器会返回token,存储在客户端,后续访问带上该token。 Cookie和Session适用于单词会话的认证和状态管理,Token更适合跨会话的认证和状态管理。
2.微服务的组件有了解吗
Nacos 做注册中心和配置中心,Gateway 做网关,OpenFeign 做服务间调用,Sentinel 做限流熔断,Seata 处理分布式事务,RocketMQ 做异步消息
3.git上的merge命令了解吗
git merge是用来合并分支的命令,
4.get和post的区别是什么
GET 请求是从服务器获取资源,POST 请求是向服务器提交数据。
GET 方法是只读操作,所以是安全且幂等的,而 POST 方法会修改服务器上的资源,并且多次 POST 请求,会创建多个资源,所以不是安全,也不是幂等的。
GET请求的请求参数放在URL中的查询字符串中,浏览器对 URL 长度限制,所以GET请求的请求参数会有长度限制,而POST请求的请求参数是放在请求体中,POST请求的请求参数长度没有限制。
5.redis的数据类型有哪些
String:缓存对象,分布式锁
Hash:缓存对象,购物车
List:阻塞队列、栈、消息队列
Set:集合聚合计算(并集、交集、差集)场景,点赞、共同关注、收藏、微信抽奖小程序
Zset:排行榜
你是怎么做数据库迁移的
1、数据量小的直接复制,检查一下就行了 2、大数据量的迁移,需要考虑数据一致性和回滚的问题。可以先用主从复制或者DTS去同步数据到新库,然后再双向写入,最后再灰度切换读流量
==和equals的区别是?
==
如果比较的是基本数据类型,比较的是值;如果比较的是引用数据类型,比较的是对象的内存地址。equals()是 Object 类中的方法,默认也是比较地址,但很多类会重写 equals 方法,比如 String、Integer 等,重写后一般比较的是对象内容。所以在比较字符串内容时,应该使用equals(),而不是==ArrayList和LinkedList有什么区别?
ArrayList 和 LinkedList 的主要区别在于底层数据结构不同。ArrayList 底层是动态数组,支持根据下标快速访问,所以查询效率高,时间复杂度是 O(1),但是在中间插入或删除元素时需要移动元素,效率较低。LinkedList 底层是双向链表,查询时需要遍历,效率是 O(n),但如果已经定位到节点,插入和删除只需要修改指针,效率较高。同时 LinkedList 每个节点需要额外保存前后指针,所以内存占用更大。实际开发中大多数场景优先使用 ArrayList。
请列举Spring常用的注解,并解释用途。
注解 作用 @Component通用组件,交给 Spring 管理 @Controller控制层组件 @Service业务层组件 @Repository持久层组件 @Autowired自动注入 Bean @Qualifier指定注入哪个 Bean @Resource按名称或类型注入 @Value注入配置值 @RestController返回 JSON 数据的控制器 @RequestMapping请求路径映射 @GetMapping处理 GET 请求 @PostMapping处理 POST 请求 @RequestBody接收 JSON 请求体 @PathVariable获取路径参数 @RequestParam获取请求参数 @Configuration配置类 @Bean注册 Bean @Transactional开启事务 @Aspect声明切面 @SpringBootApplicationSpring Boot 启动类 什么是MySQL回表?
MySQL 回表是指在 InnoDB 中通过普通索引查询数据时,普通索引的叶子节点只保存索引字段和主键值,如果查询的字段不在这个普通索引中,就需要拿到主键 ID 后,再去主键索引中查询完整行数据,这个过程叫回表。比如
select * from user where name = '张三',如果name是普通索引,就会先通过name索引找到主键 ID,再根据主键 ID 回到主键索引查整行数据。减少回表的方法主要是避免select *,以及使用覆盖索引。Redis支持的数据结构有哪些?
string,hash,list,set,zset
什么是缓存穿透?怎么解决?
缓存穿透是指请求的数据在缓存中不存在,在数据库中也不存在,导致每次请求都会直接访问数据库。如果大量请求查询这种不存在的数据,就会给数据库造成很大压力。解决方式主要有三种:第一是缓存空值,当数据库查不到数据时,也把空结果缓存一段时间;第二是使用布隆过滤器,在访问缓存和数据库前先判断数据是否可能存在,如果一定不存在就直接拦截;第三是做好参数校验,过滤掉明显非法的请求。实际项目中通常会结合缓存空值和布隆过滤器一起使用。
int和integer这两个的区别是什么?
int
是 Java 的基本数据类型,Integer是int的包装类。int默认值是 0,不能为 null;Integer默认值是 null,可以表示空值。int直接存储数值,而Integer是对象。Java 中支持自动装箱和自动拆箱,也就是int和Integer可以自动转换,但如果Integer为 null 时自动拆箱,会出现空指针异常。另外,Integer是对象,比较内容时应该使用equals(),不要直接用==
面向对象的特点讲几个?
面向对象的特点主要有封装、继承、多态和抽象。封装是把属性和方法封装到类中,并隐藏内部实现;继承是子类继承父类的属性和方法,实现代码复用;多态是同一个方法在不同对象上有不同表现,通常通过父类引用指向子类对象和方法重写实现;抽象是提取事物的共性,忽略具体实现细节,常见形式有抽象类和接口。
equals和==的区别是什么?
arraylist一般是用来干什么的?
ArrayList一般用来存储一组有序、可重复的数据。它底层是动态数组,支持按下标快速访问,所以适合查询多、遍历多的场景。实际开发中,比如数据库查询结果列表、接口返回列表、用户列表、商品列表等,都经常使用ArrayList。但是如果频繁在头部或中间插入删除元素,ArrayList效率会比较低,因为需要移动数组元素。
计算机网络: GET和POST的区别是什么?(😭)
MySQL: mysql数据库里面,主键又什么作用? 索引的作用? 怎么去合理地使用索引? 事务隔离级别有哪些?
MySQL 中主键主要用于唯一标识一条记录,主键不能为空且不能重复。在 InnoDB 中,主键索引的叶子节点保存整行数据,所以主键也决定了数据的组织方式。
索引的主要作用是提高查询效率,减少扫描行数,但索引也会占用空间,并降低插入、更新、删除的效率。合理使用索引时,要给经常作为查询条件、排序、分组、关联的字段建索引,优先选择区分度高的字段,合理设计联合索引,并遵守最左前缀原则,同时避免函数、运算、左模糊查询等导致索引失效的写法。
MySQL 的事务隔离级别有读未提交、读已提交、可重复读和串行化,其中 InnoDB 默认是可重复读。
Redis: redis的常见一些数据类型? redis和数据库这块是怎么互相去结合使用的? redis中的缓存击穿、缓存穿透和缓存雪崩是什么?
Redis 常见数据类型有 String、List、Hash、Set、ZSet。String 常用于缓存普通字符串、验证码和计数器;Hash 可以存对象;List 可以做列表或简单队列;Set 可以做去重;ZSet 可以做排行榜。
Redis 通常和数据库配合使用,Redis 作为缓存,MySQL 作为持久化存储。查询时先查 Redis,查不到再查数据库,然后把结果写入 Redis。更新时一般先更新数据库,再删除缓存。
缓存穿透是查询的数据在缓存和数据库中都不存在,可以用缓存空值、布隆过滤器解决;
缓存击穿是热点 key 过期后大量请求同时打到数据库,可以用互斥锁、逻辑过期解决;
缓存雪崩是大量 key 同时过期或者 Redis 宕机,导致请求直接打到数据库,可以通过过期时间加随机值、缓存预热、Redis 高可用、限流降级解决。
项目: Easy Excel解析用户上传的 XLSX 表格数据文件并压缩为 CSV 格式的作用? 项目中的线程池作用是什么?
实习: 多人并发打分中的 MySQL 悲观锁(SELECT ... FOR UPDATE)是怎么实现并运用的? 消息群发功能中的插入数据库是怎么实现分批异步插入提升接口响应性能的?
MySQL 的乐观锁和悲观锁是什么?
乐观锁就是在操作的时候不加锁,在提交的时候进行校验如果发现数据已经被其他事务修改会拒绝当前的事务,并重新尝试直到成功,乐观锁通过版本号或时间戳来实现
悲观锁就是在操作的时候就加上锁,其他事务不可访问,实现方式:行级锁或者表级锁
AOP是什么?(又被打断了)
AOP 是面向切面编程,它的作用是在不修改业务代码的情况下,对方法进行增强。常见应用有日志、权限、事务、异常处理等。Spring AOP 底层主要通过动态代理实现,如果目标类实现了接口,就用 JDK 动态代理;如果没有实现接口,就用 CGLIB 代理。像
@Transactional事务注解,本质上就是 AOP 的应用。常用注解@Aspect切面,@Pointcut("execution(* com.example.service..(..))")切点
MySQL有哪些常用索引?
主键索引:字段值非空且不能重复,一个表只能有一个主键索引。
普通索引:字段值可以为空也可以重复。
联合索引:多个字段组成的普通索引。
唯一索引:字段值可以为空,但非空的字段值不能重复。
提问:全文索引和 LIKE '%keyword%' 有什么区别?
LIKE '%keyword%'是前后模糊匹配,没法用 B+ 树索引,只能全表扫描。全文索引是分词后建倒排索引,能快速定位包含某个词的记录。全文索引支持自然语言搜索、布尔模式搜索,还能按相关性排序。但全文索引对中文支持不太好,需要配合 ngram 分词器。如果是正经的全文搜索需求,一般用 Elasticsearch 比 MySQL 全文索引靠谱。
如果有大数据量的表,有模糊查询和多条件查询,怎么优化
大数据量表中,如果有模糊查询和多条件查询,我会先分析 SQL 的执行计划,看是否走索引、扫描行数是多少。 对于模糊查询,如果是
LIKE 'xxx%',可以建立普通索引;如果是LIKE '%xxx%',普通 B+Tree 索引基本无法生效,这种情况可以考虑改成右模糊、使用全文索引,或者引入 Elasticsearch 做搜索。 对于多条件查询,一般会根据WHERE、ORDER BY、GROUP BY设计联合索引,索引顺序通常是等值条件在前,范围条件在后,排序字段尽量放到索引里。同时避免SELECT *,尽量使用覆盖索引减少回表。 如果数据量特别大,还可以进一步考虑分页优化、冷热数据分离、分库分表等方案。
问我联合索引,那需要满足什么条件
联合索引要满足最左前缀原则。比如有一个联合索引
(a, b, c),那么查询条件使用a、a + b、a + b + c都可以走索引;但是如果只查b或者b + c,因为没有从最左边的a开始,就不能很好利用这个索引。 另外,如果中间字段断了,比如只用a和c,一般只能用到a。如果遇到范围查询,比如a = ? and b > ? and c = ?,通常只能用到a和b,c很难继续利用。 所以设计联合索引时,一般会把等值查询字段放前面,范围查询字段放后面,同时结合字段区分度和查询频率来决定字段顺序。
Redis的持久化
Redis 的持久化主要有 RDB 和 AOF 两种方式。 RDB 是快照持久化,会在某个时间点把内存中的数据生成快照文件保存到磁盘,优点是文件小、恢复快,缺点是可能丢失两次快照之间的数据。 AOF 是追加日志持久化,会把 Redis 执行的写命令追加到 AOF 文件中,Redis 重启时通过重新执行这些命令恢复数据。AOF 数据安全性更高,常用
everysec策略,最多丢失 1 秒数据,但文件较大,恢复速度比 RDB 慢。 实际生产中一般会开启 AOF,或者使用 RDB + AOF 混合持久化,兼顾恢复速度和数据安全。