Trung cấpKỹ thuậtClaude APINguồn: Anthropic

Vượt giới hạn max_tokens — Kỹ thuật tiếp nối response dài

Nghe bài viết
00:00

Điểm nổi bật

Nhấn để đến mục tương ứng

  1. 1 Tận dụng Claude hiệu quả: import anthropic client = anthropic.Anthropic response = client.messages.create model="claude-opus-4-5", maxtokens=100, — mẹo quan trọng là cung cấp đủ ngữ cảnh để AI trả về kết quả chính xác hơn 80% so với prompt chung chung.
  2. 2 Một điều ít người đề cập: Ý tưởng: khi phát hiện maxtokens , append response cũ vào messages và gọi API lại, yêu cầu Claude tiếp tục từ chỗ dở:. Hiểu rõ bối cảnh áp dụng sẽ quyết định 80% thành công khi triển khai.
  3. 3 Giá trị cốt lõi: Cải thiện: def smartcontinuation messages: list, systemprompt: str = "", maxtokenspercall: int = 4096,. Đầu tư 15-30 phút học phần này sẽ giúp bạn tiết kiệm hàng giờ trong công việc hàng ngày.
  4. 4 Bước đầu tiên bạn nên làm: def generatelongcodespec: str, language: str = "Python" -> str: """ Generate code dài với continuation, đảm bảo. Áp dụng đúng cách sẽ thấy kết quả rõ rệt từ tuần đầu tiên.
  5. 5 Thành thật mà nói: Tính chi phí continuation Mỗi lần continuation, bạn phải gửi lại toàn bộ history input tokens tăng dần: def. Phương pháp này hiệu quả trong hầu hết trường hợp, nhưng bạn cần điều chỉnh cho phù hợp ngữ cảnh riêng.
the word ai spelled in white letters on a black surface

Claude có context window 200k tokens nhưng max_tokens trong mỗi API call bị giới hạn (thường 4.096 đến 8.192). Khi bạn yêu cầu viết một bài viết dài, generate code phức tạp, hay tạo báo cáo chi tiết, response có thể bị cắt giữa chừng. Bài này hướng dẫn kỹ thuật continuation loop để nhận toàn bộ output.

Vấn đề: stop_reason = "max_tokens"

import anthropic

client = anthropic.Anthropic()

response = client.messages.create(
    model="claude-opus-4-5",
    max_tokens=100,  # Cố ý đặt thấp để demo
    messages=[{
        "role": "user",
        "content": "Viết một bài viết 1000 từ về lịch sử Việt Nam."
    }],
)

print(f"stop_reason: {response.stop_reason}")
print(f"Content: {response.content[0].text[:200]}...")

# Output:
# stop_reason: max_tokens  ← Response bị cắt!
# Content: Việt Nam là một quốc gia có lịch sử hàng nghìn năm...

Khi stop_reason == "max_tokens", có nghĩa là Claude chưa hoàn thành — response bị cắt cứng tại giới hạn token. Khác với stop_reason == "end_turn" nghĩa là Claude đã hoàn thành tự nhiên.

Giải pháp: Continuation Loop

Ý tưởng: khi phát hiện max_tokens, append response cũ vào messages và gọi API lại, yêu cầu Claude tiếp tục từ chỗ dở:

def generate_with_continuation(
    messages: list,
    system_prompt: str = "",
    max_tokens_per_call: int = 4096,
    max_continuations: int = 10,
    model: str = "claude-opus-4-5",
) -> dict:
    """
    Generate response dài bằng cách tự động tiếp tục khi bị cắt.

    Returns:
        dict với keys: full_text, total_tokens, continuation_count, completed
    """
    full_text = ""
    total_input_tokens = 0
    total_output_tokens = 0
    continuation_count = 0
    current_messages = messages.copy()

    while continuation_count <= max_continuations:
        response = client.messages.create(
            model=model,
            max_tokens=max_tokens_per_call,
            system=system_prompt,
            messages=current_messages,
        )

        # Cộng dồn token usage
        total_input_tokens += response.usage.input_tokens
        total_output_tokens += response.usage.output_tokens

        # Lấy text từ response
        chunk = response.content[0].text
        full_text += chunk

        print(f"  Chunk {continuation_count + 1}: {len(chunk)} chars, "
              f"stop_reason={response.stop_reason}")

        # Kiểm tra điều kiện dừng
        if response.stop_reason == "end_turn":
            # Claude hoàn thành tự nhiên
            print(f"  Completed after {continuation_count} continuations!")
            return {
                "full_text": full_text,
                "total_input_tokens": total_input_tokens,
                "total_output_tokens": total_output_tokens,
                "continuation_count": continuation_count,
                "completed": True,
            }

        elif response.stop_reason == "max_tokens":
            # Bị cắt — cần tiếp tục
            continuation_count += 1

            if continuation_count > max_continuations:
                print(f"  Reached max continuations ({max_continuations})")
                break

            # Thêm response vừa nhận vào messages
            current_messages.append({
                "role": "assistant",
                "content": chunk
            })

            # Thêm lời nhắc tiếp tục
            current_messages.append({
                "role": "user",
                "content": "Tiếp tục."
            })

        else:
            # stop_reason khác (stop_sequence, v.v.)
            print(f"  Stopped with reason: {response.stop_reason}")
            break

    return {
        "full_text": full_text,
        "total_input_tokens": total_input_tokens,
        "total_output_tokens": total_output_tokens,
        "continuation_count": continuation_count,
        "completed": False,
    }

# Test
print("Generating long article...")
result = generate_with_continuation(
    messages=[{
        "role": "user",
        "content": "Viết bài viết đầy đủ về lịch sử lập trình từ 1940 đến nay, bao gồm các ngôn ngữ lập trình quan trọng và milestone lớn."
    }],
    system_prompt="Viết văn tiếng Việt rõ ràng, súc tích. QUAN TRỌNG: Không dùng dấu chấm lửng (...) khi kết thúc câu. Hoàn thành đầy đủ mọi ý tưởng.",
    max_tokens_per_call=2048,
    max_continuations=5,
)

print(f"
=== KẾT QUẢ ===")
print(f"Hoàn thành: {result['completed']}")
print(f"Số lần tiếp tục: {result['continuation_count']}")
print(f"Tổng output: {len(result['full_text'])} chars")
print(f"Tổng tokens: {result['total_input_tokens']} in + {result['total_output_tokens']} out")
print(f"
Nội dung:
{result['full_text'][:500]}...")

Vấn đề: Seamless Continuation

Kỹ thuật "Tiếp tục." đơn giản đôi khi tạo ra seam (chỗ nối lộ liễu). Claude có thể thêm "Như tôi đã đề cập..." hoặc bắt đầu đoạn mới không tự nhiên. Cải thiện:

def smart_continuation(
    messages: list,
    system_prompt: str = "",
    max_tokens_per_call: int = 4096,
    max_continuations: int = 10,
    model: str = "claude-opus-4-5",
) -> dict:
    """
    Continuation thông minh hơn: prefill với ký tự cuối để seamless.
    """
    full_text = ""
    total_input_tokens = 0
    total_output_tokens = 0
    continuation_count = 0
    current_messages = messages.copy()

    while continuation_count <= max_continuations:
        response = client.messages.create(
            model=model,
            max_tokens=max_tokens_per_call,
            system=system_prompt,
            messages=current_messages,
        )

        total_input_tokens += response.usage.input_tokens
        total_output_tokens += response.usage.output_tokens
        chunk = response.content[0].text
        full_text += chunk

        if response.stop_reason != "max_tokens":
            return {
                "full_text": full_text,
                "total_input_tokens": total_input_tokens,
                "total_output_tokens": total_output_tokens,
                "continuation_count": continuation_count,
                "completed": response.stop_reason == "end_turn",
            }

        continuation_count += 1
        if continuation_count > max_continuations:
            break

        # Lấy vài từ cuối để continuity
        last_words = chunk[-50:] if len(chunk) > 50 else chunk

        # Thêm vào messages và prefill với đoạn cuối
        current_messages.append({"role": "assistant", "content": chunk})
        current_messages.append({
            "role": "user",
            "content": "Tiếp tục viết từ chỗ vừa dừng, không cần nhắc lại nội dung trước."
        })

        print(f"  Continuation {continuation_count} (last: '...{last_words.strip()}')")

    return {
        "full_text": full_text,
        "total_input_tokens": total_input_tokens,
        "total_output_tokens": total_output_tokens,
        "continuation_count": continuation_count,
        "completed": False,
    }

Streaming với Continuation

def stream_with_continuation(
    messages: list,
    system_prompt: str = "",
    max_tokens_per_call: int = 4096,
    max_continuations: int = 10,
) -> str:
    """Stream response với auto-continuation."""
    full_text = ""
    current_messages = messages.copy()
    continuation_count = 0

    while continuation_count <= max_continuations:
        chunk_text = ""

        with client.messages.stream(
            model="claude-opus-4-5",
            max_tokens=max_tokens_per_call,
            system=system_prompt,
            messages=current_messages,
        ) as stream:
            for text in stream.text_stream:
                print(text, end="", flush=True)
                chunk_text += text

            final_message = stream.get_final_message()
            stop_reason = final_message.stop_reason

        full_text += chunk_text

        if stop_reason != "max_tokens":
            break

        continuation_count += 1
        if continuation_count > max_continuations:
            break

        current_messages.append({"role": "assistant", "content": chunk_text})
        current_messages.append({
            "role": "user",
            "content": "Tiếp tục."
        })
        print()  # Newline giữa các chunks khi streaming

    print()  # Final newline
    return full_text

Xử lý code generation dài

def generate_long_code(spec: str, language: str = "Python") -> str:
    """
    Generate code dài với continuation, đảm bảo syntax đúng.
    """
    system = f"""Bạn là senior {language} developer.
