0Pricing
AI Engineering Academy · บทเรียน

ลูปการเรียกใช้โค้ด

ออกแบบลูปเขียน-เรียกใช้-สังเกต โดยเอเจนต์สร้างโค้ด ตัวเรียกใช้ในสภาพแวดล้อมแยกทำงาน โพรเซส stdout และ stderr ถูกดักจับแล้วส่งกลับเป็นข้อมูลสังเกต และเอเจนต์แก้ไขข้อผิดพลาด

ลูปการเรียกใช้โค้ด เป็นบทเรียน AI Engineering Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Engineering Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

เอเจนต์โค้ด: การเขียนและเรียกใช้โค้ด

เอเจนต์ดำเนินการโค้ด เป็นเอเจนต์ AI ประเภทพิเศษที่แก้ปัญหาด้วยการเขียนโค้ด เรียกใช้โค้ด สังเกตผลลัพธ์ และปรับแก้ซ้ำจนงานเสร็จสมบูรณ์ ต่างจากเอเจนต์ที่ใช้เฉพาะเครื่องมือที่กำหนดไว้ล่วงหน้า เอเจนต์โค้ดสามารถสร้างเครื่องมือคำนวณใหม่ได้ทันที จึงมีความยืดหยุ่นอย่างมาก: งานใดก็ตามที่เขียนโปรแกรมได้ เอเจนต์โค้ดก็สามารถลองทำได้

วงจรเขียน-เรียกใช้-สังเกต

แก่นหลักของเอเจนต์ดำเนินการโค้ดคือวงจรที่มีสามขั้นตอน: เขียน — LLM สร้างโค้ด Python เพื่อแก้ขั้นตอนปัจจุบันของงาน เรียกใช้ — โค้ดทำงานในสภาพแวดล้อมแบบแซนด์บ็อกซ์ และมีการเก็บ stdout/stderr ไว้ สังเกต — ส่งผลลัพธ์การทำงานกลับไปยัง LLM ในฐานะการสังเกตใหม่ ซึ่ง LLM ใช้ตัดสินใจว่าจะเขียนอะไรต่อ วงจรนี้จะดำเนินต่อจนงานเสร็จสมบูรณ์หรือถึงขีดจำกัดจำนวนรอบ

def code_execution_loop(task: str, max_iterations=10):
    messages = [
        {'role': 'system', 'content': 'You are a Python coding agent. Write code to solve tasks step by step.'},
        {'role': 'user', 'content': task}
    ]
    
    for i in range(max_iterations):
        # WRITE: LLM generates code
        response = llm.complete(messages)
        code = extract_code_block(response)
        
        if not code:
            return response  # LLM gave a final answer without code
        
        # EXECUTE: run the code
        output, error = execute_safely(code)
        
        # OBSERVE: feed output back
        observation = f'Output:\n{output}' if not error else f'Error:\n{error}'
        messages.append({'role': 'assistant', 'content': response})
        messages.append({'role': 'user', 'content': observation})
    
    return 'Max iterations reached'

การแยกบล็อกโค้ดจากผลลัพธ์ของ LLM

โดยทั่วไป LLM จะครอบโค้ดที่สร้างขึ้นด้วยบล็อกโค้ดแบบมีรั้วของมาร์กดาวน์: ```python ... ``` วงจรการดำเนินการของคุณต้อง แยกโค้ด ออกจากบล็อกเหล่านี้อย่างน่าเชื่อถือก่อนเรียกใช้ ใช้นิพจน์ทั่วไปหรือตัวแยกวิเคราะห์แบบง่ายเพื่อค้นหาบล็อกที่มีรั้ว และจัดการกรณีปลายต่าง ๆ เช่น แบ็กทิกซ้อนกัน มีหลายบล็อกในคำตอบเดียว หรือมีโค้ดที่ไม่ระบุตัวระบุภาษา

import re

def extract_code_block(response: str) -> str | None:
    # Match ```python ... ``` or ``` ... ```
    pattern = r'```(?:python)?\n(.*?)```'
    matches = re.findall(pattern, response, re.DOTALL)
    if not matches:
        return None
    # Return the LAST code block (often the most complete version)
    return matches[-1].strip()

# Test
sample_response = '''I will calculate the sum:\n\n```python\nnumbers = [1, 2, 3, 4, 5]\nprint(sum(numbers))\n```'''
code = extract_code_block(sample_response)
print(repr(code))  # 'numbers = [1, 2, 3, 4, 5]\nprint(sum(numbers))'

