Quay lại blog

AI cho người mớiHướng dẫn

Hỏi LLM về CSV: gửi schema, không phải bảng

Gửi tên cột, kiểu dữ liệu và 3 dòng mẫu, nhận lại một dòng pandas, chạy nó trên toàn bộ tệp. Rẻ hơn dán dòng, và bạn có thể kiểm tra con số.

Bởi CheapTokens TeamĐã xuất bản 8 phút đọc

Các dòng mã đọc CSV, lấy kiểu cột và ba dòng, và yêu cầu một dòng pandas
Trên trang này
  1. Tại sao dán toàn bộ bảng lại sai
  2. Gửi hình dạng của bảng, không phải bảng
  3. Script: hỏi, đọc dòng, chạy nó
  4. Chi phí: dán tất cả so với schema + 3 dòng
  5. Kiểm tra con số trước khi tin nó
  6. Nếu nó không hoạt động

Bạn có một sales.csv với 5.000 dòng và một câu hỏi: sản phẩm nào bán chạy nhất trong tháng Mười? Đừng dán tệp vào chat. Gửi cho mô hình tên các cột, kiểu dữ liệu của chúng và ba dòng mẫu, yêu cầu một dòng pandas, rồi tự chạy dòng đó trên toàn bộ tệp. Mô hình không bao giờ đọc 5.000 dòng của bạn, prompt vẫn nhỏ gọn, và con số bạn nhận được đến từ mã bạn có thể chạy lại.

Đây là lý do tại sao cách đó tốt hơn, prompt trông như thế nào, một script bạn có thể sao chép, và chi phí của nó so với cách dán tất cả.

Tại sao dán toàn bộ bảng lại sai#

Đây là một câu chuyện bạn có thể nhận ra. Ai đó dán 200 dòng chi phí vào chat và yêu cầu tính tổng. Câu trả lời trở về đầy tự tin, có cả xu lẻ. Nó cũng sai, và không có gì trên màn hình cho bạn biết điều đó.

Mô hình dự đoán văn bản từng mảnh (những mảnh đó là token). Tổng của 200 số là 200 bước nhỏ không có máy tính bên trong, và một chữ số bị trượt trông giống hệt một câu trả lời đúng. Mã hoạt động khác: df['amount'].sum() cộng tất cả các dòng, mỗi lần, và cho kết quả giống nhau ở lần chạy thứ hai.

Có một vấn đề thứ hai, và đó là về kích thước. Một bảng ăn cửa sổ ngữ cảnh rất nhanh, và bạn trả tiền cho mỗi dòng ở mỗi câu hỏi. Mười câu hỏi về cùng một tệp nghĩa là mười bản sao của toàn bộ bảng được gửi làm đầu vào.

Kiểm tra nhanh

Tại sao một dòng pandas an toàn hơn yêu cầu mô hình tính tổng?

Hiện đáp án

Trả lời: Máy tính của bạn chạy mã trên mọi dòng, và bạn có thể chạy lại và kiểm tra

Mô hình vẫn có thể viết một dòng sai. Khác biệt là một dòng thì hiển thị và có thể lặp lại: bạn đọc nó, chạy nó, và so sánh kết quả với vài dòng bằng tay.

Gửi hình dạng của bảng, không phải bảng#

Mô hình không cần dữ liệu của bạn để viết mã. Nó cần biết bảng trông như thế nào: những cột nào tồn tại, chúng chứa loại giá trị gì, và một dòng được viết ra sao. Đó là schema cộng với vài dòng.

Giả sử sales.csv của bạn có bốn cột. Đây là toàn bộ prompt:

text
A pandas DataFrame named df has these columns and types:
date        object
product     object
units        int64
price      float64

First 3 rows (CSV):
date,product,units,price
2026-10-01,Oat latte mix,12,4.50
2026-10-01,Cocoa,7,3.20
2026-10-02,Oat latte mix,9,4.50

Question: Which product sold the most units in October 2026?

Reply with ONE line of pandas code that computes the answer from df.
No explanation, no markdown, no imports.

Hãy mong đợi một câu trả lời có dạng như df[df['date'].str.startswith('2026-10')].groupby('product')['units'].sum().idxmax(). Cách diễn đạt chính xác khác nhau mỗi lần chạy, nên hãy đọc dòng đó trước khi chạy.

