Last chance! 50% off DataCamp Premium
Sale ends in
Khi một bảng điều khiển được phát hành kèm lỗi, vòng lặp gỡ lỗi gần như luôn giống nhau. Bạn nhìn vào màn hình, tìm tệp liên quan, chỉnh sửa, chạy lại kiểm thử, tải lại trang và kiểm tra lại. Việc này rất tẻ nhạt, và một nửa bằng chứng nằm trong ảnh chụp màn hình thay vì trong stack trace.
Tôi bắt đầu thử nghiệm này ngay sau khi DeepSeek phát hành DeepSeek V4.1 Flash. Đây là thành viên nhỏ nhất của họ kiến trúc mới và hỗ trợ đầu vào hình ảnh. Tôi muốn biết liệu nó có thể kiểm tra một ứng dụng web bị lỗi, vá mã và tự biết khi nào đã hoàn tất hay không.
Hướng dẫn này tập trung vào một dự án: một bảng điều khiển Flask nhỏ có tên Nimbus Analytics Launch Metrics với ba lỗi để một tác nhân tìm và sửa thông qua cách DeepSeek triển khai định dạng Responses API. Lần chạy được ghi lại cũng cho thấy một lỗ hổng trong bộ công cụ của tác nhân.
Chúng ta sẽ cùng tìm hiểu cách:
Thực hiện cuộc gọi đầu tiên tới DeepSeek V4.1 Flash qua Responses API
Cung cấp cho mô hình một ảnh chụp tham chiếu, rồi gửi các ảnh chụp Playwright mới như đầu ra của công cụ
Cấp cho tác nhân các công cụ để liệt kê tệp, đọc tệp, chạy pytest và vá mã trên nhiều tệp chỉ với một lệnh gọi bằng apply_patch
Lưu và gửi lại lịch sử hội thoại vì API không lưu trạng thái
Tính chi phí từ token đầu vào được lưu đệm, suy luận và đầu ra
Responses API của DeepSeek V4.1 Flash là không lưu trạng thái, vì vậy mã Python sẽ lưu hội thoại và gửi lại ở mỗi lượt. Cùng một vòng lặp sử dụng khả năng thị giác cho ảnh tham chiếu và ảnh công cụ, chế độ suy nghĩ để kiểm tra nhiều tệp, và apply_patch để chỉnh sửa. Bốn chi tiết từ lần chạy này đã thay đổi cách tôi sẽ xây dựng phiên bản tiếp theo.
Những con số này đến từ một lần chạy đơn trên một bảng điều khiển nhỏ, không phải chuẩn đo. Số lượt, tỷ lệ trúng bộ nhớ đệm và chi phí sẽ thay đổi với ứng dụng lớn hơn hoặc bộ lỗi khác.
DeepSeek cung cấp V4.1 Flash qua API dưới ID mô hình deepseek-flash. Mô hình nhận đầu vào hình ảnh, hỗ trợ cả chế độ suy nghĩ và không suy nghĩ, có cửa sổ ngữ cảnh 1 triệu token và có thể trả về tối đa 384K token thông qua Chat Completions và Responses API.
Bài tổng quan về DeepSeek V4.1 Flash của chúng tôi đề cập đến thời điểm ra mắt, kiến trúc và các benchmark.
DeepSeek mô tả V4.1 Flash là một xương sống MoE 552 tỷ tham số, trong khi Hugging Face báo 763 tỷ tham số cho checkpoint đã công bố. Chênh lệch chủ yếu do bộ nhớ điều kiện Engram 196 tỷ tham số, cộng với bộ mã hóa và bộ chiếu thị giác, đều được cung cấp trong checkpoint nhưng nằm ngoài xương sống MoE.
Thiết kế Causal Encoder-Decoder tái sử dụng trạng thái bộ mã hóa đã lưu đệm, với 8B tham số hoạt động mỗi token khi xử lý đầu vào và 16B khi tạo đầu ra.
V4.1 Flash là mô hình đầu tiên trong họ kiến trúc V4.1 mới, với khả năng hiểu hình ảnh được tích hợp gốc. Vector nhúng hình ảnh và văn bản được huấn luyện chung ngay từ đầu giai đoạn tiền huấn luyện, thay vì bổ sung sau như ở bản thử nghiệm V4-Flash-Vision-Exp.
Responses API có trước V4.1 Flash; DeepSeek đã bổ sung hỗ trợ gốc trong đợt phát hành V4 trước đó. Các tên mô hình đã ngừng deepseek-v4-flash và deepseek-v4-flash-vision-exp giờ được chuyển hướng tới V4.1 Flash.
Giá của DeepSeek dựa trên giờ cao điểm, với mức ngoài giờ bằng 50% giờ cao điểm. Khi tôi chạy tác nhân, chi phí đầu vào được lưu đệm là $0,003 mỗi triệu token ngoài giờ và $0,006 giờ cao điểm, đầu vào không lưu đệm là $0,15 ngoài giờ và $0,30 giờ cao điểm, còn đầu ra là $0,60 ngoài giờ và $1,20 giờ cao điểm, theo trang giá của DeepSeek.
Giờ cao điểm là 01:00–04:00 và 06:00–10:00 UTC, từ thứ Hai đến thứ Sáu, không tính các ngày nghỉ lễ công của Trung Quốc. Các khung giờ còn lại là ngoài giờ, và toàn bộ ngày nghỉ lễ công của Trung Quốc đều tính ngoài giờ.
Nimbus Analytics Launch Metrics là một bảng điều khiển Flask cho tổng lượt truy cập, lượt đăng ký, tỷ lệ chuyển đổi, doanh thu và đăng ký hằng ngày. Tôi đã cài ba lỗi ở ba tệp và không nói cho tác nhân biết đó là gì. Mã nguồn và bảng điều khiển lỗi nằm trong kho GitHub này.

