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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ LANGFUSE_INIT_PROJECT_NAME=Default Project
LANGFUSE_INIT_PROJECT_PUBLIC_KEY=
LANGFUSE_INIT_PROJECT_SECRET_KEY=

# LibreChat -> Langfuse instrumentation target.
# Defaults to the local Langfuse stack. Override these three values to send
# LibreChat traces to Langfuse Cloud (or any remote Langfuse) instead. The
# prepare-demo.sh script can set these for you interactively.
LANGFUSE_PUBLIC_KEY=
LANGFUSE_SECRET_KEY=
LANGFUSE_BASE_URL=http://langfuse-web:3000

# Your login credentials
LANGFUSE_INIT_USER_EMAIL=your@email.com
LANGFUSE_INIT_USER_PASSWORD=yourpass
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ The Railway template skips Meilisearch, pgvector, and the RAG API for simplicity

This is your fastest way to get started with the Agentic Data Stack. It generates a `.env` file with random credentials for all services, then presents an interactive menu to optionally configure API keys for OpenAI, Anthropic, and/or Google. Any providers you skip will remain as `user_provided`, letting users enter their own keys in the LibreChat UI.

The script then asks whether LibreChat should send its Langfuse traces to the local Langfuse container (the default) or to a remote Langfuse project. Choose the cloud option to point LibreChat at Langfuse Cloud (or any self-hosted Langfuse) by entering the base URL, public key, and secret key for that project. You can change this later by editing `LANGFUSE_BASE_URL`, `LANGFUSE_PUBLIC_KEY`, and `LANGFUSE_SECRET_KEY` in `.env`.

You can also generate credentials separately and customize the initial administrator account credentials:

