-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/Anything LLM UI #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
profotoce59
wants to merge
4
commits into
main
Choose a base branch
from
feat/openweb-ui
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| FROM python:3.11-slim | ||
|
|
||
| WORKDIR /app | ||
|
|
||
| ENV PYTHONDONTWRITEBYTECODE=1 | ||
| ENV PYTHONUNBUFFERED=1 | ||
|
|
||
| COPY requirements.txt /app/requirements.txt | ||
| RUN pip install --no-cache-dir -r /app/requirements.txt | ||
|
|
||
| COPY app /app/app | ||
| COPY vector-store /app/vector-store | ||
|
|
||
| EXPOSE 8000 | ||
|
|
||
| CMD ["sh", "-lc", "uvicorn app.main:app --host 0.0.0.0 --port ${CHATBOT_API_INTERNAL_PORT}"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,45 +1,108 @@ | ||
| # Chatbot | ||
|
|
||
| ## Export BookStack pages to PDF | ||
| This project provides: | ||
| - BookStack page export to PDF | ||
| - Vector store indexing (Chroma) | ||
| - A RAG chatbot API (OpenAI-compatible endpoints) | ||
| - An Open WebUI interface connected to the RAG API | ||
|
|
||
| ### Prerequisites | ||
| - Python 3.9+ | ||
| - BookStack API token (token id + token secret) | ||
| - BookStack URL | ||
| ## Prerequisites | ||
|
|
||
| - Python 3.11+ | ||
| - Docker + Docker Compose | ||
| - OpenAI API key with active billing/quota | ||
| - BookStack API token (for export only) | ||
|
|
||
| ## Environment setup | ||
|
|
||
| Create `.env` from `.env.example` and fill values: | ||
|
|
||
| ```env | ||
| OPENAI_API_KEY=sk-proj-your-api-key | ||
| MODEL_LLM=yout_model | ||
| MODEL_EMBEDDING=your_embedding_model | ||
|
|
||
| BOOKSTACK_URL=your_url | ||
| BOOKSTACK_TOKEN_ID=your_bookstack_token_id | ||
| BOOKSTACK_TOKEN_SECRET=your_bookstack_token_secret | ||
|
|
||
| CHATBOT_API_BIND_IP=IP | ||
| CHATBOT_API_HOST_PORT=PORT | ||
| CHATBOT_API_INTERNAL_PORT=PORT | ||
| ANYTHINGLLM_BIND_IP=IP | ||
| ANYTHINGLLM_HOST_PORT=PORT | ||
| ``` | ||
|
|
||
| ## Python setup | ||
|
|
||
| ### Setup | ||
| 1. Create a virtual environment | ||
| ```bash | ||
| python -m venv .venv | ||
| source .venv/bin/activate | ||
| pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| 2. Install dependencies | ||
| ## 1) Export BookStack pages as PDFs | ||
|
|
||
| ```bash | ||
| pip install -r requirements.txt | ||
| python export_pages.py | ||
| ``` | ||
|
|
||
| 3. Create a `.env` file (or update it) at the project root: | ||
| ```env | ||
| BOOKSTACK_URL=your_bookstack_url | ||
| BOOKSTACK_TOKEN_ID=your_token_id | ||
| BOOKSTACK_TOKEN_SECRET=your_token_secret | ||
| ``` | ||
| PDF files are written to `exports/`. | ||
|
|
||
| ## 2) Build / refresh vector store | ||
|
|
||
| ## To run a notebook | ||
| ```bash | ||
| pip install jupyter ipykernel | ||
| python -m ipykernel install --user --name chatbot-venv --display-name "Python (chatbot-venv)" | ||
| jupyter notebook | ||
| python reload_vector_store.py | ||
| ``` | ||
|
|
||
| ### Run the export | ||
| This indexes documents from `exports/` into `vector-store/`. | ||
|
|
||
| ## 3) Run chatbot API + Open WebUI | ||
|
|
||
| ```bash | ||
| python export_pages.py | ||
| docker compose up --build | ||
| ``` | ||
|
|
||
| PDFs will be saved to `exports/` | ||
| Access: | ||
| - AnythingLLM: `http://localhost:${ANYTHINGLLM_HOST_PORT}` (default: `3001`) | ||
| - Chatbot API health: `http://localhost:${CHATBOT_API_HOST_PORT}/health` (default: `8000`) | ||
|
|
||
| Open WebUI is configured to call the local chatbot backend through OpenAI-compatible routes: | ||
| - `GET /v1/models` | ||
| - `POST /v1/chat/completions` | ||
|
|
||
| ## 4) Expose AnythingLLM on internet (secure minimal setup) | ||
|
|
||
| Files: | ||
| - `docker-compose.anythingllm.secure.yml` | ||
| - `deploy/Caddyfile` | ||
|
|
||
| This stack puts Caddy in front of AnythingLLM: | ||
| - HTTPS with automatic TLS certificates | ||
| - HTTP Basic Auth at proxy level | ||
| - AnythingLLM not exposed directly (internal only) | ||
|
|
||
| Steps: | ||
|
|
||
| 1. Create env file: | ||
|
|
||
| docker compose up | ||
|
|
||
| # Pricing OPenAI | ||
| Pour un rechargement de base on utilise en moyenne 67 000 tokens soit 1/7 centimes. | ||
| Une question côut 1/40 centimes (une toute simple). | ||
| Security notes: | ||
| - Keep AnythingLLM built-in auth enabled (multi-user recommended for internet exposure). | ||
| - Disable public signup inside AnythingLLM unless explicitly needed. | ||
| - Keep `OPENAI_API_KEY` only inside server env, never in frontend code. | ||
|
|
||
| ## 5) Automatize the vector store reload : | ||
| Create a job to automatically update the vectore store weekly : | ||
| CRON_TZ=Europe/Paris | ||
| 0 7 * * 1 chatbot/reload_job.sh >> chatbot/reindex.log 2>&1 | ||
|
|
||
|
|
||
| ## Optional: notebooks | ||
|
|
||
| ```bash | ||
| pip install jupyter ipykernel | ||
| python -m ipykernel install --user --name chatbot-venv --display-name "Python (chatbot-venv)" | ||
| jupyter notebook | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| #!/usr/bin/env python3 | ||
| import json | ||
| import os | ||
| import time | ||
| import uuid | ||
| from typing import Any | ||
|
|
||
| from fastapi import FastAPI, HTTPException | ||
| from fastapi.responses import StreamingResponse | ||
| from pydantic import BaseModel | ||
|
|
||
| BACKEND_MODEL_ID = os.getenv("BACKEND_MODEL_ID", "chatbot-rag") | ||
|
|
||
|
|
||
| class ChatMessage(BaseModel): | ||
| role: str | ||
| content: Any | ||
|
|
||
|
|
||
| class ChatCompletionRequest(BaseModel): | ||
| model: str | None = None | ||
| messages: list[ChatMessage] | ||
| temperature: float | None = None | ||
| stream: bool | None = False | ||
| max_tokens: int | None = None | ||
|
|
||
|
|
||
| app = FastAPI(title="Chatbot API", version="0.1.0") | ||
|
|
||
|
|
||
| @app.get("/v1/models") | ||
| def list_models() -> dict[str, Any]: | ||
| return { | ||
| "object": "list", | ||
| "data": [ | ||
| { | ||
| "id": BACKEND_MODEL_ID, | ||
| "object": "model", | ||
| "owned_by": "chatbot", | ||
| } | ||
| ], | ||
| } | ||
|
|
||
|
|
||
| @app.post("/v1/chat/completions") | ||
| def chat_completions(request: ChatCompletionRequest): | ||
| if not request.messages: | ||
| raise HTTPException(status_code=400, detail="messages is required") | ||
|
|
||
| answer = f"Reponse bidon API." | ||
| created = int(time.time()) | ||
| completion_id = f"chatcmpl-{uuid.uuid4().hex[:24]}" | ||
| model_id = request.model or BACKEND_MODEL_ID | ||
|
|
||
| if request.stream: | ||
| ##réponse compatible ANYTHINGLLM | ||
| def event_stream(): | ||
| chunk_1 = { | ||
| "id": completion_id, | ||
| "object": "chat.completion.chunk", | ||
| "created": created, | ||
| "model": model_id, | ||
| "choices": [{"index": 0, "delta": {"role": "assistant"}, "finish_reason": None}], | ||
| } | ||
| yield f"data: {json.dumps(chunk_1)}\n\n" | ||
|
|
||
| chunk_2 = { | ||
| "id": completion_id, | ||
| "object": "chat.completion.chunk", | ||
| "created": created, | ||
| "model": model_id, | ||
| "choices": [{"index": 0, "delta": {"content": answer}, "finish_reason": None}], | ||
| } | ||
| yield f"data: {json.dumps(chunk_2)}\n\n" | ||
|
|
||
| chunk_3 = { | ||
| "id": completion_id, | ||
| "object": "chat.completion.chunk", | ||
| "created": created, | ||
| "model": model_id, | ||
| "choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}], | ||
| } | ||
| yield f"data: {json.dumps(chunk_3)}\n\n" | ||
| yield "data: [DONE]\n\n" | ||
|
|
||
| return StreamingResponse(event_stream(), media_type="text/event-stream") | ||
|
|
||
| return { | ||
| "id": completion_id, | ||
| "object": "chat.completion", | ||
| "created": created, | ||
| "model": model_id, | ||
| "choices": [ | ||
| { | ||
| "index": 0, | ||
| "message": {"role": "assistant", "content": answer}, | ||
| "finish_reason": "stop", | ||
| } | ||
| ], | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| services: | ||
| chatbot-api: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile.api | ||
| container_name: chatbot-api-local | ||
| env_file: | ||
| - .env | ||
| environment: | ||
| - VECTOR_STORE_DIR=/app/vector-store | ||
| - COLLECTION_NAME=collection_test | ||
| - TOP_K=4 | ||
| - BACKEND_MODEL_ID=chatbot-rag | ||
| volumes: | ||
| - ./vector-store:/app/vector-store | ||
| ports: | ||
| - "${CHATBOT_API_BIND_IP}:${CHATBOT_API_HOST_PORT}:${CHATBOT_API_INTERNAL_PORT}" | ||
| restart: unless-stopped | ||
|
|
||
| anythingllm: | ||
| image: mintplexlabs/anythingllm:latest | ||
| container_name: anythingllm-local | ||
| depends_on: | ||
| - chatbot-api | ||
| cap_add: | ||
| - SYS_ADMIN | ||
| env_file: | ||
| - .env | ||
| environment: | ||
| - STORAGE_DIR=/app/server/storage | ||
| - GENERIC_OPEN_AI_BASE_PATH=http://chatbot-api:${CHATBOT_API_INTERNAL_PORT}/v1 | ||
| - OPEN_AI_BASE_PATH=http://chatbot-api:${CHATBOT_API_INTERNAL_PORT}/v1 | ||
| - AUTH_TOKEN=${ANYLLM_ADMIN_PASSWORD} | ||
| - JWT_SECRET=${JWT_SECRET} | ||
| extra_hosts: | ||
| - "host.docker.internal:host-gateway" | ||
| volumes: | ||
| - anythingllm-local-storage:/app/server/storage | ||
| ports: | ||
| - "${ANYTHINGLLM_BIND_IP}:${ANYTHINGLLM_HOST_PORT}:${ANYTHINGLLM_HOST_PORT}" | ||
| restart: unless-stopped | ||
|
|
||
| volumes: | ||
| anythingllm-local-storage: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
| COMPOSE_FILE="$PROJECT_DIR/docker-compose.yml" | ||
| LOCK_DIR="/tmp/chatbot-reindex-lock" | ||
|
|
||
| # Prevent overlapping runs. | ||
| if ! mkdir "$LOCK_DIR" 2>/dev/null; then | ||
| echo "[reindex] another run is already in progress" | ||
| exit 0 | ||
| fi | ||
| trap 'rmdir "$LOCK_DIR"' EXIT | ||
|
|
||
| cd "$PROJECT_DIR" | ||
|
|
||
| echo "[reindex] starting export + vector store reload" | ||
| docker compose -f "$COMPOSE_FILE" run --rm --no-deps --build \ | ||
| -v "$PROJECT_DIR:/work" \ | ||
| -w /work \ | ||
| chatbot-api \ | ||
| sh -lc "python export_pages.py && python reload_vector_store.py" | ||
| echo "[reindex] done" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| python-dotenv>=1.0.0 | ||
| fastapi>=0.115.0 | ||
| uvicorn[standard]>=0.30.0 | ||
| langchain-openai | ||
| langchain_chroma | ||
| langchain-text-splitters | ||
| langchain-community | ||
| langgraph | ||
| pathlib | ||
| tqdm | ||
| pypdf | ||
| pypdf |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Il sert à quoi ce fichier ?☺️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
C'est pour dire que le dossier est un package et pouvoir ensuite l'exporter depuis d'autre fichier en dehors de ce dossier