Bảng điều khiển lỗi cạnh thiết kế tham chiếu. Ảnh: Tác giả.
Ba lỗi cần loại bằng chứng khác nhau. Một lỗi xuất hiện trên ảnh chụp màn hình, một lỗi ảnh hưởng hành vi trình duyệt, và một lỗi làm pytest thất bại. Tác nhân không nhận danh sách lỗi.
Trước khi giao việc cho tác nhân, tôi định nghĩa thế nào là “đã sửa”: bộ pytest phải vượt qua, và một ảnh chụp mới phải khớp trực quan với ảnh tham chiếu. Ý kiến của mô hình là chưa đủ, nên trình chạy sẽ kiểm tra cả hai loại bằng chứng.
Vòng lặp luân phiên giữa yêu cầu gửi tới mô hình và thực thi công cụ cục bộ. V4.1 Flash trả về phần suy luận, một thông điệp, hoặc lời gọi công cụ; Python chạy các công cụ được yêu cầu và thêm kết quả vào lịch sử. Vòng lặp dừng khi mô hình trả lời mà không gọi công cụ khác hoặc chạm giới hạn mười bốn lượt.

Vòng lặp sửa chữa nối mô hình, công cụ và trình duyệt. Ảnh: Tác giả.
Bạn sẽ cần Python 3.10 trở lên và khóa API DeepSeek có tín dụng. API của DeepSeek theo định dạng yêu cầu của OpenAI, nên dự án này dùng gói openai trong Python với base_url trỏ tới DeepSeek.
Tạo môi trường ảo và cài đặt các thành phần cần thiết cho dự án.
python3 -m venv .venv
source .venv/bin/activate
pip install openai flask playwright pytest python-dotenv requests streamlit
playwright install chromium
Tôi đã thử với openai 3.14.1, flask 3.1.3, và playwright 1.63.0. Lưu khóa trong tệp .env ở thư mục gốc dự án với DEEPSEEK_API_KEY=sk-... và nạp bằng python-dotenv. Nếu khóa của bạn đã hoạt động với Responses API, hãy bỏ qua khối mã sau; nếu không, yêu cầu này sẽ kiểm tra khóa và base URL.
from openai import OpenAI
import os
from dotenv import load_dotenv
load_dotenv()
client = OpenAI(api_key=os.environ["DEEPSEEK_API_KEY"], base_url="https://api.deepseek.com")
response = client.responses.create(model="deepseek-flash", input="Say hi in five words.")
print(response.output_text)
Nếu dòng in ra là một lời chào ngắn, khóa và base URL đang hoạt động.
Đầu vào đầu tiên của tác nhân gồm một ảnh chụp tham chiếu, một nhiệm vụ ngắn và URL trực tiếp. Đây là ảnh duy nhất được gửi trong thông điệp của người dùng. Mọi ảnh chụp sau đó đến từ công cụ.
Trình chạy gửi ảnh tham chiếu dưới dạng URL dữ liệu base64 trong mọi yêu cầu. DeepSeek khuyến nghị dùng Files API khi tái sử dụng ảnh. Một file_id giúp tránh gửi lại cùng dữ liệu ảnh mỗi lần.
Trong ảnh đính kèm, tôi hỏi mô hình sẽ kiểm tra gì trước tiên, nhưng chưa có công cụ nào. Điều này cho phép tôi xem kế hoạch của nó trước khi nó có thể chỉnh sửa. Phản hồi đề xuất liệt kê tệp dự án, lần theo biến CSS và chụp ảnh màn hình; tôi dùng reasoning: {"effort": "high"}, mức suy nghĩ mặc định của DeepSeek.
Tác nhân nhận bốn công cụ hàm và một công cụ tùy chỉnh.
list_files và read_file để kiểm tra dự án, cả hai đều bị giới hạn trong dashboard/ và tests/.
run_tests chạy pytest.
capture_dashboard_screenshot khởi chạy Chromium ở chế độ headless thông qua Playwright.
Công cụ tùy chỉnh là apply_patch, được khai báo là {"type": "custom", "name": "apply_patch"} và được chấp nhận “vì tương thích với Codex.” Bất kỳ tên công cụ tùy chỉnh nào khác sẽ trả về lỗi 400, trong khi các loại dựng sẵn như tìm kiếm web và sử dụng máy tính sẽ bị bỏ qua im lặng.
Đối số của hàm đến dưới dạng văn bản JSON và được kiểm tra trước khi Python chạy. apply_patch đến với tư cách đầu vào của công cụ tùy chỉnh, nên mã xử lý riêng và kiểm tra bản vá trước khi ghi tệp. Lỗi công cụ được trả về cho mô hình thay vì dừng vòng lặp.
Khi capture_dashboard_screenshot chạy, kết quả của nó không được lưu ra đĩa. Python trả về nó như một phần input_image bên trong function_call_output. DeepSeek sau đó đọc ảnh chụp như một hình ảnh thay vì mô tả văn bản.
history.append({
"type": "function_call_output",
"call_id": item.call_id,
"output": [{"type": "input_image", "image_url": f"data:image/png;base64,{png_b64}"}],
})
Tác nhân có thể vá CSS, chụp ảnh mới và kiểm tra xem các con số đã đọc được chưa.
Lịch sử được lưu trong một danh sách Python vì API không hỗ trợ previous_response_id hoặc hội thoại phía máy chủ. Chế độ suy nghĩ cũng yêu cầu mọi mục suy luận từ các lượt công cụ trước đó.
Quan trọng: Nếu đầu ra công cụ được chèn giữa hai lời gọi trong cùng một lượt, yêu cầu tiếp theo sẽ trả về lỗi 400. Hãy thêm mọi mục từ response.output theo đúng thứ tự, rồi chạy các công cụ và thêm kết quả của chúng.
Trình chạy giới hạn tác nhân trong mười bốn lượt và hai thư mục dashboard/ và tests/ . Nó không cung cấp quyền truy cập shell, kiểm tra đối số công cụ và dùng pytest để xác minh.
Có. Qua Responses API, DeepSeek V4.1 Flash chấp nhận JSON Schema thông qua text.format. Chat Completions response_format hỗ trợ chế độ JSON nhưng không hỗ trợ schema. Sau khi vòng lặp dừng, yêu cầu cuối sẽ ghi lại lỗi, bản vá, kết quả kiểm thử, kết quả ảnh chụp và phương thức xác minh.
Dự án cũng bao gồm một ứng dụng Streamlit trong app_streamlit.py. Cùng một tác nhân chạy dưới dạng generator với stream=True, nên trang sẽ hiển thị văn bản suy luận và các lời gọi công cụ ngay khi đến. Thanh bên thay đổi mức nỗ lực suy luận và chi tiết hình ảnh.
Giao diện Streamlit truyền trực tiếp quá trình chạy của tác nhân. Video: Tác giả.
Lần chạy trông như đã hoàn tất sau một bản vá, nhưng trang trực tiếp lại không đồng ý.
Tác nhân dùng hai lượt đầu để quan sát trước khi chạm vào bất cứ thứ gì: lượt một liệt kê tệp và chụp ảnh cơ sở, lượt hai đọc app.py, index.html, style.css và tệp kiểm thử.
Lượt ba chạy pytest, rồi lượt bốn áp dụng một bản vá sửa công thức chuyển đổi, thay đổi màu số liệu và khớp truy vấn JavaScript với ID canvas.
- conversion_rate = data["conversions"] / data["signups"] * 100
+ conversion_rate = data["conversions"] / data["total_visitors"] * 100
Chạy kiểm thử ở lượt năm cho thấy cả năm đều vượt qua. Đây là lúc lần chạy không còn gọn gàng nữa. Mỗi ảnh chụp mới vẫn hiển thị tỷ lệ chuyển đổi 15% và biểu đồ trống.
Tác nhân xác nhận rằng các tệp trên đĩa đã chứa bản vá, thử lại ảnh chụp và thăm dò xem máy chủ có nạp các tệp Python và template đã đổi hay không. Hai kiểm tra độ mới tạm thời cũng không xuất hiện trên trang trực tiếp.
Đến lượt mười bốn, vòng lặp đã chạm ngân sách và xác định nguyên nhân: run_tests kiểm tra mã trên đĩa, trong khi ảnh chụp kiểm tra một tiến trình đang chạy với trạng thái cũ. Flask khởi động với debug=False, nên không có reloader tải lại mô-đun Python đã đổi, và tính năng tự động tải lại template cũng không bật.
Thay đổi CSS xuất hiện, trong khi giá trị sinh từ Python và biểu đồ dựa trên template vẫn cũ. Pytest nhập app.py từ đĩa, vì vậy kiểm thử xanh không đảm bảo trang mới.
Sau khi tôi khởi động lại Flask, bảng điều khiển khớp với ảnh tham chiếu. Mảnh ghép thiếu là một công cụ restart_server, không phải thêm bản vá mã.

