背景
Deepseek一直是我们国内程序员比较喜欢的模型平台,主要原因是国外一些模型价格贵,而且使用相对没有国内的方便毕竟有个墙,所以大家就会选择性价比很高的Deepseek,普通程序员平均token最多也就10块钱一天,虽然性能表现方面可能不如国外的,但是它便宜就是最大的优点。
但是昨天Deepseek正式开启涨价模式

下面是涨价详细比例:
可以看出这个价钱确实相比以前涨幅居然达到11倍,很多学员也反馈开始用不起Deepseek了。
不过涨价我们消费者也没啥好的办法,要么找个替代品,不过替代品和它的价格相差不了,要么继续省着点用。
特别是Android Framework 开发涉及大量大型源码文件(如 ActivityManagerService.java 超过 2 万行),日常调试依赖 logcat、dumpsys、tombstone、perfetto 等诊断数据。在大模型 API 按 Token 计费的模式下,直接将这些原始数据完整喂给 AI 会导致极高的成本。同时,Output Token 通常比 Input Token 单价更高(3~5 倍),进一步放大了开销。
这里本文主要教大家免费和付费模型两个方式来节省成本。
免费模型使用
因为网页对话这种AI使用方式都是免费的,所以大家尽量评估好相关的问题情况,看看是否需要大量读取本地代码,或者修改代码等,如果不涉及与系统文件交互等,比如一些简单的提问,或者写一写简单的demo脚本,小工具等,不需要依赖系统中的环境就可以输出的,这种大家其实也可以考虑使用网页版本的免费方式。

