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
16 changes: 4 additions & 12 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
# General
CONFIG_FILE=./config.yml
CONFIG_FILE=./config.example.yml

# Dependencies
OPENGATELLM_URL=https://albert.api.etalab.gouv.fr
OPENGATELLM_URL=http://localhost:8000
OPENGATELLM_MODEL_NAME=openweight-embedding
OPENGATELLM_MODEL_VECTOR_SIZE=1024

POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=postgres
POSTGRES_PASSWORD=changeme
## Must be the database of the API specified in OPENGATELLM_URL variable !
OPENGATELLM_DATABASE_URL=postgresql+asyncpg://postgres:changeme@localhost:5432/postgres

ELASTICSEARCH_HOST=localhost
ELASTICSEARCH_PORT=9200
ELASTICSEARCH_USERNAME=elastic
ELASTICSEARCH_PASSWORD=changeme

# For e2e tests
OPENGATELLM_USER_API_KEY=
OPENGATELLM_ADMIN_API_KEY=
26 changes: 19 additions & 7 deletions .github/tests/compose.yml
Original file line number Diff line number Diff line change
@@ -1,21 +1,33 @@
services:
postgres:
extends:
file: ../../compose.example.yml
service: postgres

elasticsearch:
extends:
file: ../../compose.example.yml
service: elasticsearch

postgres:
image: postgres:16.5
restart: always
user: postgres
environment:
- "POSTGRES_USER=postgres"
- "POSTGRES_PASSWORD=changeme"
- "POSTGRES_DB=postgres"
ports:
- "5432:5432"
volumes:
- postgres:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-U", "postgres" ]
interval: 4s
timeout: 10s
retries: 5
start_period: 60s

redis:
image: redis/redis-stack-server:7.4.0-v7
restart: always
environment:
REDIS_ARGS: "--dir /data --requirepass changeme --user redis on >password ~* allcommands --save 60 1 --appendonly yes"
ports:
- "6379:6379"
volumes:
- redis:/data
healthcheck:
Expand Down
18 changes: 16 additions & 2 deletions .github/tests/start_services.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,25 @@ dump_api_diagnostics() {
docker compose --file "${COMPOSE_FILE}" ps || true
echo "::endgroup::"

echo "::group::API container logs"
docker compose --file "${COMPOSE_FILE}" logs --no-color api || true
echo "::group::Docker Compose logs (all services)"
docker compose --file "${COMPOSE_FILE}" logs --no-color || true
echo "::endgroup::"

echo "::group::API health probe"
curl -sv "http://localhost:8000/health" || true
echo "::endgroup::"
}

on_error() {
exit_code=$?
line_no=${1:-unknown}
echo "start_services.sh failed (exit=${exit_code}) at line ${line_no}." >&2
dump_api_diagnostics
exit "${exit_code}"
}

trap 'on_error $LINENO' ERR

if ! docker compose --file "${COMPOSE_FILE}" up --detach --wait; then
echo "Services did not become healthy." >&2
dump_api_diagnostics
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/build_and_deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
name: Build and push OpenGateRAG image
runs-on: ubuntu-latest
env:
API_IMAGE_NAME: ghcr.io/etalab-ia/opengaterag
API_IMAGE_NAME: ghcr.io/opengaterag
IMAGE_TAG: ${{ github.event_name == 'release' && github.event.release.tag_name || 'latest' }}
outputs:
commit_title: ${{ steps.get_head_commit_title.outputs.title }}
Expand Down Expand Up @@ -52,7 +52,7 @@ jobs:
needs: build-opengaterag
uses: ./.github/workflows/trivy-scan.yml
with:
image-name: ghcr.io/etalab-ia/opengaterag
image-name: ghcr.io/opengaterag
image-tag: ${{ github.event_name == 'release' && github.event.release.tag_name || 'latest' }}

# deploy-dev:
Expand Down
12 changes: 12 additions & 0 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ jobs:
ALBERT_ADMIN_API_KEY: ${{ secrets.ALBERT_ADMIN_API_KEY }}
OPENGATELLM_MODEL_NAME: openweight-embeddings

- name: Dump Docker Compose logs on failure
if: failure()
run: |
echo "::group::Docker Compose status"
docker compose --file .github/tests/compose.yml ps || true
echo "::endgroup::"

echo "::group::Docker Compose logs (all services)"
docker compose --file .github/tests/compose.yml logs --no-color || true
echo "::endgroup::"

