Skip to content

Commit d509b10

Browse files
HarshHarsh
authored andcommitted
Merge branch 'develop' of https://github.com/bluewave-labs/verifywise into develop-saas
2 parents ceaed60 + 702ac3a commit d509b10

7 files changed

Lines changed: 160 additions & 62 deletions

File tree

Clients/nginx.conf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ server {
1717

1818
# Proxy API requests to backend
1919
location /api {
20-
proxy_pass http://localhost:3000; # no trailing slash - keeps /api prefix
20+
proxy_pass http://localhost:3000; # no trailing slash - keeps /api prefix
2121
proxy_http_version 1.1;
2222
proxy_set_header Host $host;
2323
proxy_set_header X-Real-IP $remote_addr;

EvalServer/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ RUN pip install --no-cache-dir torch==2.5.1 --index-url https://download.pytorch
1414
# Copy the application source
1515
COPY ./EvalServer/src .
1616

17+
# Copy the deepeval_engine module from EvaluationModule
18+
COPY ./EvaluationModule/src/deepeval_engine /app/deepeval_engine
19+
1720
# Copy the datasets from EvaluationModule
1821
COPY ./EvaluationModule/data/datasets /app/datasets
1922

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
"""Cleanup public schema - remove tables that should only exist in tenant schemas
2+
3+
Revision ID: 20251220_cleanup_public
4+
Revises: 20251220_add_missing
5+
Create Date: 2025-12-20
6+
7+
Purpose:
8+
- Remove fairness_runs from public (was never dropped from public, only from tenant schemas)
9+
- Remove deepeval_projects from public (should only exist in tenant schemas)
10+
- These tables were created by older migrations before multi-tenancy was properly implemented
11+
"""
12+
from typing import Sequence, Union
13+
14+
from alembic import op
15+
import sqlalchemy as sa
16+
17+
18+
# revision identifiers, used by Alembic.
19+
revision: str = "20251220_cleanup_public"
20+
down_revision: Union[str, None] = "20251220_missing_evals"
21+
branch_labels: Union[str, Sequence[str], None] = None
22+
depends_on: Union[str, Sequence[str], None] = None
23+
24+
25+
def upgrade() -> None:
26+
"""Remove tables from public schema that should only be in tenant schemas."""
27+
# Drop fairness_runs from public - this was the old bias/fairness feature table
28+
op.execute(sa.text('DROP TABLE IF EXISTS public.fairness_runs CASCADE'))
29+
30+
# Drop deepeval_projects from public - should only exist in tenant schemas
31+
op.execute(sa.text('DROP TABLE IF EXISTS public.deepeval_projects CASCADE'))
32+
33+
# Also clean up any other legacy bias/fairness tables from public
34+
op.execute(sa.text('DROP TABLE IF EXISTS public.bias_fairness_evaluations CASCADE'))
35+
36+
# Drop indexes that may have been created in public
37+
op.execute(sa.text('DROP INDEX IF EXISTS public.idx_deepeval_projects_tenant'))
38+
op.execute(sa.text('DROP INDEX IF EXISTS public.idx_deepeval_projects_created_at'))
39+
40+
41+
def downgrade() -> None:
42+
"""Recreate tables in public if needed (not recommended)."""
43+
# We don't want to recreate these in public - they belong in tenant schemas
44+
# But for migration reversibility, we provide empty downgrade
45+
pass
46+

EvaluationModule/src/deepeval_engine/deepeval_evaluator.py

Lines changed: 40 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -637,52 +637,52 @@ def evaluate_test_cases(
637637
)
638638
else:
639639
# Use standard single-turn metrics
640-
for metric_name, metric in metrics_to_use:
641-
try:
642-
# Some metrics require retrieval/context. If missing, skip gracefully.
643-
# RAG-specific metrics require context
644-
requires_context = metric_name in {"Faithfulness", "Context Relevancy", "Context Precision", "Context Recall"}
640+
for metric_name, metric in metrics_to_use:
641+
try:
642+
# Some metrics require retrieval/context. If missing, skip gracefully.
643+
# RAG-specific metrics require context
644+
requires_context = metric_name in {"Faithfulness", "Context Relevancy", "Context Precision", "Context Recall"}
645+
646+
retrieval_context = getattr(test_case, "retrieval_context", None)
647+
context = getattr(test_case, "context", None)
648+
has_context = bool(retrieval_context) or bool(context)
645649

646-
retrieval_context = getattr(test_case, "retrieval_context", None)
647-
context = getattr(test_case, "context", None)
648-
has_context = bool(retrieval_context) or bool(context)
649-
650-
if requires_context and not has_context:
651-
print(f" Evaluating {metric_name}... ⏭ Skipped (no context)")
652-
metric_scores[metric_name] = {
653-
"score": None,
654-
"passed": False,
655-
"threshold": getattr(metric, "threshold", None),
656-
"skipped": True,
657-
"reason": "No retrieval/context provided",
658-
}
659-
continue
650+
if requires_context and not has_context:
651+
print(f" Evaluating {metric_name}... ⏭ Skipped (no context)")
652+
metric_scores[metric_name] = {
653+
"score": None,
654+
"passed": False,
655+
"threshold": getattr(metric, "threshold", None),
656+
"skipped": True,
657+
"reason": "No retrieval/context provided",
658+
}
659+
continue
660660

661-
print(f" Evaluating {metric_name}...", end=" ")
661+
print(f" Evaluating {metric_name}...", end=" ")
662662

663-
metric.measure(test_case)
664-
score = metric.score
665-
passed = metric.is_successful()
663+
metric.measure(test_case)
664+
score = metric.score
665+
passed = metric.is_successful()
666666

667-
metric_scores[metric_name] = {
668-
"score": round(score, 3) if score is not None else None,
669-
"passed": passed,
670-
"threshold": getattr(metric, "threshold", None),
671-
"reason": getattr(metric, 'reason', 'N/A')
672-
}
667+
metric_scores[metric_name] = {
668+
"score": round(score, 3) if score is not None else None,
669+
"passed": passed,
670+
"threshold": getattr(metric, "threshold", None),
671+
"reason": getattr(metric, 'reason', 'N/A')
672+
}
673673

674-
status = "✓ PASS" if passed else "✗ FAIL"
675-
print(f"{status} (score: {score:.3f})")
674+
status = "✓ PASS" if passed else "✗ FAIL"
675+
print(f"{status} (score: {score:.3f})")
676676

677-
except Exception as e:
678-
error_msg = str(e)
679-
print(f"✗ Error: {error_msg}")
680-
metric_scores[metric_name] = {
681-
"score": None,
682-
"passed": False,
683-
"threshold": getattr(metric, "threshold", None),
684-
"error": str(e)
685-
}
677+
except Exception as e:
678+
error_msg = str(e)
679+
print(f"✗ Error: {error_msg}")
680+
metric_scores[metric_name] = {
681+
"score": None,
682+
"passed": False,
683+
"threshold": getattr(metric, "threshold", None),
684+
"error": str(e)
685+
}
686686

687687
# Calculate basic statistics based on test case type
688688
if is_conversational and isinstance(test_case, ConversationalTestCase):

Servers/database/migrations/20251104000511-create-tables-for-file-manager.js

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,6 @@ module.exports = {
66
async up(queryInterface, Sequelize) {
77
const transaction = await queryInterface.sequelize.transaction();
88
try {
9-
// Create ENUM type in public schema (shared across tenants)
10-
await queryInterface.sequelize.query(
11-
`DO $$ BEGIN
12-
CREATE TYPE public.enum_file_manager_source AS ENUM ('file_manager', 'policy_editor');
13-
EXCEPTION
14-
WHEN duplicate_object THEN null;
15-
END $$;`,
16-
{ transaction }
17-
);
189

1910
const queries = [
2011
// Create file_manager table for organization-wide file storage
@@ -28,8 +19,7 @@ module.exports = {
2819
uploaded_by INTEGER NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
2920
upload_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
3021
org_id INTEGER NOT NULL REFERENCES public.organizations(id) ON DELETE CASCADE,
31-
is_demo BOOLEAN NOT NULL DEFAULT FALSE,
32-
source public.enum_file_manager_source DEFAULT 'file_manager'
22+
is_demo BOOLEAN NOT NULL DEFAULT FALSE
3323
);`,
3424

3525
// Create file_access_logs table for audit trail
@@ -92,12 +82,6 @@ module.exports = {
9282
}
9383
}
9484

95-
// Drop ENUM type
96-
await queryInterface.sequelize.query(
97-
`DROP TYPE IF EXISTS public.enum_file_manager_source;`,
98-
{ transaction }
99-
);
100-
10185
await transaction.commit();
10286
} catch (error) {
10387
await transaction.rollback();
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
'use strict';
2+
const { getTenantHash } = require("../../dist/tools/getTenantHash");
3+
4+
/** @type {import('sequelize-cli').Migration} */
5+
module.exports = {
6+
async up(queryInterface, Sequelize) {
7+
const transaction = await queryInterface.sequelize.transaction();
8+
try {
9+
// Create ENUM type in public schema (shared across tenants)
10+
await queryInterface.sequelize.query(
11+
`DO $$ BEGIN
12+
CREATE TYPE public.enum_file_manager_source AS ENUM ('file_manager', 'policy_editor');
13+
EXCEPTION
14+
WHEN duplicate_object THEN null;
15+
END $$;`,
16+
{ transaction }
17+
);
18+
19+
const organizations = await queryInterface.sequelize.query(
20+
`SELECT id FROM organizations;`,
21+
{ transaction }
22+
);
23+
24+
for (let organization of organizations[0]) {
25+
const tenantHash = getTenantHash(organization.id);
26+
await queryInterface.sequelize.query(
27+
`ALTER TABLE "${tenantHash}".file_manager
28+
ADD COLUMN IF NOT EXISTS source public.enum_file_manager_source DEFAULT 'file_manager' NOT NULL;`,
29+
{ transaction }
30+
);
31+
}
32+
33+
await transaction.commit();
34+
} catch {
35+
await transaction.rollback();
36+
throw error;
37+
}
38+
},
39+
40+
async down(queryInterface, Sequelize) {
41+
const transaction = await queryInterface.sequelize.transaction();
42+
try {
43+
// Drop ENUM type
44+
await queryInterface.sequelize.query(
45+
`DROP TYPE IF EXISTS public.enum_file_manager_source;`,
46+
{ transaction }
47+
);
48+
49+
const organizations = await queryInterface.sequelize.query(
50+
`SELECT id FROM organizations;`,
51+
{ transaction }
52+
);
53+
54+
for (let organization of organizations[0]) {
55+
const tenantHash = getTenantHash(organization.id);
56+
await queryInterface.sequelize.query(
57+
`ALTER TABLE "${tenantHash}".file_manager
58+
DROP COLUMN IF EXISTS source;`,
59+
{ transaction }
60+
);
61+
}
62+
63+
await transaction.commit();
64+
} catch (error) {
65+
await transaction.rollback();
66+
throw error;
67+
}
68+
}
69+
};

docker-compose.prod.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ services:
1414
- $FRONTEND_PORT:80
1515
env_file:
1616
- ./.env.prod
17-
18-
# bias_and_fairness_backend:
19-
# env_file:
20-
# - ./.env.prod
2117

2218
eval_server:
2319
env_file:

0 commit comments

Comments
 (0)