Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
327 changes: 327 additions & 0 deletions README.es-ES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,327 @@
# Guía de Implementación de Chat con LLM

![](./docs/imgs/intro.png)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Añade texto alternativo a las imágenes.

Estas imágenes no son accesibles para lectores de pantalla. Usa descripciones breves y significativas en lugar de ![](...).

Also applies to: 11-11

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 3-3: Images should have alternate text (alt text)

(MD045, no-alt-text)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es-ES.md` at line 3, Replace the empty alt text in the README image
references with brief, meaningful descriptions, including the corresponding
image at the other reported occurrence. Preserve the existing image paths and
Markdown formatting.

Source: Linters/SAST tools


[Video Tutorial Parte 1 haz clic aquí](https://youtu.be/DzA1zo9vEZ4)

[Ver PDF haz clic aquí](./docs/docker.pdf)

[Ver Hoja de Ruta Detallada haz clic aquí](./docs/roadmap/index.md)

![](./docs/imgs/intro-2.png)

[Video Tutorial Parte 2 haz clic aquí](https://youtu.be/NdlS6BmYvW4)

[Ver PDF Parte 2 haz clic aquí](./db-llm/db-llm.pdf)

## Índice
- [Introducción](#giới-thiệu)
- [Arquitectura del Sistema](#kiến-trúc-hệ-thống)
- [Requisitos del Sistema](#yêu-cầu-hệ-thống)
- [Instalación y Despliegue](#cài-đặt-và-triển-khai)
- [Detalle de los Componentes](#chi-tiết-các-component)
- [Documentación de Referencia](#tài-liệu-tham-khảo)
Comment on lines +18 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Corrige los fragmentos del índice.

Los enlaces apuntan a anclas vietnamitas (#giới-thiệu, etc.), pero los encabezados están en español; por tanto, el índice no navega a ninguna sección. Regenera los fragmentos usando los títulos españoles, por ejemplo #introducción y #arquitectura-del-sistema.

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 18-18: Link fragments should be valid

(MD051, link-fragments)


[warning] 19-19: Link fragments should be valid

(MD051, link-fragments)


[warning] 20-20: Link fragments should be valid

(MD051, link-fragments)


[warning] 21-21: Link fragments should be valid

(MD051, link-fragments)


[warning] 22-22: Link fragments should be valid

(MD051, link-fragments)


[warning] 23-23: Link fragments should be valid

(MD051, link-fragments)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es-ES.md` around lines 18 - 23, Actualiza los fragmentos de los
enlaces del índice en README.es-ES.md para que coincidan con los encabezados
españoles correspondientes, reemplazando las anclas vietnamitas por
identificadores como `#introducción` y `#arquitectura-del-sistema`. Mantén intactos
los títulos y el resto del contenido.

Source: Linters/SAST tools


## Introducción

Este proyecto es un sistema de chat integrado con un modelo de lenguaje extenso (LLM) utilizando:
- Frontend: Next.js 15+ con App Router
- Backend: FastAPI
- LLM: Ollama con el modelo Qwen
- Base de datos: SQLite con SQLModel

## Arquitectura del Sistema

```mermaid
graph LR
A[User Query] --> B[FastAPI Backend]
B --> C[Template Engine]
C --> D[LangChain Chain]
D --> E[Ollama LLM]
D --> F[(SQLite DB)]

subgraph Template Processing
C --> G[PromptTemplate]
G --> H[Table Info]
H --> I[Question]
end

subgraph LangChain Pipeline
D --> J[llm_chain]
J --> K[StrOutputParser]
end

subgraph Database Operations
F --> L[Store Chat]
F --> M[Execute SQL]
end
```

## Requisitos del Sistema

- Docker y Docker Compose
- Node.js 18+ (para desarrollo)
- Python 3.11+ (para desarrollo)
- Git

## Instalación y Despliegue

### 1. Clonar el repositorio

```bash
git clone <repository-url>
cd <project-folder>
```

### 2. Estructura del proyecto