```bash
Expand Down
8 changes: 5 additions & 3 deletions librechat-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ services:
- VECTORDB_USER=${VECTORDB_USER:-myuser}
- VECTORDB_PASSWORD=${VECTORDB_PASSWORD:-mypassword}
# Langfuse Integration - Tracing and Observability
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_INIT_PROJECT_PUBLIC_KEY}
- LANGFUSE_SECRET_KEY=${LANGFUSE_INIT_PROJECT_SECRET_KEY}
- LANGFUSE_BASE_URL=http://langfuse-web:3000
# Defaults point at the local Langfuse stack; override these in .env to
# send traces to a Langfuse Cloud (or other remote) project instead.
- LANGFUSE_PUBLIC_KEY=${LANGFUSE_PUBLIC_KEY}
- LANGFUSE_SECRET_KEY=${LANGFUSE_SECRET_KEY}
- LANGFUSE_BASE_URL=${LANGFUSE_BASE_URL}
volumes:
- type: bind
source: ./.env
Expand Down
8 changes: 8 additions & 0 deletions scripts/generate-env.sh
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ LANGFUSE_INIT_PROJECT_NAME=${LANGFUSE_INIT_PROJECT_NAME}
LANGFUSE_INIT_PROJECT_PUBLIC_KEY=${LANGFUSE_INIT_PROJECT_PUBLIC_KEY}
LANGFUSE_INIT_PROJECT_SECRET_KEY=${LANGFUSE_INIT_PROJECT_SECRET_KEY}

# LibreChat -> Langfuse instrumentation target.
# Defaults to the local Langfuse stack started by langfuse-compose.yml.
# Point at Langfuse Cloud (or any remote Langfuse) by overriding these three
# values, e.g. via scripts/prepare-demo.sh.
LANGFUSE_PUBLIC_KEY=${LANGFUSE_INIT_PROJECT_PUBLIC_KEY}
LANGFUSE_SECRET_KEY=${LANGFUSE_INIT_PROJECT_SECRET_KEY}
LANGFUSE_BASE_URL=http://langfuse-web:3000

# Your login credentials
LANGFUSE_INIT_USER_EMAIL=${USER_EMAIL}
LANGFUSE_INIT_USER_PASSWORD=${USER_PASSWORD}
Expand Down
155 changes: 126 additions & 29 deletions scripts/prepare-demo.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,23 @@ multiselect() {
eval $retval='("${selected[@]}")'
}

# Upsert KEY=VALUE in $ENV_FILE — replace if present, append otherwise.
set_env_var() {
local key="$1"
local value="$2"
local escaped_value
escaped_value=$(printf '%s' "$value" | sed -e 's/[\\&|]/\\&/g')
if grep -q "^${key}=" "$ENV_FILE"; then
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s|^${key}=.*|${key}=${escaped_value}|" "$ENV_FILE"
else
sed -i "s|^${key}=.*|${key}=${escaped_value}|" "$ENV_FILE"
fi
else
printf '\n%s=%s\n' "$key" "$value" >> "$ENV_FILE"
fi
}

echo "=== API Key Configuration ==="
echo ""
echo " Select which providers to configure with API keys."
Expand All @@ -115,53 +132,133 @@ done

if [ ${#SELECTED[@]} -eq 0 ]; then
echo " No providers selected — API key environment variables not modified."
else
echo ""
echo "✅ Demo environment is ready!"
echo ""
echo " Run 'docker compose up -d' to get started."
echo ""
exit 0
for i in "${SELECTED[@]}"; do
provider="${PROVIDERS[$i]}"
env_key="${ENV_KEYS[$i]}"

while true; do
read -s -p " Enter $provider API key: " api_key
echo ""
if [ -n "$api_key" ]; then
break
fi
echo " Key cannot be empty. Try again or Ctrl+C to abort."
done

set_env_var "$env_key" "$api_key"

echo " ✓ ${provider} key saved"
done
fi

# Ensure the LibreChat-side Langfuse keys exist in .env. Older .env files
# (generated before LANGFUSE_PUBLIC_KEY / SECRET_KEY / BASE_URL were split out)
# only have the LANGFUSE_INIT_PROJECT_* values; default the new keys to the
# local Langfuse stack so the "local" choice keeps working untouched.
if ! grep -q "^LANGFUSE_BASE_URL=" "$ENV_FILE"; then
set_env_var "LANGFUSE_BASE_URL" "http://langfuse-web:3000"
fi
if ! grep -q "^LANGFUSE_PUBLIC_KEY=" "$ENV_FILE"; then
init_pub=$(grep -E "^LANGFUSE_INIT_PROJECT_PUBLIC_KEY=" "$ENV_FILE" | head -n1 | cut -d= -f2-)
set_env_var "LANGFUSE_PUBLIC_KEY" "${init_pub}"
fi
if ! grep -q "^LANGFUSE_SECRET_KEY=" "$ENV_FILE"; then
init_sec=$(grep -E "^LANGFUSE_INIT_PROJECT_SECRET_KEY=" "$ENV_FILE" | head -n1 | cut -d= -f2-)
set_env_var "LANGFUSE_SECRET_KEY" "${init_sec}"
fi

echo ""
echo "=== Langfuse Instrumentation ==="
echo ""
echo " LibreChat sends LLM traces to Langfuse for observability."
echo " By default, traces stay local (the Langfuse container in this stack)."
echo " You can instead send them to a Langfuse Cloud (or other remote) project."
echo ""

for i in "${SELECTED[@]}"; do
provider="${PROVIDERS[$i]}"
env_key="${ENV_KEYS[$i]}"
LANGFUSE_TARGET="local"
while true; do
read -p " Use Langfuse Cloud / a remote project? [y/N] " langfuse_cloud_choice
case "${langfuse_cloud_choice}" in
[yY]|[yY][eE][sS])
LANGFUSE_TARGET="cloud"
break
;;
""|[nN]|[nN][oO])
LANGFUSE_TARGET="local"
break
;;
*)
echo " Please answer y or n."
;;
esac
done

if [ "$LANGFUSE_TARGET" = "cloud" ]; then
echo ""
echo " Enter the connection details for your remote Langfuse project."
echo " (Project Settings -> API Keys in the Langfuse UI.)"
echo ""

while true; do
read -p " Langfuse base URL [https://cloud.langfuse.com]: " langfuse_base_url
langfuse_base_url="${langfuse_base_url:-https://cloud.langfuse.com}"
if [[ "$langfuse_base_url" =~ ^https?:// ]]; then
break
fi
echo " Base URL must start with http:// or https://. Try again."
done

while true; do
read -s -p " Enter $provider API key: " api_key
read -p " Langfuse public key (pk-lf-...): " langfuse_public_key
if [ -n "$langfuse_public_key" ]; then
break
fi
echo " Public key cannot be empty. Try again or Ctrl+C to abort."
done

while true; do
read -s -p " Langfuse secret key (sk-lf-...): " langfuse_secret_key
echo ""
if [ -n "$api_key" ]; then
if [ -n "$langfuse_secret_key" ]; then
break
fi
echo " Key cannot be empty. Try again or Ctrl+C to abort."
echo " Secret key cannot be empty. Try again or Ctrl+C to abort."
done

if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "s|^${env_key}=.*|${env_key}=${api_key}|" "$ENV_FILE"
else
sed -i "s|^${env_key}=.*|${env_key}=${api_key}|" "$ENV_FILE"
fi
set_env_var "LANGFUSE_BASE_URL" "$langfuse_base_url"
set_env_var "LANGFUSE_PUBLIC_KEY" "$langfuse_public_key"
set_env_var "LANGFUSE_SECRET_KEY" "$langfuse_secret_key"

echo " ✓ ${provider} key saved"
done
echo " ✓ LibreChat will send traces to ${langfuse_base_url}"
else
echo " ✓ LibreChat will send traces to the local Langfuse stack."
fi

echo ""
echo "✅ Demo environment is ready!"
echo ""
echo " Summary:"
for i in "${!PROVIDERS[@]}"; do
found=false
for s in "${SELECTED[@]}"; do
[ "$s" = "$i" ] && found=true && break
done
if $found; then
echo " ✔ ${PROVIDERS[$i]} (configured)"
else
echo " Provider summary:"
if [ ${#SELECTED[@]} -eq 0 ]; then
for i in "${!PROVIDERS[@]}"; do
echo " - ${PROVIDERS[$i]} (user_provided)"
fi
done
done
else
for i in "${!PROVIDERS[@]}"; do
found=false
for s in "${SELECTED[@]}"; do
[ "$s" = "$i" ] && found=true && break
done
if $found; then
echo " ✔ ${PROVIDERS[$i]} (configured)"
else
echo " - ${PROVIDERS[$i]} (user_provided)"
fi
done
fi
echo ""
echo " Langfuse target: ${LANGFUSE_TARGET}"
echo ""
echo " Run 'docker compose up -d' to get started."
echo ""