Skip to content
Merged
Show file tree
Hide file tree
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
53 changes: 24 additions & 29 deletions .github/workflows/api_tests/mock_vllm.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import hashlib
import time
import uuid
from typing import Any, List, Optional, Union
from typing import Any

from fastapi import FastAPI
from pydantic import BaseModel
Expand All @@ -22,19 +22,19 @@

class EmbeddingRequest(BaseModel):
model: str
input: Union[str, List[str]]
input: str | list[str]
encoding_format: str = "float"


class EmbeddingData(BaseModel):
object: str = "embedding"
embedding: List[float]
embedding: list[float]
index: int


class EmbeddingResponse(BaseModel):
object: str = "list"
data: List[EmbeddingData]
data: list[EmbeddingData]
model: str
usage: dict

Expand All @@ -49,13 +49,13 @@ class ChatMessage(BaseModel):

class ChatCompletionRequest(BaseModel):
model: str
messages: List[ChatMessage]
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = 1024
stream: Optional[bool] = False
top_p: Optional[float] = 1.0
n: Optional[int] = 1
stop: Optional[Union[str, List[str]]] = None
messages: list[ChatMessage]
temperature: float | None = 0.7
max_tokens: int | None = 1024
stream: bool | None = False
top_p: float | None = 1.0
n: int | None = 1
stop: str | list[str] | None = None


class ChatCompletionChoice(BaseModel):
Expand All @@ -75,7 +75,7 @@ class ChatCompletionResponse(BaseModel):
object: str = "chat.completion"
created: int
model: str
choices: List[ChatCompletionChoice]
choices: list[ChatCompletionChoice]
usage: ChatCompletionUsage


Expand All @@ -84,13 +84,13 @@ class ChatCompletionResponse(BaseModel):

class TextCompletionRequest(BaseModel):
model: str
prompt: Union[str, List[str]]
temperature: Optional[float] = 0.7
max_tokens: Optional[int] = 1024
stream: Optional[bool] = False
top_p: Optional[float] = 1.0
n: Optional[int] = 1
stop: Optional[Union[str, List[str]]] = None
prompt: str | list[str]
temperature: float | None = 0.7
max_tokens: int | None = 1024
stream: bool | None = False
top_p: float | None = 1.0
n: int | None = 1
stop: str | list[str] | None = None


class TextCompletionChoice(BaseModel):
Expand All @@ -104,14 +104,14 @@ class TextCompletionResponse(BaseModel):
object: str = "text_completion"
created: int
model: str
choices: List[TextCompletionChoice]
choices: list[TextCompletionChoice]
usage: ChatCompletionUsage # Same structure as chat


# ============== Helper Functions ==============


def generate_fake_embedding(text: str, dim: int = EMBEDDING_DIM) -> List[float]:
def generate_fake_embedding(text: str, dim: int = EMBEDDING_DIM) -> list[float]:
"""Generate deterministic fake embedding based on text hash."""
h = hashlib.md5(text.encode()).digest()
result = []
Expand All @@ -128,7 +128,7 @@ def count_tokens(text: str) -> int:
return 10 # Default for non-string content


def generate_mock_response(messages: List[ChatMessage]) -> str:
def generate_mock_response(messages: list[ChatMessage]) -> str:
"""Generate a mock response based on the input messages."""
last_message = messages[-1] if messages else None
if not last_message:
Expand Down Expand Up @@ -180,10 +180,7 @@ async def list_models():
async def create_embeddings(request: EmbeddingRequest) -> EmbeddingResponse:
inputs = request.input if isinstance(request.input, list) else [request.input]

data = [
EmbeddingData(embedding=generate_fake_embedding(text), index=i)
for i, text in enumerate(inputs)
]
data = [EmbeddingData(embedding=generate_fake_embedding(text), index=i) for i, text in enumerate(inputs)]

