KAT-Coder-Pro V2.5 读单个文件时很快,因为符号定义、导入语句和调用点都落在同一份上下文里,模型不需要推断。任务一跨到多个文件,导入闭合关系没有进上下文,模型只能靠命名习惯猜,于是把函数名、类名或模块路径猜错,看起来就是“丢引用”。补依赖图不是换模型,而是把这些它看不到、但改动必须依赖的关系显式喂进去。
判断边界:多文件丢引用通常可归为缺文件、缺导入关系、缺符号定义三类,先用模型输出里的错误符号定位到具体类别。处理动作是先在本地生成模块导入与调用关系,检查目标文件的上下游是否覆盖,再把文件树、依赖关系、目标文件内容按顺序组织进任务描述。验证方式是重新运行多文件修改,用编译或静态检查命令确认无未定义引用。若项目存在动态导入、反射或代码生成,静态依赖图会有缺口,需要结合环境确认。
记录多文件任务中模型找不到引用的具体位置
这一步的目的是把“丢引用”从模糊感受变成可对照的清单。把模型输出里它猜错的函数名、类名或路径逐条抄下来,注明你判断它应该来自哪个文件,三类问题的处理方式并不一样。
- 缺文件:符号确实存在于仓库里,但那份文件没有进入上下文。模型会写出一个看似合理但不存在的定义。
- 缺导入关系:文件都在上下文里,但模型不知道谁 import 谁,于是写错相对路径或漏掉中间模块。
- 缺符号定义:知道模块在哪,但该模块导出的函数或类没有出现,模型只能按命名规则编一个近似的。
# 从模型输出里摘出来的三类典型错误
调用 load_config() # 实际定义在 config/loader.py,该文件未进上下文
import { UserRepo } from './repo' # 实际路径为 ../data/user-repo
export class Client # 实际应为 ClientFactory,定义在 client/factory.py
确认方式是回到仓库里搜符号本身,例如 grep -rn 'def load_config\|class ClientFactory' src,看真实定义落在哪个文件、哪些文件引用了它。搜索能定位的趋势,就是依赖图需要补的范围。
在本地生成模块间的导入和调用关系
理想状态下,交给模型的依赖图应该是一行一条的“文件指向依赖文件”,可读、可机器解析。生成方式可以先从轻量做法起步,再按项目规模换成现成工具。
先是目录扫描,确认有哪些源文件参与,避免依赖图漏掉目录:
find src -type f -name '*.py'
find src -type f \( -name '*.ts' -o -name '*.tsx' \)
再解析导入语句,得到最直接的边。下面按语言各给一种通用做法,具体前缀需要结合项目结构调整:
# Python
grep -rn '^from \|^import ' src `--include`='*.py'
# JS / TS
grep -rn '^import \|require(' src `--include`='*.ts' `--include`='*.tsx'
# Go
go list -deps ./...
# Java
jdeps -summary path/to/classes
手写 grep 容易漏掉别名导入、re-export 和路径别名,所以当项目有构建配置时,建议直接用现成依赖工具输出关系列表:Python 侧可看 pydeps、modulegraph,JS/TS 侧可看 madge、dependency-cruiser,Java 侧可用 jdeps 或构建工具的依赖树。这些工具的价值是输出格式稳定,可先转成 源文件 -> 依赖文件 的列表再贴给模型。需要注意的是,工具给出的是静态关系,动态字符串导入、反射调用、代码生成不会出现在里面。
检查依赖图是否覆盖目标文件的上下游
只给目标文件的下游会缺调用方,只给上游会缺被调用方,容易改完一处另一处编译不过。对目标文件按两个方向过滤:上游是引用或调用它的文件,下游是它引用或调用的文件。
[上游调用方] api/handler.py -> service/order.py
job/batch.py -> service/order.py
[目标文件] service/order.py
[下游被调用方] service/order.py -> data/repo.py
service/order.py -> util/money.py
列完之后逐条对比:每个上游文件是否真的引用了目标文件里的符号,每个下游模块的接口是否被目标文件实际使用。常见遗漏集中在通过索引文件 re-export、路径别名解析到别的目录、以及测试文件里对同一符号的引用。如果发现某条边只出现在 import 语句里、代码中从未调用,可以标记为弱依赖,视任务范围决定放不放上下文。
把依赖图和目标文件一起组织进任务描述
顺序会影响模型的理解效果。建议先给文件树建立整体位置感,再给导入关系说明连接方式,最后放目标文件内容和修改要求。一个可复用的骨架如下,替换成自己的路径和代码即可:
项目结构:
src/
api/handler.py
service/order.py
data/repo.py
util/money.py
依赖关系(箭头指向被依赖):
api/handler.py -> service/order.py
job/batch.py -> service/order.py
service/order.py -> data/repo.py
service/order.py -> util/money.py
目标文件:service/order.py
<粘贴文件内容>
修改要求:为订单金额增加舍入处理
约束:保持 data/repo.py 的接口签名不变;
若需要新增工具函数,放到 util/money.py 并在此处声明
这样模型读到的第一段是位置,第二段是关系,第三段才是要改的代码,改动的落点更可控。上下文长度有限,依赖图只保留与任务相关的子图即可,把整个仓库的关系倒进去通常没有好处。
再次运行多文件修改并检查引用是否正确
补完依赖图后,重跑同一个多文件任务,重点看之前记录的猜错符号是否被修正。改完不要只靠肉眼比对,先跑静态检查或编译命令,让工具找出未定义引用和导入路径错误:
# Python
python -m compileall src
ruff check src
mypy src
# TypeScript
tsc `--noEmit`
# Go
go build ./...
# Java
mvn -q compile
检查结果按类别回看:如果是“未定义名称”,说明某个上游或下游文件没进上下文,需要回到依赖图补边;如果是“导入路径不存在”,说明相对路径或别名解析有问题,需要用目录扫描结果核对;如果静态检查通过但运行时报错,多半落在动态导入或反射调用上,这类场景静态依赖图覆盖不到,需要结合具体运行环境单独确认。把每次修正的符号和对应补上的依赖记录下来,下一轮多文件任务可以直接复用这份依赖图。