Tại sao ba dòng mà không chỉ tên cột? Vì ngày tháng. Cột kiểu nói object, chỉ có nghĩa là văn bản. Các dòng mẫu cho thấy ngày được viết là 2026-10-01, nên mô hình biết phải khớp với văn bản 2026-10, không phải 10/2026 hay tên tháng. Hầu hết các dòng pandas sai đến từ việc đoán một định dạng mà bảng chưa từng có.

Dán mọi dòng so với gửi schema và ba dòng
Cùng một câu hỏi: prompt bên trái lớn dần theo bảng, prompt bên phải giữ nguyên kích thước

Script: hỏi, đọc dòng, chạy nó#

Script dưới đây xây dựng prompt đó từ tệp của bạn, để bạn không phải gõ schema bằng tay. Nó gọi API CheapTokens qua OpenAI Python SDK: base URL https://api.cheaptokens.dev/v1, model id deepseek-ai/DeepSeek-V4-Flash-0731. Giữ khóa trong một biến môi trường, không phải trong tệp.

python
import os
import pandas as pd
from openai import OpenAI

client = OpenAI(
    base_url="https://api.cheaptokens.dev/v1",
    api_key=os.environ["CHEAPTOKENS_API_KEY"],
)

df = pd.read_csv("sales.csv")      # for .xlsx: pd.read_excel("sales.xlsx")

schema = df.dtypes.to_string()
sample = df.head(3).to_csv(index=False)
question = "Which product sold the most units in October 2026?"

prompt = f"""A pandas DataFrame named df has these columns and types:
{schema}

First 3 rows (CSV):
{sample}
Question: {question}

Reply with ONE line of pandas code that computes the answer from df.
No explanation, no markdown, no imports."""

resp = client.chat.completions.create(
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    messages=[{"role": "user", "content": prompt}],
    max_tokens=500,
)

text = resp.choices[0].message.content.strip()
code = text.removeprefix("```python").removeprefix("```").removesuffix("```").strip()
print("Model's line:", code)
print("Tokens in/out:", resp.usage.prompt_tokens, resp.usage.completion_tokens)

if resp.choices[0].finish_reason != "stop" or "import" in code or "__" in code:
    raise SystemExit("Not running this one. Read the line above and decide.")

print("Answer:", eval(code, {"df": df, "pd": pd}))

Khối cuối là phần người mới bỏ qua. eval chạy bất kỳ văn bản nào mô hình viết, trên máy của bạn, nên script từ chối các dòng có import hoặc __ và các câu trả lời bị cắt (finish_reason khác stop; xem tại sao câu trả lời dừng giữa câu). Và bạn vẫn đọc dòng được in ra trước. Nếu nó chạm vào tệp, mạng hoặc bất cứ thứ gì bạn không yêu cầu, đừng chạy nó.

Lần chạy đầu tiên in ra ba thứ: dòng của mô hình, số token cho yêu cầu này, và câu trả lời. Số token là đồng hồ đo của bạn cho phần tiếp theo.

Chi phí: dán tất cả so với schema + 3 dòng#

Để so sánh, chúng ta cần một kích thước cho một dòng. Giả sử một dòng như 2026-10-01,Oat latte mix,12,4.50 tốn khoảng 20 token. Đó là một giả định: nó phụ thuộc vào tokenizer của mô hình và các cột của bạn, và đếm token trước khi gửi cho bạn con số thực. Với 20 token một dòng, 5.000 dòng là 5.000 × 20 = 100.000 token đầu vào. Prompt schema-và-ba-dòng khoảng 300 token, bao gồm hướng dẫn. Câu trả lời ngắn trong cả hai trường hợp, giả sử 60 token, nên sự khác biệt nằm hoàn toàn ở phía đầu vào, phía lớn dần theo bảng của bạn (xem thêm trong token đầu vào so với đầu ra).

Một câu hỏi về bảng 5.000 dòng trên DeepSeek-V4-Flash, 60 token câu trả lời
  • Dán tất cả 5.000 dòng$0.0015
  • Schema + 3 dòng$0.000011

