feat(deploy): support GRAPH_BACKEND, NEO4J_* and LLM_PROVIDER in Azure deploy

- Dockerfile installs graphiti optional extras so any GRAPH_BACKEND works at runtime
- container-app.bicep adds graphBackend, neo4jUri/User/Password and llmProvider params
- 2-build-deploy.sh validates graph backend config and passes all new vars to Bicep
- config.sh.example documents new variables with inline guidance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ubuntu 2026-04-25 13:37:12 +00:00
parent d2ee1d3d5f
commit 4fceef609d
5 changed files with 106 additions and 7 deletions

View File

@ -28,7 +28,8 @@ WORKDIR /app
# Copiar i instal·lar dependències Python (aprofita caché si pyproject.toml no canvia)
COPY backend/pyproject.toml backend/uv.lock ./backend/
RUN cd backend && uv sync --frozen --no-dev
# Install all optional extras so the image supports any GRAPH_BACKEND at runtime
RUN cd backend && uv sync --frozen --no-dev --extra graphiti
# Copiar el codi font del backend i els fitxers compartits
COPY backend/ ./backend/

View File

@ -29,8 +29,18 @@ REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
# ── Validar variables obligatòries ───────────────────────────────────────────
REQUIRED_VARS=(
AZURE_SUBSCRIPTION_ID RESOURCE_GROUP PROJECT_NAME
DEMO_PASSWORD SECRET_KEY LLM_API_KEY LLM_BASE_URL LLM_MODEL_NAME ZEP_API_KEY
DEMO_PASSWORD SECRET_KEY LLM_API_KEY LLM_BASE_URL LLM_MODEL_NAME
)
# Validate graph backend config
GRAPH_BACKEND="${GRAPH_BACKEND:-zep}"
if [[ "$GRAPH_BACKEND" == "zep" && -z "${ZEP_API_KEY:-}" ]]; then
echo "ERROR: ZEP_API_KEY is required when GRAPH_BACKEND=zep"
exit 1
fi
if [[ "$GRAPH_BACKEND" == "graphiti" && -z "${NEO4J_PASSWORD:-}" ]]; then
echo "ERROR: NEO4J_PASSWORD is required when GRAPH_BACKEND=graphiti"
exit 1
fi
for var in "${REQUIRED_VARS[@]}"; do
if [[ -z "${!var:-}" ]]; then
echo "ERROR: La variable $var no està configurada a config.sh"
@ -124,7 +134,12 @@ DEPLOY_OUTPUT=$(az deployment group create \
demoPassword="$DEMO_PASSWORD" \
llmApiKey="$LLM_API_KEY" \
llmBoostApiKey="${LLM_BOOST_API_KEY:-}" \
zepApiKey="$ZEP_API_KEY" \
llmProvider="${LLM_PROVIDER:-}" \
zepApiKey="${ZEP_API_KEY:-}" \
neo4jPassword="${NEO4J_PASSWORD:-}" \
neo4jUri="${NEO4J_URI:-bolt://localhost:7687}" \
neo4jUser="${NEO4J_USER:-neo4j}" \
graphBackend="${GRAPH_BACKEND:-zep}" \
secretKey="$SECRET_KEY" \
llmBaseUrl="$LLM_BASE_URL" \
llmModelName="$LLM_MODEL_NAME" \

View File

@ -34,14 +34,29 @@ LLM_API_KEY="<la-teva-llm-api-key>"
LLM_BASE_URL="https://dashscope.aliyuncs.com/compatible-mode/v1"
LLM_MODEL_NAME="qwen-plus"
# Proveïdor LLM especial (opcional):
# gemini → configura automàticament Google AI Studio (no cal LLM_BASE_URL)
# (buit) → qualsevol API compatible OpenAI
LLM_PROVIDER=""
# ── LLM accelerador (opcional — deixar buit per desactivar) ───────────────────
LLM_BOOST_API_KEY=""
LLM_BOOST_BASE_URL=""
LLM_BOOST_MODEL_NAME=""
# ── Zep Cloud (graf de memòria) ───────────────────────────────────────────────
# ── Backend de graf ───────────────────────────────────────────────────────────
# Opcions: zep (Zep Cloud, per defecte) | graphiti (Neo4j local/Azure)
GRAPH_BACKEND="zep"
# --- Zep Cloud (si GRAPH_BACKEND=zep) ---
ZEP_API_KEY="<la-teva-zep-api-key>"
# --- Graphiti + Neo4j (si GRAPH_BACKEND=graphiti) ---
# URI bolt del servidor Neo4j (pot ser una VM Azure, ACI, etc.)
# NEO4J_URI="bolt://<ip-o-hostname>:7687"
# NEO4J_USER="neo4j"
# NEO4J_PASSWORD="<contrasenya-neo4j>"
# ── Simulació OASIS (valors per defecte recomanats) ───────────────────────────
OASIS_DEFAULT_MAX_ROUNDS="10"

View File

@ -49,9 +49,13 @@ param llmApiKey string
@secure()
param llmBoostApiKey string = ''
@description('Clau de l\'API Zep Cloud')
@description('Clau de l\'API Zep Cloud (obligatori si GRAPH_BACKEND=zep)')
@secure()
param zepApiKey string
param zepApiKey string = ''
@description('Contrasenya de Neo4j (obligatori si GRAPH_BACKEND=graphiti)')
@secure()
param neo4jPassword string = ''
@description('SECRET_KEY de Flask per a JWT (python -c "import secrets; print(secrets.token_hex(32))")')
@secure()
@ -65,6 +69,20 @@ param llmBaseUrl string = 'https://dashscope.aliyuncs.com/compatible-mode/v1'
@description('Nom del model LLM principal')
param llmModelName string = 'qwen-plus'
@description('Proveïdor LLM (gemini per a Google AI Studio; buit per a qualsevol compatible OpenAI)')
param llmProvider string = ''
// ─── Paràmetres del backend de graf ──────────────────────────────────────────
@description('Backend de graf: zep (Zep Cloud) o graphiti (Neo4j local/Azure)')
param graphBackend string = 'zep'
@description('URI de connexió bolt de Neo4j (necessari si GRAPH_BACKEND=graphiti)')
param neo4jUri string = 'bolt://localhost:7687'
@description('Usuari de Neo4j')
param neo4jUser string = 'neo4j'
// ─── Paràmetres LLM accelerador (opcionals) ──────────────────────────────────
@description('URL base de l\'API LLM acceleradora (opcional)')
@ -104,6 +122,7 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
{ name: 'llm-api-key', value: llmApiKey }
{ name: 'llm-boost-api-key', value: llmBoostApiKey }
{ name: 'zep-api-key', value: zepApiKey }
{ name: 'neo4j-password', value: neo4jPassword }
{ name: 'secret-key', value: secretKey }
]
@ -143,14 +162,21 @@ resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
{ name: 'LLM_API_KEY', secretRef: 'llm-api-key' }
{ name: 'LLM_BOOST_API_KEY', secretRef: 'llm-boost-api-key' }
{ name: 'ZEP_API_KEY', secretRef: 'zep-api-key' }
{ name: 'NEO4J_PASSWORD', secretRef: 'neo4j-password' }
{ name: 'SECRET_KEY', secretRef: 'secret-key' }
// ── Variables no sensibles ──
{ name: 'LLM_BASE_URL', value: llmBaseUrl }
{ name: 'LLM_MODEL_NAME', value: llmModelName }
{ name: 'LLM_PROVIDER', value: llmProvider }
{ name: 'LLM_BOOST_BASE_URL', value: llmBoostBaseUrl }
{ name: 'LLM_BOOST_MODEL_NAME', value: llmBoostModelName }
// ── Backend de graf ──
{ name: 'GRAPH_BACKEND', value: graphBackend }
{ name: 'NEO4J_URI', value: neo4jUri }
{ name: 'NEO4J_USER', value: neo4jUser }
// ── Simulació OASIS ──
{ name: 'OASIS_DEFAULT_MAX_ROUNDS', value: oasisDefaultMaxRounds }