return EmbeddingResponse(
data=data,
Expand All @@ -196,9 +193,7 @@ async def create_embeddings(request: EmbeddingRequest) -> EmbeddingResponse:
async def create_chat_completion(request: ChatCompletionRequest) -> ChatCompletionResponse:
"""Mock chat completion endpoint for LLM/VLM requests."""
# Calculate token counts
prompt_tokens = sum(
count_tokens(str(msg.content)) for msg in request.messages
)
prompt_tokens = sum(count_tokens(str(msg.content)) for msg in request.messages)

# Generate mock response
response_text = generate_mock_response(request.messages)
Expand Down
52 changes: 52 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Linting

on:
push:
branches: [ main, dev ]

# Temporarily disabled until merge
# pull_request:
# branches: [ main, dev ]

jobs:
lint:
runs-on: ubuntu-latest

strategy:
matrix:
python-version: ["3.12"]

steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.local/bin" >> $GITHUB_PATH
Comment on lines +28 to +31

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the actual workflow file to confirm the current implementation
find . -type f -name "lint.yml" -path "*/.github/workflows/*"

Repository: linagora/openrag

Length of output: 88


🌐 Web query:

astral-sh/setup-uv GitHub Action documentation

💡 Result:

I found the official documentation and README for the astral-sh/setup-uv GitHub Action:

  • Repository README (usage, inputs, outputs, advanced config, FAQ). Example install: uses: astral-sh/setup-uv@v7. Includes inputs like version, version-file, python-version, activate-environment, working-directory, checksum; outputs like uv-version, uv-path, venv, cache-hit. [1]

  • Astral docs guide for using uv in GitHub Actions (recommendation and example, showing pinning uv via the action). [2]

  • GitHub Marketplace entry for the action. [3]

If you want, I can paste the README sections (usage, inputs, outputs) or produce a ready-to-drop workflow snippet tailored to your OS and Python matrix.


🌐 Web query:

uv package manager latest version 2025 2026

💡 Result:

As of Jan 15, 2026:

  • Latest uv release: 0.9.25 — released Jan 13, 2026. [1][2]
  • Latest release in 2025: 0.9.21 — released Dec 30, 2025. [3]

Sources: GitHub Releases (uv 0.9.25) [1], PyPI (uv 0.9.25) [2], GitHub release list showing 2025 tags (0.9.21 on Dec 30, 2025) [3].


🏁 Script executed:

# Let's examine the actual lint.yml workflow file
cat -n ./.github/workflows/lint.yml

Repository: linagora/openrag

Length of output: 1568


Use the official astral-sh/setup-uv action for better reproducibility and maintenance.

The curl | sh approach installs the latest uv version, which lacks reproducibility. Instead, use the astral-sh/setup-uv action (v7), which provides version pinning, automatic caching, and is maintained by Astral.

♻️ Suggested replacement
-      - name: Install uv
-        run: |
-          curl -LsSf https://astral.sh/uv/install.sh | sh
-          echo "$HOME/.local/bin" >> $GITHUB_PATH
-
-      - name: Cache uv
-        uses: actions/cache@v4
-        with:
-          path: |
-            ~/.cache/uv
-          key: uv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml', '**/uv.lock') }}
-          restore-keys: |
-            uv-${{ runner.os }}-${{ matrix.python-version }}-
+      - name: Install uv
+        uses: astral-sh/setup-uv@v7
+        with:
+          version: "0.9.25"

This eliminates the manual cache step since setup-uv handles caching automatically.

🤖 Prompt for AI Agents
In @.github/workflows/lint.yml around lines 26 - 29, Replace the manual curl
installer block that adds uv (the "Install uv" step) with the official
astral-sh/setup-uv action (use astral-sh/setup-uv@v7) to pin the version and
enable automatic caching; remove the manual $HOME/.local/bin append and any
separate caching steps since setup-uv manages them, and pass a pinned version
via the action's "version" input to ensure reproducible installs.


- name: Cache uv
uses: actions/cache@v4
with:
path: |
~/.cache/uv
key: uv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('**/pyproject.toml', '**/uv.lock') }}
restore-keys: |
uv-${{ runner.os }}-${{ matrix.python-version }}-

