Skip to content

Commit b61c079

Browse files
author
Ariel Vernaza
committed
Fix by linteres
1 parent 54936da commit b61c079

26 files changed

Lines changed: 159 additions & 43 deletions

.github/workflows/tests.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,29 @@ on:
77
branches: [main, master]
88

99
jobs:
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Install uv
17+
uses: astral-sh/setup-uv@v7
18+
with:
19+
enable-cache: true
20+
21+
- name: Set up Python
22+
run: uv python install
23+
24+
- name: Install dependencies
25+
run: uv sync
26+
27+
- name: Ruff check
28+
run: uv run ruff check .
29+
30+
- name: Ruff format check
31+
run: uv run ruff format --check .
32+
1033
test:
1134
runs-on: ubuntu-latest
1235
steps:

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,20 @@ uv run pytest -v
271271
```
272272

273273
**4. CI (GitHub Actions)**
274-
On every push and pull request to `main` or `master`, the workflow in `.github/workflows/tests.yml` runs `uv sync` and `uv run pytest -v`. No secrets required; embedding tests that need optional deps are skipped in CI.
274+
On every push and pull request to `main` or `master`, the workflow in `.github/workflows/tests.yml` runs **lint** (Ruff check + format check) and **tests** (`uv run pytest -v`). No secrets required; embedding tests that need optional deps are skipped in CI.
275+
276+
**5. Linting (Ruff)**
277+
Locally: `uv run ruff check .` and `uv run ruff format --check .`. To auto-fix: `uv run ruff check . --fix` and `uv run ruff format .`. Config is in `pyproject.toml` under `[tool.ruff]`.
278+
279+
**6. Linting desde Docker Compose**
280+
Construir la imagen de test (incluye Ruff) y ejecutar lint sobre el código montado:
281+
282+
```bash
283+
docker compose --profile lint build lint
284+
docker compose --profile lint run --rm lint
285+
```
286+
287+
(Con Podman: `podman compose --profile lint build lint` y `podman compose --profile lint run --rm lint`.) El servicio `lint` monta `app/`, `tests/` y `pyproject.toml`; no hace falta reconstruir para lintar cambios. Para ejecutar tests en el mismo contenedor: `docker compose --profile lint run --rm lint uv run pytest -v`.
275288

276289
---
277290

app/api/schemas.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ class ChunkCreate(BaseModel):
3636
"""
3737

3838
text: str = Field(..., min_length=1, description="Chunk text content.")
39-
embedding: list[float] = Field(..., min_length=1, description="Vector embedding (e.g. from Cohere or Sentence Transformers).")
39+
embedding: list[float] = Field(
40+
...,
41+
min_length=1,
42+
description="Vector embedding (e.g. from Cohere or Sentence Transformers).",
43+
)
4044
name: str | None = Field(default=None, description="Optional label for the chunk.")
4145

4246

@@ -60,7 +64,9 @@ class IndexRequest(BaseModel):
6064
class SearchRequest(BaseModel):
6165
"""Request body for POST /libraries/{id}/search. Query vector and number of neighbors."""
6266

63-
embedding: list[float] = Field(..., min_length=1, description="Query vector (same dimension as indexed chunks).")
67+
embedding: list[float] = Field(
68+
..., min_length=1, description="Query vector (same dimension as indexed chunks)."
69+
)
6470
k: int = Field(..., ge=1, le=1000, description="Number of nearest neighbors to return.")
6571

6672

@@ -74,4 +80,6 @@ class SearchResultItem(BaseModel):
7480
class SearchResponse(BaseModel):
7581
"""Response for POST /libraries/{id}/search. List of (chunk_id, distance) sorted by distance ascending."""
7682

77-
results: list[SearchResultItem] = Field(..., description="Up to k nearest chunks with their distances.")
83+
results: list[SearchResultItem] = Field(
84+
..., description="Up to k nearest chunks with their distances."
85+
)

app/core/concurrency.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
from __future__ import annotations
1010

1111
import threading
12+
from collections.abc import Generator
1213
from contextlib import contextmanager
13-
from typing import Generator
1414

1515

1616
class RWLock:

app/core/embedding/cohere.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77

88
from __future__ import annotations
99

10-
import httpx
1110
from typing import Any
1211

12+
import httpx
13+
1314
# Default Cohere model dimensions (embed-english-v3.0, embed-multilingual-v3.0)
1415
COHERE_EMBED_DIM = 1024
1516

@@ -64,4 +65,4 @@ def _embed(self, texts: list[str], input_type: str) -> list[list[float]]:
6465
r.raise_for_status()
6566
data: dict[str, Any] = r.json()
6667
embeddings = data.get("embeddings", [])
67-
return [e for e in embeddings]
68+
return list(embeddings)

app/core/embedding/image.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ def _lazy_import() -> tuple[object, object, object, object]:
2222
import torch # type: ignore[import-untyped]
2323
from PIL import Image # type: ignore[import-untyped]
2424
from transformers import AutoModel, AutoProcessor # type: ignore[import-untyped]
25+
2526
return AutoModel, AutoProcessor, torch, Image
2627

2728

@@ -66,7 +67,9 @@ def dimension(self) -> int:
6667

6768
def embed_documents(self, texts: list[str]) -> list[list[float]]:
6869
"""Not supported: use a text embedder (Cohere or Transformer) for text chunks."""
69-
raise NotImplementedError("ImageEmbedder only supports embed_images; use a text embedder for documents.")
70+
raise NotImplementedError(
71+
"ImageEmbedder only supports embed_images; use a text embedder for documents."
72+
)
7073

7174
def embed_queries(self, texts: list[str]) -> list[list[float]]:
7275
"""Not supported: use embed_images for image query."""
@@ -76,8 +79,8 @@ def embed_images(self, images: list[bytes]) -> list[list[float]]:
7679
"""Indexing/search: embed image chunks (raw bytes, e.g. from PDF image extraction). Each item is one image."""
7780
if not images:
7881
return []
79-
from PIL import Image # type: ignore[import-untyped]
8082
import torch # type: ignore[import-untyped]
83+
from PIL import Image # type: ignore[import-untyped]
8184

8285
pil_images = [Image.open(io.BytesIO(img)).convert("RGB") for img in images]
8386
processor, model, device = self._get_processor_and_model()

app/core/embedding/registry.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
from app.core.embedding.base import Embedder, EmbedderKind
2020
from app.core.embedding.cohere import CohereEmbedder
21-
from app.core.embedding.transformer import TransformerEmbedder
2221
from app.core.embedding.image import ImageEmbedder
22+
from app.core.embedding.transformer import TransformerEmbedder
2323

2424

2525
def _parse_embedder_uri(uri: str) -> tuple[EmbedderKind, str | None]:
@@ -54,11 +54,15 @@ def get_embedder(
5454
raise ValueError("COHERE_API_KEY is required for cohere embedder")
5555
return CohereEmbedder(api_key=api_key)
5656
if kind == EmbedderKind.EMBEDDING_TRANSFORMER:
57-
model_name = model or os.environ.get("EMBEDDING_TRANSFORMER_MODEL", "sentence-transformers/all-MiniLM-L6-v2")
57+
model_name = model or os.environ.get(
58+
"EMBEDDING_TRANSFORMER_MODEL", "sentence-transformers/all-MiniLM-L6-v2"
59+
)
5860
dev = device or os.environ.get("EMBEDDING_DEVICE")
5961
return TransformerEmbedder(model_name=model_name, device=dev)
6062
if kind == EmbedderKind.EMBEDDING_IMAGE:
61-
model_name = model or os.environ.get("EMBEDDING_IMAGE_MODEL", "openai/clip-vit-base-patch32")
63+
model_name = model or os.environ.get(
64+
"EMBEDDING_IMAGE_MODEL", "openai/clip-vit-base-patch32"
65+
)
6266
dev = device or os.environ.get("EMBEDDING_DEVICE")
6367
return ImageEmbedder(model_name=model_name, device=dev)
6468
raise ValueError(f"Unknown embedder URI: {uri}")

app/core/embedding/transformer.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
def _lazy_import() -> tuple[object, object]:
2222
import sentence_transformers # type: ignore[import-untyped]
23+
2324
return sentence_transformers.SentenceTransformer, sentence_transformers # type: ignore[attr-defined,no-any-return]
2425

2526

app/indexes/ivf.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ def build(
9393
for i, label in enumerate(labels):
9494
cluster_ids[label].append(ids[i])
9595
cluster_vectors[label].append(vectors[i])
96-
cluster_vectors_arr = [np.array(cv, dtype=np.float64) if cv else np.empty((0, d)) for cv in cluster_vectors]
96+
cluster_vectors_arr = [
97+
np.array(cv, dtype=np.float64) if cv else np.empty((0, d)) for cv in cluster_vectors
98+
]
9799
return cls(cluster_ids, cluster_vectors_arr, centroids, n_probe)
98100

99101
def search(self, query: list[float], k: int) -> SearchResult:

app/indexes/kd_tree.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@
1919
@dataclass
2020
class _Leaf:
2121
"""Leaf node: holds a single point (id, vector)."""
22+
2223
id: UUID
2324
vector: np.ndarray
2425

2526

2627
@dataclass
2728
class _Internal:
2829
"""Internal node: split dimension and value, left and right subtrees."""
30+
2931
split_dim: int
3032
split_value: float
3133
left: _Leaf | _Internal

0 commit comments

Comments
 (0)