Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
ea32814
Add performance tracking to embedding search
sahilds1 Nov 20, 2025
1fc41a7
Simplify embedding search
sahilds1 Nov 24, 2025
156644b
Add persistent tracking for semantic search performance and usage
sahilds1 Nov 26, 2025
6a84359
Add semantic search usage migration file
sahilds1 Nov 26, 2025
0278a4e
Merge branch 'develop' into 380-track-chatbot-costs
sahilds1 Dec 18, 2025
9ddcd08
Merge branch 'develop' into 380-track-chatbot-costs
sahilds1 Dec 19, 2025
bf79b4a
Fix User logged as None
sahilds1 Dec 19, 2025
163e107
Address the user tracking issue without a 401 error
sahilds1 Dec 19, 2025
b2d264e
Merge pull request #414 from sahilds1/380-track-chatbot-costs
taichan03 Dec 23, 2025
764048c
Update VITE_API_BASE_URL to point to the new prod url
TineoC Dec 28, 2025
afb9130
Merge pull request #429 from CodeForPhilly/feat/update-prod-domain
TineoC Dec 31, 2025
b8a3619
Add centralized API endpoints configuration and refactor API calls
TineoC Jan 6, 2026
7a590e5
refactor: use relative URLs and centralize API endpoints
TineoC Jan 6, 2026
70e26ef
remove fiel
TineoC Jan 6, 2026
76cee02
sanitizer
AkhilRB0204 Jan 14, 2026
556d5dd
Merge remote-tracking branch 'origin/develop' into fix/handle-relativ…
TineoC Jan 15, 2026
18be6a7
Merge pull request #432 from TineoC/fix/handle-relative-domains
TineoC Jan 15, 2026
1c458f0
ci: refactor pipelines for continuous deployment to sandbox
TineoC Jan 15, 2026
4942546
Merge pull request #442 from CodeForPhilly/ci/cd-refactor
TineoC Jan 15, 2026
76a99a9
build: use cpu-only torch to reduce image size and fix CI build
TineoC Jan 15, 2026
6bfaa30
Merge pull request #443 from CodeForPhilly/ci/cd-refactor
TineoC Jan 15, 2026
ca8c21f
fix(ci): use actions/checkout@v4 instead of non-existent v5
TineoC Jan 15, 2026
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
21 changes: 19 additions & 2 deletions .github/workflows/containers-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ name: "Containers: Publish"
on:
release:
types: [published]
push:
branches: [develop]

permissions:
packages: write
Expand All @@ -12,7 +14,7 @@ jobs:
name: Build and Push
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/checkout@v4

- name: Login to ghcr.io Docker registry
uses: docker/login-action@v3
Expand All @@ -24,7 +26,13 @@ jobs:
- name: Compute Docker container image addresses
run: |
DOCKER_REPOSITORY="ghcr.io/${GITHUB_REPOSITORY,,}"
DOCKER_TAG="${GITHUB_REF:11}"

if [[ "${{ github.event_name }}" == "release" ]]; then
DOCKER_TAG="${GITHUB_REF:11}"
else
SHORT_SHA=$(echo "${{ github.sha }}" | cut -c1-7)
DOCKER_TAG="dev-${SHORT_SHA}"
fi

echo "DOCKER_REPOSITORY=${DOCKER_REPOSITORY}" >> $GITHUB_ENV
echo "DOCKER_TAG=${DOCKER_TAG}" >> $GITHUB_ENV
Expand All @@ -51,3 +59,12 @@ jobs:

- name: "Push Docker container image app:v*"
run: docker push "${DOCKER_REPOSITORY}/app:${DOCKER_TAG}"

- name: Save Docker Tag
run: echo "${DOCKER_TAG}" > docker_tag.txt

- name: Upload Docker Tag
uses: actions/upload-artifact@v4
with:
name: docker-tag
path: docker_tag.txt
41 changes: 32 additions & 9 deletions .github/workflows/deploy-downstream.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
name: "Deploy: Downstream Clusters"