การเก็บ stdout และ stderr

เมื่อเรียกใช้โค้ดที่เอเจนต์สร้างขึ้น คุณต้องเก็บทั้ง stdout (ผลลัพธ์ปกติ) และ stderr (ข้อความข้อผิดพลาดและร่องรอยการเรียกใช้) เพื่อส่งกลับไปยัง LLM วิธีที่ง่ายที่สุดคือใช้มอดูล subprocess ของ Python โดยเรียกใช้โค้ดเป็นกระบวนการแยกและเก็บสตรีมทั้งสอง กำหนดระยะหมดเวลาเพื่อป้องกันไม่ให้โค้ดที่ค้างขัดขวางการทำงานของเอเจนต์

import subprocess
import tempfile
import os

def execute_code(code: str, timeout_seconds=30) -> tuple[str, str]:
    # Write code to a temp file
    with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
        f.write(code)
        tmp_path = f.name
    
    try:
        result = subprocess.run(
            ['python', tmp_path],
            capture_output=True,
            text=True,
            timeout=timeout_seconds
        )
        stdout = result.stdout[:5000]  # cap output length
        stderr = result.stderr[:2000]  # cap error length
        return stdout, stderr
    except subprocess.TimeoutExpired:
        return '', f'TimeoutError: code exceeded {timeout_seconds}s limit'
    finally:
        os.unlink(tmp_path)  # always clean up temp file

การจัดการข้อผิดพลาดอย่างชาญฉลาด

เมื่อโค้ดทำให้เกิดข้อผิดพลาด ข้อความข้อผิดพลาด (ร่องรอยการเรียกใช้ ชนิดข้อยกเว้น หมายเลขบรรทัด) จะถูกส่งกลับไปยัง LLM ในฐานะการสังเกต จากนั้น LLM จะวิเคราะห์ข้อผิดพลาดและเขียนโค้ดที่แก้ไขแล้ว เพื่อช่วยให้ LLM แก้ไขข้อผิดพลาดได้อย่างมีประสิทธิภาพ ให้ใส่ ข้อความข้อผิดพลาดที่ตรงตามจริง ในการสังเกต ระบุ บรรทัดโค้ดที่ทำให้เกิดข้อผิดพลาด และขอให้ LLM แก้ไขอย่างชัดเจนก่อนลองอีกครั้ง

def format_error_observation(code: str, error: str) -> str:
    lines = code.split('\n')
    
    # Extract line number from traceback if available
    line_match = re.search(r'line (\d+)', error)
    error_context = ''
    if line_match:
        line_num = int(line_match.group(1))
        if 1 <= line_num <= len(lines):
            error_context = f'\nFailing line: {lines[line_num - 1].strip()}'
    
    return f'''Execution failed with error:{error_context}\n\n{error}\n\nPlease analyze the error and write corrected code.'''

# Usage in loop
output, err = execute_code(code)
if err:
    observation = format_error_observation(code, err)
else:
    observation = f'Output:\n{output}\n\nContinue with the next step or provide the final answer.'

การตรวจจับว่างานเสร็จสมบูรณ์

วงจรการดำเนินการโค้ดต้องทราบว่าเมื่อใดควร หยุด สัญญาณทั่วไปที่บ่งบอกว่างานเสร็จ ได้แก่ LLM ส่งคำตอบที่ไม่มีบล็อกโค้ด (มีเพียงคำตอบภาษาธรรมชาติ) LLM เขียนเครื่องหมายพิเศษ เช่น # TASK_COMPLETE โค้ดสร้างไฟล์ผลลัพธ์ที่เอเจนต์ได้รับคำสั่งให้สร้าง หรือฟังก์ชันตรวจสอบยืนยันว่าผลลัพธ์ตรงตามเกณฑ์ความสำเร็จ ควรกำหนดขีดจำกัดจำนวนรอบไว้เป็นทางเลือกสำรองเสมอ

COMPLETION_MARKERS = ['TASK COMPLETE', 'FINAL ANSWER:', 'DONE:']

