csv-editor

star 31

如何用 artifact_* 工具對 CSV 做 CRUD。任何 CSV 操作前先查這份。

quan0715 By quan0715 schedule Updated 4/22/2026

name: csv-editor description: 如何用 artifact_* 工具對 CSV 做 CRUD。任何 CSV 操作前先查這份。

csv_editor:
  golden_rule: >
    禁止手動解析 CSV、禁止寫 Python 腳本處理 CSV、禁止用 artifact_write 寫 .csv、
    禁止用 artifact_read + offset/limit 找符合條件的列。所有 CSV 動作都有專用工具,
    找對應的那一個就好。

  note: >
    所有 artifact 工具的 step 參數為 optional,正常流程省略即可(工具自動依 filename 定位)。
    僅在同 session 出現同名檔案時才需帶 step 消歧義。

  decision_tree:
    - 問: 我要新開一份 CSV,資料直接來自 MCP / API 的 response?
      答: artifact_csv_from_json
    - 問: 我要新開一份 CSV,資料是我自己組的 rows(list of dicts)?
      答: artifact_write_csv
    - 問: 我只想知道「有幾列符合條件」(e.g. 還剩幾筆沒評 / 沒 sync)?
      答: artifact_csv_search   # 便宜、不回 rows
    - 問: 我要從 CSV 挑幾列、幾欄組成 MCP payload?
      答: artifact_csv_to_json   # 帶 columns/where/limit,回 records
    - 問: 我只想改既有 CSV 裡面幾列的幾格(例如寫回 score 或 synced)?
      答: artifact_csv_patch    # 不要用 artifact_write_csv,會覆蓋全檔
    - 問: 我想看原始內容(debug 用)?
      答: artifact_read          # 支援 offset/limit 分頁,但不要拿來解析 CSV

  tools:

    artifact_csv_from_json:
      when: 從 MCP/API 的 response seed 一份新的 CSV(最常見的開檔場景)。
      minimum_example: |
        # records 的每個元素已經就是一列 → identity mapping(省略 column_mapping)
        artifact_csv_from_json(
          filename="grade.csv",
          records=response["items"],                           # list of dict
          defaults={"score": "", "reason": "", "synced": ""},   # 補上 records 沒有的欄位
        )
      with_column_mapping: |
        # 當原始 record 的 key 跟想要的 CSV 欄名不同,或需要 dot-path 取巢狀欄位
        artifact_csv_from_json(
          filename="answers.csv",
          records=response["items"],
          column_mapping={
            "exam_answer_id": "exam_answer_id",
            "student_id":     "username",
            "answer_text":    "answer.text",    # 巢狀 dot-path
            "original_score": "score",
          },
          defaults={"new_score": "", "reason": ""},
        )
      gotchas:
        - records 為空時 identity mapping 無法推欄名 → 要給 column_mapping。
        - defaults 的 key 會附加在 column_mapping 後面,順序就是 CSV 欄順序。

    artifact_write_csv:
      when: 你手上已經有 columns + rows(list of dicts),不是直接來自 response。
      minimum_example: |
        artifact_write_csv(
          filename="rubric_scores.csv",
          columns=["criterion", "max_score"],
          rows=[{"criterion": "完整性", "max_score": 3}, ...],
        )
      gotchas:
        - rows 裡某欄 missing → 自動填空字串,不會報錯。
        - columns 必傳真的 array,不要傳 JSON 字串(工具會退回 error)。

    artifact_csv_search:
      when: 只想知道「有幾列符合條件」來決定要不要開下一批 / 是否進下階段。
      minimum_example: |
        # 還剩幾筆沒評?
        artifact_csv_search(
          filename="grade.csv",
          where={"score": ""},
        )
        # → {"matched": 45, "total_rows": 150}
      returns: |
        {"matched": int, "total_rows": int}   # 不回 records,省 token
      gotchas:
        - 不回傳任何 row 資料 → 想要 records 請用 artifact_csv_to_json。
        - 沒給 where → matched == total_rows。

    artifact_csv_to_json:
      when: 要從 CSV 挑出指定欄位 + 符合條件的列,組成 records 餵回 MCP。
      minimum_example: |
        # 找所有 synced 還是空的列,取 batch_grade 需要的三欄,最多 20 筆
        batch = artifact_csv_to_json(
          filename="grade.csv",
          columns=["exam_answer_id", "score", "reason"],
          where={"synced": ""},
          limit=20,
        )
        # batch["records"] 可直接丟進:
        qjudge_grading(action="batch_grade", grades=batch["records"])
      where_semantics:
        - dict 相等比對,AND-combined;empty string ("") 匹配空欄。
        - 不支援運算式 / 大於小於 / OR。若需要複雜過濾,分多次呼叫後合併。
      returns: |
        {
          "count":         20,    # 本次回傳的列數(套用 limit 之後)
          "total_matched": 123,   # 符合 where 的總列數(未套 offset/limit)
          "records":       [{...}, ...]
        }
      gotchas:
        - columns 必填:強迫你明確宣告 payload 形狀(避免一次倒全欄進 context)。
        - 所有值都以字串比對;"5" 跟 5 會視為相等。

    artifact_csv_patch:
      when: 要改既有 CSV 幾列的幾格,其他列要保留。
      minimum_example: |
        # 本批批改完,只送改動的 20 列
        artifact_csv_patch(
          filename="grade.csv",
          key_column="exam_answer_id",
          updates=[
            {"exam_answer_id": 2673, "score": "6", "reason": "..."},
            ...
          ],
        )
      returns: |
        {
          "updated":    20,           # 成功 merge 的筆數
          "missing":    [...],        # updates 裡的 key 找不到對應列的 id list
          "total_rows": 145,           # 寫回後 CSV 的列數
          "artifact":   {...}          # 下游 write 的 metadata
        }
      gotchas:
        - updates 每個元素必須含 key_column;沒對到的 key 會進 missing,不會中斷。
        - key_column 不在 CSV 欄位 → 直接錯誤。
        - update 內若放 key_column 以外不存在的欄名,會被忽略(不新增欄)。

    artifact_read:
      when: debug / 人類可讀 / 想看 raw content。不要拿來解析 CSV 或找列。
      minimum_example: |
        artifact_read(filename="grade.csv", offset=0, limit=50)
      gotchas:
        - 回傳的 content 會在 200k 字元處被截斷;大檔必用 offset/limit。
        - 就算 .csv 也是回整段文字,不會幫你解析。解析用 csv_to_json / csv_search。

  anti_patterns:
    - 用 artifact_read 讀 grade.csv 後自己 split("\n") / split(",") 組 payload
        → 改用 artifact_csv_to_json。
    - 用 artifact_read 配 offset/limit 找「第 N 批還沒評的列」
        → 改用 artifact_csv_search(看剩幾筆) + artifact_csv_to_json(取 rows)。
    - 批改完只 artifact_write_csv 送本批 20 列
        → 會覆蓋整檔,其他列消失。改用 artifact_csv_patch。
    - MCP response 直接 artifact_write(filename="x.csv", content=...)
        → 引號/換行/中文標點遲早踩雷。改用 artifact_csv_from_json。
    - 把 exam_answer_id / username 當成 row index 來算「第幾筆」
        → 它們是欄位值,不是列序。用 where filter 精準定位。
Install via CLI
npx skills add https://github.com/quan0715/QJudge --skill csv-editor
Repository Details
star Stars 31
call_split Forks 1
navigation Branch main
article Path SKILL.md
More from Creator