on:
release:
types: [published]
workflow_run:
workflows: ["Containers: Publish"]
types:
- completed
workflow_dispatch:
inputs:
tag:
Expand All @@ -14,6 +16,7 @@ jobs:
update-sandbox:
name: Update Sandbox Cluster
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.head_branch == 'develop') }}
outputs:
tag: ${{ steps.get_tag.outputs.TAG }}
steps:
Expand All @@ -26,8 +29,12 @@ jobs:
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "TAG=${{ inputs.tag }}" >> $GITHUB_OUTPUT
else
echo "TAG=${GITHUB_REF:11}" >> $GITHUB_OUTPUT
gh run download ${{ github.event.workflow_run.id }} -n docker-tag
TAG=$(cat docker_tag.txt)
echo "TAG=${TAG}" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout Sandbox Cluster
uses: actions/checkout@v4
Expand Down Expand Up @@ -57,9 +64,25 @@ jobs:

update-live:
name: Update Live Cluster
needs: update-sandbox
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' || (github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event == 'release') }}
steps:
- name: Checkout App
uses: actions/checkout@v4

- name: Get Release Tag
id: get_tag
run: |
if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
echo "TAG=${{ inputs.tag }}" >> $GITHUB_OUTPUT
else
gh run download ${{ github.event.workflow_run.id }} -n docker-tag
TAG=$(cat docker_tag.txt)
echo "TAG=${TAG}" >> $GITHUB_OUTPUT
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout Live Cluster
uses: actions/checkout@v4
with:
Expand All @@ -71,17 +94,17 @@ jobs:
working-directory: live/balancer
run: |
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
./kustomize edit set image ghcr.io/codeforphilly/balancer-main/app:${{ needs.update-sandbox.outputs.tag }}
./kustomize edit set image ghcr.io/codeforphilly/balancer-main/app:${{ steps.get_tag.outputs.TAG }}
rm kustomize