def is_task_complete(response: str, code: str | None, output: str, success_fn=None) -> bool:
    # Check for explicit completion markers
    for marker in COMPLETION_MARKERS:
        if marker in response.upper():
            return True
    
    # No code generated - LLM is done
    if code is None:
        return True
    
    # Custom success function (e.g., check output file exists)
    if success_fn and success_fn(output):
        return True
    
    return False

# Example success function
def report_was_generated(output: str) -> bool:
    import os
    return os.path.exists('analysis_report.pdf')

การส่งข้อมูลระหว่างรอบการทำงาน

ความท้าทายประการหนึ่งของวงจรการดำเนินการโค้ดคือ การคงอยู่ของสถานะ ระหว่างรอบการทำงาน แต่ละบล็อกโค้ดจะทำงานในกระบวนการ Python ใหม่ ดังนั้นตัวแปรที่กำหนดไว้ในรอบหนึ่งจะไม่พร้อมใช้งานในรอบถัดไป วิธีแก้ ได้แก่ การเขียนข้อมูลระหว่างทางลงไฟล์ การใช้กระบวนการถาวรที่แทรกโค้ดผ่าน exec() หรือการสั่งให้ LLM กำหนดตัวแปรที่จำเป็นใหม่อย่างชัดเจนที่จุดเริ่มต้นของแต่ละบล็อกโค้ด

# Strategy 1: Save to files between iterations
# Iteration 1: LLM writes
'''
import pandas as pd
df = pd.read_csv('data.csv')
df_cleaned = df.dropna()
df_cleaned.to_parquet('cleaned.parquet')  # save for next iteration
print('Cleaned rows:', len(df_cleaned))
'''

# Iteration 2: LLM reads previous output
'''
import pandas as pd
df = pd.read_parquet('cleaned.parquet')  # reload from file
result = df.groupby('category').sum()
result.to_csv('result.csv')
print(result.head())
'''

การจัดโครงสร้างพรอมต์ระบบ

พรอมต์ระบบสำหรับเอเจนต์ดำเนินการโค้ดต้องสอน LLM ให้ใช้วงจรอย่างมีประสิทธิภาพ องค์ประกอบสำคัญที่ควรระบุ ได้แก่ วิธีเขียนบล็อกโค้ด Python ที่เรียกใช้ได้ วิธีตรวจสอบผลลัพธ์ระหว่างทางก่อนดำเนินการต่อ วิธีส่งสัญญาณว่างานเสร็จสมบูรณ์ ไลบรารีใดบ้างที่พร้อมใช้งานในแซนด์บ็อกซ์ และเส้นทางไฟล์ใดบ้างที่เอเจนต์ได้รับอนุญาตให้อ่านและเขียน

CODE_AGENT_SYSTEM_PROMPT = '''
You are a Python code execution agent. Solve tasks by writing and running code.

Rules:
1. Write ALL code inside ```python ... ``` blocks.
2. Write small, testable code blocks - do not try to do everything in one block.
3. When you see execution output, analyze it and decide whether to continue or fix errors.
4. Available libraries: pandas, numpy, matplotlib, requests, json, os, pathlib.
5. You can read/write files only in /workspace/ directory.
6. When the task is fully complete, say TASK COMPLETE and summarize the result.
7. If you are stuck after 3 attempts at the same error, say ESCALATE and explain the problem.
'''

การตัดทอนผลลัพธ์และการจัดการโทเค็น

โค้ดที่เอเจนต์สร้างขึ้นอาจสร้างผลลัพธ์จำนวนมหาศาล เช่น ผลการพิมพ์ DataFrame รายการยาว หรือบันทึกจำนวนมาก การส่งผลลัพธ์ทั้งหมดกลับไปยัง LLM ทำให้สิ้นเปลืองโทเค็นและอาจเกินขนาดหน้าต่างบริบท ควร ตัดทอนผลลัพธ์การทำงาน ก่อนเพิ่มลงในการสนทนาเสมอ ค่าตั้งต้นที่เหมาะสมคือ 2000-5000 อักขระ พร้อมหมายเหตุว่าผลลัพธ์ถูกตัดทอนแล้ว เพื่อให้ LLM ทราบว่าอาจยังมีข้อมูลให้สำรวจเพิ่มเติม

MAX_OUTPUT_CHARS = 3000

