Initial upload
This commit is contained in:
12
recipes/ai/memory/README.md
Normal file
12
recipes/ai/memory/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
# Memory Stack (External Ollama)
|
||||
|
||||
## Deploy
|
||||
```
|
||||
bash deploy.sh http://<OLLAMA-IP>:<PORT>
|
||||
```
|
||||
|
||||
## Test
|
||||
```
|
||||
curl http://localhost:8085/health
|
||||
```
|
||||
25
recipes/ai/memory/compose.yaml
Normal file
25
recipes/ai/memory/compose.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
|
||||
version: "3.8"
|
||||
services:
|
||||
qdrant:
|
||||
image: qdrant/qdrant:latest
|
||||
container_name: memory-qdrant
|
||||
volumes:
|
||||
- /srv/docker/services/memory/qdrant:/qdrant/storage
|
||||
ports:
|
||||
- "127.0.0.1:6333:6333"
|
||||
restart: unless-stopped
|
||||
|
||||
memory-api:
|
||||
build:
|
||||
context: ./memory-api
|
||||
container_name: memory-api
|
||||
environment:
|
||||
- QDRANT_URL=http://qdrant:6333
|
||||
- OLLAMA_API={{OLLAMA_API}}
|
||||
- COLLECTION_NAME=chat-memory
|
||||
ports:
|
||||
- "127.0.0.1:8085:8085"
|
||||
depends_on:
|
||||
- qdrant
|
||||
restart: unless-stopped
|
||||
32
recipes/ai/memory/deploy.sh
Normal file
32
recipes/ai/memory/deploy.sh
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ensure_root
|
||||
detect_pkg_manager
|
||||
install_docker
|
||||
|
||||
if ask_to_install "RAG Memory Stack (Qdrant + Memory API)"; then
|
||||
log "=== RAG Memory Stack Installation ==="
|
||||
|
||||
read -rp "Ollama API URL (z.B. http://127.0.0.1:11434): " OLLAMA_API_URL
|
||||
OLLAMA_API_URL=${OLLAMA_API_URL:-http://127.0.0.1:11434}
|
||||
|
||||
BASE="/srv/docker/services/memory"
|
||||
$SUDO mkdir -p "$BASE/qdrant"
|
||||
$SUDO cp -r "$(dirname "${BASH_SOURCE[0]}")/memory-api" "$BASE/"
|
||||
$SUDO cp "$(dirname "${BASH_SOURCE[0]}")/compose.yaml" "$BASE/docker-compose.yml"
|
||||
cd "$BASE"
|
||||
|
||||
$SUDO sed -i "s|{{OLLAMA_API}}|$OLLAMA_API_URL|g" docker-compose.yml
|
||||
|
||||
log "🚀 Starte RAG Memory Stack..."
|
||||
$SUDO docker compose up -d --build
|
||||
|
||||
log "Attempting to pull embedding model from remote Ollama..."
|
||||
$SUDO curl -s -X POST "$OLLAMA_API_URL/api/pull" -H 'Content-Type: application/json' -d '{"name": "nomic-embed-text"}' || log "Notice: Model pull failed (possibly using a gateway). Continuing."
|
||||
|
||||
log "✅ RAG Memory Stack läuft unter: http://<server-ip>:8085"
|
||||
else
|
||||
log "${YELLOW}⏭ RAG Memory Stack übersprungen.${NC}"
|
||||
fi
|
||||
8
recipes/ai/memory/memory-api/Dockerfile
Normal file
8
recipes/ai/memory/memory-api/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
FROM python:3.11-slim
|
||||
WORKDIR /app
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
COPY app.py .
|
||||
EXPOSE 8085
|
||||
CMD ["python", "app.py"]
|
||||
40
recipes/ai/memory/memory-api/app.py
Normal file
40
recipes/ai/memory/memory-api/app.py
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
from fastapi import FastAPI
|
||||
import requests, os
|
||||
from qdrant_client import QdrantClient
|
||||
from qdrant_client.models import PointStruct
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
QDRANT_URL = os.getenv("QDRANT_URL")
|
||||
OLLAMA_API = os.getenv("OLLAMA_API")
|
||||
COLLECTION_NAME = os.getenv("COLLECTION_NAME", "chat-memory")
|
||||
|
||||
client = QdrantClient(url=QDRANT_URL)
|
||||
|
||||
@app.get("/health")
|
||||
def health():
|
||||
return {"status": "ok", "qdrant": QDRANT_URL, "ollama": OLLAMA_API}
|
||||
|
||||
def embed(text):
|
||||
r = requests.post(f"{OLLAMA_API}/api/embeddings", json={"model":"nomic-embed-text","prompt":text})
|
||||
return r.json()["embedding"]
|
||||
|
||||
@app.post("/store")
|
||||
def store(item: dict):
|
||||
text = item["text"]
|
||||
metadata = item.get("metadata", {})
|
||||
vec = embed(text)
|
||||
pid = hashlib.sha256(text.encode()).hexdigest()
|
||||
client.upsert(collection_name=COLLECTION_NAME, points=[PointStruct(id=pid, vector=vec, payload={"text": text, **metadata})])
|
||||
return {"stored": True}
|
||||
|
||||
@app.post("/search")
|
||||
def search(query: dict):
|
||||
q = query["text"]
|
||||
top_k = query.get("top_k", 5)
|
||||
vec = embed(q)
|
||||
result = client.search(collection_name=COLLECTION_NAME, query_vector=vec, limit=top_k)
|
||||
return [{"score": r.score, "text": r.payload["text"]} for r in result]
|
||||
4
recipes/ai/memory/memory-api/requirements.txt
Normal file
4
recipes/ai/memory/memory-api/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
fastapi
|
||||
uvicorn
|
||||
requests
|
||||
qdrant-client
|
||||
Reference in New Issue
Block a user