简单说就是需要我们准确去评估需求是否比较简单,本身可以通过对话就搞定的,这种场景只适合不要对本地代码进行交互的简单任务,不适合非常复杂需要理解读取aosp源码,还需要帮忙触发系统编译验证等场景。
付费模型节省Token方法
1. 代码上下文的精准裁剪
1.1 骨架化提取
对于单个 AOSP 源文件,通常只有目标方法及其直接依赖的成员变量和类结构相关。建议只提取以下内容:
- 类的包名、导入的关键类型(可选)
- 核心成员变量声明(与问题相关的状态字段)
- 目标方法的完整签名及内部实现片段(聚焦于逻辑分支、状态机转移、锁操作等)
例如,分析 ActivityTaskManagerService.startActivityAsUser 中的权限检查逻辑,可以只粘贴该方法的 checkPermission 调用相关代码块,以及 mPermissionManager 等成员定义。其他无关的私有辅助方法、Javadoc、dump 方法等一律省略。
实际操作时,可以通过 IDE 的折叠功能或手动复制,将 1.5 万行的文件压缩到 300 行以内。Input Token 可减少 90% 以上。
1.2 调用链切片
分析跨进程 Binder 通信时,不需要贴出完整的 AIDL 实现或服务端全部代码。建议用简洁的伪代码描述调用路径,仅当涉及到具体实现细节时粘贴对应方法片段。
示例格式:
[Client] ContextImpl.startActivity() -> IActivityManager (Binder proxy)
[IPC] IActivityManager.aidl (interface definition, only method signature)
[Server] ActivityTaskManagerService.startActivityAsUser()
- 权限检查: checkPermission() 相关代码(粘贴 30 行)
- Task 栈操作: moveTaskToFront() 相关代码(粘贴 40 行)
这种做法让 AI 明白调用关系,同时避免传输大量无关代码。
2. 日志与 Trace 数据的本地前置清洗
2.1 Logcat 过滤
未经处理的 logcat 包含大量时间戳、PID/TID、重复心跳日志等冗余信息。建议使用 grep 和 awk 在本地提取关键行:
adb logcat -d | grep -E "ActivityManager|WindowManager" | awk '{$1=""; $2=""; print substr($0,3)}' > filtered.log
该命令移除时间戳和 PID,只保留 Tag 和消息内容。再按需保留目标进程或特定 TAG,通常可将 2000 行压缩到 50 行以内。
2.2 dumpsys 截取
dumpsys window windows 等命令会输出数百个窗口状态,建议只截取与当前问题相关的包名或窗口 ID:
adb shell dumpsys window windows | grep -A 20 "mCurrentFocus" > window_focus.txt
或使用 dumpsys activity 时只输出目标 Activity 的堆栈信息:
adb shell dumpsys activity activities | grep -A 30 "TaskRecord.*your.package"
2.3 Tombstone / Native Crash
对于 tombstone 文件,重点提取:
- 崩溃线程的 native backtrace
- Fault address 和 memory map 附近区域
- 关键寄存器值(PC、LR、SP)
其余线程的堆栈和完整寄存器 dump 通常不参与分析,可丢弃。
2.4 Perfetto / Systrace
Perfetto 生成的原始 trace 文件可达几百 MB。建议先在本地 Perfetto UI 中加载,定位到异常时间区间(如长时间持有锁、掉帧卡顿),然后将该区间内的关键事件(如 binder 事务、锁等待、GPU 完成)以文本列表形式导出,或手动摘录耗时超过阈值的 slices。只有这些文本摘要才输入给 AI。
3. 分级模型路由策略
并非所有任务都需要使用最强大的旗舰模型。我们可以建立一套分级机制,根据任务复杂度选择不同模型,从而平衡成本和效果。
| 任务类别 | 推荐模型 | 成本等级 |
|---|---|---|
| 正则表达式编写、脚本转换、日志格式化、基础语法解释 | 本地 Ollama(Qwen-7B/DeepSeek)或 GPT-4o-mini / Claude Haiku | 极低 |
| 单个方法重构、AIDL 接口设计、单一 crash 栈分析、单元测试生成 | DeepSeek-V3、Claude 3 Sonnet、GPT-4o(中等档) | 中等 |
| 系统级死锁分析、SurfaceFlinger 渲染管线竞态、跨版本兼容性重构、多进程 ANR 根因 | Claude 3.5 Sonnet / GPT-4o(旗舰) | 高(仅限少量调用) |
建议在内部工具中根据关键词自动匹配模型等级,例如提问包含"死锁"、“SurfaceFlinger”、"跨版本"等词汇时切换旗舰,否则使用中等模型。
4. 会话隔离与上下文缓存
4.1 单任务会话
长期在同一个会话中追加问题会导致每次请求都携带之前所有对话历史,造成 Input Token 线性增长。建议:
- 每个独立 Bug 或功能点启动一个新会话。
- 当需要切换分析方向时,主动总结当前阶段的结论(3~5 句话),然后开启新会话,将总结作为系统提示的一部分提供给 AI,丢弃之前的试错代码和中间推理。
- 避免在同一个会话中让 AI 多次修改同一段代码,每次修改后即关闭会话,下次重新贴入最新版本。
4.2 利用 Prompt Caching
部分 API 服务商支持提示词缓存(如 Anthropic 的 Prompt Caching)。对于频繁使用的稳定内容(如团队自定义的 AIDL 接口规范、特定 Android 版本的 API 差异说明、内部编译环境变量),可以将这些内容放在提示词最前面,并设置为可缓存。命中缓存后,该部分内容的 Input Token 可享受 50%~90% 的折扣。
实际操作时,建议将固定背景信息与每次变化的提问内容分离,将固定段放到 prompt 头部,并设置 cache_control 标记(以 Anthropic API 为例)。
5. 分步迭代式需求拆解与过程评审
5.1 一次性提交完整需求的问题
很多开发者习惯一次性将完整需求描述发给 AI,期望直接得到最终代码或根因结论。这种做法存在两个问题:
- 上下文过载:需求越长、越复杂,AI 在中间步骤丢失初始约束的概率越高。
- 偏离无法及时纠正:AI 可能在某个中间步骤采用了错误的实现路径,但由于用户没有检查中间产出,等到最终结果出来才发现方向完全错误,不仅浪费了本次调用的 Token,还需要开启新会话从头再来。
5.2 将需求拆解为可验证的小步骤
以"修改 AMS 中 Activity 启动流程,增加一个自定义权限检查"为例,不建议直接让 AI 一次性修改整个 startActivityAsUser 方法。建议拆解为以下步骤依次进行:
Step 1: 确认插入点
- 向 AI 提供
startActivityAsUser的简化代码片段,询问"在哪个位置插入权限检查最合适?" - 评审 AI 给出的位置是否符合预期(是否在跨进程调用边界内?是否持有锁?)
Step 2: 设计检查逻辑的桩代码
- 让 AI 生成一个空壳方法
checkCustomPermission(...),仅包含参数定义和返回值占位。 - 评审方法签名是否需要传入 IBinder 或调用者 PID/UID。
Step 3: 实现具体检查逻辑
- 在确认了插入点和桩代码后,让 AI 填充具体实现,包括读取系统设置、比对白名单等。
- 评审实现是否考虑了异常路径(权限服务不可用、IO 失败等)。
Step 4: 生成 patch 并附加日志
- 让 AI 生成 git diff 格式的输出,并在关键分支加入 Slog 埋点。
- 评审 patch 是否遗漏了 import 变更或资源文件更新。
每个步骤之间,开发者需要主动审查 AI 的输出。如果发现某一步的设计不合理(例如插入点选在了持有大锁的区域内),应立即停止当前步骤,向 AI 反馈具体问题,而不是让 AI 继续沿着错误方向推进。
5.3 Bug 排查场景下的分步策略
对于根因分析类任务,同样建议分步进行:
Step 1: 定位异常现象
- 提供过滤后的 logcat(50 行以内),让 AI 识别最可疑的 ERROR/WARN 行,并给出 3 个可能的方向。
Step 2: 排除干扰因素
- 根据 AI 的第一个输出,要求其排除其中两个方向,给出最可能的唯一假设。
- 评审该假设是否与已知的系统行为(如 Android 版本差异、硬件平台限制)矛盾。
Step 3: 验证假设
- 让 AI 建议一条可执行的验证方案(例如使用
dumpsys查看特定状态、添加临时调试日志)。 - 执行验证后,将结果反馈给 AI,确认或修正假设。
Step 4: 生成修复方案
- 在假设被确认后,让 AI 给出具体的代码修改建议。
5.4 主动干预的时机和方式
在分步协作过程中,建议在每次收到 AI 回复后执行以下评审检查清单:
- 该步骤的输出是否与初始约束条件一致(如目标 API 版本、团队编码规范)?
- 是否存在明显的边界条件遗漏(空指针、异常捕获、资源释放)?
- 是否引入了新的依赖或修改了不应改动的公共接口?
一旦发现任何一项不满足,应立即通过新的 Prompt 向 AI 明确反馈偏差:
"你上一步建议的插入点在 takeLock() 之前,但 takeLock() 会阻塞 binder 线程池,请换到 takeLock() 之后且 resumeActivity() 之前的区间重新设计。"
这种"AI 产出 → 人工评审 → 修正指令 → 继续"的闭环迭代,虽然单次任务的会话轮数增加了,但每轮的输入/输出 Token 都保持精简(每轮只处理一个聚焦问题),总 Token 开销远低于"一次大需求让 AI 跑偏后重来"的成本。同时,开发者对最终产出的可控性明显增强。
6. 严格控制输出 Token
Output Token 单价较高,应通过提示词约束 AI 的回复长度和格式。在每次请求的系统提示或用户提示末尾添加明确的输出要求。
示例约束:
输出要求:
1. 不要有任何开场白、致谢或总结性废话。
2. 直接给出结论或修改后的代码。如果需要说明,最多使用 3 条项目符号,每条不超过 20 个中文字。
3. 代码修改以 git diff 格式呈现,仅包含改动的方法或代码块,不要重写整个文件。
实测表明,这类约束可将平均 Output Token 从 800 压缩到 200 以内,且信息密度明显提高。
7. 日常操作对照表
| 环节 | 传统做法(高消耗) | 优化做法(低消耗) |
|---|---|---|
| 代码输入 | 粘贴整个 .java 或 .cpp 文件 | 仅提取目标方法 + 关键成员 + 类骨架 |
| 日志输入 | 粘贴数千行原始 logcat | 本地 grep/awk 过滤,保留 < 50 行关键信息 |
| 会话管理 | 持续使用同一个会话 | 每个 Bug 新开会话,切换方向时总结后重建 |
| 需求提交 | 一次性提交完整需求 | 拆分为多个小步骤,每步评审后再继续 |
| 输出生成 | 让 AI 自由输出完整代码 | 指定 diff 格式,限定要点数量 |
| 模型选择 | 始终使用最强旗舰模型 | 按任务复杂度分级使用不同模型 |
结语
不要以为有了AI工具你就可以啥也不管,其实AI只是你的辅助,你绝不可以过渡依赖AI,对于AI工具去需求实现和bug修复的每个过程,自己也要清楚核心思路等。
有了AI不是让你可以啥都不需要懂,不需要学习了,有了AI只是让你的工作和学习效率更高了,每个人都会用AI,但是AI上限其实决定于你的个人知识能力,而不是AI本身。
就像菜鸡用AI去实现fw实战需求和你高手用AI实现能一样效果么?
通过在本地进行充分的静态分析和数据过滤,将精炼后的信息输入给合适的模型,并严格控制会话历史、输出长度以及需求拆解粒度,我们系统开发者可以在保证分析质量的前提下显著降低 API 调用成本。同时,由于输入噪音减少、中间步骤经过人工评审,AI 的回答准确率和最终产出的可控性也会明显提升。

151

被折叠的 条评论
为什么被折叠?



