1. مقدمة في LCEL
LCEL (لغة تعبير سلسلة) هي إطار عمل بسيط وسهل الاستخدام لبناء سلاسل معقدة. يوفر واجهة موحدة وأساسيات مركبة لتسهيل بناء السلاسل. ينفذ كل كائن LCEL واجهة Runnable
، حيث يعرّف مجموعة من طرق الاستدعاء المستخدمة بشكل شائع (مثل invoke
، batch
، stream
، ainvoke
، إلخ). لذلك، يمكن لسلاسل كائنات LCEL أيضًا دعم هذه الطرق تلقائيًا، مما يجعل سلسلة كل كائن LCEL ذاته كائن LCEL.
2. الاستدعاء
2.1. بدون استخدام LCEL
بدون استخدام LCEL، يمكنك استخدام مقتطف الكود التالي لتمرير سلسلة موضوع واسترداد سلسلة نكتة.
from typing import List
import openai
prompt_template = "قل لي نكتة قصيرة عن {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("آيس كريم")
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(
"قل لي نكتة قصيرة عن {topic}"
)
output_parser = StrOutputParser()
model = ChatOpenAI(model="gpt-3.5-turbo")
chain = (
{"topic": RunnablePassthrough()}
| prompt
| model
| output_parser
)
chain.invoke("آيس كريم")
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("آيس كريم")
3.2. باستخدام LCEL
يوضح مقتطف الكود التالي كيفية تدفق باستخدام LCEL.
for chunk in chain.stream("آيس كريم"):
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(["آيس كريم", "مكرونة", "فطائر"])
4.2. باستخدام LCEL
معالجة الدُفعة باستخدام LCEL مباشرة. يوضح مقتطف الكود التالي كيفية استخدام LCEL لمعالجة الدُفعة.
chain.batch(["آيس كريم", "مكرونة", "فطائر"])