Cả hai con số đều nhỏ tính bằng đô la, và đó là sự thật: một mô hình rẻ làm cho cả cách lãng phí cũng phải chăng. Khoảng cách là thứ lớn dần. Hỏi 20 câu một ngày và prompt dán-tất-cả được gửi 20 lần. Gấp đôi bảng và chi phí của nó gấp đôi, trong khi prompt schema không nhúc nhích. Và có một bức tường cứng: với cửa sổ ngữ cảnh 380K token, 380.000 ÷ 20 = 19.000 dòng là mức tối đa bạn có thể dán, trước khi chừa chỗ cho câu trả lời. Một bản xuất 50.000 dòng đơn giản là không vừa. Prompt schema thì vừa, bất kể kích thước bảng.

Nhập bảng của riêng bạn và xem chi phí hàng ngày:

Máy tính chi phí

Bảng của bạn dán toàn bộ: 20 câu hỏi một ngày

Token đầu vào mỗi yêu cầu: 100.000 · Token đầu ra mỗi yêu cầu: 60 · Số yêu cầu mỗi ngày: 20

Mô hìnhMỗi ngàyMỗi tháng
GLM-5.3-Flash$0.04$1.20
DeepSeek-V4-Flash$0.0301$0.904
MiniMax-M2.7$0.10$3.01

Đổi in thành 300 để thấy cách schema. DeepSeek-V4-Flash trên CheapTokens có một mức giá bất kể giờ nào, không phụ phí giờ cao điểm, và một số dư bao trùm mọi mô hình, nên bạn có thể đổi model id thành zai-org/GLM-5.3-Flash (ngữ cảnh 390K) mà không cần tài khoản thứ hai. Giá hiện tại ở trang giá.

Kiểm tra con số trước khi tin nó#

Vòng lặp luôn giống nhau. Làm mỗi lần, và một câu trả lời sai sẽ bị bắt ở bước bốn thay vì trong một báo cáo.

Sắp xếp thứ tự

Sắp xếp vòng lặp theo thứ tự

  1. Mô tả bảng: kiểu cột và 3 dòng mẫu
  2. Yêu cầu một dòng pandas, không gì khác
  3. Đọc dòng, rồi chạy nó trên toàn bộ tệp
  4. Kiểm tra kết quả bằng tay trên vài dòng
Vòng lặp: bảng, schema và ba dòng, một dòng pandas, con số của bạn
Mô hình chỉ thấy bước giữa; toàn bộ bảng không bao giờ rời máy tính của bạn

Bước bốn rẻ. Lọc tệp xuống còn một số dòng (df[df['product'] == 'Cocoa'].head(10)), cộng chúng trong đầu hoặc trong bảng tính, và so sánh. Nếu dòng của mô hình sai, nó thường sai một cách rõ ràng: nó đếm dòng thay vì cộng units, hoặc nó chọn sai tháng.

Để biết thêm các thói quen như thế này, xem tại sao AI bịa đặt và 4 thói quen prompt giảm thiểu điều đó.

Nếu nó không hoạt động#

  • KeyError: 'Date'. Mô hình viết tên cột với chữ hoa khác. Dán dòng tiêu đề thực vào prompt, mà ba dòng mẫu đã làm, và thêm "dùng tên cột chính xác như hiển thị".
  • Câu trả lời có một câu trước mã. eval của bạn thất bại với SyntaxError. Lặp lại "MỘT dòng mã pandas, không giải thích" ở cuối prompt, hướng dẫn cuối cùng có trọng lượng nhất.
  • Câu trả lời là một bảng, không phải một số. Nói rõ hình dạng bạn muốn: "trả về một số duy nhất" hoặc "trả về một Series sắp xếp giảm dần".
  • Ngày tháng ra sai. Các dòng mẫu cho thấy định dạng thực. Nếu ngày của bạn là 14/10/2026, mô hình cần thấy điều đó; thêm pd.to_datetime(df['date'], dayfirst=True) vào prompt như cách bạn muốn ngày được đọc.
  • finish_reason là length. Câu trả lời bị cắt bởi max_tokens. Một dòng đơn lẻ vừa trong 500 token, nên kiểm tra prompt: mô hình có thể đang giải thích dài dòng.

Thiết lập đầy đủ cho yêu cầu đầu tiên của bạn, từ khóa đến phản hồi, có trong tài liệu CheapTokens.