1. مقدمه‌ای درباره LCEL

LCEL (زبان بیان لنگ یا LangChain Expression Language) یک چارچوب ساده و آسان برای ساخت زنجیره‌های پیچیده است. این یک رابط یکپارچه و اولویت‌های ترکیبی را فراهم می‌کند تا ساخت زنجیره‌ها را آسان‌تر کند. هر شیئ LCEL رابط Runnable را پیاده‌سازی می‌کند که یک مجموعه‌ای از روش‌های فراخوانی متد‌های معمول (مانند invoke، batch، stream، ainvoke و غیره) را تعریف می‌کند. بنابراین، زنجیره‌های شی‌های LCEL همچنین این روش‌های فراخوانی را به طور خودکار پشتیبانی می‌کنند، زیرا زنجیره هر شی LCEL به تنهایی یک شی LCEL است.

2. فراخوانی

2.1. بدون استفاده از LCEL

بدون استفاده از LCEL، می‌توانید از کد زیر برای ارسال یک رشته موضوع و دریافت یک شوخی استفاده کنید.

from typing import List
import openai

prompt_template = "Tell me a short joke about {topic}"
client = openai.OpenAI()

def call_chat_model(messages: List[dict]) -> str:
    response = client.chat.completions.create(
        model="gpt-3.5-turbo", 
        messages=messages,
    )
    return response.choices[0].message.content

def invoke_chain(topic: str) -> str:
    prompt_value = prompt_template.format(topic=topic)
    messages = [{"role": "user", "content": prompt_value}]
    return call_chat_model(messages)

invoke_chain("ice cream")

2.2. با استفاده از LCEL

در مقابل، با استفاده از LCEL می‌توان به طور خلاصه‌تر قابلیت مشابه را به دست آورد. کد زیر نشان می‌دهد که چگونه با استفاده از اشیاء LCEL به راحتی می‌توان یک زنجیره را ایجاد کرد.

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough

prompt = ChatPromptTemplate.from_template(
    "Tell me a short joke about {topic}"
)
output_parser = StrOutputParser()
model = ChatOpenAI(model="gpt-3.5-turbo")
chain = (
    {"topic": RunnablePassthrough()} 
    | prompt
    | model
    | output_parser
)

chain.invoke("ice cream")

3. استریمینگ

3.1. بدون استفاده از LCEL

کد زیر نشان می‌دهد که چگونه می‌توان نتایج پردازش را بدون استفاده از LCEL استریم کرد.

from typing import Iterator

def stream_chat_model(messages: List[dict]) -> Iterator[str]:
    stream = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=messages,
        stream=True,
    )
    for response in stream:
        content = response.choices[0].delta.content
        if content is not None:
            yield content

def stream_chain(topic: str) -> Iterator[str]:
    prompt_value = prompt.format(topic=topic)
    stream = stream_chat_model([{"role": "user", "content": prompt_value}])
    for chunk in stream:
        print(chunk, end="", flush=True)

stream_chain("ice cream")

3.2. با استفاده از LCEL

استریم کردن نتایج پردازش با استفاده از LCEL راحت‌تر است. کد زیر نشان می‌دهد که چگونه می‌توان با LCEL استریم کرد.

for chunk in chain.stream("ice cream"):
    print(chunk, end="", flush=True)

4. پردازش دسته‌ای

4.1. بدون استفاده از LCEL

کد زیر نشان می‌دهد که چگونه می‌توان یک دسته از ورودی‌ها را به صورت موازی پردازش کرد بدون استفاده از LCEL.

from concurrent.futures import ThreadPoolExecutor

def batch_chain(topics: list) -> list:
    with ThreadPoolExecutor(max_workers=5) as executor:
        return list(executor.map(invoke_chain, topics))

batch_chain(["ice cream", "spaghetti", "dumplings"])

4.2. با استفاده از LCEL

پردازش دسته‌ای با استفاده از LCEL بسیار ساده است. کد زیر نشان می‌دهد که چگونه می‌توان از LCEL برای پردازش دسته‌ای استفاده کرد.

chain.batch(["ice cream", "spaghetti", "dumplings"])