Chạy Claude Code Ngoại tuyến trên M3 Pro với Qwen3.6: Cấu hình và Tối ưu hóa

Phần cứng11 tháng 6, 2026·9 phút đọc

Bài viết chia sẻ kinh nghiệm chạy Claude Code hoàn toàn ngoại tuyến trên chip Apple M3 Pro sử dụng mô hình Qwen3.6 thông qua Ollama. Tác giả đi sâu vào các bước thiết lập kỹ thuật, bốn bản vá lỗi quan trọng để hệ thống hoạt động ổn định, cũng như phân tích tác động của phần cứng đối với hiệu năng xử lý.

Chạy Claude Code Ngoại tuyến trên M3 Pro với Qwen3.6: Cấu hình và Tối ưu hóa

Ban đầu, Claude Code được kết nối với một mô hình chạy cục bộ trên laptop. Tôi cung cấp một sự cố Kubernetes để điều tra, nhưng sau mười phút, Claude Code bị hết thời gian chờ (timeout) mà không đưa ra kết quả nào. Mô hình không sử dụng bất kỳ công cụ tích hợp nào; nó dành toàn bộ thời gian cho phép để "suy nghĩ".

Nó tải được, nhưng chưa hoạt động.

Sau bốn lần sửa đổi, cùng một chiếc laptop đó đã thực hiện từ việc điều tra sự cố đến việc mở một pull request — tìm ra nguyên nhân gốc rễ, viết bản vá, đẩy nhánh, và tạo PR thông qua gh — mà không có bất kỳ dữ liệu nào rời khỏi máy. Nó mất thời gian, nhưng nó đã hoàn thành vòng lặp. Khoảng cách giữa "tải được" và "hoạt động được" chính là bốn bản sửa lỗi đó. Một khi vượt qua chúng, yếu tố quyết định sự khác biệt giữa một phiên làm việc kéo dài 34 phút và một phiên nhanh chóng chính là phần cứng, không phải phương pháp tiếp cận.

Tại sao cần chạy nội bộ (Local)?

Có một lý do quan trọng nhất: dữ liệu không được phép vượt qua tường lửa. Trong các môi trường được kiểm soát nghiêm ngặt và các cụm máy tách mạng (air-gapped), việc chạy nội bộ không phải là sở thích mà là yêu cầu bắt buộc. Tin tốt là: nó hoạt động được.

Đối với những người khác, việc chạy nội bộ mang lại sự riêng tư và chi phí cố định. Bạn phải trả bằng độ trễ và một mô hình nhỏ hơn các phiên bản tiên tiến nhất — nhưng, như vòng lặp hoàn thành ở trên cho thấy, khả năng thực hiện nhiệm vụ không phải là thứ bạn phải đánh đổi. Tốc độ mới là thứ bạn đánh đổi.

Cấu hình hệ thống (The Stack)

Trước hết, hãy xác định cấu hình máy. Tất cả các con số phụ thuộc vào điều này.

Phần cứng: Apple M3 Pro, 18 nhân GPU, 36 GiB bộ nhớ thống nhất (unified memory), băng thông bộ nhớ ~150 GB/s.

Mô hình: qwen3.6:35b-a3b-coding-nvfp4 — 35.1 tỷ tham số, kiến trúc Mixture-of-Experts (MoE) với ~3 tỷ tham số hoạt động cho mỗi token, lượng tử hóa NVFP4. Dung lượng đĩa 21 GB, chiếm khoảng 20 GiB RAM khi đã tải.

Runtime: Ollama 0.24.0, sử dụng MLX runner (backend riêng cho Apple Silicon, không phải đường dẫn llama.cpp/Metal).

Client: Claude Code v2.1.84, trỏ về endpoint Ollama cục bộ.

Kiến trúc MoE cho phép một mô hình 35B chạy cục bộ. Chỉ có khoảng 3B tham số hoạt động mỗi token, nên chi phí tính toán tương đương với mô hình dày đặc 14B, trong khi câu trả lời lại tiệm cận mức 35B. Một mô hình dày đặc 35B sẽ không vừa với 36 GiB RAM.

Môi trường đã được tinh chỉnh:

  • OLLAMA_MLX=1: Sử dụng MLX runner của Apple Silicon.
  • OLLAMA_CONTEXT_LENGTH=32768: Dung lượng bộ nhớ cho phép.
  • OLLAMA_FLASH_ATTENTION=1: Giảm bộ nhớ cho cơ chế attention.
  • OLLAMA_MULTIUSER_CACHE=1: Tái sử dụng bộ nhớ đệm tiền tố (prefix cache) giữa các yêu cầu.
  • OLLAMA_KEEP_ALIVE=24h: Giữ mô hình 20 GiB nằm trong RAM; việc tải lại rất chậm.

