news 2026/9/24 17:52:49

第 09 篇:重排——Rerank 与 RRF

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第 09 篇:重排——Rerank 与 RRF

第 09 篇:重排——Rerank 与 RRF

第 08 篇结尾把一件事按下了:“名单怎么从候选变成上下文,是拿到名单以后的事。”
这一篇就把它打开。夹在检索与生成之间的那一步叫重排
它回答的是同一个问题的两半:几十条候选里,到底哪几条该进提示词?

但这一篇最值钱的结论不是“重排有用”——那是意料之中的。真正意外的是第六节那个实测:
把向量库从 Elasticsearch 换成 Qdrant,向量分数变了,重排分数却一位都没变。
这个结果把“哪一步可以跨后端复用、哪一步不行”这条线画清楚了。

下面这张是本篇全部实测数据汇总出来的对照面板:左边是同一批候选重排前后、
以及“向量 / 融合 / 重排”三种排序的并列,右边是耗时、原始响应体、本工程接口返回,
最下面是换到 Qdrant 之后的跨后端核对。后面每一节都会从这块面板里取一格来讲。

一、粗筛之后为什么还要再排一遍

1.1 粗筛的两处先天不足

向量检索为了让上百万条数据能在毫秒级查完,做了两件事,各留了一处不足:

做了什么换来了什么代价
近似最近邻(ANN)搜索近似,不是精确的最近邻
把一整段文本压成一个固定长度向量可比、可索引段内细节被平均掉

