เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ
ainvoke(), astream() และสายงานแบบอะซิงโครนัสใน LangChain และ LangGraph
เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ เป็นบทเรียน AI Agents ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน AI Agents และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
การดำเนินการแบบอะซิงโครนัสใน LangChain
LangChain มีรุ่นแบบอะซิงโครนัสสำหรับอินเทอร์เฟซทั้งหมด ทุกองค์ประกอบที่มี invoke() จะมี ainvoke() ด้วย และทุกองค์ประกอบที่มี stream() จะมี astream() การทำงานแบบอะซิงโครนัสเป็นแนวทางที่แนะนำสำหรับเอเจนต์ในระบบจริง
ainvoke() สำหรับการเรียก LLM แบบอะซิงโครนัส
ainvoke() เป็นรูปแบบแบบอะซิงโครนัสที่เทียบเท่ากับ invoke() ใช้ภายในฟังก์ชันแบบอะซิงโครนัสเพื่อเรียก LLM โดยไม่บล็อกการทำงาน วิธีนี้ทำให้เอเจนต์หรือคำขอหลายรายการใช้ลูปเหตุการณ์ร่วมกันได้
import asyncio
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model='gpt-4o-mini', api_key='sk-...')
async def async_agent_call(question: str) -> str:
# ainvoke: non-blocking, releases event loop while waiting for OpenAI
response = await llm.ainvoke([HumanMessage(content=question)])
return response.content
async def handle_multiple_users(questions: list) -> list:
# All three LLM calls run concurrently
results = await asyncio.gather(*[async_agent_call(q) for q in questions])
return results
questions = [
'What is Python?',
'What is TypeScript?',
'What is Rust?'
]
results = asyncio.run(handle_multiple_users(questions))
for q, a in zip(questions, results):
print(f'Q: {q[:30]}... A: {a[:50]}...')astream() สำหรับการสตรีมโทเค็น
astream() จะส่งคืนโทเค็นทันทีที่มาถึงจาก LLM วิธีนี้ช่วยให้คุณสตรีมคำตอบแก่ผู้ใช้แบบเรียลไทม์ โดยไม่ต้องรอให้ผลลัพธ์ทั้งหมดมาถึง
import asyncio
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model='gpt-4o-mini', api_key='sk-...')
async def stream_response(question: str):
print(f'Streaming answer to: {question}\n')
full_response = ''
async for chunk in llm.astream([HumanMessage(content=question)]):
token = chunk.content
if token:
print(token, end='', flush=True) # Print each token as it arrives
full_response += token
print() # New line after streaming
return full_response
async def main():
await stream_response('List 3 benefits of async programming in Python')
asyncio.run(main())AsyncCallbackHandler
การเรียกกลับของ LangChain จะทำงานเมื่อเกิดเหตุการณ์เฉพาะ เช่น การเริ่มต้น LLM การสิ้นสุด LLM การเริ่มต้นเครื่องมือ และข้อผิดพลาดของสายงาน AsyncCallbackHandler จัดการเหตุการณ์เหล่านี้แบบอะซิงโครนัสโดยไม่บล็อกลูปของเอเจนต์
from langchain_core.callbacks import AsyncCallbackHandler
from typing import Any, Dict, List
import time
class LatencyCallbackHandler(AsyncCallbackHandler):
def __init__(self):
self.step_times = {}
self.step_counts = {}
async def on_llm_start(self, serialized: Dict, prompts: List[str], **kwargs):
run_id = str(kwargs.get('run_id', ''))
self.step_times[run_id] = time.perf_counter()
async def on_llm_end(self, response, **kwargs):
run_id = str(kwargs.get('run_id', ''))
if run_id in self.step_times:
elapsed_ms = (time.perf_counter() - self.step_times[run_id]) * 1000
print(f'LLM call completed in {elapsed_ms:.0f}ms')
async def on_tool_start(self, serialized: Dict, input_str: str, **kwargs):
tool_name = serialized.get('name', 'unknown')
print(f'Tool starting: {tool_name}')
async def on_tool_error(self, error: Exception, **kwargs):
print(f'Tool error: {error}')
handler = LatencyCallbackHandler()
print('Async callback handler created')
# Use: llm.ainvoke([...], config={'callbacks': [handler]})ฟังก์ชันโหนดแบบอะซิงโครนัสของ LangGraph
โหนดของ LangGraph สามารถเป็นฟังก์ชันแบบอะซิงโครนัสได้ เมื่อคุณกำหนดโหนดด้วย async def LangGraph จะรอผลลัพธ์ระหว่างการดำเนินการกราฟ นี่คือรูปแบบที่แนะนำสำหรับกราฟในระบบจริง
import asyncio
from langgraph.graph import StateGraph, END
from typing import TypedDict, List
class AgentState(TypedDict):
question: str
entities: List[str]
context: str
answer: str
async def extract_entities_node(state: AgentState) -> AgentState:
await asyncio.sleep(0.1) # Simulate async NLP call
entities = state['question'].split()[:3] # Simplified
return {'entities': entities}
async def retrieve_context_node(state: AgentState) -> AgentState:
await asyncio.sleep(0.2) # Simulate async vector search
context = f'Context for entities: {state["entities"]}'
return {'context': context}
async def generate_answer_node(state: AgentState) -> AgentState:
await asyncio.sleep(0.3) # Simulate async LLM call
answer = f'Answer based on: {state["context"]}'
return {'answer': answer}
# Build async graph
graph = StateGraph(AgentState)
graph.add_node('extract', extract_entities_node)
graph.add_node('retrieve', retrieve_context_node)
graph.add_node('generate', generate_answer_node)
graph.set_entry_point('extract')
graph.add_edge('extract', 'retrieve')
graph.add_edge('retrieve', 'generate')
graph.add_edge('generate', END)
app = graph.compile()
print('Async LangGraph compiled')การสตรีมแบบอะซิงโครนัสจาก LangGraph
LangGraph รองรับการสตรีมสถานะระหว่างทางแบบอะซิงโครนัสขณะที่กราฟทำงาน ใช้ astream() เพื่อดูผลลัพธ์ของแต่ละโหนดทันทีที่เสร็จสิ้น แทนที่จะรอให้การทำงานทั้งหมดเสร็จ
import asyncio
async def stream_graph_execution(graph_app, initial_state: dict):
print('Graph execution streaming:')
async for step_output in graph_app.astream(initial_state):
for node_name, state_delta in step_output.items():
print(f' Node [{node_name}] completed:')
for key, value in state_delta.items():
print(f' {key}: {value}')
# Run the async graph
initial = {
'question': 'What is machine learning?',
'entities': [],
'context': '',
'answer': ''
}
asyncio.run(stream_graph_execution(app, initial))การจำกัดอัตราการเรียกด้วยเซมาฟอร์
OpenAI และบริการ LLM อื่น ๆ มีขีดจำกัดอัตราการเรียกคำขอต่อนาที ใช้ Semaphore แบบอะซิงโครนัสเพื่อให้มั่นใจว่าคุณจะไม่เกินขีดจำกัด แม้จะเรียกใช้งานเอเจนต์หลายรายการพร้อมกัน
import asyncio
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage
llm = ChatOpenAI(model='gpt-4o-mini', api_key='sk-...')
# Limit to 10 concurrent LLM calls
LLM_SEMAPHORE = asyncio.Semaphore(10)
async def rate_limited_llm_call(question: str) -> str:
async with LLM_SEMAPHORE:
response = await llm.ainvoke([HumanMessage(content=question)])
return response.content
async def process_large_batch(questions: list) -> list:
print(f'Processing {len(questions)} questions with max 10 concurrent LLM calls')
tasks = [rate_limited_llm_call(q) for q in questions]
results = await asyncio.gather(*tasks, return_exceptions=True)
successes = [r for r in results if not isinstance(r, Exception)]
failures = [r for r in results if isinstance(r, Exception)]
print(f'Success: {len(successes)}, Failed: {len(failures)}')
return results
# Process 50 questions with max 10 concurrent calls
questions = [f'Question {i}: What is concept number {i}?' for i in range(20)]
asyncio.run(process_large_batch(questions))การกำหนดเครื่องมือแบบอะซิงโครนัส
ใน LangChain ฟังก์ชันเครื่องมือสามารถทำงานแบบอะซิงโครนัสได้ เครื่องมือแบบอะซิงโครนัสจะถูกรอผลลัพธ์ระหว่างการทำงานของเอเจนต์ ทำให้การเรียกส่วนเชื่อมต่อโปรแกรมประยุกต์ภายในเครื่องมือไม่บล็อกการทำงาน
import asyncio
import httpx
from langchain.tools import tool
@tool
async def async_web_search(query: str) -> str:
'''Search the web for information about the query.'''
async with httpx.AsyncClient() as client:
# Real implementation would use a search API
response = await client.get(
'https://api.search.example.com/search',
params={'q': query, 'api_key': 'your-key'},
timeout=10.0
)
response.raise_for_status()
results = response.json()
return '\n'.join([r['snippet'] for r in results.get('items', [])[:3]])
@tool
async def async_fetch_document(url: str) -> str:
'''Fetch and return the text content of a URL.'''
async with httpx.AsyncClient() as client:
response = await client.get(url, timeout=15.0)
return response.text[:3000] # Limit content size
print('Async tools defined')
print('Use with: agent.ainvoke({"input": "your question"})')เอเจนต์แบบอะซิงโครนัสด้วย OpenAI โดยตรง
คุณสามารถสร้างลูปเอเจนต์แบบอะซิงโครนัสเต็มรูปแบบโดยใช้ OpenAI SDK โดยตรงโดยไม่ต้องใช้ LangChain วิธีนี้ให้การควบคุมสูงสุดและมีค่าใช้จ่ายในการทำงานน้อยที่สุด
import asyncio
import openai
import json
client = openai.AsyncOpenAI(api_key='sk-...')
TOOLS = [
{'type': 'function', 'function': {
'name': 'web_search',
'description': 'Search the web',
'parameters': {'type': 'object', 'properties': {'query': {'type': 'string'}}, 'required': ['query']}
}}
]
async def async_tool_call(tool_name: str, args: dict) -> str:
if tool_name == 'web_search':
await asyncio.sleep(0.3) # Simulate search
return f'Search results for: {args["query"]}'
return 'Unknown tool'
async def async_agent_loop(question: str, max_turns: int = 5) -> str:
messages = [{'role': 'user', 'content': question}]
for turn in range(max_turns):
response = await client.chat.completions.create(
model='gpt-4o-mini', messages=messages, tools=TOOLS
)
msg = response.choices[0].message
messages.append(msg)
if not msg.tool_calls:
return msg.content
# Execute tool calls in parallel
tool_results = await asyncio.gather(*[
async_tool_call(tc.function.name, json.loads(tc.function.arguments))
for tc in msg.tool_calls
])
for tc, result in zip(msg.tool_calls, tool_results):
messages.append({'role': 'tool', 'tool_call_id': tc.id, 'content': result})
return 'Max turns reached'
result = asyncio.run(async_agent_loop('What is the latest news on AI?'))
print(result)การยกเลิกและการคืนทรัพยากร
งานแบบอะซิงโครนัสสามารถถูกยกเลิกได้ จัดการ asyncio.CancelledError อย่างถูกต้อง เพื่อให้มั่นใจว่าทรัพยากรจะได้รับการคืนเมื่อการทำงานของเอเจนต์ถูกยกเลิก (เช่นจากคำขอของผู้ใช้หรือเวลาหมด)
import asyncio
async def cancellable_agent(question: str):
try:
print('Agent starting')
await asyncio.sleep(0.5) # Step 1
print('Step 1 done')
await asyncio.sleep(0.5) # Step 2 - may be cancelled here
print('Step 2 done')
return 'Completed'
except asyncio.CancelledError:
print('Agent was cancelled - cleaning up')
# Clean up resources: close connections, log cancellation
raise # Always re-raise CancelledError
finally:
print('Cleanup always runs')
async def run_with_timeout(question: str, timeout: float):
task = asyncio.create_task(cancellable_agent(question))
try:
result = await asyncio.wait_for(task, timeout=timeout)
return result
except asyncio.TimeoutError:
print(f'Agent exceeded {timeout}s timeout')
task.cancel()
return None
# Run with 0.7s timeout (not enough for both steps)
result = asyncio.run(run_with_timeout('test', timeout=0.7))
print('Final result:', result)การทดสอบโค้ดเอเจนต์แบบอะซิงโครนัส
ทดสอบฟังก์ชันเอเจนต์แบบอะซิงโครนัสด้วย pytest-asyncio ทำเครื่องหมายฟังก์ชันทดสอบด้วย @pytest.mark.asyncio เพื่อให้ทำงานในลูปเหตุการณ์
import pytest
import asyncio
from unittest.mock import AsyncMock, patch
# Install: pip install pytest-asyncio
# pytest.ini: [pytest] asyncio_mode = auto
@pytest.mark.asyncio
async def test_async_agent_call():
with patch('openai.AsyncOpenAI') as mock_openai:
mock_client = AsyncMock()
mock_openai.return_value = mock_client
mock_response = AsyncMock()
mock_response.choices[0].message.content = 'Mocked answer'
mock_response.choices[0].message.tool_calls = None
mock_client.chat.completions.create.return_value = mock_response
# Test the async function
result = await async_agent_call('What is Python?')
assert isinstance(result, str)
print('Async test passed')
@pytest.mark.asyncio
async def test_parallel_execution():
start = asyncio.get_event_loop().time()
results = await asyncio.gather(
asyncio.sleep(0.1),
asyncio.sleep(0.1),
asyncio.sleep(0.1)
)
elapsed = asyncio.get_event_loop().time() - start
assert elapsed < 0.3, 'Should complete in parallel'
print(f'Parallel test passed: {elapsed:.2f}s')แบบทดสอบความเข้าใจ: เฟรมเวิร์กแบบอะซิงโครนัส
ทดสอบความเข้าใจของคุณเกี่ยวกับเฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส
สรุปเฟรมเวิร์กแบบอะซิงโครนัส
LangChain แบบอะซิงโครนัสมี ainvoke(), astream() และ AsyncCallbackHandler สำหรับเอเจนต์แบบอะซิงโครนัสที่พร้อมใช้งานในระบบจริง LangGraph รองรับฟังก์ชันโหนดแบบอะซิงโครนัสโดยกำเนิด ใช้เซมาฟอร์เพื่อจำกัดอัตราการเรียก ใช้ไคลเอ็นต์ AsyncOpenAI สำหรับการเรียกโดยตรง และใช้ pytest-asyncio สำหรับการทดสอบ การจัดการการยกเลิกอย่างถูกต้องช่วยให้คืนทรัพยากรได้อย่างเรียบร้อยเมื่อเอเจนต์ถูกรบกวนหรือหยุดทำงาน
คำถามที่พบบ่อย
บทเรียน “เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส AI Agents ให้อัปเกรดเป็น CoddyKit PRO คอร์ส AI Agents มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ”
ainvoke(), astream() และสายงานแบบอะซิงโครนัสใน LangChain และ LangGraph คุณปฏิบัติ AI Agents ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน AI Agents หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน AI Agents บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน AI Agents นี้ได้ไหม
ได้ บทเรียน AI Agents ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- Python แบบอะซิงโครนัสสำหรับนักพัฒนาเอเจนต์
- คิวเหตุการณ์และตัวกลางรับส่งข้อความ
- การทำงานของเครื่องมือแบบขนานโดยไม่บล็อก
- เฟรมเวิร์กเอเจนต์แบบอะซิงโครนัส: LangChain และอื่น ๆ