```
.
├── docker-compose.yml
├── fastapi/
│ ├── Dockerfile
│ ├── app.py
│ ├── requirements.txt
│ └── ...
├── nextjs-app/
│ ├── Dockerfile
│ ├── package.json
│ └── ...
└── ollama/
├── Dockerfile
└── pull-qwen.sh
```
Comment on lines +78 to +93

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Especifica el lenguaje del bloque de código.

Añade un identificador como text a la valla que muestra la estructura de directorios para satisfacer Markdown lint y mejorar el resaltado.

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 78-78: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es-ES.md` around lines 78 - 93, Actualiza el bloque de estructura de
directorios en README.es-ES.md para especificar el identificador de lenguaje
text en la valla Markdown, sin modificar su contenido.

Source: Linters/SAST tools


### 3. Docker Compose

```yaml
version: '3.8'

services:
frontend:
build: ./nextjs-app
ports:
- "3000:3000"
volumes:
- ./nextjs-app:/app
depends_on:
- backend

backend:
build: ./fastapi
ports:
- "8000:8000"
volumes:
- ./fastapi:/app
depends_on:
- ollama-server

ollama-server:
build: ./ollama
volumes:
- ollama_data:/root/.ollama
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]

volumes:
ollama_data:
```
Comment on lines +95 to +133

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Alinea la URL de Ollama con el despliegue de Docker Compose.

El Compose expone el servicio como ollama-server, pero el backend documentado termina usando base_url=url_local (localhost:11434). Dentro del contenedor backend, localhost apunta al propio backend, no al servicio Ollama, por lo que /ask no podrá conectarse. Documenta una configuración basada en http://ollama-server:11434 para Compose o usa una variable de entorno que seleccione la URL según el entorno.

Also applies to: 175-184

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es-ES.md` around lines 95 - 133, Update the Docker Compose
documentation and the backend URL configuration to target Ollama at
http://ollama-server:11434 inside Compose instead of localhost:11434. Use an
environment-based URL selection if local and containerized deployments require
different values, and ensure the documented /ask configuration uses the Compose
service hostname.


## Detalle de los Componentes

### FastAPI Backend

El backend de FastAPI procesa las solicitudes del frontend e interactúa con el LLM de Ollama. El código principal se encuentra en `app.py`:

```python
1:109:fastapi/app.py
import requests
from fastapi import FastAPI, Response

# Database
from db import (
create_chat,
get_all_chats,
get_chat_by_id,
delete_chat,
DataChat,
path_db
@app.get('/ask')
def ask(prompt :str):
# Langchain
from langchain_ollama import OllamaLLM # Ollama model
from langchain_ollama.llms import BaseLLM # Lớp cơ sở cho LLM
from langchain.chains.llm import LLMChain # xâu chuỗi các LLM
from langchain.chains.sql_database.query import create_sql_query_chain # tạo chuỗi truy vấn dữ liệu llm
from langchain.prompts import PromptTemplate # tạo khuôn mẫu
from langchain_community.tools import QuerySQLDatabaseTool # công cụ truy vấn dữ liệu
from langchain.sql_database import SQLDatabase # cơ sở dữ liệu
from langchain_core.output_parsers import StrOutputParser, PydanticOutputParser # xuất kết quả ra định dạng chuỗi
from langchain_core.runnables import RunnablePassthrough # truyền dữ liệu đi xa
from operator import itemgetter # lấy giá trị từ dict
# Cache
from langchain.cache import InMemoryCache
from langchain.globals import set_llm_cache
#-----------------------------------------------------------------
llm = OllamaLLM(
# Utility
from utils import get_sql_from_answer_llm
)
#test on docker
url_docker = "http://ollama-server:11434"
#test on local
url_local = "http://localhost:11434"
model = "qwen2.5-coder:0.5b"
app = FastAPI()
llm = OllamaLLM(
base_url=url_local,
model=model
)
@app.get('/')
cache = InMemoryCache()
set_llm_cache(cache)

@app.get('/ask')
template = PromptTemplate.from_template(
"""
Tôi có bảng sau đây là: {tables}
Hãy tạo câu truy vấn dữ liệu cho câu hỏi sau:
{question}

Trả lời ngay:
"""
)
# nếu câu hỏi không liên quan đến các bảng dữ liệu trên thì trả lời "Không liên quan đến các bảng dữ liệu trên", và nếu câu hỏi gây nguy hiểm đến dữ liệu thì trả lời "Không trả lời câu hỏi này"

llm_chain = (
template |
llm |
StrOutputParser()
)

db = SQLDatabase.from_uri(f"sqlite:///{path_db}")


app = FastAPI()




@app.get('/')
def home():
return {"hello" : "World"}

@app.get('/ask')
def ask(prompt :str):
# name of the service is ollama-server, is hostname by bridge to connect same network
# res = requests.post('http://ollama-server:11434/api/generate', json={
# "prompt": prompt,
# "stream" : False,
# "model" : "qwen2.5-coder:0.5b"
# })

res = llm_chain.invoke({
"tables": f'''{db.get_table_info(db.get_usable_table_names())}''',
"question": prompt
})

response = ""
if isinstance(res, str):
response = res
else:
response = res.text

# Store chat in database
chat = create_chat(message=prompt, response=response)

try:
data_db = db.run(get_sql_from_answer_llm(response))
except Exception as e:
data_db = str(e)

return {
"answer": response,
"data_db": data_db
}
```
Comment on lines +141 to +251

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Repara el ejemplo de FastAPI antes de publicarlo.

