1. Introducción a LCEL
LCEL (Lenguaje de Expresión de LangChain) es un marco simple y fácil de usar para construir cadenas complejas. Proporciona una interfaz unificada y primitivas compuestas para facilitar la construcción de cadenas. Cada objeto LCEL implementa la interfaz Runnable
, definiendo un conjunto de métodos de invocación comúnmente utilizados (como invocar
, lote
, secuencia
, ainvoke
, etc.). Por lo tanto, las cadenas de objetos LCEL también pueden admitir automáticamente estos métodos de invocación, haciendo que la cadena de cada objeto LCEL sea en sí mismo un objeto LCEL.
2. Invocación
2.1. Sin usar LCEL
Sin usar LCEL, puedes usar el siguiente fragmento de código para pasar una cadena de tema y recuperar una broma.
from typing import List
import openai
plantilla_prompt = "Cuéntame una breve broma sobre {tema}"
cliente = openai.OpenAI()
def llamar_modelo_chat(mensajes: List[dict]) -> str:
respuesta = cliente.chat.completions.create(
modelo="gpt-3.5-turbo",
mensajes=mensajes,
)
return respuesta.choices[0].mensaje.contenido
def invocar_cadena(tema: str) -> str:
valor_prompt = plantilla_prompt.format(tema=tema)
mensajes = [{"rol": "usuario", "contenido": valor_prompt}]
return llamar_modelo_chat(mensajes)
invocar_cadena("helado")
2.2. Usando LCEL
En cambio, usando LCEL se puede lograr la misma funcionalidad de manera más concisa. El siguiente fragmento de código demuestra cómo construir fácilmente una cadena utilizando objetos 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(
"Cuéntame una breve broma sobre {tema}"
)
parser_salida = StrOutputParser()
modelo = ChatOpenAI(modelo="gpt-3.5-turbo")
cadena = (
{"tema": RunnablePassthrough()}
| prompt
| modelo
| parser_salida
)
cadena.invocar("helado")
3. Streaming
3.1. Sin usar LCEL
El siguiente fragmento de código muestra cómo procesar resultados en streaming sin usar LCEL.
from typing import Iterator
def streaming_chat_model(mensajes: List[dict]) -> Iterator[str]:
stream = cliente.chat.completions.create(
modelo="gpt-3.5-turbo",
mensajes=mensajes,
stream=True,
)
for respuesta in stream:
contenido = respuesta.choices[0].delta.contenido
if contenido is not None:
yield contenido
def cadena_stream(tema: str) -> Iterator[str]:
valor_prompt = plantilla_prompt.format(tema=tema)
stream = streaming_chat_model([{"rol": "usuario", "contenido": valor_prompt}])
for chunk in stream:
print(chunk, end="", flush=True)
cadena_stream("helado")
3.2. Usando LCEL
Procesar resultados en streaming usando LCEL es más conveniente. El siguiente fragmento de código muestra cómo realizar streaming con LCEL.
for fragmento in cadena.stream("helado"):
print(fragmento, end="", flush=True)
4. Procesamiento por lotes
4.1. Sin usar LCEL
El siguiente fragmento de código muestra cómo procesar en paralelo un lote de entradas sin usar LCEL.
from concurrent.futures import ThreadPoolExecutor
def cadena_lote(temas: list) -> list:
with ThreadPoolExecutor(max_workers=5) as executor:
return list(executor.map(invocar_cadena, temas))
cadena_lote(["helado", "espaguetis", "dumplings"])
4.2. Usando LCEL
El procesamiento por lotes utilizando LCEL es muy sencillo. El siguiente fragmento de código muestra cómo usar LCEL para el procesamiento por lotes.
cadena.lote(["helado", "espaguetis", "dumplings"])