聊一下近期爆火的Jev

我的看法 Jev最近很火,对比一下Bert,对比一下生成模型。 Jev的优点如下。 第一个是“不会幻觉”。 更准确的说法是:它不会输出 schema 之外的内容。比如你只给它 keep、drop_result、drop_call 三个动作,它不会编一个 maybe_keep 出来。 但它仍然可能选错。 这叫类型安全,不叫语义正确。 第二个是“概率可信”。 概率校准是 Jev 的核心卖点。它希望做到:模型说 0.8 的判断,长期看真的有接近 80% 是对的。这个方向很重要,但目前公开资料里,RLCD 的训练细节和第三方校准数据还不充分。 所以在工程里不能直接把 0.9 当成上线规则。 第三个就是,这是一个通用模型,可以通过自然语言快速上线,不用进行任何训练。 实践 类型 本质 你问 Jev 的问题 典型用途 choice 多选一 “属于哪一类?” 分类、路由、意图识别 score 有序程度判断 “程度有多高?” 严重度、风险、质量评分 noul 是/否概率 “这件事成立吗?” 条件判断、检测、过滤 Choise Request { "state": "My running shoes arrived in the wrong size. Can I swap them for a size 10?", "questions": { "department": { "type": "choice", "instructions": "Which team should handle this?", "criteria": { "returns": "Exchanges, wrong or damaged items", "shipping": "Delivery status, delays, lost packages", "billing": "Charges, invoices, payment problems" } } } } Response ...

2026年9月22日 · 2 分钟

Java 性能问题定位:从系统指标到应用排查

Java 性能问题定位:从系统指标到应用排查 这篇笔记参考了阿里云相关博客中的排查思路,原文写得很细,我在此基础上按自己的使用习惯重新做了整理。 线上 Java 应用一旦出现响应变慢、资源飙升或进程异常,排查范围很容易越铺越大,下面会从业务代码、CPU、线程、内存、GC、磁盘 I/O、网络 I/O 和常用命令几个角度,把常见的定位方法串起来。 实际的性能问题很少只对应一个异常指标,更多时候是系统层、组件层与应用层互相影响后的结果;排查时可以从最贴近业务的应用层入手,拿到初步方向后,再回到系统指标中交叉验证。 性能优化工具图谱 ├── 系统层 │ ├── CPU │ │ ├── 🚩 CPU利用率(top/vmstat/sar/dstat) │ │ ├── 🚩 CPU平均负载(top/uptime) │ │ └── 上下文切换次数(pidstat/vmstat/dstat) │ ├── 内存 │ │ ├── 全局内存使用 │ │ │ ├── 🚩 已用/剩余/可用内存(free/vmstat/sar) │ │ │ └── 缓冲区/缓存(pcstat/cachestat/cachetop) │ │ └── 进程内存使用 │ │ ├── 🚩 虚拟内存/常驻内存/共享内存(top/ps/pidstat) │ │ ├── 🚩 SWAP 内存使用/换入换出速度(top/free/vmstat/sar) │ │ ├── 缺页异常(ps/pidstat) │ │ └── 内存分布(pmap/jmap) │ ├── 磁盘 │ │ ├── 空间容量(df/du) │ │ ├── 🚩 吞吐量/磁盘 I/O 使用率(iostat/dstat/sar) │ │ └── 缓冲区/缓存(pcstat/cachestat/cachetop) │ └── 网络 │ ├── 🚩 吞吐量(sar) │ ├── 网络延迟(ping) │ ├── 🚩 网络连接数/错误数(netstat/ss/sar) │ └── 网络抓包(tcpdump/wireshark) ├── 组件层 │ ├── 数据库 │ │ ├── SQL 调优 │ │ ├── 🚩 索引调优 │ │ └── 连接池配置 │ ├── 网络 IO │ │ ├── I/O 调度模型 │ │ ├── 序列化框架 │ │ └── 线程调度模型 │ ├── Web 容器 │ │ └── 线程池配置 │ └── 缓存/MQ…… └── 应用层 ├── 线程 │ ├── 死锁检查(jstack/arthas) │ ├── 🚩 线程状态分布(jstack/arthas) │ ├── 锁竞争分布(jstack/arthas) │ ├── 🚩 代码执行热点(jprofiler/zprofiler) │ ├── 🚩 占用 CPU 较重的线程(top + pidstat + jstack) │ └── 代码追踪(btrace/housemd/greys/arthas) ├── 内存 │ ├── 内存分配 │ │ ├── 常驻内存/虚拟内存(top) │ │ ├── 对象分配热点(jprofiler/zprofiler) │ │ ├── 🚩 堆内对象分布(jmap/zprofiler/MAT) │ │ ├── 类加载相关(jstat/greys/arthas) │ │ ├── 🚩 内存泄漏(gperf/MAT/zprofiler) │ │ └── 堆外内存(jmap + MAT + NMT + gdb + perf) │ └── 垃圾回收 │ ├── GC 线程使用(jinfo) │ ├── 对象晋升年龄(gclog) │ ├── 🚩 GC 的频率和时间(jstat/gclog) │ ├── 垃圾回收器类型/JVM 参数(jinfo/jcmd) │ └── 🚩 堆大小设置及分区大小(jinfo/jstat) ├── 网络 │ ├── 带宽使用 │ ├── 流量异动 │ └── 网络分区 └── ★ 业务(日志、监控…) ├── 🚩 代码逻辑 ├── 远程调用 └── 架构设计 CPU 与线程 观察 CPU 时,最常看的指标是下面三项,常用工具包括 top、ps、uptime、vmstat 和 pidstat。 ...

