Mengalirkan Keluaran di LangChain
Terapkan pengaliran token melalui rantai LCEL agar aplikasi menampilkan setiap kata saat tiba, bukan menunggu respons lengkap, sehingga latensi yang dirasakan pengguna meningkat.
Mengalirkan Keluaran di LangChain adalah pelajaran AI Engineering Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar AI Engineering Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus AI Engineering Academy mencakup 4 pelajaran total.
Mengapa Pengaliran Penting
Tanpa pengaliran, pengguna hanya menatap layar kosong sambil menunggu LLM menyelesaikan pembuatan respons—yang dapat memerlukan waktu 5–30 detik untuk respons yang panjang. Dengan pengaliran, token muncul saat dibuat sehingga memberikan umpan balik secara langsung. Hal ini meningkatkan persepsi kecepatan respons secara drastis. LCEL LangChain secara otomatis meneruskan pengaliran melalui seluruh rantai ketika Anda memanggil .stream().
Pengaliran Dasar dengan .stream()
Setiap rantai LCEL menyediakan metode .stream() yang mengembalikan iterator berisi potongan. Untuk rantai yang diakhiri dengan StrOutputParser, setiap potongan merupakan bagian dari string. Anda mengiterasi potongan tersebut lalu mencetak atau menghasilkannya saat tiba. Pengaliran berlangsung pada tingkat HTTP—setiap token dari API OpenAI diteruskan melalui pengurai segera setelah tiba.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
chain = (
ChatPromptTemplate.from_template('Explain {topic} in detail.')
| ChatOpenAI(model='gpt-4o-mini')
| StrOutputParser()
)
# Stream tokens to stdout
for chunk in chain.stream({'topic': 'quantum entanglement'}):
print(chunk, end='', flush=True)
print() # final newlinePengaliran Asinkron dengan .astream()
.astream() adalah versi asinkron dari .stream(). Fitur ini mengembalikan iterator asinkron yang Anda konsumsi dengan async for. Inilah pendekatan yang tepat dalam FastAPI, Starlette, dan kerangka kerja web asinkron lainnya ketika pengendali permintaan merupakan coroutine. Penggunaan pengaliran sinkron dalam pengendali asinkron akan memblokir loop peristiwa.
import asyncio
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
chain = (
ChatPromptTemplate.from_template('Write a poem about {subject}')
| ChatOpenAI(model='gpt-4o-mini')
| StrOutputParser()
)
async def stream_response():
async for chunk in chain.astream({'subject': 'the ocean'}):
print(chunk, end='', flush=True)
asyncio.run(stream_response())Pengaliran dalam FastAPI dengan StreamingResponse
Dalam FastAPI, bungkus generator asinkron dalam StreamingResponse dengan media_type='text/plain' untuk mengalirkan token teks ke peramban. Untuk peristiwa yang dikirim server (SSE), gunakan media_type='text/event-stream' dan format setiap potongan sebagai data: ...\n\n. Peramban kemudian menerima token saat token tersebut dibuat tanpa menunggu respons lengkap.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
async def generate_stream(topic: str):
async for chunk in chain.astream({'topic': topic}):
yield chunk
@app.get('/stream')
async def stream_endpoint(topic: str):
return StreamingResponse(
generate_stream(topic),
media_type='text/plain'
)
# SSE format for frontend EventSource
async def sse_stream(topic: str):
async for chunk in chain.astream({'topic': topic}):
yield f'data: {chunk}\n\n'Pengaliran melalui Langkah Perantara
Rantai LCEL meneruskan pengaliran melalui setiap langkah yang mendukungnya. StrOutputParser memahami pengaliran dan langsung meneruskan potongan. Namun, beberapa pengurai—seperti JsonOutputParser—harus menampung seluruh output sebelum mengurainya, sehingga pengaliran terhenti. LangChain membuat hal ini jelas: jika suatu langkah tidak kompatibel dengan pengaliran, langkah tersebut mengumpulkan output sebelum meneruskannya ke langkah berikutnya.
from langchain_core.output_parsers import JsonOutputParser
# This chain does NOT stream token by token
# JsonOutputParser must buffer the full response before parsing JSON
json_chain = (
ChatPromptTemplate.from_template('Return JSON: {task}')
| ChatOpenAI(model='gpt-4o-mini')
| JsonOutputParser() # buffers until complete
)
# But partial JSON streaming IS possible with streaming_json_parser
for partial in json_chain.stream({'task': 'list 3 colors'}):
print(partial) # prints partial dict as it fills inastream_events untuk Kontrol Terperinci
.astream_events() menyediakan API pengaliran yang lebih terperinci dan menghasilkan peristiwa untuk setiap langkah dalam rantai, bukan hanya output akhir. Setiap peristiwa memiliki bidang kind (rantai_dimulai, aliran_llm, rantai_berakhir) dan muatan data. Dengan demikian, Anda dapat mengalirkan hasil pemanggilan alat, penalaran perantara, dan output akhir secara terpisah ke berbagai bagian UI.
async def stream_with_events(question: str):
async for event in chain.astream_events(
{'question': question},
version='v2'
):
kind = event['event']
if kind == 'on_llm_stream':
chunk = event['data']['chunk'].content
print(chunk, end='', flush=True)
elif kind == 'on_chain_end':
print('\n[Done]')
elif kind == 'on_tool_start':
print(f'\n[Tool: {event["name"]}]')Menampung Output yang Dialirkan
Terkadang Anda perlu mengalirkan token kepada pengguna dan mengambil respons lengkap untuk pencatatan atau pemrosesan lebih lanjut. Gunakan .astream() dengan akumulator berupa daftar. Gabungkan potongan setelah perulangan untuk memperoleh teks lengkap. Pola ini memungkinkan Anda menampilkan output yang dialirkan secara langsung sekaligus menyimpan respons lengkap untuk analitik, penyimpanan sementara, atau evaluasi.
async def stream_and_capture(question: str) -> str:
full_response = []
async for chunk in chain.astream({'question': question}):
print(chunk, end='', flush=True) # stream to user
full_response.append(chunk) # also collect
print() # newline
complete = ''.join(full_response)
await log_response(question, complete) # log full text
return completePengaliran dengan Pemanggilan Alat
Ketika model menghasilkan pemanggilan alat dalam respons yang dialirkan, argumen fungsi tiba sebagai fragmen token. Anda harus menampung string argumen JSON hingga pemanggilan alat selesai sebelum menjalankannya. LangChain menanganinya secara otomatis dalam pelaksana agennya, tetapi jika Anda membuat loop pengaliran khusus, Anda harus memeriksa finish_reason dan mengakumulasikan fragmen tool_call.function.arguments.
from openai import AsyncOpenAI
client = AsyncOpenAI()
async def stream_with_tools(prompt: str):
tool_call_buffer = {}
async with client.chat.completions.stream(
model='gpt-4o-mini',
messages=[{'role': 'user', 'content': prompt}],
tools=[weather_tool_schema]
) as stream:
async for chunk in stream:
delta = chunk.choices[0].delta
if delta.tool_calls:
for tc in delta.tool_calls:
idx = tc.index
if idx not in tool_call_buffer:
tool_call_buffer[idx] = ''
if tc.function.arguments:
tool_call_buffer[idx] += tc.function.argumentsPembatalan dan Batas Waktu saat Mengalirkan
Respons panjang yang dialirkan memerlukan dukungan pembatalan. Dalam Python asinkron, Anda dapat membatalkan asyncio.Task yang membungkus aliran tersebut. Dalam FastAPI, kerangka kerja menangani pembatalan akibat pemutusan koneksi klien secara otomatis saat menggunakan StreamingResponse. Tetapkan batas waktu melalui parameter timeout pada klien OpenAI, atau bungkus aliran dengan asyncio.wait_for() untuk menghentikannya setelah durasi maksimum.
import asyncio
async def stream_with_timeout(question: str, timeout: float = 30.0):
async def _stream():
async for chunk in chain.astream({'question': question}):
yield chunk
try:
async for chunk in asyncio.timeout(_stream(), timeout):
print(chunk, end='', flush=True)
except asyncio.TimeoutError:
print('\n[Stream timed out after 30 seconds]')
except asyncio.CancelledError:
print('\n[Stream cancelled by client disconnect]')SSE Sisi Klien dengan JavaScript
Di frontend, API EventSource bawaan peramban menggunakan peristiwa yang dikirim server. Ketika titik akhir FastAPI menghasilkan potongan data: token\n\n, EventSource memicu peristiwa message untuk setiap potongan. Tambahkan setiap token ke DOM saat tiba untuk membuat efek mesin tik. Untuk kontrol lebih besar, fetch() dengan response.body.getReader() memberi Anda akses penuh ke pengaliran.
// Frontend JavaScript (not Python)
const source = new EventSource('/stream?topic=quantum+computing');
const outputDiv = document.getElementById('output');
source.onmessage = (event) => {
outputDiv.textContent += event.data;
};
source.onerror = () => {
source.close();
outputDiv.textContent += ' [done]';
};
// Alternative: fetch with ReadableStream
const response = await fetch('/stream?topic=ai');
const reader = response.body.getReader();
while (true) {
const {done, value} = await reader.read();
if (done) break;
outputDiv.textContent += new TextDecoder().decode(value);
}Praktik Terbaik Pengaliran
Ikuti praktik terbaik berikut saat menerapkan pengaliran: selalu gunakan flush=True saat mencetak ke stdout agar buffering tidak terjadi. Tetapkan stream_usage=True jika Anda memerlukan jumlah token yang akurat selama pengaliran. Keluarkan penanda data: [DONE]\n\n di akhir aliran SSE agar klien mengetahui kapan harus menutup koneksi. Uji titik akhir pengaliran dengan curl --no-buffer untuk memastikan token tiba secara bertahap.
# Complete SSE endpoint with DONE sentinel
async def sse_generator(question: str):
try:
async for chunk in chain.astream({'question': question}):
# Escape any newlines in the chunk
safe_chunk = chunk.replace('\n', ' ')
yield f'data: {safe_chunk}\n\n'
finally:
yield 'data: [DONE]\n\n'
@app.get('/chat/stream')
async def chat_stream(question: str):
return StreamingResponse(
sse_generator(question),
media_type='text/event-stream',
headers={'Cache-Control': 'no-cache', 'X-Accel-Buffering': 'no'}
)Pemeriksaan Singkat
Uji pemahaman Anda tentang output yang dialirkan dalam LangChain.
Rangkuman Pelajaran
Dalam pelajaran ini, Anda mempelajari bahwa stream() dan astream() memungkinkan Anda mengiterasi potongan token saat token tersebut dibuat, sehingga menghilangkan waktu tunggu panjang untuk respons lengkap; StreamingResponse dalam FastAPI dengan format SSE mengirimkan token secara langsung ke klien peramban; dan astream_events() menyediakan kait peristiwa terperinci untuk setiap langkah dalam rantai, termasuk pemanggilan alat dan output perantara. Selanjutnya, kita akan mempelajari pengelolaan memori untuk percakapan multi-giliran.
Belajar Python dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 30
- Pelajaran
- 120
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Mengalirkan Keluaran di LangChain” gratis?
Ya — teks lengkap “Mengalirkan Keluaran di LangChain” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus AI Engineering Academy, upgrade ke CoddyKit PRO. Kursus AI Engineering Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Mengalirkan Keluaran di LangChain”?
Terapkan pengaliran token melalui rantai LCEL agar aplikasi menampilkan setiap kata saat tiba, bukan menunggu respons lengkap, sehingga latensi yang dirasakan pengguna meningkat. Kamu berlatih AI Engineering Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai AI Engineering Academy?
Tidak diperlukan pengalaman sebelumnya. AI Engineering Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.
Berapa lama pelajaran “Mengalirkan Keluaran di LangChain” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran AI Engineering Academy ini?
Ya. Setiap pelajaran AI Engineering Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Arsitektur LangChain dan Abstraksi Inti
- Membangun Rantai dengan LCEL
- Rantai Bercabang dan Paralel
- Mengalirkan Keluaran di LangChain