- name: Create Live PR
uses: peter-evans/create-pull-request@v6
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
path: live
commit-message: "Deploy balancer ${{ needs.update-sandbox.outputs.tag }} to live"
title: "Deploy balancer ${{ needs.update-sandbox.outputs.tag }}"
body: "Updates balancer image tag to ${{ needs.update-sandbox.outputs.tag }}"
branch: "deploy/balancer-${{ needs.update-sandbox.outputs.tag }}"
commit-message: "Deploy balancer ${{ steps.get_tag.outputs.TAG }} to live"
title: "Deploy balancer ${{ steps.get_tag.outputs.TAG }}"
body: "Updates balancer image tag to ${{ steps.get_tag.outputs.TAG }}"
branch: "deploy/balancer-${{ steps.get_tag.outputs.TAG }}"
base: main
delete-branch: true
6 changes: 4 additions & 2 deletions Dockerfile.prod
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@ ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y netcat && rm -rf /var/lib/apt/lists/*

# Install Python dependencies
RUN pip install --upgrade pip
RUN pip install --upgrade pip --no-cache-dir
COPY server/requirements.txt .
RUN pip install -r requirements.txt
# Install CPU-only torch to save space (avoids ~4GB of CUDA libs)
RUN pip install torch --index-url https://download.pytorch.org/whl/cpu --no-cache-dir
RUN pip install -r requirements.txt --no-cache-dir

# Copy backend application code
COPY server/ .
Expand Down
2 changes: 1 addition & 1 deletion frontend/.env.production
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VITE_API_BASE_URL=https://balancer.live.k8s.phl.io/
VITE_API_BASE_URL=https://balancerproject.org/
38 changes: 22 additions & 16 deletions frontend/src/api/apiClient.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import axios from "axios";
import { FormValues } from "../pages/Feedback/FeedbackForm";
import { Conversation } from "../components/Header/Chat";
const baseURL = import.meta.env.VITE_API_BASE_URL;
import {
V1_API_ENDPOINTS,
CONVERSATION_ENDPOINTS,
endpoints,
} from "./endpoints";

// Use empty string for relative URLs - all API calls will be relative to current domain
const baseURL = "";

export const publicApi = axios.create({ baseURL });

Expand Down Expand Up @@ -31,7 +38,7 @@ const handleSubmitFeedback = async (
message: FormValues["message"],
) => {
try {
const response = await publicApi.post(`/v1/api/feedback/`, {
const response = await publicApi.post(V1_API_ENDPOINTS.FEEDBACK, {
feedbacktype: feedbackType,
name,
email,
Expand All @@ -49,7 +56,7 @@ const handleSendDrugSummary = async (
guid: string,
) => {
try {
const endpoint = guid ? `/v1/api/embeddings/ask_embeddings?guid=${guid}` : '/v1/api/embeddings/ask_embeddings';
const endpoint = endpoints.embeddingsAsk(guid);
const response = await adminApi.post(endpoint, {
message,
});
Expand All @@ -63,7 +70,7 @@ const handleSendDrugSummary = async (

const handleRuleExtraction = async (guid: string) => {
try {
const response = await adminApi.get(`/v1/api/rule_extraction_openai?guid=${guid}`);
const response = await adminApi.get(endpoints.ruleExtraction(guid));
// console.log("Rule extraction response:", JSON.stringify(response.data, null, 2));
return response.data;
} catch (error) {
Expand All @@ -77,7 +84,7 @@ const fetchRiskDataWithSources = async (
source: "include" | "diagnosis" | "diagnosis_depressed" = "include",
) => {
try {
const response = await publicApi.post(`/v1/api/riskWithSources`, {
const response = await publicApi.post(V1_API_ENDPOINTS.RISK_WITH_SOURCES, {
drug: medication,
source: source,
});
Expand All @@ -101,12 +108,10 @@ const handleSendDrugSummaryStream = async (
callbacks: StreamCallbacks,
): Promise<void> => {
const token = localStorage.getItem("access");
const endpoint = `/v1/api/embeddings/ask_embeddings?stream=true${
guid ? `&guid=${guid}` : ""
}`;
const endpoint = endpoints.embeddingsAskStream(guid);

try {
const response = await fetch(baseURL + endpoint, {
const response = await fetch(endpoint, {
method: "POST",
headers: {
"Content-Type": "application/json",
Expand Down Expand Up @@ -206,7 +211,7 @@ const handleSendDrugSummaryStreamLegacy = async (

const fetchConversations = async (): Promise<Conversation[]> => {
try {
const response = await publicApi.get(`/chatgpt/conversations/`);
const response = await publicApi.get(CONVERSATION_ENDPOINTS.CONVERSATIONS);
return response.data;
} catch (error) {
console.error("Error(s) during getConversations: ", error);
Expand All @@ -216,7 +221,7 @@ const fetchConversations = async (): Promise<Conversation[]> => {

const fetchConversation = async (id: string): Promise<Conversation> => {
try {
const response = await publicApi.get(`/chatgpt/conversations/${id}/`);
const response = await publicApi.get(endpoints.conversation(id));
return response.data;
} catch (error) {
console.error("Error(s) during getConversation: ", error);
Expand All @@ -226,7 +231,7 @@ const fetchConversation = async (id: string): Promise<Conversation> => {

const newConversation = async (): Promise<Conversation> => {
try {
const response = await adminApi.post(`/chatgpt/conversations/`, {
const response = await adminApi.post(CONVERSATION_ENDPOINTS.CONVERSATIONS, {
messages: [],
});
return response.data;
Expand All @@ -243,7 +248,7 @@ const continueConversation = async (
): Promise<{ response: string; title: Conversation["title"] }> => {
try {
const response = await adminApi.post(
`/chatgpt/conversations/${id}/continue_conversation/`,
endpoints.continueConversation(id),
{
message,
page_context,
Expand All @@ -258,7 +263,7 @@ const continueConversation = async (

const deleteConversation = async (id: string) => {
try {
const response = await adminApi.delete(`/chatgpt/conversations/${id}/`);
const response = await adminApi.delete(endpoints.conversation(id));
return response.data;
} catch (error) {
console.error("Error(s) during deleteConversation: ", error);
Expand All @@ -273,7 +278,7 @@ const updateConversationTitle = async (
{ status: string; title: Conversation["title"] } | { error: string }
> => {
try {
const response = await adminApi.patch(`/chatgpt/conversations/${id}/update_title/`, {
const response = await adminApi.patch(endpoints.updateConversationTitle(id), {
title: newTitle,
});
return response.data;
Expand All @@ -289,7 +294,8 @@ const sendAssistantMessage = async (
previousResponseId?: string,
) => {
try {
const response = await publicApi.post(`/v1/api/assistant`, {
const api = localStorage.getItem("access") ? adminApi : publicApi;
const response = await api.post(V1_API_ENDPOINTS.ASSISTANT, {
message,
previous_response_id: previousResponseId,
});
Expand Down
Loading
Loading