RAG+Agent+微调组合拳:搭建一个完整的AI驱动Android开发助手
Android工程师的AI开发实战系列 · 第4/4篇(完结篇)
用Android思维理解RAG、Agent和微调,从移动端老兵到AI开发者的跨界之路
第1篇:RAG:给大模型装一个靠谱的「本地数据库」
第2篇:Agent智能体:让AI自己调API干活
第3篇:微调:让通用大模型变成你的「专属定制ROM」
第4篇:RAG+Agent+微调组合拳(本篇·完结)
上周五下午四点半,我跑了一个小时的Lint检查,日志里哗哗往外喷Warning,我盯着屏幕想:要是有个AI助手能帮我查文档、跑命令、还能按团队代码风格给建议,那该多爽?
这不是幻想。经过前三篇的铺垫——RAG让大模型能查知识、Agent让大模型能动手干活、微调让大模型懂你的风格——今天我们把三块拼图合到一起,搭一个真正能用的AI Android开发助手。
说实话,单用任何一个技术都有明显短板。就像你不可能只用Activity写出一个复杂App——你需要Fragment管UI、Service跑后台、BroadcastReceiver响应事件。RAG、Agent、微调各司其职,组合起来才是完整能力。
为什么必须组合?单一技术的天花板
先快速回顾一下各自的能力边界:
| 技术 | 擅长 | 短板 |
|---|---|---|
| RAG | 查知识、引用文档 | 只能读,不能动手 |
| Agent | 调工具、执行操作 | 没有领域知识沉淀 |
| 微调 | 风格统一、领域精准 | 知识冻结、不会用工具 |
想象一个场景:你问AI助手「我们项目里怎么处理Token过期刷新的?」
纯RAG:能从文档里找到Token刷新的相关代码,但给的建议可能和你们团队风格不一致。纯Agent:能帮你搜代码、跑命令,但它不知道该搜什么关键词、该去哪个模块找。纯微调:风格对味了,但知识可能过时——上个月才改的刷新策略它不知道。
组合起来就不一样了:RAG从最新代码库检索出Token刷新的实现;Agent调grep/git log拿到变更历史;微调后的模型用团队风格组织回答。这才是一个靠谱的回答链路。
架构设计:用MVVM思维理解三层融合
做Android的都熟悉MVVM三层分离。巧的是,RAG+Agent+微调的组合恰好可以用这个框架类比:
用户提问
↓
微调模型(View层·表现)
作用 → 理解意图、统一输出风格、团队用语
↓
Agent(ViewModel层·逻辑)
作用 → 编排工具调用、决策执行路径
↓
RAG(Model层·数据)
作用 → 提供知识检索、文档引用、代码搜索
↓
输出回答
这个类比不只是方便理解——它还指导了我的实现策略:就像MVVM里ViewModel不直接操作View、Model不关心展示逻辑一样,三个模块的职责要清晰隔离,通过接口通信。
实战项目:AI Android开发助手
别光说理论,我们来真的。目标:搭一个能在日常开发中实际派上用场的AI助手。它要能:
• 查官方文档和项目Wiki(RAG)
• 执行Gradle命令、跑Lint、搜代码(Agent)
• 用团队代码风格给出建议(微调)
知识库搭建:三种数据源的RAG索引
知识库是地基。我的方案是分三层建索引:
第一层:Android官方文档。把developer.android.com的核心文档抓下来做chunk,每个chunk 512 token,overlap 64。重点索引API Reference、Architecture Guide、Performance部分。
第二层:项目Wiki和技术设计文档。从Confluence/飞书/企业微信文档导出Markdown,同样切片入库。这部分是团队私有知识,价值最高。
第三层:项目源码和Git历史。这个最tricky——不是把整个代码库塞进去,而是索引函数签名、类声明、关键注释。配合git log里的commit message做关联检索。
// 知识库索引构建配置
data class IndexConfig(
val sources: List<
DataSource>,
val chunkSize: Int =
512,
val overlap: Int =
64,
val embedding: String =
"text-embedding-3-small"
)
sealed class DataSource {
data class OfficialDocs(
val baseUrl: String,
val sections: List<
String>
) : DataSource()
data class ProjectWiki(
val exportPath: String,
val format: String =
"markdown"
) : DataSource()
data class SourceCode(
val repoPath: String,
val includeGitLog:
Boolean = true,
val indexLevel:
IndexLevel =
IndexLevel.SIGNATURE
) : DataSource()
}
踩坑提醒:源码索引千万别用全量文本。一个中型Android项目动不动几十万行代码,全塞进向量库不仅慢,而且检索精度反而下降。只索引「声明级」信息(函数签名+docstring+关键注释),细节靠Agent实时grep。
工具集设计:Agent的Function Calling武器库
Agent需要工具才能干活。就像Android里的Intent能启动各种组件一样,我们给Agent设计一组工具接口:
val tools = listOf(
// 代码搜索
Tool(
name = "search_code",
desc = "在项目中搜索代码",
params = mapOf(
"query" to
"搜索关键词",
"file_pattern" to
"文件过滤,如*.kt"
)
),
// Gradle命令
Tool(
name = "run_gradle",
desc = "执行Gradle任务",
params = mapOf(
"task" to
"任务名如:app:lint",
"args" to
"额外参数"
)
),
// Lint检查
Tool(
name = "run_lint",
desc = "对指定模块跑Lint",
params = mapOf(
"module" to
"模块路径"
)
),
// Git操作
Tool(
name = "git_log",
desc = "查看Git提交历史",
params = mapOf(
"path" to
"文件或目录路径",
"count" to
"条数,默认10"
)
),
// 文件读取
Tool(
name = "read_file",
desc = "读取文件内容",
params = mapOf(
"path" to
"文件路径",
"lines" to
"行范围如1-50"
)
)
)
关键设计决策:工具粒度要适中。太粗(一个"执行任意shell命令")会让模型乱来;太细(每个gradle task单独一个工具)会让工具列表爆炸。我的原则是:每个工具对应一个你会在Terminal里执行的命令类别。
微调数据集:从团队历史中挖金矿
微调的目标是让模型「说话像我们团队的人」。数据从哪来?三个金矿:
1. Code Review记录。每条CR评论天然就是一对 (代码context, 审查建议),直接转成instruction-response格式。质量极高,因为都是高级工程师写的。
2. 技术群聊中的Q&A。从IM记录里提取「有人问问题→有人给出好答案」的对话对。需要人工筛选,但量不用太大,500-1000条就有明显效果。
3. 好的Commit Message和PR描述。这些反映了团队的表达习惯和技术用语。
// 微调数据条目示例
data class TrainingSample(
val system: String =
"你是团队的Android技术顾问",
val instruction: String,
val response: String
)
// 从CR记录生成训练样本
fun crToSample(
cr: CodeReview
): TrainingSample {
return TrainingSample(
instruction = """
请审查这段代码:
```kotlin
${cr.codeSnippet}
```""",
response = cr.reviewComment
)
}
端云协同:轻量推理放端侧
这是我觉得最有Android特色的部分。做App的人天然理解「不是所有逻辑都要走网络」——能本地处理的就别打接口。AI助手同理:
| 场景 | 执行位置 | 理由 |
|---|---|---|
| 代码补全提示 | 端侧(小模型) | 低延迟要求、隐私敏感 |
| 意图分类 | 端侧(分类器) | 极简模型就够用 |
| RAG检索+生成 | 云端 | 需要大模型+向量库 |
| Agent工具调用 | 云端编排+本地执行 | 决策在云,执行在本地 |
| 结果缓存 | 端侧SQLite | 相同问题秒回 |
这不就是WorkManager决策「本地跑还是推到服务端」的翻版吗?标准是一样的:延迟敏感度、计算量、数据隐私、网络条件。
// 路由决策器
class InferenceRouter(
private val localModel:
OnDeviceModel,
private val cloudClient:
CloudAIClient,
private val cache:
ResponseCache
) {
suspend fun route(
query: UserQuery
): AIResponse {
// 1.先查缓存
cache.get(query)?.let {
return it
}
// 2.端侧意图分类
val intent = localModel
.classify(query)
return when (intent) {
Intent.SIMPLE_COMPLETE ->
localModel.complete(
query)
Intent.NEED_KNOWLEDGE ->
cloudClient.ragQuery(
query)
Intent.NEED_ACTION ->
cloudClient.agentRun(
query)
else ->
cloudClient.chat(
query)
}.also { cache.put(
query, it) }
}
}
生产部署:复用Android发版经验
把AI助手当成一个「服务」来运维,你会发现很多经验可以直接迁移:
灰度发布——先给5%的团队成员用新版模型/新RAG索引,观察一周没问题再全量。和App灰度逻辑一模一样。
A/B测试——同一个问题,让base模型和微调模型各答一次,让用户选哪个好。收集到的偏好数据还能回馈到下一轮微调。
监控告警——响应延迟P99、Token消耗量、工具调用失败率、用户满意度评分。和App的崩溃率、ANR率、用户留存是一个思路。
回滚机制——微调后的模型表现不好?一键切回base model。RAG索引有问题?回退到上一个版本的索引快照。就像App热修复。
// 部署配置 - 很Android味道的写法
data class DeployConfig(
// 灰度比例
val rolloutPercent:
Int = 5,
// 是否开启A/B
val abTestEnabled:
Boolean = true,
// 模型版本管理
val models: ModelVersions =
ModelVersions(
base = "gpt-4o",
finetuned = "ft:gpt-4o:
team-android:v3",
fallback = "gpt-4o-mini"
),
// 告警阈值
val alerts: AlertThresholds =
AlertThresholds(
p99LatencyMs = 5000,
errorRate = 0.05,
dailyTokenBudget =
1_000_000
)
)
成本优化:和App性能优化一脉相承
AI服务最大的开支是Token消耗。但如果你做过Android性能优化,这些策略你会觉得似曾相识:
缓存策略 = OkHttp Cache。相同或相似问题的回答直接从缓存返回。用语义相似度(cosine > 0.95)判断是否命中缓存,而不是精确字符串匹配。
请求合并 = Coil的请求去重。多人同时问类似问题时,合并成一个请求,结果广播给所有等待者。
模型量化 = APK瘦身。端侧部署的小模型用INT4量化,精度损失可接受,推理速度翻倍。和PNG转WebP、SO裁剪是同一个trade-off思维。
分级响应 = 懒加载。简单问题用小模型快速回答,复杂问题才调用大模型。就像RecyclerView先加载文字,图片异步填充。
成本参考:一个10人团队每天产生约200次查询,按GPT-4o定价,纯云端每月约$300-500。加上缓存+分级响应,实测可以压到$80-120。这钱省出来够请团队吃两顿火锅了。
完整调用链路:一次问答的生命周期
来看一个完整的例子。用户问:「帮我看看NetworkModule里的Retrofit配置,超时时间是不是太短了?」
用户提问
↓
Step1: 意图分类(端侧)
结果 → NEED_KNOWLEDGE + NEED_ACTION
↓
Step2: RAG检索
查到 → OkHttp超时最佳实践文档 + 项目Wiki网络配置说明
↓
Step3: Agent执行工具
search_code → 找到NetworkModule.kt第42行
read_file → 读取具体配置:connectTimeout=10s
git_log → 上次修改是3个月前,改小了超时
↓
Step4: 微调模型生成回答
输出 → 用团队风格组织:问题分析+建议+代码示例
↓
返回用户
整个链路下来,用户得到的不是泛泛而谈的「建议增加超时时间」,而是:「你们项目NetworkModule.kt第42行connectTimeout是10s,三个月前小明从30s改成10s(commit: abc123),结合最近上报的超时率上升,建议改回15-20s。参考OkHttp官方建议,对于移动网络场景,15s是比较合理的值。要不要我帮你提个MR?」
这才是一个真正有用的AI开发助手。
未来:端侧大模型的可能性
写到这里,我不得不提一个让我特别兴奋的方向:端侧大模型。
Google的Gemini Nano已经跑在Pixel上了,MediaPipe LLM Inference API让端侧推理变得越来越easy。想象一下:如果端侧模型足够强,整个RAG+Agent+微调的链路可以完全在本地跑——零延迟、零成本、完全隐私。
当然现在还早。端侧模型的能力大概在GPT-3.5水平,对于复杂的推理和代码生成还差点意思。但趋势很明确:两年前我们觉得手机跑LLM是天方夜谭,现在已经可以跑7B参数的模型了。再给两年时间?
作为Android工程师,我们是最有资格去探索这个方向的人。我们懂端侧性能优化、懂内存管理、懂电量控制、懂异构计算(NPU/GPU/CPU调度)。这些能力在AI Native App时代会变得极其值钱。
系列完结:从这里开始,路在脚下
四篇文章写下来,我想传达的核心观点很简单:Android工程师学AI开发没有想象中那么难,因为你已经有了大量可迁移的思维框架。
RAG就是给大模型加了个「本地数据库」,和Room/SQLite是一码事——你在管数据的存取和检索。Agent就是个升级版的Service——它监听指令、调用能力、返回结果。微调就是「定制ROM」——基于通用系统,适配你的特定需求。组合起来,就是一个完整App的架构。
接下来怎么走?我的建议是:
• 先搭一个最小版本的RAG助手(一个下午就能搞定)
• 加几个工具让它变成Agent(一两天)
• 收集团队数据做一次微调(一周)
• 部署给团队用,收集反馈迭代(持续)
不要追求完美。先让它跑起来、用起来,然后在实际使用中发现问题、改进迭代。这不就是我们做App的方式吗?MVP先行,数据驱动,快速迭代。
这个系列到这里就结束了。感谢一路读到这里的你。如果这四篇文章让你觉得「嗯,AI开发好像也没那么遥远」,那我的目的就达到了。
下一步,动手吧。代码不会骗人。
系列回顾
第1篇:RAG——给大模型装一个靠谱的「本地数据库」
第2篇:Agent智能体——让AI自己调API干活
第3篇:微调——让通用大模型变成你的「专属定制ROM」
第4篇:三大技术组合拳(本篇)
感谢关注,我们下个系列见
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)