diff --git a/Dockerfile b/Dockerfile index 0a7b336..df4dc8a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,10 +28,10 @@ COPY --from=builder /app/wheels /wheels RUN pip install --no-cache-dir /wheels/* # Copy application code -COPY companion/ ./companion/ -COPY companion/forge/ ./companion/forge/ -COPY companion/indexer_daemon/ ./companion/indexer_daemon/ -COPY companion/rag/ ./companion/rag/ +COPY src/companion/ ./companion/ +COPY src/companion/forge/ ./companion/forge/ +COPY src/companion/indexer_daemon/ ./companion/indexer_daemon/ +COPY src/companion/rag/ ./companion/rag/ # Create directories for data RUN mkdir -p /data/vectors /data/memory /models diff --git a/Dockerfile.indexer b/Dockerfile.indexer index 6c81024..9ead366 100644 --- a/Dockerfile.indexer +++ b/Dockerfile.indexer @@ -13,9 +13,9 @@ RUN pip install --no-cache-dir \ pydantic lancedb pyarrow requests watchdog typer rich numpy httpx # Copy application code -COPY companion/ ./companion/ -COPY companion/indexer_daemon/ ./companion/indexer_daemon/ -COPY companion/rag/ ./companion/rag/ +COPY src/companion/ ./companion/ +COPY src/companion/indexer_daemon/ ./companion/indexer_daemon/ +COPY src/companion/rag/ ./companion/rag/ # Create directories for data RUN mkdir -p /data/vectors diff --git a/config.json b/config.json index 9062ee0..06bf052 100644 --- a/config.json +++ b/config.json @@ -55,7 +55,7 @@ "rag": { "embedding": { "provider": "ollama", - "model": "mxbai-embed-large", + "model": "mxbai-embed-large:335m", "base_url": "http://localhost:11434", "dimensions": 1024, "batch_size": 32 diff --git a/docker-compose.yml b/docker-compose.yml index 6e1f18d..d94c309 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: "3.8" services: companion-api: @@ -20,7 +20,13 @@ services: - companion-network restart: unless-stopped healthcheck: - test: ["CMD", "python", "-c", "import requests; requests.get('http://localhost:7373/health')"] + test: + [ + "CMD", + "python", + "-c", + "import requests; requests.get('http://localhost:7373/health')", + ] interval: 30s timeout: 10s retries: 3 @@ -34,7 +40,7 @@ services: volumes: - ./config.json:/app/config.json:ro - companion-data:/data - - /home/san/KnowledgeVault:/vault:ro # Mount Obsidian vault as read-only + - ./sample-data/Default:/app/sample-data/Default:ro # Mount Obsidian vault as read-only environment: - COMPANION_CONFIG=/app/config.json - COMPANION_DATA_DIR=/data diff --git a/pyproject.toml b/pyproject.toml index 8002fe9..3f7ea84 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ train = [ "trl>=0.7.0", ] -[tool.hatchling] +[tool.hatch.build.targets.wheel] packages = ["src/companion"] [build-system] diff --git a/src/companion/api.py b/src/companion/api.py index 2dc6015..54d557c 100644 --- a/src/companion/api.py +++ b/src/companion/api.py @@ -70,8 +70,7 @@ async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: orchestrator = ChatOrchestrator( config=config, search_engine=search_engine, - memory=memory, - http_client=http_client, + session_memory=memory, ) yield diff --git a/src/companion/rag/chunker.py b/src/companion/rag/chunker.py index 4c9c9f6..e66359d 100644 --- a/src/companion/rag/chunker.py +++ b/src/companion/rag/chunker.py @@ -28,16 +28,27 @@ class ChunkingRule: def sliding_window_chunks(text: str, chunk_size: int, chunk_overlap: int) -> List[str]: - words = text.split() - if not words: + """Split text into chunks based on character count (not word count).""" + if not text: return [] chunks = [] step = chunk_size - chunk_overlap - for i in range(0, len(words), step): - chunk_words = words[i : i + chunk_size] - chunks.append(" ".join(chunk_words)) - if i + chunk_size >= len(words): + start = 0 + text_len = len(text) + + while start < text_len: + end = min(start + chunk_size, text_len) + # Try to break at word boundary + if end < text_len: + # Look for whitespace to break at + while end > start and not text[end].isspace(): + end -= 1 + if end == start: # No good break found, force cut + end = min(start + chunk_size, text_len) + chunks.append(text[start:end].strip()) + start += step + if end >= text_len: break return chunks