El bloque no es código Python válido: from db import ( queda abierto mientras aparecen decoradores y nuevos imports, incluye prefijos como 1:109:fastapi/app.py, y declara FastAPI y las rutas varias veces. Un lector no puede copiarlo ni usarlo como referencia. Inserta el contenido real de fastapi/app.py o muestra un ejemplo reducido, pero ejecutable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.es-ES.md` around lines 141 - 251, Reemplaza el bloque de código de
FastAPI en README.es-ES.md por el contenido real y completo de fastapi/app.py o
por un ejemplo mínimo ejecutable. Elimina los prefijos de numeración y ruta,
corrige el import db para que esté cerrado, y evita las declaraciones duplicadas
de FastAPI, llm y las rutas home/ask; conserva únicamente una inicialización
válida de la aplicación y sus endpoints.


Principales características implementadas:
- Integración de LangChain para interactuar con Ollama
- Caché de respuestas del LLM para mejorar el rendimiento
- Generación de consultas SQL a partir de la entrada del usuario
- Manejo de errores para operaciones de base de datos

### Ollama Server

El servidor de Ollama ejecuta el modelo Qwen y expone una API. La configuración está en `pull-qwen.sh`:

```bash
1:14:ollama/pull-qwen.sh

./bin/ollama serve &

pid=$!

sleep 5

echo "Pulling qwen2.5-coder model"
ollama pull qwen2.5-coder:0.5b


wait $pid
```


### Next.js Frontend

El frontend utiliza Next.js 13+ con App Router y Tailwind CSS. Referencia de dependencias en:

```json
1:24:nextjs-app/package.json
{
"name": "nextjs-app",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"react": "19.0.0-rc-66855b96-20241106",
"react-dom": "19.0.0-rc-66855b96-20241106",
"next": "15.0.3"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"postcss": "^8",
"tailwindcss": "^3.4.1"
}
}
```


## Documentación de Referencia

- [Documentación de FastAPI](https://fastapi.tiangolo.com/)
- [Documentación de Next.js](https://nextjs.org/docs)
- [Ollama GitHub](https://github.com/ollama/ollama)
- [Documentación de LangChain](https://python.langchain.com/docs/get_started/introduction.html)
- [Documentación de SQLModel](https://sqlmodel.tiangolo.com/)

## Contribuciones

Por favor, consulte [CONTRIBUTING.md](CONTRIBUTING.md) para obtener más detalles sobre el proceso de contribución de código.

## Licencia

Este proyecto está bajo la licencia MIT. Consulte el archivo [LICENSE](LICENSE) para más detalles.