View File

@ -475,6 +475,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/07/6c/aa3f2f849e01cb6a001cd8554a88d4c77c5c1a31c95bdf1cf9301e6d9ef4/defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61", size = 25604, upload-time = "2021-03-08T10:59:24.45Z" },
]
[[package]]
name = "diskcache"
version = "5.6.3"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/3f/21/1c1ffc1a039ddcc459db43cc108658f32c57d271d7289a2794e401d0fdb6/diskcache-5.6.3.tar.gz", hash = "sha256:2c3a3fa2743d8535d832ec61c2054a1641f41775aa7c556758a109941e33e4fc", size = 67916, upload-time = "2023-08-31T06:12:00.316Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3f/27/4570e78fc0bf5ea0ca45eb1de3818a23787af9b390c0b0a0033a1b8236f9/diskcache-5.6.3-py3-none-any.whl", hash = "sha256:5e31b2d5fbad117cc363ebaf6b689474db18a1f6438bc82358b024abd4c2ca19", size = 45550, upload-time = "2023-08-31T06:11:58.822Z" },
]
[[package]]
name = "distlib"
version = "0.4.0"
@ -592,6 +601,24 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/51/c7/b64cae5dba3a1b138d7123ec36bb5ccd39d39939f18454407e5468f4763f/fsspec-2025.12.0-py3-none-any.whl", hash = "sha256:8bf1fe301b7d8acfa6e8571e3b1c3d158f909666642431cc78a1b7b4dbc5ec5b", size = 201422, upload-time = "2025-12-03T15:23:41.434Z" },
]
[[package]]
name = "graphiti-core"
version = "0.11.6"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "diskcache" },
{ name = "neo4j" },
{ name = "numpy" },
{ name = "openai" },
{ name = "pydantic" },
{ name = "python-dotenv" },
{ name = "tenacity" },
]
sdist = { url = "https://files.pythonhosted.org/packages/30/94/3f84400e5f02ea8e9dc79784202de4173cbc16f4b3ad1bd4302da888e4d8/graphiti_core-0.11.6.tar.gz", hash = "sha256:31d26621834d7d4b8865059ab749feb18af15937b59c69598a640a5dfabea331", size = 71928, upload-time = "2025-05-15T17:58:02.304Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/ac/2e/c8f22f01585bf173d1c82f6d4615511aebc75aeda764c69aa394446fa93c/graphiti_core-0.11.6-py3-none-any.whl", hash = "sha256:6ec4807a884f5ea88b942d0c8b7bcd2e107c7358ab4f98ef2a2092c229929707", size = 111001, upload-time = "2025-05-15T17:58:00.542Z" },
]
[[package]]
name = "gunicorn"
version = "25.3.0"
@ -1275,6 +1302,10 @@ dev = [
{ name = "pytest" },
{ name = "pytest-asyncio" },
]
graphiti = [
{ name = "graphiti-core" },
{ name = "neo4j" },
]
[package.dev-dependencies]
dev = [
@ -1290,7 +1321,9 @@ requires-dist = [
{ name = "charset-normalizer", specifier = ">=3.0.0" },
{ name = "flask", specifier = ">=3.0.0" },
{ name = "flask-cors", specifier = ">=6.0.0" },
{ name = "graphiti-core", marker = "extra == 'graphiti'", specifier = ">=0.3.0" },
{ name = "gunicorn", specifier = ">=22.0.0" },
{ name = "neo4j", marker = "extra == 'graphiti'", specifier = ">=5.23.0" },
{ name = "openai", specifier = ">=1.0.0" },
{ name = "pipreqs", marker = "extra == 'dev'", specifier = ">=0.5.0" },
{ name = "pydantic", specifier = ">=2.0.0" },
@ -1301,7 +1334,7 @@ requires-dist = [
{ name = "python-dotenv", specifier = ">=1.0.0" },
{ name = "zep-cloud", specifier = "==3.13.0" },
]
provides-extras = ["dev"]
provides-extras = ["graphiti", "dev"]
[package.metadata.requires-dev]
dev = [
@ -3003,6 +3036,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252, upload-time = "2022-10-06T17:21:44.262Z" },
]
[[package]]
name = "tenacity"
version = "9.1.4"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/47/c6/ee486fd809e357697ee8a44d3d69222b344920433d3b6666ccd9b374630c/tenacity-9.1.4.tar.gz", hash = "sha256:adb31d4c263f2bd041081ab33b498309a57c77f9acf2db65aadf0898179cf93a", size = 49413, upload-time = "2026-02-07T10:45:33.841Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/d7/c1/eb8f9debc45d3b7918a32ab756658a0904732f75e555402972246b0b8e71/tenacity-9.1.4-py3-none-any.whl", hash = "sha256:6095a360c919085f28c6527de529e76a06ad89b23659fa881ae0649b867a9d55", size = 28926, upload-time = "2026-02-07T10:45:32.24Z" },
]
[[package]]
name = "texttable"
version = "1.7.0"