1. Introduzione a LCEL
LCEL (LangChain Expression Language) è un framework semplice e facile da usare per la costruzione di catene complesse. Fornisce un'interfaccia unificata e primitive composite per rendere più semplice la costruzione di catene. Ogni oggetto LCEL implementa l'interfaccia Runnable
, definendo un insieme di metodi di invocazione comunemente utilizzati (come invoke
, batch
, stream
, ainvoke
, ecc.). Pertanto, le catene degli oggetti LCEL possono automaticamente supportare questi metodi di invocazione, rendendo la catena di ogni oggetto LCEL stessa un oggetto LCEL.
2. Invocazione
2.1. Senza l'uso di LCEL
Senza l'uso di LCEL, è possibile utilizzare il seguente frammento di codice per passare una stringa di argomento e recuperare una stringa scherzosa.
from typing import List
import openai
prompt_template = "Dimmi una battuta breve su {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": "utente", "content": prompt_value}]
return call_chat_model(messages)
invoke_chain("gelato")
2.2. Utilizzando LCEL
Al contrario, utilizzando LCEL è possibile ottenere la stessa funzionalità in modo più conciso. Il seguente frammento di codice dimostra come costruire facilmente una catena usando gli oggetti 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(
"Dimmi una battuta breve su {topic}"
)
output_parser = StrOutputParser()
model = ChatOpenAI(model="gpt-3.5-turbo")
chain = (
{"topic": RunnablePassthrough()}
| prompt
| model
| output_parser
)
chain.invoke("gelato")
3. Streaming
3.1. Senza l'uso di LCEL
Il seguente frammento di codice dimostra come elaborare i risultati in streaming senza l'uso di 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": "utente", "content": prompt_value}])
for chunk in stream:
print(chunk, end="", flush=True)
stream_chain("gelato")
3.2. Utilizzando LCEL
Elaborare i risultati in streaming utilizzando LCEL è più conveniente. Il seguente frammento di codice dimostra come effettuare lo streaming con LCEL.
for chunk in chain.stream("gelato"):
print(chunk, end="", flush=True)
4. Elaborazione Batch
4.1. Senza l'uso di LCEL
Il seguente frammento di codice dimostra come elaborare in parallelo un batch di input senza l'uso di 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(["gelato", "spaghetti", "ravioli"])
4.2. Utilizzando LCEL
L'elaborazione in batch utilizzando LCEL è molto semplice. Il seguente frammento di codice dimostra come utilizzare LCEL per l'elaborazione in batch.
chain.batch(["gelato", "spaghetti", "ravioli"])