# Cómo integrar LangChain con GPT para tareas personalizadas

## 1. ¿Por qué LangChain?

La librería **LangChain** surgió para facilitar la orquestación de modelos de lenguaje (LLM) como GPT. En lugar de pelearte con peticiones HTTP y formatos de prompts, LangChain te da piezas LEGO que puedes ensamblar para:

- Encapsular prompts complejos.
- Añadir memoria conversacional.
- Conectar fuentes externas (bases de datos, APIs, archivos).
- Diseñar cadenas (chains) reutilizables.

---

## 2. Prerrequisitos

1. Conocimientos básicos de Python (`>=3.8`).
2. Cuenta de OpenAI y **API Key** válida.
3. Terminal con `pip` configurado.

> Tip: En local basta con un editor de texto y la terminal. Si prefieres Jupyter, todos los fragmentos funcionarán sin cambios.

---

## 3. Instalación rápida

```bash
# Crea un entorno virtual (opcional, pero recomendado)
python -m venv .venv
source .venv/bin/activate  # En Windows: .venv\Scripts\activate

# Instala las dependencias principales
pip install langchain openai python-dotenv
```

- `langchain`: la orquestación.
- `openai`: cliente oficial de la API.
- `python-dotenv`: gestionará tu API Key de forma segura.

---

## 4. Configuración de la clave de OpenAI

```bash
# Crea un archivo .env en la raíz de tu proyecto
echo "OPENAI_API_KEY=tu_clave_aquí" > .env
```

El código leerá la variable mediante `dotenv`. Evita subir `.env` a GitHub usando `.gitignore`.

---

## 5. Tu primer pipeline con LangChain + GPT

A continuación un **script mínimo** que pregunta al usuario y envía la consulta a GPT.

```python
# archivo: my_first_chain.py

from dotenv import load_dotenv
import os
from langchain import PromptTemplate, LLMChain
from langchain.chat_models import ChatOpenAI

# 1) Cargar variables de entorno
load_dotenv()

# 2) Instanciar el modelo de lenguaje
llm = ChatOpenAI(        # Modelo chat-based
    temperature=0.7,     # Creatividad
    model_name="gpt-3.5-turbo"  # Cambia a gpt-4 si tienes acceso
)

# 3) Definir el template del prompt
prompt = PromptTemplate(
    input_variables=["tarea"],
    template="""Eres un asistente experto. {tarea} En 5 puntos claros."""
)

# 4) Construir la chain
chain = LLMChain(llm=llm, prompt=prompt)

if __name__ == "__main__":
    consulta = input("¿Qué necesitas que haga GPT? ")
    respuesta = chain.run(tarea=consulta)
    print("\nRespuesta:\n", respuesta)
```

Ejecuta con:

```bash
python my_first_chain.py
```

---

## 6. Añadiendo memoria: chat persistente

Para un bot que recuerde el contexto de la conversación, usa `ConversationBufferMemory`.

```python
# archivo: chat_con_memoria.py

from dotenv import load_dotenv
from langchain.prompts import ChatPromptTemplate
from langchain.chains import ConversationChain
from langchain.chat_models import ChatOpenAI
from langchain.memory import ConversationBufferMemory

load_dotenv()

llm = ChatOpenAI(temperature=0.5)

# Buffer en RAM (se reinicia al cerrar el programa)
memoria = ConversationBufferMemory(return_messages=True)

chat = ConversationChain(
    llm=llm,
    memory=memoria,
    prompt=ChatPromptTemplate.from_messages([
        ("system", "Eres un tutor experto en IA."),
        ("human", "{input}"),
    ])
)

print("Escribe 'salir' para terminar.\n")
while True:
    user_input = input("Tú: ")
    if user_input.lower() in {"salir", "exit", "quit"}:
        break
    respuesta = chat.predict(input=user_input)
    print("IA:", respuesta)
```

---

## 7. Despliegue ultraligero con FastAPI

¿Quieres un endpoint REST? Combina FastAPI + LangChain.

```python
# archivo: api_langchain.py

from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from langchain.llms import OpenAI
from langchain import PromptTemplate, LLMChain

load_dotenv()

app = FastAPI(title="LangChain GPT API")

class Consulta(BaseModel):
    pregunta: str

llm = OpenAI(temperature=0.3)
plantilla = PromptTemplate(
    input_variables=["pregunta"],
    template="Responde de manera concisa: {pregunta}"
)
chain = LLMChain(llm=llm, prompt=plantilla)

@app.post("/preguntar")
async def preguntar(body: Consulta):
    try:
        respuesta = chain.run(pregunta=body.pregunta)
        return {"respuesta": respuesta.strip()}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
```

```bash
pip install fastapi uvicorn  # Si aún no los tienes
uvicorn api_langchain:app --reload
```

Ya tienes un servicio que acepta `POST /preguntar` con JSON `{ "pregunta": "..." }`.

---

## 8. Errores frecuentes y cómo solucionarlos

| Error | Causa | Solución rápida |
|-------|-------|-----------------|
| `openai.error.AuthenticationError` | Clave de API ausente o mal escrita | Verifica `.env` y que la variable sea `OPENAI_API_KEY` |
| `RateLimitError` | Exceso de peticiones | Implementa backoff o sube de plan |
| Respuesta vacía | Prompt mal formado | Revisa `input_variables` y placeholders |

---

## 9. Buenas prácticas

- Usa **temperatura baja** para tareas deterministas.
- Almacena logs de prompts y respuestas para depurar.
- Reserva `system` prompts para fijar el tono y rol del asistente.
- Si tu aplicación es multi-usuario, combina `ConversationBufferMemory` con un identificador de sesión.

---

## 10. Recursos adicionales

- Documentación oficial de LangChain: <https://python.langchain.com/>
- API Reference de OpenAI: <https://platform.openai.com/docs>
- Ejemplos de producción (repos públicos):
  - <https://github.com/hwchase17/langchain-hub>
- Tutoriales complementarios (en español):
  - <https://youtu.be/6xAl-6V2YEQ>

---

¡Listo! Con estas bases ya puedes construir asistentes, buscadores inteligentes o cualquier flujo personalizado usando LangChain y GPT. Aprovecha el código como plantilla y adapta los prompts a tu caso de uso.