Viết code đầy đủ, production-ready, có comments.
QUAN TRỌNG: Khi bị interrupt giữa chừng, hãy hoàn thành block code hiện tại trước.
Không để code bị cắt giữa function hay class."""

    result = generate_with_continuation(
        messages=[{
            "role": "user",
            "content": f"Viết {language} code đầy đủ cho: {spec}"
        }],
        system_prompt=system,
        max_tokens_per_call=4096,
        max_continuations=8,
    )

    # Validate code đủ không
    code = result["full_text"]

    # Kiểm tra các dấu hiệu code bị cắt
    incomplete_markers = ["...", "# TODO: Continue", "# ..."]
    has_incomplete = any(m in code for m in incomplete_markers)

    if not result["completed"]:
        print("WARNING: Code có thể chưa hoàn chỉnh")
    if has_incomplete:
        print("WARNING: Phát hiện dấu hiệu code bị cắt")

    return code

# Generate REST API
api_code = generate_long_code(
    "REST API cho e-commerce với FastAPI: endpoints cho products, orders, users. Bao gồm models, routers, và database operations.",
    language="Python"
)

Tips quan trọng

Tính chi phí continuation

Mỗi lần continuation, bạn phải gửi lại toàn bộ history (input tokens tăng dần):

def estimate_continuation_cost(
    initial_input_tokens: int,
    avg_output_per_call: int,
    n_continuations: int,
    input_price_per_mtok: float = 3.0,
    output_price_per_mtok: float = 15.0,
) -> dict:
    """Ước tính chi phí cho n continuations."""
    total_input = 0
    total_output = 0

    for i in range(n_continuations + 1):
        # Input tăng dần vì phải gửi lại history
        input_tokens = initial_input_tokens + i * avg_output_per_call
        total_input += input_tokens
        total_output += avg_output_per_call

    cost_input = (total_input / 1_000_000) * input_price_per_mtok
    cost_output = (total_output / 1_000_000) * output_price_per_mtok

    return {
        "total_input_tokens": total_input,
        "total_output_tokens": total_output,
        "estimated_cost_usd": cost_input + cost_output,
    }

# Ví dụ: 5 continuations, mỗi call output 2000 tokens
cost = estimate_continuation_cost(
    initial_input_tokens=1000,
    avg_output_per_call=2000,
    n_continuations=5,
)
print(f"Estimated cost: ${cost['estimated_cost_usd']:.4f}")
print(f"Total tokens: {cost['total_input_tokens'] + cost['total_output_tokens']:,}")

Khi nào không nên dùng continuation?

  • Thay vào đó: Dùng max_tokens lớn hơn ngay từ đầu (claude-opus-4-5 hỗ trợ 8.192)
  • Chia task: Thay vì viết "bài 5000 từ", chia thành 5 sections riêng biệt
  • Summarize thay vì expand: Đôi khi response ngắn hơn mà vẫn đủ thông tin

Kết hợp với Streaming

Để UX tốt nhất trong production, kết hợp streaming + continuation:

  1. Stream response trong real-time để user thấy ngay
  2. Detect max_tokens ở cuối stream
  3. Tự động request continuation (có thể show spinner nhỏ)
  4. Continue streaming từ continuation response

Kỹ thuật continuation là building block quan trọng cho mọi ứng dụng cần output dài — từ code generators đến report writers. Kết hợp với Prompt Caching để giảm chi phí input tokens tăng dần trong mỗi continuation call.

Tính năng liên quan:Long OutputContinuationAPIToken Management

Bai viet co huu ich khong?

Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.

Bình luận (0)
Ảnh đại diện
Đăng nhập để bình luận...
Đăng nhập để bình luận
  • Đang tải bình luận...

Đăng ký nhận bản tin

Nhận bài viết hay nhất về sản phẩm và vận hành, gửi thẳng vào hộp thư của bạn.

Bảo mật thông tin. Hủy đăng ký bất cứ lúc nào. Chính sách bảo mật.