Từ con số 0 đến phiên làm việc hoạt động

Giả sử bạn đang sử dụng Apple Silicon và kubectl đã được trỏ đến cụm của bạn.

  1. Cài đặt Ollama, xác nhận phiên bản. Phải là 0.24.0 hoặc mới hơn (xem bản sửa #2).

  2. Tải mô hình. Một lần, khoảng 21 GB.

    ollama pull qwen3.6:35b-a3b-coding-nvfp4
    
  3. Chạy server với môi trường tinh chỉnh. Để nó chạy nền.

    OLLAMA_MLX=1 \
    OLLAMA_CONTEXT_LENGTH=32768 \
    OLLAMA_FLASH_ATTENTION=1 \
    OLLAMA_MULTIUSER_CACHE=1 \
    OLLAMA_KEEP_ALIVE=24h \
    OLLAMA_NO_CLOUD=1 \
    ollama serve
    
  4. Trỏ Claude Code về mô hình cục bộ và khởi chạy từ thư mục làm việc:

    ANTHROPIC_BASE_URL=http://localhost:11434 \
    MAX_THINKING_TOKENS=0 \
    claude --model qwen3.6:35b-a3b-coding-nvfp4
    

    Không có ANTHROPIC_API_KEY trong môi trường — việc thiếu key này khiến Claude Code sử dụng endpoint cục bộ thay vì liên hệ dịch vụ đám mây của Anthropic.

  5. Lệnh nhắc đầu tiên — một bài kiểm tra khói (smoke test), không phải màn trình diễn chính. Hãy chọn điều gì đó đơn giản buộc phải gọi đúng một công cụ:

    "Chạy kubectl get pods -A và cho tôi biết có anything nào có vẻ không khỏe không."

    Bạn sẽ thấy: cuộc gọi công cụ đầu tiên diễn ra trong vài giây, sau đó bạn có thể phải đợi khoảng 60 giây trong khi mô hình thực hiện quá trình prefill (nạp dữ liệu đầu vào như lời nhắc và ngữ cảnh vào bộ nhớ). Các phiên sau đó sẽ nhanh hơn nhờ bộ nhớ đệm tiền tố lưu trữ các phần tĩnh của lời nhắc.

  6. Xác nhận không có dữ liệu nào rời khỏi máy. Server in ra "Ollama cloud disabled: true" khi khởi động; base URL là localhost, và không có API key nào được thiết lập. Lưu lượng truy cập duy nhất là loopback.

Bốn bản sửa lỗi khiến nó hoạt động

Đây là những bản sửa lỗi khiến thiết lập này hoạt động. Bỏ qua chúng và hệ thống sẽ bị tắc nghẽn. Tất cả đều là vấn đề phần mềm, không phải phần cứng.

1. Tắt suy luận (Thinking) — Nó tiêu tốn toàn bộ ngân sách để lý luận

Qwen3.6 là một mô hình lý luận. Mặc định, tính năng "thinking" của Claude Code được bật khiến lượt đầu tiên tiêu tốn toàn toàn ngân sách cho một chuỗi suy luận không giới hạn. Với tốc độ ~5–8 token/giây, nó cứ suy luận mãi cho đến khi hết giờ của Claude Code. Kết quả: 10 phút đầu tiên vô ích.

Bản sửa là một biến môi trường: MAX_THINKING_TOKENS=0. Một bài kiểm tra so sánh cho thấy quy mô: cùng một câu hỏi "2+2 bằng mấy" tốn 128 token suy luận và 6.7 giây khi bật tính năng này, so với 1 token và 0.6 giây khi tắt.

2. Bạn cần Ollama 0.24, không phải 0.20

Việc cố gắng nhúng cài đặt vào Modelfile không hoạt động cho mô hình này trong Ollama 0.20. Lệnh ollama create từ cơ sở MLX dường như thành công, nhưng API trả về "model not found". Các dẫn xuất GGUF hoạt động, nhưng MLX thất bại.

Vấn đề này đã được sửa trong 0.24.0, phiên bản dọn dẹp việc tạo mô hình safetensor MLX và định tuyến tham số think đúng cách qua API tương thích OpenAI.

3. MLX runner bỏ qua template Modelfile của bạn

Ngay cả trên phiên bản 0.24, việc tắt suy luận thông qua Modelfile thất bại âm thầm. MLX runner sử dụng trình kết xuất và trình phân tích cú pháp riêng của nó (qwen3.5), ghi đè template của bạn. Bài học lớn hơn là: các công cụ tinh chỉnh từ thời llama.cpp không chuyển sang đường dẫn MLX. Hãy kiểm soát suy luận bằng tham số API think:false hoặc MAX_THINKING_TOKENS=0.

4. Bỏ qua cơn bão 404

Khi chạy, nhật ký sẽ hiển thị các đợt 18+ cuộc gọi thất bại tới /v1/messages/v1/messages/count_tokens cho mỗi yêu cầu. Claude Code thăm dò các endpoint gốc của Anthropic mà Ollama không xử lý. Những lỗi 404 này rất nhanh và không thay đổi gì. Hãy bỏ qua chúng.

Tốc độ do phần cứng quyết định

Với các bản sửa lỗi này, hệ thống hoạt động. Điều quan trọng bây giờ là phần cứng của bạn.

Phiên làm việc bị giới hạn bởi tốc độ prefill. Mỗi lượt tương tác đều phải đọc lại lời nhắc — lời nhắc hệ thống của Claude Code, định nghĩa công cụ, tệp CLAUDE.md và cuộc trò chuyện cho đến thời điểm đó — trước khi tạo ra token. Trên phần cứng này (M3 Pro 36GB), việc nạp 25K token mất 60–70 giây, và prefill chiếm hơn 90% thời gian yêu cầu.

Tốc độ prefill được thiết lập bởi băng thông bộ nhớ đối với một mô hình 20 GiB, và mức ~150 GB/s của M3 Pro là mức sàn. Apple Silicon có băng thông cao hơn — các dòng Max và Ultra — sẽ nâng trần này trực tiếp, vì nút thắt cổ chai chính là băng thông.

Cửa sổ ngữ cảnh 32K — và những gì thêm bộ nhớ mang lại

Cửa sổ ngữ cảnh là 32.000 token. Đây không phải là lựa chọn theo sở thích, mà là dựa trên những gì vừa với bộ nhớ. Ollama đặt cửa sổ ngữ cảnh mặc định dựa trên bộ nhớ GPU được phát hiện. Trong trường hợp này, máy có 24–48 GiB bộ nhớ thường nhận được cửa sổ 32.000 token.

Kích thước cửa sổ rất quan trọng vì công việc SRE thực tế thường không tôn trọng một cửa sổ nhỏ. Một phiên tác nhân (agentic) điều tra và chỉnh sửa tệp sẽ nhanh chóng xây dựng ngữ cảnh. Một phiên như vậy trên laptop này đã đẩy cuộc trò chuyện lên tới ~56K token — vượt quá cửa sổ 32K — và runtime đã phải thực hiện việc loại bỏ và xử lý lại (evict and reprocess).

Trên 36 GiB, quy tắc là: giữ phiên làm việc trong phạm vi, nằm trong 32K, và chạy sạch sẽ; nếu lan rộng quá mức, bạn sẽ cảm nhận ngay lập tức sự "giật cục" của bộ nhớ. Trên một máy có đủ dung lượng cho cửa sổ 256K, quy tắc này gần như không còn tồn tại.

Điều gì tồn tại, điều gì được nâng cấp, và bài viết này dành cho ai

Được nâng cấp nhờ phần cứng:

  • Tốc độ prefill — giới hạn bởi băng thông; Max/Ultra/silicon mới hơn sẽ tăng tốc.
  • Cửa sổ ngữ cảnh — 32K trên 36–48 GiB trở thành 256K ở mức 64 GiB+.
  • Áp lực bộ nhớ — các đỉnh 93% biến mất với dư địa; biến mất ở mức 48 GiB.

Tồn tại bất kể phần cứng:

  • Việc chặn suy luận vẫn mong manh — hãy tính toán cho các suy luận lạc đường ngay cả khi đã đặt cờ.
  • MLX phá vỡ thói quen llama.cpp — các mẹo Modelfile và template không được chuyển sang.

Ai nên chạy thiết lập này:

  • Bất kỳ ai sở hữu Mac Apple Silicon với ~48 GiB RAM trở lên. Nó chạy thoải mái — bạn có một Claude Code nội bộ hoàn chỉnh hoạt động trơn tru.
  • Các đội ngũ nhạy cảm với việc dữ liệu rời khỏi tường lửa. Nếu dữ liệu cụm và mã nguồn không được phép vượt qua biên giới — vì quy định, hợp đồng, hoặc chính sách — đây là giải pháp, và nó hoạt động hiệu quả.
Chia sẻ:FacebookX
Nội dung tổng hợp bằng AI, mang tính tham khảo. Xem bài gốc ↗