2026年5月3日 · 8 分钟

大语言模型的可观测性应该有哪些

LLM 与 AI Agent 可观测性 传统微服务常看请求量、错误率和耗时,到了 AI 应用里,也可以先用 Token、Error、Duration 建立一组基础指标;不过这三项只能说明服务有没有运行、花了多少钱、速度是否正常,还不能回答模型为什么给出了这个结果,更无法判断一次 HTTP 200 背后的答案是不是正确。 对普通 LLM 调用来说,一次请求已经可能包括 prompt 拼装、模型推理、内容清洗和结果返回;换成 LLM Agent / AI Agent 后,链路还会加入意图识别、RAG 检索、工具选择、参数构造、多次 LLM 调用与重试,因此真正需要建设的不是“多打一批日志”,而是让整条执行轨迹能够被还原、评分和归因。 1. 为什么传统 APM 还不够 传统 APM 擅长回答“哪里慢了”“哪里报错了”,但 AI Agent 会出现一些没有异常堆栈的失败,例如模型很自信地答错、选中了相似但不适用的工具、参数类型正确却语义错误,或者在几个工具之间来回循环,最终造成 token 和账单持续增长;这些现象在 HTTP 状态码上可能全部是成功,用户拿到的结果却不可用。 因此,AI Agent 可观测性至少要能回答下面几类问题: 一次任务内部执行过哪些步骤,每一步花了多少时间和 Token RAG 召回了哪些文档,排序和 score 是否合理,最终答案有没有使用这些证据 Agent 选择了哪个工具,tool args 是否正确,调用顺序与依赖关系有没有被满足 最终输出是否准确、相关、完整,格式和安全要求有没有达到 失败发生在 Prompt、retrieval、Tool、LLM 还是 orchestration,能否复现到具体 span 单次请求、用户、组织和模型分别产生了多少成本,异常调用是否触发了熔断或 fallback AgentTrace 将结构化轨迹分为 operational、cognitive、contextual 三类 surface,并把可观测性用于安全、可复现性、问责与实时监控;这类设计比单纯保存最终 input/output 更接近 Agent 的实际运行方式。 ...

2026年4月25日 · 5 分钟

MySQL 与 Elasticsearch 双写一致性