第 08 篇实测到的那个反例正是第二处的后果:查Redis
真正含这个词的块(02-知识库#0)在向量分支只排第二,输给了一个字面上压根不含它的块:

纯向量:✘ 01-员工手册#1 0.2281 | ✔ 02-知识库#0 0.2190 ← 差 0.0091 就换了名次 纯全文:✔ 02-知识库#0 1.244 ← 只有它含这个词

1.2 重排换了做法:把 query 和候选放在一起过模型

  • 粗筛(向量/全文检索):query 与文档各自变成向量,然后比距离。
    两边从没见过面,相似度是“两个压缩结果的夹角”。
  • 重排(rerank 模型):query 和每一条候选拼在一起送进模型,
    模型直接判断“这段文本能不能回答这个问题”。

做法更细,代价也更贵:N 条候选就是 N 次前向计算
全库几万条块不可能都送进去,所以它天然只能做精排——先粗筛几十条,再重排取前几条:

用户问题

粗筛
向量检索 / 全文检索
目标:别漏
代价:毫秒级

候选池 10~50 条

精排
rerank 模型逐条打分
目标:排序准
代价:与候选数成正比

截断 topK 条

拼进上下文

两次排序的目标不一样:粗筛怕漏(召回优先),重排怕错(精度优先)。
所以粗筛阶段不该设相似度阈值——提前砍掉几条,等于让重排少了可挑的料。
这一点在代码里是显式写死的:

// 粗筛:池子放宽到 topK 的两倍(至少 10 条),且不设阈值——// 阈值是"事后砍",而重排正是那个更该决定砍谁的角色,先砍会让它无从下手。poolSize=Math.max(topK*2,10);List<Document>pool=retrievalService.search(question,poolSize,0.0);hits=rerankService.rerankDocuments(question,pool,topK);

1.3 RRF 是什么,和重排差在哪

第 08 篇已经实现了 RRF(倒数排名融合)。它和重排常被混为一谈,其实是两件事:

RRF 融合重排模型
输入两路已有的名次query + 每条候选原文
输出名次的重排全新的相关性分数(0~1)
会不会引入新信息不会,只是两路名次的加权,模型重新读了一遍文本
能不能推翻共识不能,两路都排前面的必然还在前面
依赖需要两路检索都可用只需要一个重排接口

两者的差别在第五节的数据里会非常清楚:融合名次永远落在两路名次之间
而重排名次可以把向量检索排第 6 的块直接提到第 3

二、接上 rerank:本系列的第三套协议

2.1 同一家厂商,三种协议

到这一节为止,整条链路已经用到三家服务的三种协议。这是接真实模型时最容易被低估的成本:

能力厂商协议地址
对话sensenova 网关OpenAI 兼容https://token.sensenova.cn(不能带/v1
向量化阿里云百炼OpenAI 兼容https://dashscope.aliyuncs.com/compatible-mode(也不能带/v1
重排阿里云百炼原生协议https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank

同一家厂商,embedding 有兼容端点、rerank 没有。实测把同样的请求打给兼容端点:

POST https://dashscope.aliyuncs.com/compatible-mode/v1/rerank -> HTTP 404,响应体为空(耗时 120 ms)

空响应体是这几类错误里最难查的一种:401(密钥错)、429(限流)都会带一段说明,
而 404 空响应既不像配置错、也不像限流,唯一的定位手段是“换个地址再试一次”。
所以这一路必须自己拼 JSON、自己解析 JSON,跟对话/向量化是两套完全不同的代码。

2.2 原生的请求体与响应体(真实抓取)

POSThttps://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank{"model":"qwen3.7-text-rerank","input":{"query":"年假有多少天","documents":["员工每年享有 5 天带薪年假,入职满一年后开始计算,未休完的年假可以结转至次年三月底。","公司为全体员工提供补充医疗保险,覆盖门诊与住院费用,报销比例最高 90%。","运维值班分为白班与夜班,白班 9:00 到 18:00,夜班 18:00 到次日 9:00,交接必须有记录。"]},"parameters":{"return_documents":false,"top_n":3}}

真实响应(214 ms,325 token):

{"output":{"results":[{"index":0,"relevance_score":0.913086706435771},{"index":1,"relevance_score":0.1489603740749516},{"index":2,"relevance_score":0.007197711682332408}]},"usage":{"prompt_tokens":325,"total_tokens":325},"request_id":"f6ca7b8e-6c65-9bf4-bc9d-e949ba75d98a"}

三件事值得记下:

  1. 真正有用的只有output.results,每项是index(原候选里的下标,从 0 起)与
    relevance_score(0~1)。它不会回传正文,也不保证index连续——
    只有进了top_n的候选才出现;
  2. 上面三条演示文本的分数是0.9131 / 0.1490 / 0.0072
    一条讲年假的文本拿 0.91,一条讲医保的拿 0.15,一条讲值班的只有 0.007。
    区分度肉眼可见;
  3. return_documents设成false:正文我们手里已经有了,让接口原样回传纯属浪费带宽。

2.3 客户端的四个关键决定

publicRerankResponsererank(Stringquery,List<String>documents,inttopN){if(documents.isEmpty()){returnnewRerankResponse(List.of(),0,0,"(候选为空,未发起请求)");}...Stringraw=client.post().uri(properties.baseUrl()).header("Authorization","Bearer "+properties.apiKey()).contentType(MediaType.APPLICATION_JSON).body(body)// 用 String 接响应而不是直接反序列化成对象:// 原始响应体要回显给接口和日志,出问题时能一眼看到后端到底说了什么.body(String.class);...List<Hit>hits=parse(raw,documents.size());
  1. String收响应,再自己解析。多写十行,换来两件事:原始响应体能回显给接口
    (排查时不用抓包),解析失败时能把原文一起抛出来;
  2. index越界立即抛异常:下标越界意味着“调用方与接口对候选的理解不一致”,
    这是必须暴露的编程错误,不能默默丢掉;
  3. 读超时单独放宽到 30 秒。重排是逐对计算,候选多时耗时会线性上涨,
    超时给小了会表现成“偶发网络抖动”,而真正的原因是模型没算完;
  4. 候选为空时不发请求。省一次调用,也避免“空数组”这种边界情况引发接口的奇怪响应。

配置单独一份,因为它是独立的模型服务:

rag:rerank:base-url:https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerankapi-key:${DASHSCOPE_API_KEY:...}model:qwen3.7-text-rerankread-timeout-ms:30000

启动时踩的一个坑rerank包最初放在com.example.rerank下,
而启动类在com.example.rag——Spring Boot 的组件扫描根就是启动类所在的包,
于是启动直接失败:
Parameter 1 of constructor in com.example.rag.chat.RagChatService required a bean of type 'com.example.rerank.RerankService' that could not be found.
解法不是放宽@ComponentScan,而是把包移到com.example.rag.rerank,与工程其余部分保持一致。

“用String收响应、再回显给接口”这条决定落到实处,就是本工程对外的那个只读接口——
一次调用同时给出before(向量顺序)与after(重排顺序),外加原始响应体:

三、重排到底改了什么:前后对照

3.1 一个问题看得最清楚

问题“年假有多少天”,粗筛池 6 条(库里总共就 6 块),重排取前 5:

序号重排前(向量名次与分数)重排后(重排名次与分数)
101-员工手册#0 0.568801-员工手册#00.9251(向量第 1)
201-员工手册#1 0.377701-员工手册#1 0.3252(向量第 2)
303-运维值班规范#1 0.294002-知识库#1 0.2476(向量第 6)
402-知识库#0 0.293802-知识库#0 0.1962(向量第 4)
503-运维值班规范#0 0.277503-运维值班规范#0 0.0946(向量第 5)
602-知识库#1 0.2630(未进前 5,接口不返回)

两件事同时发生:

  • 名次换了:向量第 6 名的02-知识库#1被提到第 3,把向量第 3 名的
    03-运维值班规范#1挤出前五。重排后挤进前 5、原本不在前 5 的:1 条
  • 分数的分布变了:向量的第一名与第二名只差0.1911(0.5688 − 0.3777),
    重排差0.5999(0.9251 − 0.3252)——区分度是向量的 3.1 倍

第二件事比第一件更实用:向量分数挤在 0.26~0.57 这个窄带里,
阈值稍微动一点,命中数就从 5 跳到 1(第 08 篇的扫描表就是证据)。
而重排分数是 0.9251 / 0.3252 / 0.2476 / 0.1962 / 0.0946——
第一名拉开一大截,剩下几条明显是陪跑,这种分布才敢拿来卡阈值。

3.2 五个问题:不是每个问题都需要重排

问题token耗时向量前 5 → 重排后前 5提升
年假有多少天2494158 ms01#0, 01#1, 03#1, 02#0, 03#001#0, 01#1, 02#1, 02#0, 03#01
数据订正超过一万行由谁执行2530129 ms03#1, 01#1, 01#0, 03#0, 02#103#1, 03#0, 01#0, 01#1, 02#01
云枢知识库支持哪些文件格式2512125 ms02#0, 02#1, 01#1, 01#0, 03#0重排后完全一致0
180 天2506127 ms01#1, 01#0, 03#1, 03#0, 02#101#1, 01#0, 03#0, 02#0, 02#11
v3.2.12506134 ms02#0, 03#0, 03#1, 01#0, 02#102#0, 01#0, 03#0, 02#1, 01#11

01#0=01-员工手册#0,以此类推)

逐条读下来有三个观察:

  • 五个问题里四个各提升了 1 条,改动幅度不大但方向一致:都是把“更该进上下文的那条”提上来;
  • “云枢知识库支持哪些文件格式”一条没动,且向量分数本来就分得开
    (0.6667 / 0.5298 / 0.4558 …)。粗筛已经排对的时候,重排不会画蛇添足——
    这一点很重要,说明重排是“修正”而不是“打乱”;
  • 前两名在全部五个问题里都没被改动过。重排动的是中后段的名次
    也就是决定“哪一条是第 3、第 4 名”这种真正影响上下文质量的位置。

3.3 一个容易被忽略的实现细节

重排只返回进了top_n的候选。上表里02#0(向量第 6)在重排结果里是不存在的,
接口一行都不给。所以回填代码不能写成“按返回顺序取第 i 条候选”,必须按下标对:

// 按 index 回填。注意:只有进了 top_n 的候选会出现在 results 里,// 没进榜的候选不会返回,所以这里不能假设"返回项数 == 候选数"。for(intrank=0;rank<response.hits().size();rank++){RerankClient.Hithit=response.hits().get(rank);intcandidateIndex=hit.index();Documentcandidate=candidates.get(candidateIndex);...}

写错这一行的后果很隐蔽:名次看着有变化,但换到的是另一条文档——
比“完全没重排”更难发现,因为接口返回的一切看起来都正常。

四、它救回了什么:字面串案例

第 08 篇留下的那批“向量守不住的字面串”,正好拿来验收重排。判定基准是
“真正含这个字面串的块”(用 ES 的match_phrase直接查出来):

字面串含它的块向量第一名重排第一名结论
Redis02-知识库#0✘ 01-员工手册#102-知识库#0重排救回
DELETE03-运维值班规范#1✔ 03-运维值班规范#1✔ 03-运维值班规范#1都命中
18:0001-员工手册#1✔ 01-员工手册#1✔ 01-员工手册#1都命中
DBA03-运维值班规范#1、#0✔ 03-运维值班规范#1✔ 03-运维值班规范#1都命中
xlsx02-知识库#1、#0✔ 02-知识库#1✔ 02-知识库#1都命中

五个里四个本来就是对的,唯一错的那个被纠正了。
这个比例(5 个错 1 个)比“重排能修一切”更接近真实:
它是一层保险,不是万能药。绝大多数问题粗筛就排对了,重排的价值恰好体现在剩下的少数上——
而那少数往往就是线上用户投诉的那几个查询。

五、三种排序放一起看

同一批 6 条候选,同一个问题,三种排序并列(ES 侧实测):

问题“年假有多少天”

向量名次向量分融合名次重排名次重排分
01-员工手册#010.5679110.9251
01-员工手册#120.3796220.3252
03-运维值班规范#130.29825(未进前 5)-
02-知识库#040.2979340.1962
03-运维值班规范#050.2798450.0946
02-知识库#160.2661630.2476

问题“数据订正超过一万行由谁执行”

向量名次向量分融合名次重排名次重排分
03-运维值班规范#110.6088111.0000
01-员工手册#120.3365240.1686
01-员工手册#030.3270430.2154
03-运维值班规范#040.2905320.4066
02-知识库#150.27106(未进前 5)-
02-知识库#060.2571550.1655

三件事一眼可见:

  1. 融合名次永远夹在两路原始名次之间。它是“名次的加权”,不引入新信息。
    03-运维值班规范#1(第 1 行):向量第 3、融合第 5——因为全文那一路没排它;
  2. 重排名次可以跳出两路给出的顺序02-知识库#1向量第 6、融合第 6,
    重排直接给到第 3。融合永远做不到这件事:两路都排最后的块,融合只会继续把它排最后;
  3. 重排分数出现 1.0000。第二张表里讲数据订正的那块拿了满分——
    它确实是唯一直接回答“由 DBA 执行”的段落。这种明确的分数是向量余弦给不出来的。

六、换掉向量库,重排结果会不会变?

这是这一篇最值得单独立一节的结果。

同样的问题、同样这批候选,分别在ElasticsearchQdrant上跑一遍
(切 profile 重启应用即可,检索代码一行没改):

向量分(ES)向量分(Qdrant)重排分(ES)重排分(Qdrant)重排分差值
01-员工手册#00.56790.56690.92510.9251一致
01-员工手册#10.37960.37560.32520.3252一致
03-运维值班规范#10.29820.2953-(未进前 5)-(未进前 5)-
02-知识库#00.29790.30080.19620.1962一致
03-运维值班规范#00.27980.28330.09460.0946一致
02-知识库#10.26610.27690.24760.2476一致

向量分数两库不同(这正是第 07 篇量过的分数噪声),重排分数逐位相同。

四个问题的重排名次也逐一核对过,全部一致:

问题ES 重排名次Qdrant 重排名次
年假有多少天01#0, 01#1, 02#1, 02#0, 03#0
数据订正超过一万行由谁执行03#1, 03#0, 01#0, 01#1, 02#0
云枢知识库支持哪些文件格式02#0, 02#1, 01#1, 01#0, 03#0
180 天01#1, 01#0, 03#0, 02#0, 02#1

原因不复杂:重排模型的输入只有 query 与文本,它根本不知道向量库是谁
前面所有的分数差异都发生在“文本如何变成向量、向量如何比距离”这一段,
而重排压根不在这一段里。

6.1 顺带得到的第二个结论:融合在 Qdrant 上直接不可用

同一批实验在 Qdrant 上跑“三路对照”时,融合那一列整列是空的:

问题 [年假有多少天] 融合可用=False 重排 token=2494 耗时=158 ms 提升 1 条 块 向量名次 向量分 融合名次 重排名次 重排分 01-员工手册#0 1 0.5669 None 1 0.9251 ... 03-运维值班规范#1 4 0.2953 None None -

这正是第 08 篇的结论在两处能力上的分界:

能力依赖什么ESQdrant跨后端可复用
混合检索(向量 + 全文)后端自身的全文检索能力✘ 拿不到ElasticsearchClient
重排一个独立的重排接口

判据很简单:这一步是在“用后端的能力”,还是在“用文本”?
混合检索用的是后端的倒排索引,所以换库就断;
重排只吃文本,所以换库无感。这个判据可以直接拿来做架构决策——
哪些能力该封装成独立服务、哪些必须绑在某个存储上。

七、代价:重排不是免费的

7.1 候选越多越贵

问题“数据订正超过一万行由谁执行”,逐步加大候选数:

请求候选数实际池大小token接口耗时每条候选返回条数
331058123 ms41 ms3
551819133 ms27 ms5
1062530128 ms21 ms5
2062530124 ms21 ms5

两点:

  • token 与耗时随候选数上升,这是“逐对计算”的直接体现。本库只有 6 块,
    所以请求 10 和 20 实际都只送了 6 条(池大小那列就是证据)——语料太小,
    这个实验只能看出趋势,看不出线性;
  • 每条候选约21~41 ms。按这个量级推算:50 条候选约 1~2 秒。
    这个延迟对同步接口是可以接受的,但它决定了候选池不能随便放大
    更不可能拿它替代粗筛。

7.2 真正的代价在提示词上(实测)

这是最容易忽略的一处。同一个问题,走两条路径问答:

问题路径检索/重排prompt token上下文答案
年假有多少天不重排1154 ms / 0685900 字年假按司龄计算… [1]
年假有多少天重排10321 ms / 174 ms20013173 字年假天数按司龄计算… [1]
数据订正超过一万行由谁执行不重排1154 ms / 0248204 字数据订正超过一万行由 DBA 执行 [1]
数据订正超过一万行由谁执行重排10278 ms / 128 ms20773301 字由 DBA 执行 [1]

答案两两几乎一样,但 prompt token 涨了 3~8 倍(685 → 2001,248 → 2077)。

原因是我在实现里做的一个选择:重排路径取消了相似度阈值(为了让重排有料可挑),
于是上下文从“阈值筛剩下的 1 条”变成“重排要的前 5 条”。
这不是重排本身的问题,而是重排必须配一个截断策略

  • 要么把topK降下来(比如重排前 10 条、只取 2 条进上下文);
  • 要么用重排分数做二级阈值——本例里 0.5 就够:
    第一名 0.9251 稳稳过线,第二名 0.3252 与以下全部被挡掉,上下文只留真正相关的那一条。

重排真正的收益场景是“粗筛把答案排在第 3~10 名”
那时重排把它提到第 1,同时把陪跑的块挡在截断线外,既提质量又省 token。
如果粗筛本来就只返回 1 条,重排只是徒增成本。

7.3 共享池网关的限流:错误码会被包装

跑实验时连续问答很快撞上限流。日志里的原始错误是:

HTTP 429 - {"error":{"message":"inference exceeds tpm/rpm limit", "type":"rate_limit_error","code":"insufficient_quota"}}

接口对外返回的是 HTTP 500(异常被统一包装过)。这个差别很容易带偏排查方向:
看到 500 会去翻代码,实际原因在日志里,是模型侧限流。
第一次写的重试逻辑只匹配429,于是永远不触发重试,实验直接中断。
改成“任何失败都退避重试”之后,等 35 秒重来即可通过。

这条对生产同样成立:限流要按“业务失败”兜底,而不是按错误码兜底——
错误码在到达你手里之前可能已经被包装过一轮。

八、工程规则

  1. 重排只做精排。候选池按 10~50 条设计,别拿它替代粗筛;
  2. 粗筛阶段不设阈值。先给重排一个完整的池子,截断留给重排之后;
  3. 重排之后一定要截断。实测不截断会让 prompt token 涨 3~8 倍而答案不变;
  4. 重排分数可以当二级阈值用。它 0~1、区分度是余弦的 3 倍以上,
    本例 0.5 就能把陪跑块全部挡掉;
  5. 接新协议先探测。同一家厂商 embedding 有兼容端点、rerank 没有,
    兼容端点还会返回 404 空响应体——不探测就只能在启动时报错里猜;
  6. 回填要按index,不能按返回顺序。未进top_n的候选根本不会返回;
  7. 限流按失败退避,不按错误码。错误码可能已被框架包装成 500;
  8. 判据:这一步用后端的能力还是用文本?用文本的(重排)可以跨后端复用,
    用后端能力的(全文检索)换库即断。

小结

这一篇把“从候选到上下文之间”那一步填上了:

  • 重排换了个做法:粗筛是 query 与文档各自压成向量再比距离,重排是把两者放在一起过模型。
    更准,但代价是逐对计算,只能做精排;
  • 它确实改动了排序:五个问题里四个各提升 1 条,前两名一次没动过——
    动的是决定上下文质量的中后段;
  • 分数分布的变化比名次更实用:向量第一名只领先 0.1911,重排领先 0.5999,
    区分度 3.1 倍,这种分布才敢拿来卡阈值;
  • 它救回了字面串:Redis从“输给不含它的块”被纠正为第一名;
    五个探测词里只有一个原本是错的,重排是保险不是万能药;
  • 三种排序的定位清楚了:融合只在两路已有名次之间做加权、不引入新信息;
    重排能跳出两路顺序(把向量第 6 名提到第 3);
  • 它不吃后端:换向量库后向量分数变了,重排分数逐位相同——
    重排的输入只有 query 与文本。这条判据比结论本身更值钱;
  • 代价在提示词上:不配截断时 prompt token 涨 3~8 倍而答案不变;
    重排分数当二级阈值(本例 0.5)是最省事的收口方式;
  • 限流会把错误码包装掉:网关 429 到了接口层变成 500,重试要按失败兜底。

到这里,“检索 → 重排 → 取前几条”这条挑选链路是完整的了。
但把这几条拼成提示词还有它自己的问题:总共能放多少字、超了砍谁、资料不够时怎么让模型坦白说不知道——
那属于上下文与生成那一侧的事,按下不表。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 17:52:40

基于 Java Spring Boot 的幼儿早教微信小程序设计与实现

温馨提示&#xff1a;本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 1. 引言 随着移动互联网的普及和微信生态的快速发展&#xff0c;微信小程序凭借其即用即走、无需下载安装、传播便捷等优势&#xff0c;已成为教育服务领域的重要载体。…

作者头像 李华
网站建设 2026/9/24 17:52:00

2026短视频配音工具怎么选?实用功能才是关键

打开应用商店搜"配音"&#xff0c;跳出来的工具没有一百也有八十。榜单天天变&#xff0c;"第一名"月月换&#xff0c;但说实话&#xff0c;选配音工具跟选手机一个道理——参数表再漂亮&#xff0c;不如看实用功能对不对得上你的活儿。2026年的AI配音早已…

作者头像 李华
网站建设 2026/9/24 17:51:58

云原生Serverless架构挑战及解决方案

云原生 Serverless&#xff0c;核心是事件驱动、按需弹性、按调用计费、平台托管底层资源&#xff0c;开发者只写业务代码&#xff0c;不用管理服务器 / 容器节点。主流形态&#xff1a;FaaS函数即服务&#xff0c;AWS Lambda、阿里云函数计算、腾讯云 SCF&#xff0c;也包含 B…

作者头像 李华
网站建设 2026/9/24 17:51:09

秋分时节, 与团队文化的平衡之道

快乐能量体验式培训公司 新媒体专栏 秋分时节&#xff0c;与团队文化的平衡之道 把效率与人性&#xff0c;放进同一架天平 传播快乐 拓展潜能 有活力&#xff0c;更能有成绩秋分时节与团队文化的平衡之道 秋分&#xff0c;把一年的光阴&#xff0c;轻轻地分成了两半。…

作者头像 李华
网站建设 2026/9/24 17:50:08

论负载均衡技术

摘要2024 年 3 月至 10 月&#xff0c;我作为系统架构师参与了某省级政务一体化服务平台项目的设计与开发工作。该平台面向省内千万居民&#xff0c;提供社保查询、不动产登记、企业办事等线上政务服务&#xff0c;项目采用微服务架构&#xff0c;用户访问存在明显的潮汐流量特…

作者头像 李华
网站建设 2026/9/24 17:48:32

从Java到Python:小白程序员如何精准转型AI?收藏这份学习路线图!

本文针对传统IT从业者转型AI的迷茫&#xff0c;提供清晰的学习路径。文章首先分析了AI不同岗位方向&#xff0c;如应用开发、算法研究、测试和产品经理等&#xff0c;并探讨了Java、Python、Go等编程语言的选择。接着&#xff0c;文章提出AI应用开发的学习主线&#xff0c;从模…

作者头像 李华