- name: Install dependencies with uv
run: |
uv sync --group lint

- name: Run Ruff linting
run: |
uv run ruff check . --output-format=github

- name: Check formatting
run: |
uv run ruff format --check .
148 changes: 148 additions & 0 deletions LINTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Linting Setup Guide

This project uses **Ruff** for Python linting and code formatting. All developers must ensure their code passes linting checks before submitting pull requests.

## Installation

The linting dependencies are already included in `pyproject.toml`. Install them with:

```bash
uv sync --group lint
```

Or install all groups including dev:

```bash
uv sync
```

## Running Linting Locally

### Check for linting issues

```bash
uv run ruff check .
```

### Auto-fix linting issues

```bash
uv run ruff check . --fix
```

### Check code formatting

```bash
uv run ruff format --check .
```

### Auto-format code

```bash
uv run ruff format .
```

## Ruff Configuration

Ruff configuration is defined in `pyproject.toml` under `[tool.ruff]` and `[tool.ruff.lint]` sections.

### Key Rules Enabled

- **E, W**: PEP 8 errors and warnings
- **F**: Pyflakes (undefined names, unused imports)
- **I**: isort-style import sorting
- **C4**: flake8-comprehensions (optimization suggestions)
- **UP**: pyupgrade (modernize Python code)
- **PIE**: flake8-pie (misc linting rules)
- **RUF**: Ruff-specific rules (**`not applied currently`**)

### Excluded Directories

The following directories are excluded from linting:
- `.git`, `.venv`, `.pytest_cache`, `.ruff_cache`, `.vscode`
- `node_modules`, `vdb`, `ray_mount`, `model_weights`, `logs`
- `.astro`, `openrag.egg-info`

## CI/CD Integration

A GitHub Actions workflow (`.github/workflows/lint.yml`) automatically runs on every push and pull request. The workflow:

1. Checks for linting issues with `ruff check`
2. Verifies code formatting with `ruff format --check`
3. Reports results directly to GitHub (with file and line annotations)

### Pull Request Requirements

All pull requests must pass the linting CI check. If your PR fails:

1. Run `uv run ruff check . --fix` to auto-fix issues
2. Run `uv run ruff format .` to format the code
3. Review any remaining issues that require manual fixes
4. Commit and push your changes

## Pre-commit Hook (Optional)
One can also setup a pre-commit hook to run linting automatically before each commit.

```bash
cat > .git/hooks/pre-commit << 'EOF'
#!/bin/bash

# Get list of staged Python files
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep '\.py$')

if [ -z "$FILES" ]; then
exit 0
fi

# Run ruff check (will auto-fix if possible)
echo "Running ruff check..."
uv run ruff check $FILES --fix

# Run ruff format
echo "Running ruff format..."
uv run ruff format $FILES

# Re-add the modified files
git add $FILES

# Run ruff check again without --fix to catch remaining errors
echo "Checking for remaining issues..."
uv run ruff check $FILES

# If ruff check fails, block the commit
if [ $? -ne 0 ]; then
echo "Ruff check failed. Please fix errors before committing."
exit 1
fi

exit 0
EOF

chmod +x .git/hooks/pre-commit
```
Comment thread
coderabbitai[bot] marked this conversation as resolved.

* To disable pre-commit

```bash
rm .git/hooks/pre-commit
```

## Troubleshooting

### "ruff: command not found"
Make sure you've installed the lint dependencies:
```bash
uv sync --group lint
```

### Auto-fix doesn't resolve all issues
Some issues require manual fixes. Review the error messages and fix them manually, then commit again.
Sometimes, you will have to ignore a particular check if deemed unnecessary

```python
# Example: C417 rule suggest that map here is unnecessary
Comment thread
Ahmath-Gadji marked this conversation as resolved.


docs_with_tokens = list(map(lambda d: (_length_function(d.page_content), d), docs)) # noqa: C417

```
Loading