def format_observation(stdout: str, stderr: str) -> str:
    if stderr:
        # Errors take priority - show full error
        return f'Error:\n{stderr[:MAX_OUTPUT_CHARS]}'
    
    if len(stdout) > MAX_OUTPUT_CHARS:
        truncated = stdout[:MAX_OUTPUT_CHARS]
        remaining = len(stdout) - MAX_OUTPUT_CHARS
        return f'{truncated}\n... [output truncated, {remaining} more characters]'
    
    return f'Output:\n{stdout}' if stdout else 'Code executed successfully (no output)'

วงจรโค้ดในการใช้งานจริง

เอเจนต์ดำเนินการโค้ดสำหรับการวิเคราะห์ข้อมูลจริงอาจทำงาน 5-15 รอบเพื่อโหลด CSV สำรวจโครงสร้าง ทำความสะอาดข้อมูล คำนวณสถิติ สร้างแผนภูมิ และจัดทำรายงานสรุป แต่ละรอบต่อยอดจากรอบก่อนหน้า โดย LLM ปรับแนวทางตามค่าข้อมูลจริงและรูปร่างของข้อมูลที่ค้นพบขณะทำงาน การปรับเปลี่ยนแบบไดนามิกนี้เองที่ทำให้เอเจนต์โค้ดมีประสิทธิภาพอย่างมากสำหรับงานเชิงสำรวจ

ข้อควรพิจารณาด้านความปลอดภัยในวงจรโค้ด

การเรียกใช้โค้ดที่ LLM สร้างขึ้นบนโครงสร้างพื้นฐานของคุณมีความเสี่ยงด้านความปลอดภัยอย่างมาก ห้ามเรียกใช้โค้ดของเอเจนต์โดยไม่มีแซนด์บ็อกซ์โดยเด็ดขาด LLM อาจสร้างโค้ดโดยไม่ตั้งใจ (หรือเนื่องจากการแทรกคำสั่งในพรอมต์) ซึ่งลบไฟล์ ลักลอบส่งข้อมูลออกไป ส่งคำขอเครือข่ายไปยังบริการภายนอก หรือใช้ทรัพยากรระบบจนหมด ควรเรียกใช้ในสภาพแวดล้อมแบบแยกที่มีขีดจำกัดทรัพยากรที่เข้มงวด การจำกัดเครือข่าย และขอบเขตระบบไฟล์เสมอ

ตรวจสอบความเข้าใจอย่างรวดเร็ว

ทดสอบความเข้าใจเกี่ยวกับวงจรการดำเนินการโค้ดจากบทเรียนนี้

ทบทวนบทเรียน

ในบทเรียนนี้ คุณได้เรียนรู้ว่า วงจรเขียน-เรียกใช้-สังเกต เป็นรูปแบบหลักของเอเจนต์ดำเนินการโค้ด stdout และ stderr จากการทำงานจะถูกส่งกลับเป็นการสังเกตเพื่อชี้นำการสร้างโค้ดครั้งถัดไปของ LLM และ การตัดทอนผลลัพธ์ รวมถึงขีดจำกัดจำนวนรอบเป็นกลไกความปลอดภัยที่จำเป็น ต่อไปเราจะสำรวจการทำแซนด์บ็อกซ์สำหรับการดำเนินการโค้ดด้วย Docker และ RestrictedPython

คำถามที่พบบ่อย

บทเรียน “ลูปการเรียกใช้โค้ด” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “ลูปการเรียกใช้โค้ด” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Engineering Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Engineering Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “ลูปการเรียกใช้โค้ด”

ออกแบบลูปเขียน-เรียกใช้-สังเกต โดยเอเจนต์สร้างโค้ด ตัวเรียกใช้ในสภาพแวดล้อมแยกทำงาน โพรเซส stdout และ stderr ถูกดักจับแล้วส่งกลับเป็นข้อมูลสังเกต และเอเจนต์แก้ไขข้อผิดพลาด คุณปฏิบัติ AI Engineering Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Engineering Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Engineering Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 1 จากทั้งหมด 4 บทเรียน

บทเรียน “ลูปการเรียกใช้โค้ด” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน AI Engineering Academy นี้ได้ไหม

ได้ บทเรียน AI Engineering Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. ลูปการเรียกใช้โค้ด
  2. การทำแซนด์บ็อกซ์ด้วย Docker และ RestrictedPython
  3. การจัดการสถานะระหว่างขั้นตอนการเรียกใช้
  4. การสร้างเอเจนต์วิเคราะห์ข้อมูล
← กลับไปที่ AI Engineering Academy