场景引入 如果你设计了一个类似 B 站的视频网站中的搜索系统,或许在初期 MySQL 的 like 模糊搜已经能满足你对视频的标题、简介的搜索需求。 SELECT * FROM videos WHERE title LIKE '%'||:search_term||'%' OR description LIKE '%'||:search_term||'%'; 如果后期系统视频的量级上来了,对性能有一定要求了,你或许已经开始考虑 ES 了。后面如果你还想让与搜索关键词相关的创作者名称、视频评论、关联标签也能级联视频搜出来,甚至弄一个各种业务维度的融合公式,那么 ES 这样的搜索引擎再适合不过了! 但是,如果数据写一份 MySQL,还要落一份 ES 来支撑筛选/搜索,要怎么写入两个异构的存储系统、并保证它们的一致性呢? Note 如果你有更好的场景欢迎提出/补充~ 方案一:同步双写 优点 简单粗暴 ES 同步写入快 缺点 业务耦合,扩展性差,代码侵入性强(要在写 MySQL 的地方后写 ES 的代码,要在代码设计上做好收敛) 影响性能,写入两个存储,响应时间变长(本来 MySQL 的写入性能不是很高,再加一个 ES,系统的性能必然会下降),吞吐也会下降 存在双写失败丢数据风险(比如写完MySQL,ES 就挂了) 方案二:异步双写 优点 性能高 不易出现数据丢失问题,主要基于 MQ 消息的消费保障机制,比如 ES 宕机或者写入失败,还能重新消费 MQ 消息 多源写入之间相互隔离(业务侧只管发消息),解耦数据生产者和消费者,便于扩展更多的数据源写入 缺点 同样存在业务耦合的问题,写完 DB 之后,还需要发个 MQ(代码设计上做好收敛,也可以关注一下所用 orm 框架有没有 hook 之类的能力,支持你“写后 xxx”) 接入新的数据源需要实现新的消费者代码 系统复杂度增加,引入了消息中间件 MQ是异步消费模型,存在延迟问题 Tip MQ 可以缓冲和 DB 的负载能力不一致问题 ...

2025年11月17日 · 1 分钟

博客真实案例学习设计模式

起因 最近在实习的时候一直在思考怎么提高代码健壮性与可复用性。 工程实践这块确实存在一些欠缺,应当与设计模式相结合,努力提高代码的健壮性的同时,也提高大佬们复用我逻辑的可能性。 设计模式 设计模式应当是最有用的,和本科期间写的玩具项目不同,没有多人维护,生命周期也可能只在一个月,甚至更少。 设计模式原则 面向对象的设计模式有七大基本原则: 开闭原则(Open Closed Principle,OCP) 单一职责原则(Single Responsibility Principle, SRP) 里氏代换原则(Liskov Substitution Principle,LSP) 依赖倒转原则(Dependency Inversion Principle,DIP) 接口隔离原则(Interface Segregation Principle,ISP) 合成/聚合复用原则(Composite/Aggregate Reuse Principle,CARP) 最少知识原则(Least Knowledge Principle,LKP)或者迪米特法则(Law of Demeter,LOD) 简单理解就是:开闭原则是总纲,它指导我们要对扩展开放,对修改关闭; 单一职责原则指导我们实现类要职责单一;里氏替换原则指导我们不要破坏继承体系; 依赖倒置原则指导我们要面向接口编程; 接口隔离原则指导我们在设计接口的时候要精简单一; 迪米特法则指导我们要降低耦合。 设计模式就是通过这七个原则,来指导我们如何做一个好的设计。但是设计模式不是一套“奇技淫巧”,它是一套方法论,一种高内聚、低耦合的设计思想。我们可以在此基础上自由的发挥,甚至设计出自己的一套设计模式。 当然,学习设计模式或者是在工程中实践设计模式,必须深入到某一个特定的业务场景中去,再结合对业务场景的理解和领域模型的建立,才能体会到设计模式思想的精髓。如果脱离具体的业务逻辑去学习或者使用设计模式,那是极其空洞的。接下来我们将通过外卖营销业务的实践,来探讨如何用设计模式来实现可重用、易维护的代码。 几个case初探设计模式 言而总之,掌握一个方法论,高内聚、低耦合。 奖励发放逻辑 — 从 if 分支到策略 + 工厂模式 原先的逻辑是RewardService,后续维护起来实在太过繁琐,过多的if else读的头都晕了,维护起来也不方便。 一是不符合开闭原则,可以预见,如果后续新增品类券的话,需要直接修改主干代码,而我们提倡代码应该是对修改封闭的; 二是不符合迪米特法则,发奖逻辑和各个下游接口高度耦合,这导致接口的改变将直接影响到代码的组织,使得代码的可维护性降低。 // 奖励服务 class RewardService { // 外部服务 private WaimaiService waimaiService; private HotelService hotelService; private FoodService foodService; // 使用对入参的条件判断进行发奖 public void issueReward(String rewardType, Object ... params) { if ("Waimai".equals(rewardType)) { WaimaiRequest request = new WaimaiRequest(); // 构建入参 request.setWaimaiReq(params); waimaiService.issueWaimai(request); } else if ("Hotel".equals(rewardType)) { HotelRequest request = new HotelRequest(); request.addHotelReq(params); hotelService.sendPrize(request); } else if ("Food".equals(rewardType)) { FoodRequest request = new FoodRequest(params); foodService.getCoupon(request); } else { throw new IllegalArgumentException("rewardType error!"); } } } 将各个同下游接口交互的功能抽象成单独的服务,封装其参数组装及异常处理,使得发奖主逻辑与其解耦 用策略模式和适配器模式 ...