- name: Run e2e tests
run: |
# Create a local virtual environment and install dependencies
Expand All @@ -79,3 +90,4 @@ jobs:
OPENGATELLM_URL: http://localhost:8000
OPENGATELLM_MODEL_NAME: openweight-embeddings
OPENGATELLM_MODEL_VECTOR_SIZE: 1024
OPENGATELLM_DATABASE_URL: postgresql+asyncpg://postgres:changeme@localhost:5432/postgres
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
export $(cat .env | grep -v ^# | xargs)
```

> [!NOTE]
> The database setup by `OPENGATELLM_DATABASE_URL` environment variable must be the same as the database used by the API specified in `OPENGATELLM_URL` environment variable.

* Run API locally

```bash
Expand Down
37 changes: 1 addition & 36 deletions compose.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: opengatellm

services:
rag:
image: ghcr.io/etalab-ia/opengatellm/rag:latest
image: ghcr.io/opengaterag:latest
restart: always
env_file: .env
environment:
Expand All @@ -14,41 +14,6 @@ services:
healthcheck:
test: [ "CMD-SHELL", "curl -sf http://localhost:8000/health || exit 1" ]

postgres:
image: postgres:16.5
restart: always
user: postgres
environment:
- "POSTGRES_USER=${POSTGRES_USER:-postgres}"
- "POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-changeme}"
- "POSTGRES_DB=postgres"
ports:
- "${POSTGRES_PORT:-5432}:5432"
volumes:
- postgres:/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready", "-U", "postgres" ]
interval: 4s
timeout: 10s
retries: 5
start_period: 60s

redis:
image: redis/redis-stack-server:7.4.0-v7
restart: always
environment:
REDIS_ARGS: "--dir /data --requirepass ${REDIS_PASSWORD:-changeme} --user ${REDIS_USER:-redis} on >password ~* allcommands --save 60 1 --appendonly yes"
ports:
- "${REDIS_PORT:-6379}:6379"
volumes:
- redis:/data
healthcheck:
test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ]
interval: 4s
timeout: 10s
retries: 5
start_period: 60s

elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:9.0.2
restart: always
Expand Down
15 changes: 7 additions & 8 deletions config.example.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
# -------------------------------- dependencies ---------------------------------
dependencies:
opengatellm:
url: ${OPENGATELLM_URL:-https://albert.api.etalab.gouv.fr}
url: ${OPENGATELLM_URL:-http://localhost:8000}
model_name: ${OPENGATELLM_MODEL_NAME:-openweight-embedding}
model_vector_size: ${OPENGATELLM_MODEL_VECTOR_SIZE:-1024}

postgres: # required
url: postgresql+asyncpg://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-changeme}@${POSTGRES_HOST:-localhost}:${POSTGRES_PORT:-5432}/${POSTGRES_DB:-postgres}
postgres:
url: ${OPENGATELLM_DATABASE_URL:-postgresql+asyncpg://postgres:changeme@localhost:5432/postgres}
echo: False
pool_size: 5
connect_args:
server_settings:
statement_timeout: "120s"
command_timeout: 60


elasticsearch:
index_name: opengatellm
index_language: english
index_name: opengaterag
index_language: french
number_of_shards: 1
number_of_replicas: 0
refresh_interval: 1s
Expand All @@ -30,13 +29,13 @@ dependencies:
settings:
# disabled_routers: ["collections"]
# hidden_routers: ["documents"]
# app_title: My OpenGateLLM API
# app_title: My OpenGateRAG API

# log_level: INFO
# log_format: [%(asctime)s][%(process)d:%(name)s][%(levelname)s] %(client_ip)s - %(message)s

swagger_version: 0.1.0
# swagger_contact_url: https://github.com/etalab-ia/OpenGateLLM
# swagger_contact_url: https://github.com/etalab-ia/OpenGateRAG
# swagger_contact_email: john.doe@example.com
# swagger_docs_url: /docs
# swagger_redoc_url: /redoc
Expand Down
12 changes: 6 additions & 6 deletions opengaterag/api/utils/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ class ConfigBaseModel(BaseModel):
@custom_validation_error()
class ElasticsearchDependency(ConfigBaseModel):
"""
Elasticsearch is an optional dependency of OpenGateLLM. Elasticsearch is used as a vector store. If this dependency is provided, all documents endpoint are enabled.
Elasticsearch is a required dependency of OpenGateRAG. Elasticsearch is used as a vector store. If this dependency is provided, all documents endpoint are enabled.
Pass all arguments of `elasticsearch.Elasticsearch` class, see https://elasticsearch-py.readthedocs.io/en/latest/api/elasticsearch.html for more information.
Other arguments declared below are used to configure the Elasticsearch index.
"""

index_name: constr(strip_whitespace=True, min_length=1) = Field(default="opengatellm", description="Name of the Elasticsearch index.", examples=["my_index"]) # fmt: off
index_name: constr(strip_whitespace=True, min_length=1) = Field(default="opengaterag", description="Name of the Elasticsearch index.", examples=["my_index"]) # fmt: off
index_language: ElasticsearchIndexLanguage = Field(default=ElasticsearchIndexLanguage.ENGLISH, description="Language of the Elasticsearch index.", examples=[ElasticsearchIndexLanguage.ENGLISH.value]) # fmt: off
number_of_shards: int = Field(default=12, ge=1, le=75, description="Number of shards for the Elasticsearch index.", examples=[4]) # fmt: off
number_of_replicas: int = Field(default=1, ge=0, description="Number of replicas for the Elasticsearch index.", examples=[1]) # fmt: off
Expand All @@ -125,7 +125,7 @@ class OpengateLLMDependency(ConfigBaseModel):
@custom_validation_error()
class PostgresDependency(ConfigBaseModel):
"""
Postgres is a required dependency of OpenGateLLM. In this section, you can pass all postgres python SDK arguments, see https://docs.sqlalchemy.org/en/21/core/engines.html#engine-creation-apihttps://docs.sqlalchemy.org/en/21/core/engines.html#engine-creation-api for more information.
Postgres is a required dependency of OpenGateRAG. In this section, you can pass all postgres python SDK arguments, see https://docs.sqlalchemy.org/en/21/core/engines.html#engine-creation-apihttps://docs.sqlalchemy.org/en/21/core/engines.html#engine-creation-api for more information.
Only the `url` argument is required. The connection URL must use the asynchronous scheme, `postgresql+asyncpg://`. If you provide a standard `postgresql://` URL, it will be automatically converted to use asyncpg.
"""

Expand Down Expand Up @@ -194,11 +194,11 @@ class Settings(ConfigBaseModel):
usage_tokenizer: Tokenizer = Field(default=Tokenizer.TIKTOKEN_GPT2, description="Tokenizer used to compute usage of the API.")

# swagger
swagger_summary: str = Field(default="OpenGateLLM connect to your models. You can configuration this swagger UI in the configuration file, like hide routes or change the title.", description="Display summary of your API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", examples=["My API description."]) # fmt: off
swagger_summary: str = Field(default="You can configuration this swagger UI in the configuration file, like hide routes or change the title.", description="Display summary of your API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", examples=["My API description."]) # fmt: off
swagger_version: str = Field(default="latest", description="Display version of your API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", examples=["2.5.0"]) # fmt: off
swagger_description: str = Field(default="[See documentation](https://github.com/etalab-ia/opengatellm/blob/main/README.md)", description="Display description of your API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", examples=["[See documentation](https://github.com/etalab-ia/opengatellm/blob/main/README.md)"]) # fmt: off
swagger_description: str = Field(default="[See documentation](https://github.com/etalab-ia/opengaterag/blob/main/README.md)", description="Display description of your API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", examples=["[See documentation](https://github.com/etalab-ia/opengaterag/blob/main/README.md)"]) # fmt: off
swagger_contact: dict | None = Field(default=None, description="Contact informations of the API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.") # fmt: off
swagger_license_info: dict = Field(default={"name": "MIT Licence", "identifier": "MIT", "url": "https://raw.githubusercontent.com/etalab-ia/opengatellm/refs/heads/main/LICENSE"}, description="Licence informations of the API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.") # fmt: off
swagger_license_info: dict = Field(default={"name": "MIT Licence", "identifier": "MIT", "url": "https://raw.githubusercontent.com/etalab-ia/opengaterag/refs/heads/main/LICENSE"}, description="Licence informations of the API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.") # fmt: off
swagger_terms_of_service: str | None = Field(default=None, description="A URL to the Terms of Service for the API in swagger UI. If provided, this has to be a URL.", examples=["https://example.com/terms-of-service"]) # fmt: off
swagger_openapi_tags: list[dict[str, str | dict[str, str]]] = Field(default_factory=list, description="OpenAPI tags of the API in swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.", json_schema_extra={"default": []}) # fmt: off
swagger_openapi_url: str = Field(default="/openapi.json", pattern=r"^/", description="OpenAPI URL of swagger UI, see https://fastapi.tiangolo.com/tutorial/metadata for more information.") # fmt: off
Expand Down
Loading