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
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ SCD_INITIAL_ADMIN_PASSWORD=change-me
ANTHROPIC_API_KEY=
# Default model: claude-sonnet-4-6
# ANTHROPIC_SUMMARY_MODEL=claude-sonnet-4-6
# Leave unset to call the public Anthropic API directly. Set to route through
# a proxy such as litellm (e.g. https://litellm.fnal.gov).
# ANTHROPIC_BASE_URL=

# ── OIDC / Keycloak SSO ───────────────────────────────────────────────────────
# Set all three to enable the "Log in with SSO" button.
Expand Down
7 changes: 4 additions & 3 deletions apps/reports/ai_summary.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,14 @@ def generate(qs, user=None, template=None) -> str:
system_prompt = config.system_prompt
user_template = config.user_template

model = getattr(settings, 'ANTHROPIC_SUMMARY_MODEL', 'claude-sonnet-4-6')
base_url = getattr(settings, 'ANTHROPIC_BASE_URL', '') or None
model = settings.ANTHROPIC_SUMMARY_MODEL
base_url = settings.ANTHROPIC_BASE_URL or None
client = anthropic.Anthropic(api_key=api_key, **({"base_url": base_url} if base_url else {}))
message = client.messages.create(
model=model,
max_tokens=2048,
system=system_prompt,
messages=[{'role': 'user', 'content': user_template.format(entries=_format_entries(qs))}],
)
return message.content[0].text
text_blocks = [block.text for block in message.content if block.type == 'text']
return '\n'.join(text_blocks)
1 change: 1 addition & 0 deletions helm/compose/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ data:
GUNICORN_TIMEOUT: {{ .Values.gunicorn.timeout | quote }}
GUNICORN_LOG_LEVEL: {{ .Values.gunicorn.logLevel | quote }}
ANTHROPIC_SUMMARY_MODEL: {{ .Values.anthropic.summaryModel | quote }}
ANTHROPIC_BASE_URL: {{ .Values.anthropic.baseUrl | quote }}
EMAIL_HOST: {{ .Values.email.host | quote }}
EMAIL_PORT: {{ .Values.email.port | quote }}
EMAIL_HOST_USER: {{ .Values.email.user | quote }}
Expand Down
1 change: 1 addition & 0 deletions helm/compose/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ gunicorn:
anthropic:
apiKey: ""
summaryModel: "claude-sonnet-4-6"
baseUrl: ""

# ── Email (SMTP) ───────────────────────────────────────────────────────────────
email:
Expand Down
17 changes: 16 additions & 1 deletion scripts/start-scd-reporting
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
# (or set SCD_INITIAL_ADMIN_PASSWORD env var)
# --anthropic-key <key> Anthropic API key for the AI Summary feature
# (or set ANTHROPIC_API_KEY env var)
# --anthropic-model <model> Model name for the AI Summary feature (default: claude-sonnet-4-6)
# (or set ANTHROPIC_SUMMARY_MODEL env var)
# --anthropic-base-url <url> Base URL for the Anthropic API, e.g. to route through a proxy
# (or set ANTHROPIC_BASE_URL env var)
# --oidc-secret-file <path> Path to a file containing the OIDC client secret
# (or set OIDC_CLIENT_SECRET_FILE env var)
# --oidc-provider-url <url> OIDC discovery URL or base realm URL
Expand Down Expand Up @@ -70,6 +74,8 @@ fi
# ── Argument parsing ──────────────────────────────────────────────────────────
ADMIN_PASSWORD="${SCD_INITIAL_ADMIN_PASSWORD:-}"
ANTHROPIC_KEY="${ANTHROPIC_API_KEY:-}"
ANTHROPIC_BASE_URL="${ANTHROPIC_BASE_URL:-}"
ANTHROPIC_SUMMARY_MODEL="${ANTHROPIC_SUMMARY_MODEL:-}"
OIDC_SECRET_FILE="${OIDC_CLIENT_SECRET_FILE:-}"
OIDC_PROVIDER_URL="${OIDC_PROVIDER_URL:-}"
OIDC_CLIENT_ID="${OIDC_CLIENT_ID:-}"
Expand All @@ -85,6 +91,8 @@ while [[ $# -gt 0 ]]; do
case $1 in
--admin-password) ADMIN_PASSWORD="$2"; shift 2 ;;
--anthropic-key) ANTHROPIC_KEY="$2"; shift 2 ;;
--anthropic-model) ANTHROPIC_SUMMARY_MODEL="$2"; shift 2 ;;
--anthropic-base-url) ANTHROPIC_BASE_URL="$2"; shift 2 ;;
--oidc-secret-file) OIDC_SECRET_FILE="$2"; shift 2 ;;
--oidc-provider-url) OIDC_PROVIDER_URL="$2"; shift 2 ;;
--oidc-client-id) OIDC_CLIENT_ID="$2"; shift 2 ;;
Expand Down Expand Up @@ -219,11 +227,18 @@ fi
if [[ -n "$GOOGLE_CLIENT_ID" && -n "$GOOGLE_CLIENT_SECRET" ]]; then
success "Google OAuth enabled"
fi

#
# AI Settings
export ANTHROPIC_API_KEY="$ANTHROPIC_KEY"
export ANTHROPIC_BASE_URL="$ANTHROPIC_BASE_URL"
export ANTHROPIC_SUMMARY_MODEL="$ANTHROPIC_SUMMARY_MODEL"
Comment on lines +230 to +234
#
# SSO Settings
export OIDC_CLIENT_SECRET_FILE="$OIDC_SECRET_FILE"
export OIDC_PROVIDER_URL="$OIDC_PROVIDER_URL"
export OIDC_CLIENT_ID="$OIDC_CLIENT_ID"
#
# Google Login Settings
export GOOGLE_CLIENT_ID="$GOOGLE_CLIENT_ID"
export GOOGLE_CLIENT_SECRET="$GOOGLE_CLIENT_SECRET"
nohup python manage.py runserver "$HOST:$PORT" >> "$LOG_FILE" 2>&1 &
Expand Down