Khởi động lại giúp các thay đổi đã vá hiển thị. Ảnh: Tác giả.
Có, tác nhân đã sửa bảng điều khiển trên đĩa. Nó chỉ thay đổi ba tệp lỗi, và pytest đi từ bốn lỗi sang năm kiểm thử đều vượt qua. Trang trực tiếp hiển thị mọi bản sửa sau khi Flask khởi động lại.
Vì tác nhân gửi lại lịch sử của mình, các yêu cầu sau lặp lại nhiều phần đầu vào từ các lượt trước. DeepSeek kiểm tra tiền tố lặp lại này với bộ nhớ đệm tự động. Bộ nhớ đệm hoạt động theo nguyên tắc nỗ lực tối đa, nên các con số này chỉ áp dụng cho lần chạy này.
Qua mười bốn lượt sửa và yêu cầu báo cáo JSON cuối, API báo 156.724 token đầu vào, gồm 137.088 token được lưu đệm, tỷ lệ trúng 87%. Đầu ra là 11.497 token, gồm 9.362 token suy luận. Lần chạy rơi vào ngoài giờ, nên cả mười lăm yêu cầu chỉ tốn khoảng $0,0103.

Đầu ra suy luận là hạng mục chi phí lớn nhất. Ảnh: Tác giả.
Một codebase lớn hơn, nhiều ảnh chụp hơn hoặc ít lần trúng bộ nhớ đệm hơn sẽ làm thay đổi số token và chi phí.
Ba giới hạn API quan trọng trước khi trình chạy này vượt ra ngoài bản demo.
Không hỗ trợ phản hồi nền, nên các lượt dài sẽ chặn đến khi hoàn thành.
parallel_tool_calls và max_tool_calls bị bỏ qua; gọi công cụ song song vẫn bật.
Không hỗ trợ cắt tự động, nên các yêu cầu vượt quá giới hạn ngữ cảnh sẽ trả về lỗi 400.
Trước khi dùng mẫu này trong dịch vụ thực tế, hãy đặt các điều khiển trong mã ứng dụng thay vì trong hướng dẫn cho mô hình.
Dùng apply_patch khi một thay đổi cần cập nhật nhiều tệp cùng lúc, như trong trường hợp này. Chạy kiểm thử sau bản vá, vì một lệnh gọi lỗi có thể làm hỏng nhiều tệp.
Dùng read_file và write_file khi mỗi chỉnh sửa cần kiểm tra hoặc phê duyệt riêng. Chúng tốn nhiều lượt hơn, nhưng một chỉnh sửa lỗi chỉ ảnh hưởng một tệp tại một thời điểm.
Vòng lặp sửa lỗi giao diện đã sửa cả ba lỗi trong một bản vá, nhưng lần chạy không hoàn toàn sạch sẽ. Pytest vượt qua trong khi Flask vẫn phục vụ mã Python và template cũ, nên tác nhân không thể xác nhận trang cuối cùng cho đến khi tôi khởi động lại máy chủ.
Tôi sẽ bổ sung công cụ restart_server và so sánh theo pixel trước khi thử nghiệm ứng dụng lớn hơn. Tôi sẽ giữ ranh giới tệp và giới hạn lượt, rồi coi pytest và so sánh ảnh chụp là hai kiểm tra riêng. Vượt qua một kiểm tra không bao giờ thay thế cho kiểm tra còn lại.
Có. Responses API chấp nhận URL hình ảnh công khai, URL dữ liệu base64 hoặc file_id của Files API.
Lệnh gọi run_tests tiếp theo sẽ hiển thị hồi quy, và vòng lặp tiếp tục cho đến khi nó dừng hoặc chạm giới hạn lượt. Ứng dụng cũng nên giữ một bản sao để có thể khôi phục.
DeepSeek từng lên kế hoạch ngừng V4 Pro ngay sau khi V4.1 Flash ra mắt, sau đó đảo ngược quyết định do nhu cầu người dùng. V4 Pro vẫn khả dụng với cách tính phí như cũ.
Định dạng này xuất phát từ công cụ Codex của OpenAI, và DeepSeek mô tả hỗ trợ của họ là “vì tương thích với Codex.” Một API khác sẽ chỉ chấp nhận {"type": "custom", "name": "apply_patch"} nếu nó hỗ trợ cùng định nghĩa công cụ.
Có. Trọng số mô hình có sẵn trên Hugging Face theo giấy phép MIT. Hướng dẫn này sử dụng API do DeepSeek lưu trữ và không đề cập đến phục vụ mô hình hoặc yêu cầu phần cứng.
Tôi là một kỹ sư dữ liệu và người xây dựng cộng đồng, làm việc với pipeline dữ liệu, đám mây và công cụ AI, đồng thời viết các hướng dẫn thực hành, tác động cao cho DataCamp và các nhà phát triển mới nổi.
Học AI cùng DataCamp!
Khóa học
Khóa học
Lộ trình
blog
Matt Crabtree
10 phút