2025年8月1日 · 4 分钟

《高效能人士的七个习惯》读书笔记

围绕产出与产能平衡、从依赖到独立、公众领域成功与持续更新,整理七个习惯的核心原则和行动清单。

2025年7月11日 · 2 分钟

从源码入手剖析Spring Boot 启动

看一下SpringBoot启动流程,有助于理解Bean等… import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class MySpringBootApp { public static void main(String[] args) { SpringApplication.run(MySpringBootApp.class, args); } } 先看new 事件监听器和初始化器都是从springFactory中初始化拿到的,通过setter方法注入实现 deduceMainApplication仅仅是推断出所在的主类 new已经实现了,接下来看run是如何实现的 接下来逐行拆解 环境对象实现 构建并准备 Environment 环境对象,包含以下几个来源: ...

2025年7月5日 · 9 分钟

初识搜索

初识搜索 58同城站内搜索 站内搜索是内部系统生成的数据,例如“发布系统”会将生成的帖子主动推给build_data系统 对于spider(全网)、search&index、rank三个系统: (1)spider(全网)和search&index是相对工程的系统 (2)rank是和业务、策略紧密、算法相关的系统,搜索体验的差异主要在此。 搜索原理与核心数据结构 正排索引可以理解为Map<url, list>,能够由网页快速(时间复杂度O(1))找到内容的一个数据结构。 倒排索引可以理解为Map<item, list>,能够由查询词快速(时间复杂度O(1))找到包含这个查询词的网页的数据结构。 举个例子,假设有3个网页: url1 -> “我爱北京” url2 -> “我爱到家” url3 -> “到家美好” 这是一个正排索引Map<url, page_content>。 分词之后: url1 -> {我,爱,北京} url2 -> {我,爱,到家} url3 -> {到家,美好} 这是一个分词后的正排索引Map<url, list>。 分词后倒排索引: 我 -> {url1, url2} 爱 -> {url1, url2} 北京 -> {url1} 到家 -> {url2, url3} 美好 -> {url3} 由检索词item快速找到包含这个查询词的网页Map<item, list>就是倒排索引。 搜索的过程是什么样的? 假设搜索词是“我爱”,用户会得到什么网页呢? (1)分词,“我爱”会分词为{我,爱},时间复杂度为O(1) (2)每个分词后的item,从倒排索引查询包含这个item的网页list,时间复杂度也是O(1): 我 -> {url1, url2} 爱 -> {url1, url2} (3)求list的交集,就是符合所有查询词的结果网页,对于这个例子,{url1, url2}就是最终的查询结果 ...

2025年6月28日 · 1 分钟