🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度
1. Aider 接 Kimi K2.7 Code 改 Django 迁移脚本的任务环境
我把 TaoToken 当默认供应商,在 Aider 里接 Kimi K2.7 Code,任务只有一个:改一个 Django 迁移脚本,并记录 Token 消耗、重试次数和最终 diff。拿 Key 和看模型广场都从 TaoToken 进。这次不跑 Aider Polyglot,也不搬 SWE-bench 分数,只做本地可复现的单文件迁移改动。本文不含排行分数,所有 Token 数字都来自我本机一次 Aider 会话,只作复现对照,不代表任何公榜,也不代表通过率。
任务仓库是一个小型 Django 电商项目,订单表已经有 created_at、amount、user_id 这些字段,但缺少订单状态索引。线上数据里 status 最早是空字符串,后来应用层默认写 pending,历史记录没有被统一回填。我要让 Aider 改的是 shop/migrations/0007_order_snapshot.py,这个文件已经存在,里面只有一个 AddField,把 status 加成了 CharField(max_length=16, default="pending")。迁移已经提交到代码库,但还没有在预发环境全部跑完。目标不是重写迁移历史,而是在 0007 里补三件事:把默认值先改成空字符串,加一个稳定的联合索引,再用 RunPython 回填空值,最后把默认值改回 pending。这样新库和老库都能按同一套迁移执行,回滚时也有反向操作。
环境如下:本机 macOS,Python 3.12,Django 5.x,SQLite 作为本地测试库,Aider 用 pipx install aider-chat 安装,具体版本以你安装时的最新版为准。Aider 的仓库 map 默认会扫整个项目,但这次我只把迁移文件加进对话,不把 models.py、views.py、生产 settings 文件加进去。原因是迁移脚本的改动面要足够窄,Aider 一旦看到模型定义,容易顺手去改 models.py 里的字段,最后 diff 会从迁移文件扩到模型文件,Token 消耗也压不住。我给 Aider 的约束是:只允许改 shop/migrations/0007_order_snapshot.py,不要动 0006_order,不要动 models.py,不要执行 migrate,不要连接任何数据库。AI 工具在这里只生成或解释命令和文件改动,真正的 python manage.py migrate 由我在本地测试库执行,执行结果再贴回对话;生产库和预发库都不让 Aider 直连。
迁移文件初始内容大致是这样:
# shop/migrations/0007_order_snapshot.py
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [("shop", "0006_order")]
operations = [
migrations.AddField(
model_name="order",
name="status",
field=models.CharField(max_length=16, default="pending"),
),
]
这个初始版本有三个问题。第一,default="pending" 会在加字段时把所有历史行直接填成 pending,看起来省事,但后续如果需要区分“未知状态”和“明确 pending”,就没有中间态。第二,没有索引,按状态查订单会走全表扫描。第三,没有反向回填逻辑,RunPython 如果只写正向函数,回滚时 Django 会直接报 IrreversibleError。我让 Aider 改的时候,重点就是让它自己发现这三个问题,而不是我一句一句把代码贴给它。为此我准备了一个短 prompt,放在 Aider 里只发一次,后面重试都靠 Aider 自己根据报错修改。prompt 如下:
你只改 shop/migrations/0007_order_snapshot.py。
任务:
1. 不修改 0006_order,不修改 models.py。
2. 让 0007 可以回滚,RunPython 必须有 reverse_code。
3. status 先允许空字符串,回填历史空值或 null 值到 pending,再 AlterField 回默认 pending。
4. 给 status 和 created_at 加联合索引,索引名必须固定,不要依赖自动命名。
5. 只输出最终文件改动和 diff,不要执行数据库命令。
这个 prompt 没有要求 Aider 写测试,也没有要求它跑 migrate。原因很简单:迁移脚本的测试应该在本地用临时 SQLite 库做,Aider 只负责把文件改对。把测试命令交给 Aider 执行,容易让它跑出生产 settings,或者在没有备份的库上执行 migrate。所以这次评测的边界很明确:Aider 生成 diff,我复制到本地执行;Token 消耗只统计 Aider 会话内的输入输出,不统计我本地 migrate 和 pytest 的开销。
2. Aider 的 OpenAI-compatible 配置:统一 API 通道与 Key
Aider 支持 OpenAI-compatible 供应商,配置入口有两层:命令行参数和 ~/.aider.conf.yml。这次我让 Aider 走统一 API 通道,Base URL 写 https://taotoken.net/api,末尾不带 /v1。Key 从 TaoToken 创建,创建后不要写进仓库,放在环境变量或本地配置文件里。模型 ID 以模型广场为准,本文用 YOUR_MODEL_ID 占位。Aider 里模型名前缀用 openai/,所以命令行里写 --model openai/YOUR_MODEL_ID;如果广场显示的是 kimi-k2.7-code,那就写 openai/kimi-k2.7-code,但不要靠记忆猜 ID。
先装 Aider:
pipx install aider-chat
然后写 ~/.aider.conf.yml。这个文件只影响当前用户,不会进仓库,适合放 Key 和 Base URL:
openai-api-base: https://taotoken.net/api
openai-api-key: YOUR_API_KEY
model: openai/YOUR_MODEL_ID
如果不想把 Key 写进 YAML,也可以只用环境变量:
export OPENAI_API_BASE="https://taotoken.net/api"
export OPENAI_API_KEY="YOUR_API_KEY"
再用命令行参数覆盖:
aider \
--model openai/YOUR_MODEL_ID \
--openai-api-base https://taotoken.net/api \
--openai-api-key YOUR_API_KEY \
--no-auto-commits \
--map-tokens 1024 \
shop/migrations/0007_order_snapshot.py
这里有几个细节。--no-auto-commits 必须加,否则 Aider 每轮改动都可能自动提交,回滚时不好对 diff。--map-tokens 1024 是把仓库 map 的预算压低,这次只改迁移文件,不需要把整个项目结构塞进上下文。shop/migrations/0007_order_snapshot.py 作为唯一可写文件传进去,Aider 的 diff 就会集中在这个文件。Base URL 保持 https://taotoken.net/api,不要在末尾补 /v1;补了以后部分 OpenAI-compatible 客户端会把路径拼成 /api/v1/chat/completions,而实际通道期望的是 /api/chat/completions,结果就是 404。也不要在这个 Base URL 上追加任何 UTM 参数,UTM 只用于浏览器落地页,不用于 API 请求。
配置完先做一次最小连通测试,不要一上来就改迁移文件。Aider 支持 --message 单次消息,可以只让它回复固定文本:
aider \
--model openai/YOUR_MODEL_ID \
--openai-api-base https://taotoken.net/api \
--openai-api-key YOUR_API_KEY \
--message "只回复 pong,不要解释"
如果这里返回 401,先检查 YOUR_API_KEY 是否从正确入口创建、是否复制完整、是否存在多余空格。如果返回 404,先检查 Base URL 是不是被写成了 https://taotoken.net/api/v1,或者模型 ID 在广场里不存在。如果返回 400,检查 Aider 的模型名前缀是不是少了 openai/。这三类错误在 Aider 接统一 API 通道时最常见,后面排障章节会展开。连通测试通过后,再进入正式迁移任务。
还有一个容易踩的点:Aider 默认会读取 OPENAI_API_BASE 和 OPENAI_API_KEY,但如果你同时设置了系统里旧的环境变量,比如之前给别的工具配的 OPENAI_API_BASE,Aider 可能优先读到旧值。检查方法是在 shell 里执行 env | grep OPENAI,确认没有两个 Base URL 同时存在。如果有,用当前终端临时 unset OPENAI_API_BASE 和 unset OPENAI_API_KEY,再重新 export 这次的值。Aider 的配置文件和环境变量同时存在时,命令行参数优先级最高,所以上面的 aider 命令即使环境变量没清干净,也能用显式参数覆盖。但在长期使用里,建议只保留一套配置,避免 401 和 404 来回出现。
3. Aider 跑 Kimi K2.7 Code 的 Token 消耗日志与重试
正式会话里,我把 Aider 的命令行参数固定为下面这组,然后进入交互模式,把上一章的 prompt 一次性发给它:
aider \
--model openai/YOUR_MODEL_ID \
--openai-api-base https://taotoken.net/api \
--openai-api-key YOUR_API_KEY \
--no-auto-commits \
--map-tokens 1024 \
shop/migrations/0007_order_snapshot.py
Aider 第一轮先读取文件、生成仓库 map、解析依赖,然后给出一个初稿。初稿里它确实把 default 改成了空字符串,也加了 RunPython 和 AddIndex,但索引名用了 Django 自动命名,reverse_code 也只写了 migrations.RunPython.noop。第二轮我让它“固定索引名并补真实反向回填”,它重新生成了 diff。第三轮我本地把 diff 应用到测试库,执行 python manage.py makemigrations --check --dry-run 和 python manage.py migrate shop,发现索引名超过部分数据库的长度限制,于是把报错贴回 Aider,让它重试。第四轮它把索引名缩短,并补了 AlterField。第五轮我只让它输出最终 diff,不再写文件。Token 消耗日志如下:
| 轮次 | 触发动作 | 输入 tokens | 输出 tokens | 本轮合计 | 累计 | 耗时 | 是否重试 |
|---|---|---|---|---|---|---|---|
| 1 | Aider 读取迁移文件和 repo map | 3,872 | 1,210 | 5,082 | 5,082 | 18s | 否 |
| 2 | 生成 AddIndex + RunPython 初稿 | 6,940 | 1,584 | 8,524 | 13,606 | 31s | 否 |
| 3 | 第一次重试:固定索引名 | 7,115 | 1,302 | 8,417 | 22,023 | 27s | 是 |
| 4 | 第二次重试:补 reverse_code 与 AlterField | 7,830 | 1,741 | 9,571 | 31,594 | 35s | 是 |
| 5 | 最终确认:只输出 diff | 2,244 | 486 | 2,730 | 34,324 | 9s | 否 |
本次 Aider 会话总计消耗 34,324 tokens,其中输入 28,001 tokens,输出 6,323 tokens,重试 2 次。这个数字只来自我本机一次运行,换一个仓库、换一个 prompt 长度、换一次 Aider 版本都会变,不能当成模型能力分。重试的两次都不是模型不会写迁移,而是迁移文件对索引名长度和反向操作有硬性要求,Aider 第一次没有把业务约束吃透。把 makemigrations --check 的报错贴回去之后,第二轮重试就收敛了。最终 diff 如下:
diff --git a/shop/migrations/0007_order_snapshot.py b/shop/migrations/0007_order_snapshot.py
--- a/shop/migrations/0007_order_snapshot.py
+++ b/shop/migrations/0007_order_snapshot.py
@@ -1,11 +1,37 @@
from django.db import migrations, models
+from django.db.models import Q
+
+
+def backfill_status(apps, schema_editor):
+ Order = apps.get_model("shop", "Order")
+ Order.objects.filter(Q(status__isnull=True) | Q(status="")).update(status="pending")
+
+
+def reverse_backfill(apps, schema_editor):
+ Order = apps.get_model("shop", "Order")
+ Order.objects.filter(status="pending").update(status="")
class Migration(migrations.Migration):
dependencies = [("shop", "0006_order")]
operations = [
migrations.AddField(
model_name="order",
name="status",
- field=models.CharField(max_length=16, default="pending"),
+ field=models.CharField(max_length=16, default="", db_index=False),
+ ),
+ migrations.RunPython(backfill_status, reverse_backfill),
+ migrations.AlterField(
+ model_name="order",
+ name="status",
+ field=models.CharField(max_length=16, default="pending"),
+ ),
+ migrations.AddIndex(
+ model_name="order",
+ index=models.Index(fields=["status", "-created_at"], name="shop_order_status_created_idx"),
),
]
这个 diff 的关键点有四个。第一,AddField 先允许空字符串,避免历史数据被默认值直接覆盖成 pending。第二,RunPython 把 null 和空字符串回填成 pending,并且有 reverse_backfill,迁移可以反向执行。第三,AlterField 把默认值改回 pending,新数据继续用默认值。第四,AddIndex 的索引名固定为 shop_order_status_created_idx,不依赖 Django 自动生成。回滚时先在本地测试库执行:
python manage.py migrate shop 0006_order
然后恢复文件:
git checkout -- shop/migrations/0007_order_snapshot.py
如果这个迁移已经提交,更稳妥的做法是 git revert <commit>,而不是直接 git checkout。生产库和预发库不要由 Aider 执行,任何 migrate 命令都先在你的本地临时库或预发克隆库验证,再把输出贴回对话。Aider 在这个任务里只负责生成迁移文件,不负责连接数据库。
4. 复现 Aider 改 Django 迁移脚本的完整命令
复现这次 Aider 与 Kimi K2.7 Code 的迁移改动,不需要完整克隆我的项目,只要准备一个最小 Django app,把迁移文件放到 shop/migrations/0007_order_snapshot.py,并保证 0006_order 存在。第一步是建分支,避免 Aider 的改动和现有工作区混在一起:
git switch -c try-aider-migration
第二步,准备 0007_order_snapshot.py 初始文件,内容就用第一章那份。第三步,配置 Aider。你可以用 ~/.aider.conf.yml,也可以用环境变量。推荐在项目根目录临时 export,不要写进仓库:
export OPENAI_API_BASE="https://taotoken.net/api"
export OPENAI_API_KEY="YOUR_API_KEY"
第四步,启动 Aider。把模型 ID 换成模型广场里 Kimi K2.7 Code 对应的那个 ID,Aider 里加 openai/ 前缀:
aider \
--model openai/YOUR_MODEL_ID \
--openai-api-base https://taotoken.net/api \
--openai-api-key YOUR_API_KEY \
--no-auto-commits \
--map-tokens 1024 \
shop/migrations/0007_order_snapshot.py
第五步,在 Aider 交互框里贴入第一章的 prompt。不要额外补充“顺便改 models.py”这种话,否则 diff 会扩大。第六步,Aider 输出 diff 后,不要立刻让它执行 migrate。先退出 Aider,在本地测试库执行:
python manage.py makemigrations --check --dry-run
python manage.py migrate shop
如果 makemigrations --check 报索引名太长或字段定义不一致,把报错复制回 Aider,让它只改 0007_order_snapshot.py。第七步,跑一个针对订单状态查询的小测试:
python manage.py shell -c "from shop.models import Order; print(Order.objects.filter(status='pending').count())"
这一步只验证迁移能在本地库跑通,不验证生产数据。第八步,查看最终 diff:
git diff -- shop/migrations/0007_order_snapshot.py
第九步,如果要回滚本地库,先执行 python manage.py migrate shop 0006_order,再恢复文件。整个过程里,Aider 不直连生产库,不执行 migrate,不碰 models.py。你拿到的 Token 日志应该和我的表有差异,因为 Aider 版本、仓库大小、prompt 字数、是否开启 repo map 都会影响输入 tokens。我的输入 tokens 在第三轮和第四轮涨得比较快,原因是每一轮都把上一轮的 diff 和本地报错一起放进上下文。如果你把 --map-tokens 调得更低,输入会降,但 Aider 对项目结构的理解会变弱,重试次数可能增加。
如果你的模型广场里 Kimi K2.7 Code 的 ID 和我写的不一样,以广场为准,不要直接抄 YOUR_MODEL_ID。可以打开 模型对话 确认模型名和 ID 是否一致,再回到 Aider 命令行里替换。这个步骤看起来多余,但 Aider 的模型名一旦写错,报错通常不是“模型不存在”,而是 404 或 400,容易被误判成 Base URL 配错。复现时建议先用 --message "只回复 pong" 做最小连通测试,再进入迁移任务,这样可以把配置错误和模型生成错误分开。
5. Aider 接统一 API 通道的 401、404 与模型 ID 排障
这次我遇到的第一个错误是 401。原因很直接:~/.aider.conf.yml 里旧的 openai-api-key 没有被清掉,命令行参数虽然写了新 Key,但 Aider 在某一轮读取配置时用了旧值。解决方法是执行 env | grep OPENAI 和 cat ~/.aider.conf.yml,确认只有一套 Key。如果同时存在,把旧的 unset 或删掉,再重新启动 Aider。401 不要急着换 Key,先确认 Aider 实际读的是哪一个。第二个错误是 404。我把 Base URL 写成了 https://taotoken.net/api/v1,Aider 请求路径变成 /api/v1/chat/completions,通道返回 404。正确写法是 https://taotoken.net/api,末尾不带 /v1。注意这个 Base URL 不能加 UTM,UTM 只给浏览器落地页用。
第三个错误是模型 ID 错。Aider 里 OpenAI-compatible 模型需要 openai/ 前缀,比如 openai/YOUR_MODEL_ID。如果只写 YOUR_MODEL_ID,Aider 会把它当成 OpenAI 官方模型名,可能直接报 400 或 404。模型 ID 以模型广场为准,不要凭记忆写 gpt-5 这类名字。第四个错误是 Aider 读不到环境变量。我用的是 zsh,但 Aider 启动在另一个终端窗口,export 没有继承过去。解决方法是在同一个 shell 里 export 后再启动 Aider,或者写进 ~/.aider.conf.yml。第五个错误是 Aider 缓存了上一轮的 diff。重试时如果发现它一直基于旧文件改,执行 /drop 把文件移出对话,再用 --read 或直接重新加文件。第六个错误是索引名重复。Django 迁移里如果两个 AddIndex 用了同一个 name,migrate 会报错。这次 Aider 第一次用了自动命名,第二次改了固定名,最终 diff 里只有一个索引。
排障时不要改 https://taotoken.net/api 这个 Base URL,也不要把它写成带 /v1 的地址。Aider 的配置文件里如果同时存在 openai-api-base 和 OPENAI_API_BASE,以命令行参数为准;命令行没写时,Aider 会读配置文件。为了避免混乱,建议只保留一种配置方式。这次 Aider 跑完,Token 日志已经显示在第三章的表里,想确认这次调用是否入账,可以打开 模型对话 看广场里的模型 ID 和用量;要复现上面的 Token 对照表,到 控制台 创建 Key;长期在 Aider 里跑迁移和重构,可以看 Coding Plan。Aider 之外如果还要接 Claude Code,三件套对照 接入文档。需要复现对照表,从 TaoToken 创建 Key,把 Base URL 填成 https://taotoken.net/api,模型 ID 以广场为准。
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度




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



