Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Tool đọc/sửa file: đọc, ghi và edit chính xác

Đã đọc 0/9 mục · còn khoảng 3 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Khả năng sửa file là thứ khiến coding agent hữu ích. Nhưng ghi đè cả file dễ làm mất code. Bài này ta xây bộ tool file an toàn: read_file, list_dir, write_file, và quan trọng nhất — edit_file kiểu thay thế chuỗi chính xác.

Vì sao không nên chỉ dùng write_file

Nếu tool duy nhất để sửa là write_file (ghi đè toàn bộ), LLM phải in lại cả file mỗi lần sửa một dòng. Hệ quả: tốn token, dễ cắt xén nội dung ngoài ý muốn, và với file lớn thì LLM hay "quên" phần cuối. Giải pháp là edit theo mảnh.

Bước 1: Tool edit_file dạng find/replace

def edit_file(path, old_string, new_string):
    text = open(path, encoding="utf-8").read()
    count = text.count(old_string)
    if count == 0:
        return "ERROR: không tìm thấy old_string. Hãy read_file lại."
    if count > 1:
        return f"ERROR: old_string xuất hiện {count} lần, không duy nhất. Thêm ngữ cảnh."
    open(path, "w", encoding="utf-8").write(
        text.replace(old_string, new_string))
    return "OK: đã thay thế 1 vị trí."

Ba quy tắc vàng của edit an toàn:

  • Không tìm thấy → báo lỗi, buộc LLM đọc lại file (tránh sửa mù).
  • Trùng nhiều → từ chối, buộc LLM cung cấp ngữ cảnh dài hơn để định vị duy nhất.
  • Duy nhất → thay và xác nhận.
Cơ chế này ép LLM sửa dựa trên nội dung thật nó vừa đọc, thay vì nội dung nó tưởng tượng.

Bước 2: write_file cho file mới

def write_file(path, content):
    import os
    os.makedirs(os.path.dirname(path) or ".", exist_ok=True)
    open(path, "w", encoding="utf-8").write(content)
    return f"OK: đã ghi {len(content)} ký tự vào {path}."

Dùng write_file để tạo mới; dùng edit_file để sửa file có sẵn. Mô tả tool nên nói rõ sự phân công này để LLM chọn đúng.

Bước 3: list_dir để agent tự định hướng

def list_dir(path="."):
    import os
    return "\n".join(sorted(os.listdir(path)))

Agent thường bắt đầu bằng list_dir để hiểu cấu trúc dự án trước khi đọc file cụ thể — giống lập trình viên mở cây thư mục.

Ví dụ: đổi tên biến trong 1 hàm

  • LLM read_file("utils.py") → thấy def calc(x): return x*taxrate.
  • LLM edit_file("utils.py", old="return xtaxrate", new="return x TAX_RATE").
  • Tool báo OK (chuỗi duy nhất) → LLM chạy test xác nhận.
Nếu xtaxrate xuất hiện ở 2 hàm, tool báo "trùng 2 lần" và LLM sẽ thêm ngữ cảnh: old="def calc(x): return xtaxrate" để định vị đúng.

Khung tư duy: Read-before-Edit

Luật bất di bất dịch: agent phải read_file trước khi edit_file cùng một file trong lượt đó. Vì old_string phải khớp chính xác nội dung hiện tại. Nhiều framework còn chặn cứng: từ chối edit nếu file chưa được đọc trong phiên.

Checklist tool file

  • [ ] edit_file từ chối khi old_string trùng nhiều hoặc không thấy.
  • [ ] Thông báo lỗi hướng dẫn LLM cách sửa ("read lại", "thêm ngữ cảnh").
  • [ ] write_file chỉ dùng tạo mới; edit dùng sửa file cũ.
  • [ ] read_file trả kèm số dòng khi cần định vị.
  • [ ] Có giới hạn kích thước đọc để không nhồi file khổng lồ vào context.

Sai lầm thường gặp

  • Chỉ có write_file. Agent ghi đè và vô tình xóa phần code không liên quan.
  • Cho phép edit khi old_string trùng nhiều. replace sẽ đổi tất cả vị trí — gây sửa nhầm hàng loạt.
  • Không buộc read trước edit. LLM sửa dựa trên trí nhớ sai, old_string không khớp, mất thời gian thử lại.
  • Thông báo lỗi cụt lủn ("failed"). LLM không biết vì sao và cách khắc phục; hãy nói rõ nguyên nhân.
  • Đọc file nhị phân/khổng lồ làm tràn context window và tốn token vô ích.
Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi