From ff7f6706d86714dfa8053194a527edd16bf2424a Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sat, 24 May 2025 16:44:58 +0500 Subject: [PATCH 01/73] Update deploy-to-hf.yml --- .github/workflows/deploy-to-hf.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-to-hf.yml b/.github/workflows/deploy-to-hf.yml index 72184449..c2982aa1 100644 --- a/.github/workflows/deploy-to-hf.yml +++ b/.github/workflows/deploy-to-hf.yml @@ -50,10 +50,9 @@ jobs: cp .huggingface.yaml hf-space/ # Use rsync to copy all files except those in .gitignore - rsync -av --exclude-from=.gitignore --exclude="hf-space" --exclude=".git" ./ hf-space/ - + rsync -av --exclude="*.png" --exclude-from=.gitignore --exclude="hf-space" --exclude=".git" ./ hf-space/ # Push changes cd hf-space git add . git commit -m "${{ github.event.head_commit.message || 'Update from GitHub Actions' }}" - git push -f origin main \ No newline at end of file + git push -f origin main From a92ac1f4fd47d1b4d5c9a4790f7d242b605d8f6a Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Fri, 18 Jul 2025 00:15:11 +0800 Subject: [PATCH 02/73] Update credits-config.ts Shortened the trial period --- auto-analyst-frontend/lib/credits-config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auto-analyst-frontend/lib/credits-config.ts b/auto-analyst-frontend/lib/credits-config.ts index 1be559bc..5bc9b428 100644 --- a/auto-analyst-frontend/lib/credits-config.ts +++ b/auto-analyst-frontend/lib/credits-config.ts @@ -49,9 +49,9 @@ export interface TrialConfig { * Trial period configuration - Change here to update across the entire app */ export const TRIAL_CONFIG: TrialConfig = { - duration: 2, + duration: 1, unit: 'days', - displayText: '2-Day Free Trial', + displayText: '1-Day Free Trial', credits: 500 } @@ -388,4 +388,4 @@ export class CreditConfig { } return (total - used) > 0 } -} \ No newline at end of file +} From 06b5828e008c45c9f5af24328f13573f9592f6be Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 08:20:47 +0800 Subject: [PATCH 03/73] Update credits-config.ts --- auto-analyst-frontend/lib/credits-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/lib/credits-config.ts b/auto-analyst-frontend/lib/credits-config.ts index 5bc9b428..f6ceb78b 100644 --- a/auto-analyst-frontend/lib/credits-config.ts +++ b/auto-analyst-frontend/lib/credits-config.ts @@ -49,9 +49,9 @@ export interface TrialConfig { * Trial period configuration - Change here to update across the entire app */ export const TRIAL_CONFIG: TrialConfig = { - duration: 1, + duration: 0, unit: 'days', - displayText: '1-Day Free Trial', + displayText: 'Start Analyzing!', credits: 500 } From 311e483bd64442e8cfd60959c0447daabe21b824 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 08:22:47 +0800 Subject: [PATCH 04/73] Update credits-config.ts --- auto-analyst-frontend/lib/credits-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/lib/credits-config.ts b/auto-analyst-frontend/lib/credits-config.ts index f6ceb78b..5b759488 100644 --- a/auto-analyst-frontend/lib/credits-config.ts +++ b/auto-analyst-frontend/lib/credits-config.ts @@ -51,7 +51,7 @@ export interface TrialConfig { export const TRIAL_CONFIG: TrialConfig = { duration: 0, unit: 'days', - displayText: 'Start Analyzing!', + displayText: 'Analyzing!', credits: 500 } From c8f3743b7afa6c5d830f011e1a2d7155db6407b7 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 08:27:25 +0800 Subject: [PATCH 05/73] Update credits-config.ts --- auto-analyst-frontend/lib/credits-config.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/lib/credits-config.ts b/auto-analyst-frontend/lib/credits-config.ts index 5b759488..a7b06cbb 100644 --- a/auto-analyst-frontend/lib/credits-config.ts +++ b/auto-analyst-frontend/lib/credits-config.ts @@ -49,8 +49,8 @@ export interface TrialConfig { * Trial period configuration - Change here to update across the entire app */ export const TRIAL_CONFIG: TrialConfig = { - duration: 0, - unit: 'days', + duration: 5, + unit: 'minutes', displayText: 'Analyzing!', credits: 500 } From b8217028807aeee0cf669fd1d37d48d7d8cbc1e2 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 08:34:32 +0800 Subject: [PATCH 06/73] Update page.tsx --- auto-analyst-frontend/app/pricing/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/pricing/page.tsx b/auto-analyst-frontend/app/pricing/page.tsx index 1f6a29a2..7b9ea6f3 100644 --- a/auto-analyst-frontend/app/pricing/page.tsx +++ b/auto-analyst-frontend/app/pricing/page.tsx @@ -35,7 +35,7 @@ const pricingTiers = [ `${TrialUtils.getTrialDisplayText()}`, ], highlight: true, - trial: true, + trial: false, }, { name: 'Enterprise', @@ -486,4 +486,4 @@ export default function PricingPage() { ); -} \ No newline at end of file +} From fda1ae0d000f3be079ce0662af2cb4000c6e0034 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 08:50:48 +0800 Subject: [PATCH 07/73] Update route.ts --- auto-analyst-frontend/app/api/checkout-sessions/route.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/auto-analyst-frontend/app/api/checkout-sessions/route.ts b/auto-analyst-frontend/app/api/checkout-sessions/route.ts index cd569969..8e473e1c 100644 --- a/auto-analyst-frontend/app/api/checkout-sessions/route.ts +++ b/auto-analyst-frontend/app/api/checkout-sessions/route.ts @@ -97,7 +97,7 @@ export async function POST(request: NextRequest) { planName, interval, priceId, - isTrial: 'true', + isTrial: 'false', trialEndDate: TrialUtils.getTrialEndDate(), ...(promoCode && { promoCode }), ...(couponId && { couponId }), @@ -109,7 +109,7 @@ export async function POST(request: NextRequest) { clientSecret: setupIntent.client_secret, customerId: customerId, discountApplied: !!couponId, - isTrialSetup: true, + isTrialSetup: false, planName, interval, priceId, @@ -139,4 +139,4 @@ async function calculateDiscountedAmount(amount: number, couponId: string): Prom console.error('Error calculating discount:', error) return amount } -} \ No newline at end of file +} From 85189f1684000f10af79296890a40ab46454fad0 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:00:31 +0800 Subject: [PATCH 08/73] Update route.ts --- auto-analyst-frontend/app/api/checkout-sessions/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/api/checkout-sessions/route.ts b/auto-analyst-frontend/app/api/checkout-sessions/route.ts index 8e473e1c..57fa220d 100644 --- a/auto-analyst-frontend/app/api/checkout-sessions/route.ts +++ b/auto-analyst-frontend/app/api/checkout-sessions/route.ts @@ -97,8 +97,8 @@ export async function POST(request: NextRequest) { planName, interval, priceId, - isTrial: 'false', - trialEndDate: TrialUtils.getTrialEndDate(), + // isTrial: 'false', + // trialEndDate: TrialUtils.getTrialEndDate(), ...(promoCode && { promoCode }), ...(couponId && { couponId }), }, From ca4e76136f18005020c389704c5edad9cadd3dc8 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:09:44 +0800 Subject: [PATCH 09/73] Update route.ts --- .../app/api/trial/start/route.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index ef2095ad..cf220e8e 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -95,7 +95,7 @@ export async function POST(request: NextRequest) { const subscriptionParams: Stripe.SubscriptionCreateParams = { customer: customerId, items: [{ price: priceId }], - trial_end: trialEndTimestamp, + // trial_end: trialEndTimestamp, expand: ['latest_invoice.payment_intent'], payment_behavior: 'default_incomplete', default_payment_method: setupIntent.payment_method as string, @@ -112,8 +112,8 @@ export async function POST(request: NextRequest) { planName: metadata.planName || planName || 'Standard', interval: metadata.interval || interval || 'month', priceId, - isTrial: 'true', - trialEndDate: TrialUtils.getTrialEndDate(), + // isTrial: 'true', + // trialEndDate: TrialUtils.getTrialEndDate(), createdFromSetupIntent: setupIntentId, }, } @@ -144,17 +144,17 @@ export async function POST(request: NextRequest) { const subscriptionData = { plan: 'Standard Plan', planType: 'STANDARD', // Immediate Standard access as requested - status: 'trialing', // Use Stripe's standard trialing status + status: 'active', // Use Stripe's standard trialing status amount: amount?.toString() || '15', interval: interval || 'month', purchaseDate: now.toISOString(), - trialStartDate: now.toISOString(), - trialEndDate: trialEndDate, + // trialStartDate: now.toISOString(), + // trialEndDate: trialEndDate, creditResetDate: creditResetDate.toISOString().split('T')[0], // Store reset date lastUpdated: now.toISOString(), stripeCustomerId: customerId, stripeSubscriptionId: subscription.id, // Store actual subscription ID - willChargeOn: trialEndDate + // willChargeOn: trialEndDate } // Initialize trial credits (500 credits immediately) with custom reset date @@ -188,4 +188,4 @@ export async function POST(request: NextRequest) { error: error.message || 'Failed to start trial' }, { status: 500 }) } -} \ No newline at end of file +} From 1e2013b2e3148345f9cdf0aa53f058e09f369329 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:12:56 +0800 Subject: [PATCH 10/73] Update route.ts --- auto-analyst-frontend/app/api/trial/start/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index cf220e8e..b7a8d1aa 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -178,7 +178,7 @@ export async function POST(request: NextRequest) { used: 0, remaining: TrialUtils.getTrialCredits() }, - trialEndDate: trialEndDate, + // trialEndDate: trialEndDate, message: 'Trial started successfully! You have immediate access to 500 credits.' }) From befaca7c6b30ffdd83fb914b702488ae68864fb9 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:14:59 +0800 Subject: [PATCH 11/73] Update route.ts --- .../app/api/trial/start/route.ts | 186 ++++++------------ 1 file changed, 56 insertions(+), 130 deletions(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index b7a8d1aa..7b404de5 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -1,191 +1,117 @@ -import { NextRequest, NextResponse } from 'next/server' -import { getToken } from 'next-auth/jwt' -import Stripe from 'stripe' -import redis, { creditUtils, KEYS } from '@/lib/redis' -import { TrialUtils, CreditConfig } from '@/lib/credits-config' - -export const dynamic = 'force-dynamic' - -// Initialize Stripe -const stripe = process.env.STRIPE_SECRET_KEY - ? new Stripe(process.env.STRIPE_SECRET_KEY, { - apiVersion: '2025-05-28.basil', - }) - : null - export async function POST(request: NextRequest) { try { - // Get the user token - const token = await getToken({ req: request }) + const token = await getToken({ req: request }); if (!token?.sub) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } if (!stripe) { - return NextResponse.json({ error: 'Stripe configuration error' }, { status: 500 }) + return NextResponse.json({ error: 'Stripe configuration error' }, { status: 500 }); } - const userId = token.sub - const body = await request.json() - - // Handle both setupIntentId (new flow) and legacy parameters - const { setupIntentId, subscriptionId, paymentIntentId, planName, interval, amount } = body - - // Check if user already has an active trial/subscription first - const existingSubscription = await redis.hgetall(KEYS.USER_SUBSCRIPTION(userId)) - if (existingSubscription && ['trialing', 'active'].includes(existingSubscription.status as string)) { - // Return success if already processed to avoid duplicate processing - return NextResponse.json({ + const userId = token.sub; + const body = await request.json(); + const { setupIntentId, subscriptionId, paymentIntentId, planName, interval, amount } = body; + + // Check for existing active subscription + const existingSubscription = await redis.hgetall(KEYS.USER_SUBSCRIPTION(userId)); + if (existingSubscription && ['active'].includes(existingSubscription.status as string)) { + return NextResponse.json({ success: true, alreadyProcessed: true, subscriptionId: existingSubscription.stripeSubscriptionId || subscriptionId, - message: 'Trial already active', - subscription: existingSubscription, - credits: { - total: TrialUtils.getTrialCredits(), - used: parseInt(existingSubscription.creditsUsed as string || '0'), - remaining: TrialUtils.getTrialCredits() - parseInt(existingSubscription.creditsUsed as string || '0') - } - }) + message: 'Subscription already active', + subscription: existingSubscription + }); } - // If we have a subscriptionId but no setupIntentId, this might be a re-call from success page - if (subscriptionId && !setupIntentId) { - return NextResponse.json({ - error: 'Trial was already processed successfully. Please check your account page.', - alreadyProcessed: true - }, { status: 400 }) - } - - // NEW FLOW: Require setupIntentId for proper payment method verification if (!setupIntentId) { - return NextResponse.json({ error: 'Setup Intent ID is required for trial signup' }, { status: 400 }) + return NextResponse.json({ error: 'Setup Intent ID is required' }, { status: 400 }); } - // Verify the setup intent is successful - const setupIntent = await stripe.setupIntents.retrieve(setupIntentId) - + const setupIntent = await stripe.setupIntents.retrieve(setupIntentId); if (setupIntent.status !== 'succeeded') { - return NextResponse.json({ - error: 'Payment method setup not completed. Please complete payment method verification.', - setupStatus: setupIntent.status - }, { status: 400 }) + return NextResponse.json({ + error: 'Payment method setup not completed.', + setupStatus: setupIntent.status + }, { status: 400 }); } - // Extract metadata from setup intent - const metadata = setupIntent.metadata - if (!metadata) { - return NextResponse.json({ error: 'Missing setup intent metadata' }, { status: 400 }) - } - - const priceId = metadata.priceId - const customerId = setupIntent.customer as string - const couponId = metadata.couponId + const metadata = setupIntent.metadata; + const priceId = metadata?.priceId; + const customerId = setupIntent.customer as string; + const couponId = metadata?.couponId; if (!priceId || !customerId) { - return NextResponse.json({ error: 'Missing required payment information' }, { status: 400 }) + return NextResponse.json({ error: 'Missing payment information' }, { status: 400 }); } - // Store customer mapping for webhooks - await redis.set(`stripe:customer:${customerId}`, String(userId)) + await redis.set(`stripe:customer:${customerId}`, String(userId)); - // NOW create the subscription (after payment method is confirmed) - const trialEndTimestamp = TrialUtils.getTrialEndTimestamp() - const subscriptionParams: Stripe.SubscriptionCreateParams = { customer: customerId, items: [{ price: priceId }], - // trial_end: trialEndTimestamp, expand: ['latest_invoice.payment_intent'], payment_behavior: 'default_incomplete', default_payment_method: setupIntent.payment_method as string, payment_settings: { save_default_payment_method: 'on_subscription', }, - trial_settings: { - end_behavior: { - missing_payment_method: 'cancel' - } - }, metadata: { - userId: userId || 'anonymous', + userId, planName: metadata.planName || planName || 'Standard', interval: metadata.interval || interval || 'month', priceId, - // isTrial: 'true', - // trialEndDate: TrialUtils.getTrialEndDate(), createdFromSetupIntent: setupIntentId, }, - } + }; - // Apply discount if coupon is valid if (couponId) { - subscriptionParams.discounts = [{ coupon: couponId }] + subscriptionParams.discounts = [{ coupon: couponId }]; } - // Create subscription with trial - const subscription = await stripe.subscriptions.create(subscriptionParams) + const subscription = await stripe.subscriptions.create(subscriptionParams); - if (subscription.status !== 'trialing') { - return NextResponse.json({ - error: 'Failed to create trial subscription', - subscriptionStatus: subscription.status - }, { status: 500 }) + if (!['active', 'incomplete', 'past_due'].includes(subscription.status)) { + return NextResponse.json({ + error: 'Failed to create subscription', + subscriptionStatus: subscription.status + }, { status: 500 }); } - const now = new Date() - const trialEndDate = TrialUtils.getTrialEndDate(now) - - // Calculate credit reset date - 1 month from checkout (not trial end) - const creditResetDate = new Date(now) - creditResetDate.setMonth(creditResetDate.getMonth() + 1) - - // Set up trial subscription with STANDARD plan type but trial status + const now = new Date(); + const creditResetDate = new Date(now); + creditResetDate.setMonth(creditResetDate.getMonth() + 1); + const subscriptionData = { plan: 'Standard Plan', - planType: 'STANDARD', // Immediate Standard access as requested - status: 'active', // Use Stripe's standard trialing status + planType: 'STANDARD', + status: subscription.status, amount: amount?.toString() || '15', interval: interval || 'month', purchaseDate: now.toISOString(), - // trialStartDate: now.toISOString(), - // trialEndDate: trialEndDate, - creditResetDate: creditResetDate.toISOString().split('T')[0], // Store reset date + creditResetDate: creditResetDate.toISOString().split('T')[0], lastUpdated: now.toISOString(), stripeCustomerId: customerId, - stripeSubscriptionId: subscription.id, // Store actual subscription ID - // willChargeOn: trialEndDate - } - - // Initialize trial credits (500 credits immediately) with custom reset date - await creditUtils.initializeTrialCredits(userId, subscription.id, trialEndDate) - - // Set custom credit reset date (1 month from checkout) + stripeSubscriptionId: subscription.id + }; + + // Initialize paid credits (not trial) + await creditUtils.initializePaidCredits(userId, subscription.id); // you may need to rename or define this await redis.hset(KEYS.USER_CREDITS(userId), { resetDate: creditResetDate.toISOString().split('T')[0] - }) - - // Store subscription data in Redis - await redis.hset(KEYS.USER_SUBSCRIPTION(userId), subscriptionData) - - + }); + await redis.hset(KEYS.USER_SUBSCRIPTION(userId), subscriptionData); + return NextResponse.json({ success: true, subscriptionId: subscription.id, subscription: subscriptionData, - credits: { - total: TrialUtils.getTrialCredits(), - used: 0, - remaining: TrialUtils.getTrialCredits() - }, - // trialEndDate: trialEndDate, - message: 'Trial started successfully! You have immediate access to 500 credits.' - }) - + message: 'Subscription started successfully!' + }); + } catch (error: any) { - console.error('Error starting trial:', error) - return NextResponse.json({ - error: error.message || 'Failed to start trial' - }, { status: 500 }) + console.error('Error creating subscription:', error); + return NextResponse.json({ error: error.message || 'Subscription error' }, { status: 500 }); } -} +} From 8ed3df82b349a863917ceefb4f12f73527cb584c Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:19:13 +0800 Subject: [PATCH 12/73] Update route.ts --- .../app/api/trial/start/route.ts | 186 ++++++++++++------ 1 file changed, 130 insertions(+), 56 deletions(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index 7b404de5..843778f2 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -1,117 +1,191 @@ +import { NextRequest, NextResponse } from 'next/server' +import { getToken } from 'next-auth/jwt' +import Stripe from 'stripe' +import redis, { creditUtils, KEYS } from '@/lib/redis' +import { TrialUtils, CreditConfig } from '@/lib/credits-config' + +export const dynamic = 'force-dynamic' + +// Initialize Stripe +const stripe = process.env.STRIPE_SECRET_KEY + ? new Stripe(process.env.STRIPE_SECRET_KEY, { + apiVersion: '2025-05-28.basil', + }) + : null + export async function POST(request: NextRequest) { try { - const token = await getToken({ req: request }); + // Get the user token + const token = await getToken({ req: request }) if (!token?.sub) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } if (!stripe) { - return NextResponse.json({ error: 'Stripe configuration error' }, { status: 500 }); + return NextResponse.json({ error: 'Stripe configuration error' }, { status: 500 }) } - const userId = token.sub; - const body = await request.json(); - const { setupIntentId, subscriptionId, paymentIntentId, planName, interval, amount } = body; - - // Check for existing active subscription - const existingSubscription = await redis.hgetall(KEYS.USER_SUBSCRIPTION(userId)); - if (existingSubscription && ['active'].includes(existingSubscription.status as string)) { - return NextResponse.json({ + const userId = token.sub + const body = await request.json() + + // Handle both setupIntentId (new flow) and legacy parameters + const { setupIntentId, subscriptionId, paymentIntentId, planName, interval, amount } = body + + // Check if user already has an active trial/subscription first + const existingSubscription = await redis.hgetall(KEYS.USER_SUBSCRIPTION(userId)) + if (existingSubscription && ['trialing', 'active'].includes(existingSubscription.status as string)) { + // Return success if already processed to avoid duplicate processing + return NextResponse.json({ success: true, alreadyProcessed: true, subscriptionId: existingSubscription.stripeSubscriptionId || subscriptionId, - message: 'Subscription already active', - subscription: existingSubscription - }); + message: 'Trial already active', + subscription: existingSubscription, + credits: { + total: TrialUtils.getTrialCredits(), + used: parseInt(existingSubscription.creditsUsed as string || '0'), + remaining: TrialUtils.getTrialCredits() - parseInt(existingSubscription.creditsUsed as string || '0') + } + }) } + // If we have a subscriptionId but no setupIntentId, this might be a re-call from success page + if (subscriptionId && !setupIntentId) { + return NextResponse.json({ + error: 'Trial was already processed successfully. Please check your account page.', + alreadyProcessed: true + }, { status: 400 }) + } + + // NEW FLOW: Require setupIntentId for proper payment method verification if (!setupIntentId) { - return NextResponse.json({ error: 'Setup Intent ID is required' }, { status: 400 }); + return NextResponse.json({ error: 'Setup Intent ID is required for trial signup' }, { status: 400 }) } - const setupIntent = await stripe.setupIntents.retrieve(setupIntentId); + // Verify the setup intent is successful + const setupIntent = await stripe.setupIntents.retrieve(setupIntentId) + if (setupIntent.status !== 'succeeded') { - return NextResponse.json({ - error: 'Payment method setup not completed.', - setupStatus: setupIntent.status - }, { status: 400 }); + return NextResponse.json({ + error: 'Payment method setup not completed. Please complete payment method verification.', + setupStatus: setupIntent.status + }, { status: 400 }) } - const metadata = setupIntent.metadata; - const priceId = metadata?.priceId; - const customerId = setupIntent.customer as string; - const couponId = metadata?.couponId; + // Extract metadata from setup intent + const metadata = setupIntent.metadata + if (!metadata) { + return NextResponse.json({ error: 'Missing setup intent metadata' }, { status: 400 }) + } + + const priceId = metadata.priceId + const customerId = setupIntent.customer as string + const couponId = metadata.couponId if (!priceId || !customerId) { - return NextResponse.json({ error: 'Missing payment information' }, { status: 400 }); + return NextResponse.json({ error: 'Missing required payment information' }, { status: 400 }) } - await redis.set(`stripe:customer:${customerId}`, String(userId)); + // Store customer mapping for webhooks + await redis.set(stripe:customer:${customerId}, String(userId)) + // NOW create the subscription (after payment method is confirmed) + const trialEndTimestamp = TrialUtils.getTrialEndTimestamp() + const subscriptionParams: Stripe.SubscriptionCreateParams = { customer: customerId, items: [{ price: priceId }], + // trial_end: trialEndTimestamp, expand: ['latest_invoice.payment_intent'], payment_behavior: 'default_incomplete', default_payment_method: setupIntent.payment_method as string, payment_settings: { save_default_payment_method: 'on_subscription', }, + trial_settings: { + end_behavior: { + missing_payment_method: 'cancel' + } + }, metadata: { - userId, + userId: userId || 'anonymous', planName: metadata.planName || planName || 'Standard', interval: metadata.interval || interval || 'month', priceId, + // isTrial: 'true', + // trialEndDate: TrialUtils.getTrialEndDate(), createdFromSetupIntent: setupIntentId, }, - }; + } + // Apply discount if coupon is valid if (couponId) { - subscriptionParams.discounts = [{ coupon: couponId }]; + subscriptionParams.discounts = [{ coupon: couponId }] } - const subscription = await stripe.subscriptions.create(subscriptionParams); + // Create subscription with trial + const subscription = await stripe.subscriptions.create(subscriptionParams) - if (!['active', 'incomplete', 'past_due'].includes(subscription.status)) { - return NextResponse.json({ - error: 'Failed to create subscription', - subscriptionStatus: subscription.status - }, { status: 500 }); + if (subscription.status !== 'trialing') { + return NextResponse.json({ + error: 'Failed to create trial subscription', + subscriptionStatus: subscription.status + }, { status: 500 }) } - const now = new Date(); - const creditResetDate = new Date(now); - creditResetDate.setMonth(creditResetDate.getMonth() + 1); - + const now = new Date() + const trialEndDate = TrialUtils.getTrialEndDate(now) + + // Calculate credit reset date - 1 month from checkout (not trial end) + const creditResetDate = new Date(now) + creditResetDate.setMonth(creditResetDate.getMonth() + 1) + + // Set up trial subscription with STANDARD plan type but trial status const subscriptionData = { plan: 'Standard Plan', - planType: 'STANDARD', - status: subscription.status, + planType: 'STANDARD', // Immediate Standard access as requested + status: 'active', // Use Stripe's standard trialing status amount: amount?.toString() || '15', interval: interval || 'month', purchaseDate: now.toISOString(), - creditResetDate: creditResetDate.toISOString().split('T')[0], + trialStartDate: now.toISOString(), + trialEndDate: trialEndDate, + creditResetDate: creditResetDate.toISOString().split('T')[0], // Store reset date lastUpdated: now.toISOString(), stripeCustomerId: customerId, - stripeSubscriptionId: subscription.id - }; - - // Initialize paid credits (not trial) - await creditUtils.initializePaidCredits(userId, subscription.id); // you may need to rename or define this + stripeSubscriptionId: subscription.id, // Store actual subscription ID + willChargeOn: trialEndDate + } + + // Initialize trial credits (500 credits immediately) with custom reset date + await creditUtils.initializeTrialCredits(userId, subscription.id, trialEndDate) + + // Set custom credit reset date (1 month from checkout) await redis.hset(KEYS.USER_CREDITS(userId), { resetDate: creditResetDate.toISOString().split('T')[0] - }); - await redis.hset(KEYS.USER_SUBSCRIPTION(userId), subscriptionData); - + }) + + // Store subscription data in Redis + await redis.hset(KEYS.USER_SUBSCRIPTION(userId), subscriptionData) + + return NextResponse.json({ success: true, subscriptionId: subscription.id, subscription: subscriptionData, - message: 'Subscription started successfully!' - }); - + credits: { + total: TrialUtils.getTrialCredits(), + used: 0, + remaining: TrialUtils.getTrialCredits() + }, + trialEndDate: trialEndDate, + message: 'Trial started successfully! You have immediate access to 500 credits.' + }) + } catch (error: any) { - console.error('Error creating subscription:', error); - return NextResponse.json({ error: error.message || 'Subscription error' }, { status: 500 }); + console.error('Error starting trial:', error) + return NextResponse.json({ + error: error.message || 'Failed to start trial' + }, { status: 500 }) } -} +} From 8295bffbdda6e76397112f8e1748bdfc17b1e36c Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:20:26 +0800 Subject: [PATCH 13/73] Update route.ts --- auto-analyst-frontend/app/api/checkout-sessions/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/api/checkout-sessions/route.ts b/auto-analyst-frontend/app/api/checkout-sessions/route.ts index 57fa220d..bf1d6950 100644 --- a/auto-analyst-frontend/app/api/checkout-sessions/route.ts +++ b/auto-analyst-frontend/app/api/checkout-sessions/route.ts @@ -97,8 +97,8 @@ export async function POST(request: NextRequest) { planName, interval, priceId, - // isTrial: 'false', - // trialEndDate: TrialUtils.getTrialEndDate(), + isTrial: 'true', + trialEndDate: TrialUtils.getTrialEndDate(), ...(promoCode && { promoCode }), ...(couponId && { couponId }), }, From da9dc0632371b597cab02330982d95089bdb8bcc Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:31:17 +0800 Subject: [PATCH 14/73] Update page.tsx --- auto-analyst-frontend/app/pricing/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/pricing/page.tsx b/auto-analyst-frontend/app/pricing/page.tsx index 7b9ea6f3..cb7db708 100644 --- a/auto-analyst-frontend/app/pricing/page.tsx +++ b/auto-analyst-frontend/app/pricing/page.tsx @@ -35,7 +35,7 @@ const pricingTiers = [ `${TrialUtils.getTrialDisplayText()}`, ], highlight: true, - trial: false, + trial: true, }, { name: 'Enterprise', From 3faeacd1ea2341fc3658797f27def25c6c95ceb1 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:32:21 +0800 Subject: [PATCH 15/73] Update route.ts --- auto-analyst-frontend/app/api/checkout-sessions/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/checkout-sessions/route.ts b/auto-analyst-frontend/app/api/checkout-sessions/route.ts index bf1d6950..bc3844b1 100644 --- a/auto-analyst-frontend/app/api/checkout-sessions/route.ts +++ b/auto-analyst-frontend/app/api/checkout-sessions/route.ts @@ -109,7 +109,7 @@ export async function POST(request: NextRequest) { clientSecret: setupIntent.client_secret, customerId: customerId, discountApplied: !!couponId, - isTrialSetup: false, + isTrialSetup: true, planName, interval, priceId, From 60e387aba58e2376d89623e19aeaa6b7201c66ad Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:35:01 +0800 Subject: [PATCH 16/73] Update route.ts --- auto-analyst-frontend/app/api/trial/start/route.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index 843778f2..b6129e58 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -95,7 +95,7 @@ export async function POST(request: NextRequest) { const subscriptionParams: Stripe.SubscriptionCreateParams = { customer: customerId, items: [{ price: priceId }], - // trial_end: trialEndTimestamp, + trial_end: trialEndTimestamp, expand: ['latest_invoice.payment_intent'], payment_behavior: 'default_incomplete', default_payment_method: setupIntent.payment_method as string, @@ -112,8 +112,8 @@ export async function POST(request: NextRequest) { planName: metadata.planName || planName || 'Standard', interval: metadata.interval || interval || 'month', priceId, - // isTrial: 'true', - // trialEndDate: TrialUtils.getTrialEndDate(), + isTrial: 'true', + trialEndDate: TrialUtils.getTrialEndDate(), createdFromSetupIntent: setupIntentId, }, } @@ -144,7 +144,7 @@ export async function POST(request: NextRequest) { const subscriptionData = { plan: 'Standard Plan', planType: 'STANDARD', // Immediate Standard access as requested - status: 'active', // Use Stripe's standard trialing status + status: 'trialing', // Use Stripe's standard trialing status amount: amount?.toString() || '15', interval: interval || 'month', purchaseDate: now.toISOString(), From 46da874a647a51682e1b5edfaf0adfe8fa15d0eb Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:37:47 +0800 Subject: [PATCH 17/73] Update route.ts --- auto-analyst-frontend/app/api/trial/start/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index b6129e58..e2243bde 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -87,7 +87,7 @@ export async function POST(request: NextRequest) { } // Store customer mapping for webhooks - await redis.set(stripe:customer:${customerId}, String(userId)) + await redis.set(stripe,customer:${customerId}, String(userId)) // NOW create the subscription (after payment method is confirmed) const trialEndTimestamp = TrialUtils.getTrialEndTimestamp() From 4fce7d4d612402cb3a92bd030b102e54c112091c Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Sun, 3 Aug 2025 09:42:49 +0800 Subject: [PATCH 18/73] Update route.ts --- auto-analyst-frontend/app/api/trial/start/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/trial/start/route.ts b/auto-analyst-frontend/app/api/trial/start/route.ts index e2243bde..5a9e8f24 100644 --- a/auto-analyst-frontend/app/api/trial/start/route.ts +++ b/auto-analyst-frontend/app/api/trial/start/route.ts @@ -87,7 +87,7 @@ export async function POST(request: NextRequest) { } // Store customer mapping for webhooks - await redis.set(stripe,customer:${customerId}, String(userId)) + await redis.set(`stripe:customer:${customerId}`, String(userId)) // NOW create the subscription (after payment method is confirmed) const trialEndTimestamp = TrialUtils.getTrialEndTimestamp() From 56cad20b0559d6b59d3f68fd22344f2f19deb91d Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Thu, 7 Aug 2025 14:06:11 +0800 Subject: [PATCH 19/73] Update model_registry.py Added more models & removed some --- .../src/utils/model_registry.py | 42 ++++--------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/auto-analyst-backend/src/utils/model_registry.py b/auto-analyst-backend/src/utils/model_registry.py index 1d8ac1f3..394d1bbf 100644 --- a/auto-analyst-backend/src/utils/model_registry.py +++ b/auto-analyst-backend/src/utils/model_registry.py @@ -14,18 +14,12 @@ # Cost per 1K tokens for different models MODEL_COSTS = { "openai": { - "gpt-4.1": {"input": 0.002, "output": 0.008}, - "gpt-4.1-mini": {"input": 0.0004, "output": 0.0016}, - "gpt-4.1-nano": {"input": 0.00010, "output": 0.0004}, - "gpt-4.5-preview": {"input": 0.075, "output": 0.15}, - "gpt-4o": {"input": 0.0025, "output": 0.01}, - "gpt-4o-mini": {"input": 0.00015, "output": 0.0006}, + "o1": {"input": 0.015, "output": 0.06}, "o1-pro": {"input": 0.015, "output": 0.6}, "o1-mini": {"input": 0.00011, "output": 0.00044}, "o3": {"input": 0.002, "output": 0.008}, "o3-mini": {"input": 0.00011, "output": 0.00044}, - "gpt-3.5-turbo": {"input": 0.0005, "output": 0.0015}, }, "anthropic": { "claude-3-5-haiku-latest": {"input": 0.00025, "output": 0.000125}, @@ -37,16 +31,9 @@ }, "groq": { "deepseek-r1-distill-llama-70b": {"input": 0.00075, "output": 0.00099}, - "llama-3.3-70b-versatile": {"input": 0.00059, "output": 0.00079}, - "llama3-8b-8192": {"input": 0.00005, "output": 0.00008}, - "llama3-70b-8192": {"input": 0.00059, "output": 0.00079}, - "mistral-saba-24b": {"input": 0.00079, "output": 0.00079}, - "gemma2-9b-it": {"input": 0.0002, "output": 0.0002}, - "qwen-qwq-32b": {"input": 0.00029, "output": 0.00039}, - "meta-llama/llama-4-maverick-17b-128e-instruct": {"input": 0.0002, "output": 0.0006}, - "meta-llama/llama-4-scout-17b-16e-instruct": {"input": 0.00011, "output": 0.00034}, - "deepseek-r1-distill-qwen-32b": {"input": 0.00075, "output": 0.00099}, - "llama-3.1-70b-versatile": {"input": 0.00059, "output": 0.00079}, + "gpt-oss-120B":{"input": 0.00075, "output": 0.00099}, + "gpt-oss-20B":{"input": 0.00075, "output": 0.00099} + }, "gemini": { "gemini-2.5-pro-preview-03-25": {"input": 0.00015, "output": 0.001} @@ -114,13 +101,6 @@ # Model metadata (display name, context window, etc.) MODEL_METADATA = { # OpenAI - "gpt-4.1": {"display_name": "GPT-4.1", "context_window": 128000}, - "gpt-4.1-mini": {"display_name": "GPT-4.1 Mini", "context_window": 128000}, - "gpt-4.1-nano": {"display_name": "GPT-4.1 Nano", "context_window": 128000}, - "gpt-4o": {"display_name": "GPT-4o", "context_window": 128000}, - "gpt-4.5-preview": {"display_name": "GPT-4.5 Preview", "context_window": 128000}, - "gpt-4o-mini": {"display_name": "GPT-4o Mini", "context_window": 128000}, - "gpt-3.5-turbo": {"display_name": "GPT-3.5 Turbo", "context_window": 16385}, "o1": {"display_name": "o1", "context_window": 128000}, "o1-pro": {"display_name": "o1 Pro", "context_window": 128000}, "o1-mini": {"display_name": "o1 Mini", "context_window": 128000}, @@ -134,15 +114,9 @@ # GROQ "deepseek-r1-distill-llama-70b": {"display_name": "DeepSeek R1 Distill Llama 70b", "context_window": 32768}, - "llama-3.3-70b-versatile": {"display_name": "Llama 3.3 70b", "context_window": 8192}, - "llama3-8b-8192": {"display_name": "Llama 3 8b", "context_window": 8192}, - "llama3-70b-8192": {"display_name": "Llama 3 70b", "context_window": 8192}, - "mistral-saba-24b": {"display_name": "Mistral Saba 24b", "context_window": 32768}, - "gemma2-9b-it": {"display_name": "Gemma 2 9b", "context_window": 8192}, - "qwen-qwq-32b": {"display_name": "Qwen QWQ 32b | Alibaba", "context_window": 32768}, - "meta-llama/llama-4-maverick-17b-128e-instruct": {"display_name": "Llama 4 Maverick 17b", "context_window": 128000}, - "meta-llama/llama-4-scout-17b-16e-instruct": {"display_name": "Llama 4 Scout 17b", "context_window": 16000}, - "llama-3.1-70b-versatile": {"display_name": "Llama 3.1 70b Versatile", "context_window": 8192}, + "gpt-oss-120B":{"display_name": "OpenAI gpt oss 120B, "context_window": 128000}, + "gpt-oss-20B"::{"display_name": "OpenAI gpt oss 20B, "context_window": 128000}, + # Gemini "gemini-2.5-pro-preview-03-25": {"display_name": "Gemini 2.5 Pro", "context_window": 1000000}, @@ -206,4 +180,4 @@ def get_all_models_for_provider(provider): def get_models_by_tier(tier_id): """Get all models for a specific tier""" - return MODEL_TIERS.get(tier_id, {}).get("models", []) \ No newline at end of file + return MODEL_TIERS.get(tier_id, {}).get("models", []) From 51f47e060acc535c976fa65d09f2712f31f8a32b Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Thu, 7 Aug 2025 14:16:02 +0800 Subject: [PATCH 20/73] Update model-registry.ts --- auto-analyst-frontend/lib/model-registry.ts | 64 +++++---------------- 1 file changed, 13 insertions(+), 51 deletions(-) diff --git a/auto-analyst-frontend/lib/model-registry.ts b/auto-analyst-frontend/lib/model-registry.ts index 6e38123e..3105d68b 100644 --- a/auto-analyst-frontend/lib/model-registry.ts +++ b/auto-analyst-frontend/lib/model-registry.ts @@ -14,18 +14,11 @@ export const PROVIDERS = { // Cost per 1K tokens for different models export const MODEL_COSTS = { openai: { - "gpt-4.1": { input: 0.002, output: 0.008 }, - "gpt-4.1-mini": { input: 0.0004, output: 0.0016 }, - "gpt-4.1-nano": { input: 0.00010, output: 0.0004 }, - "gpt-4.5-preview": { input: 0.075, output: 0.15 }, - "gpt-4o": { input: 0.0025, output: 0.01 }, - "gpt-4o-mini": { input: 0.00015, output: 0.0006 }, "o1": { input: 0.015, output: 0.06 }, "o1-pro": { input: 0.015, output: 0.6 }, "o1-mini": { input: 0.00011, output: 0.00044 }, "o3": { input: 0.002, output: 0.008 }, - "o3-mini": { input: 0.00011, output: 0.00044 }, - "gpt-3.5-turbo": { input: 0.0005, output: 0.0015 } + "o3-mini": { input: 0.00011, output: 0.00044 } }, anthropic: { "claude-3-opus-latest": { input: 0.015, output: 0.075 }, @@ -37,16 +30,9 @@ export const MODEL_COSTS = { }, groq: { "deepseek-r1-distill-llama-70b": {"input": 0.00075, "output": 0.00099}, - "llama-3.3-70b-versatile": {"input": 0.00059, "output": 0.00079}, - "llama3-8b-8192": {"input": 0.00005, "output": 0.00008}, - "llama3-70b-8192": {"input": 0.00059, "output": 0.00079}, - "mistral-saba-24b": {"input": 0.00079, "output": 0.00079}, - "gemma2-9b-it": {"input": 0.0002, "output": 0.0002}, - "qwen-qwq-32b": {"input": 0.00029, "output": 0.00039}, - "meta-llama/llama-4-maverick-17b-128e-instruct": {"input": 0.0002, "output": 0.0006}, - "meta-llama/llama-4-scout-17b-16e-instruct": {"input": 0.00011, "output": 0.00034}, - "deepseek-r1-distill-qwen-32b": {"input": 0.00075, "output": 0.00099}, - "llama-3.1-70b-versatile": {"input": 0.00059, "output": 0.00079}, + "gpt-oss-120B":{"input": 0.00075, "output": 0.00099}, + "gpt-oss-20B":{"input": 0.00075, "output": 0.00099} + }, gemini: { "gemini-2.5-pro-preview-03-25": { input: 0.00015, output: 0.001 } @@ -60,41 +46,29 @@ export const MODEL_TIERS = { "credits": 1, "models": [ "claude-3-5-haiku-latest", - "llama3-8b-8192", - "gemma2-9b-it", - "meta-llama/llama-4-scout-17b-16e-instruct" + "gpt-oss-20B" ] }, "tier2": { "name": "Standard", "credits": 3, "models": [ - "gpt-4.1-nano", - "gpt-4o-mini", + "o1-mini", "o3-mini", - "qwen-qwq-32b", - "meta-llama/llama-4-maverick-17b-128e-instruct" ] }, "tier3": { "name": "Premium", "credits": 5, "models": [ - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4o", "o3", - "gpt-3.5-turbo", "claude-3-7-sonnet-latest", "claude-3-5-sonnet-latest", "claude-sonnet-4-20250514", "deepseek-r1-distill-llama-70b", - "llama-3.3-70b-versatile", - "llama3-70b-8192", - "mistral-saba-24b", - "deepseek-r1-distill-qwen-32b", - "llama-3.1-70b-versatile", + "gpt-oss-120B", + "gemini-2.5-pro-preview-03-25" ] }, @@ -121,13 +95,6 @@ export const TIER_COLORS = { // Model metadata (display name, context window, etc.) export const MODEL_METADATA: Record = { // OpenAI - "gpt-4.1": { displayName: "GPT-4.1", contextWindow: 128000 }, - "gpt-4.1-mini": { displayName: "GPT-4.1 Mini", contextWindow: 128000 }, - "gpt-4.1-nano": { displayName: "GPT-4.1 Nano", contextWindow: 128000 }, - "gpt-4o": { displayName: "GPT-4o", contextWindow: 128000 }, - "gpt-4.5-preview": { displayName: "GPT-4.5 Preview", contextWindow: 128000 }, - "gpt-4o-mini": { displayName: "GPT-4o Mini", contextWindow: 128000 }, - "gpt-3.5-turbo": { displayName: "GPT-3.5 Turbo", contextWindow: 16385 }, "o1": { displayName: "o1", contextWindow: 128000 }, "o1-pro": { displayName: "o1 Pro", contextWindow: 128000 }, "o1-mini": { displayName: "o1-mini", contextWindow: 128000 }, @@ -143,15 +110,10 @@ export const MODEL_METADATA: Record Date: Thu, 7 Aug 2025 14:17:11 +0800 Subject: [PATCH 21/73] Update model_registry.py --- .../src/utils/model_registry.py | 23 ++++++------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/auto-analyst-backend/src/utils/model_registry.py b/auto-analyst-backend/src/utils/model_registry.py index 394d1bbf..d4630aa8 100644 --- a/auto-analyst-backend/src/utils/model_registry.py +++ b/auto-analyst-backend/src/utils/model_registry.py @@ -47,41 +47,32 @@ "credits": 1, "models": [ "claude-3-5-haiku-latest", - "llama3-8b-8192", - "gemma2-9b-it", - "meta-llama/llama-4-scout-17b-16e-instruct" + "gpt-oss-20B" + + ] }, "tier2": { "name": "Standard", "credits": 3, "models": [ - "gpt-4.1-nano", - "gpt-4o-mini", + "o1-mini", "o3-mini", - "qwen-qwq-32b", - "meta-llama/llama-4-maverick-17b-128e-instruct" ] }, "tier3": { "name": "Premium", "credits": 5, "models": [ - "gpt-4.1", - "gpt-4.1-mini", - "gpt-4o", "o3", - "gpt-3.5-turbo", + "claude-3-7-sonnet-latest", "claude-3-5-sonnet-latest", "claude-sonnet-4-20250514", "deepseek-r1-distill-llama-70b", - "llama-3.3-70b-versatile", - "llama3-70b-8192", - "mistral-saba-24b", - "deepseek-r1-distill-qwen-32b", - "llama-3.1-70b-versatile", + "gpt-oss-120B", + "gemini-2.5-pro-preview-03-25" ] }, From 5ff6f89b5d272c9a36b4333d725a44281f6382f5 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Thu, 7 Aug 2025 14:21:48 +0800 Subject: [PATCH 22/73] Update model-registry.ts --- auto-analyst-frontend/lib/model-registry.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/lib/model-registry.ts b/auto-analyst-frontend/lib/model-registry.ts index 3105d68b..9350f7a5 100644 --- a/auto-analyst-frontend/lib/model-registry.ts +++ b/auto-analyst-frontend/lib/model-registry.ts @@ -110,8 +110,8 @@ export const MODEL_METADATA: Record Date: Thu, 7 Aug 2025 14:22:30 +0800 Subject: [PATCH 23/73] Update model-registry.ts --- auto-analyst-frontend/lib/model-registry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/lib/model-registry.ts b/auto-analyst-frontend/lib/model-registry.ts index 9350f7a5..a66ae556 100644 --- a/auto-analyst-frontend/lib/model-registry.ts +++ b/auto-analyst-frontend/lib/model-registry.ts @@ -111,7 +111,7 @@ export const MODEL_METADATA: Record Date: Thu, 7 Aug 2025 14:24:21 +0800 Subject: [PATCH 24/73] Update model_registry.py --- auto-analyst-backend/src/utils/model_registry.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/src/utils/model_registry.py b/auto-analyst-backend/src/utils/model_registry.py index d4630aa8..8f09cce5 100644 --- a/auto-analyst-backend/src/utils/model_registry.py +++ b/auto-analyst-backend/src/utils/model_registry.py @@ -105,8 +105,8 @@ # GROQ "deepseek-r1-distill-llama-70b": {"display_name": "DeepSeek R1 Distill Llama 70b", "context_window": 32768}, - "gpt-oss-120B":{"display_name": "OpenAI gpt oss 120B, "context_window": 128000}, - "gpt-oss-20B"::{"display_name": "OpenAI gpt oss 20B, "context_window": 128000}, + "gpt-oss-120B":{"display_name": "OpenAI gpt oss 120B", "context_window": 128000}, + "gpt-oss-20B":{"display_name": "OpenAI gpt oss 20B", "context_window": 128000}, # Gemini From 252b171abc5417afb2018d8075d4ef6ba5f9e4a8 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:30:09 +0800 Subject: [PATCH 25/73] Update model_registry.py Added gpt-5 and claude-opus-4-1 --- .../src/utils/model_registry.py | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/auto-analyst-backend/src/utils/model_registry.py b/auto-analyst-backend/src/utils/model_registry.py index 8f09cce5..60af5567 100644 --- a/auto-analyst-backend/src/utils/model_registry.py +++ b/auto-analyst-backend/src/utils/model_registry.py @@ -1,8 +1,3 @@ -""" -Models registry for the Auto-Analyst application. -This file serves as the single source of truth for all model information. -""" - # Model providers PROVIDERS = { "openai": "OpenAI", @@ -14,12 +9,14 @@ # Cost per 1K tokens for different models MODEL_COSTS = { "openai": { - "o1": {"input": 0.015, "output": 0.06}, "o1-pro": {"input": 0.015, "output": 0.6}, "o1-mini": {"input": 0.00011, "output": 0.00044}, "o3": {"input": 0.002, "output": 0.008}, "o3-mini": {"input": 0.00011, "output": 0.00044}, + "gpt-5": {"input": 0.00125, "output": 0.01}, # updated real cost + "gpt-5-mini": {"input": 0.00025, "output": 0.002}, # updated real cost + "gpt-5-nano": {"input": 0.00005, "output": 0.0004}, # updated real cost }, "anthropic": { "claude-3-5-haiku-latest": {"input": 0.00025, "output": 0.000125}, @@ -28,12 +25,12 @@ "claude-sonnet-4-20250514": {"input": 0.003, "output": 0.015}, "claude-3-opus-latest": {"input": 0.015, "output": 0.075}, "claude-opus-4-20250514": {"input": 0.015, "output": 0.075}, + "claude-opus-4-1": {"input": 0.015, "output": 0.075}, # approximate placeholder }, "groq": { "deepseek-r1-distill-llama-70b": {"input": 0.00075, "output": 0.00099}, - "gpt-oss-120B":{"input": 0.00075, "output": 0.00099}, - "gpt-oss-20B":{"input": 0.00075, "output": 0.00099} - + "gpt-oss-120B": {"input": 0.00075, "output": 0.00099}, + "gpt-oss-20B": {"input": 0.00075, "output": 0.00099} }, "gemini": { "gemini-2.5-pro-preview-03-25": {"input": 0.00015, "output": 0.001} @@ -47,18 +44,16 @@ "credits": 1, "models": [ "claude-3-5-haiku-latest", - "gpt-oss-20B" - - + "gpt-oss-20B" ] }, "tier2": { "name": "Standard", "credits": 3, "models": [ - "o1-mini", "o3-mini", + "gpt-5-nano" # Added ] }, "tier3": { @@ -66,14 +61,13 @@ "credits": 5, "models": [ "o3", - "claude-3-7-sonnet-latest", "claude-3-5-sonnet-latest", "claude-sonnet-4-20250514", "deepseek-r1-distill-llama-70b", "gpt-oss-120B", - - "gemini-2.5-pro-preview-03-25" + "gemini-2.5-pro-preview-03-25", + "gpt-5-mini" # Added ] }, "tier4": { @@ -86,6 +80,14 @@ "claude-3-opus-latest", "claude-opus-4-20250514" ] + }, + "tier5": { # New highest tier + "name": "Ultimate", + "credits": 50, + "models": [ + "gpt-5", + "claude-opus-4-1" + ] } } @@ -97,18 +99,22 @@ "o1-mini": {"display_name": "o1 Mini", "context_window": 128000}, "o3": {"display_name": "o3", "context_window": 128000}, "o3-mini": {"display_name": "o3 Mini", "context_window": 128000}, + "gpt-5": {"display_name": "GPT-5", "context_window": 400000}, + "gpt-5-mini": {"display_name": "GPT-5 Mini", "context_window": 150000}, # estimated + "gpt-5-nano": {"display_name": "GPT-5 Nano", "context_window": 64000}, # estimated + # Anthropic "claude-3-opus-latest": {"display_name": "Claude 3 Opus", "context_window": 200000}, "claude-3-7-sonnet-latest": {"display_name": "Claude 3.7 Sonnet", "context_window": 200000}, "claude-3-5-sonnet-latest": {"display_name": "Claude 3.5 Sonnet", "context_window": 200000}, "claude-3-5-haiku-latest": {"display_name": "Claude 3.5 Haiku", "context_window": 200000}, - + "claude-opus-4-1": {"display_name": "Claude Opus 4.1", "context_window": 200000}, + # GROQ "deepseek-r1-distill-llama-70b": {"display_name": "DeepSeek R1 Distill Llama 70b", "context_window": 32768}, - "gpt-oss-120B":{"display_name": "OpenAI gpt oss 120B", "context_window": 128000}, - "gpt-oss-20B":{"display_name": "OpenAI gpt oss 20B", "context_window": 128000}, + "gpt-oss-120B": {"display_name": "OpenAI gpt oss 120B", "context_window": 128000}, + "gpt-oss-20B": {"display_name": "OpenAI gpt oss 20B", "context_window": 128000}, - # Gemini "gemini-2.5-pro-preview-03-25": {"display_name": "Gemini 2.5 Pro", "context_window": 1000000}, } From 20ace65c11cef4ce7566886c4ffeb320ce192c3c Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Fri, 8 Aug 2025 14:33:52 +0800 Subject: [PATCH 26/73] Update model-registry.ts Adding gpt-5 and claude-opus 4.1 --- auto-analyst-frontend/lib/model-registry.ts | 120 +++++++++++--------- 1 file changed, 64 insertions(+), 56 deletions(-) diff --git a/auto-analyst-frontend/lib/model-registry.ts b/auto-analyst-frontend/lib/model-registry.ts index a66ae556..8c19f420 100644 --- a/auto-analyst-frontend/lib/model-registry.ts +++ b/auto-analyst-frontend/lib/model-registry.ts @@ -18,7 +18,10 @@ export const MODEL_COSTS = { "o1-pro": { input: 0.015, output: 0.6 }, "o1-mini": { input: 0.00011, output: 0.00044 }, "o3": { input: 0.002, output: 0.008 }, - "o3-mini": { input: 0.00011, output: 0.00044 } + "o3-mini": { input: 0.00011, output: 0.00044 }, + "gpt-5": { input: 0.00125, output: 0.01 }, // real cost + "gpt-5-mini": { input: 0.00025, output: 0.002 }, // real cost + "gpt-5-nano": { input: 0.00005, output: 0.0004 } // real cost }, anthropic: { "claude-3-opus-latest": { input: 0.015, output: 0.075 }, @@ -26,13 +29,13 @@ export const MODEL_COSTS = { "claude-3-5-sonnet-latest": { input: 0.003, output: 0.015 }, "claude-3-5-haiku-latest": { input: 0.0008, output: 0.0004 }, "claude-sonnet-4-20250514": { input: 0.003, output: 0.015 }, - "claude-opus-4-20250514": { input: 0.015, output: 0.075 } + "claude-opus-4-20250514": { input: 0.015, output: 0.075 }, + "claude-opus-4-1": { input: 0.015, output: 0.075 } // approximate real cost }, groq: { - "deepseek-r1-distill-llama-70b": {"input": 0.00075, "output": 0.00099}, - "gpt-oss-120B":{"input": 0.00075, "output": 0.00099}, - "gpt-oss-20B":{"input": 0.00075, "output": 0.00099} - + "deepseek-r1-distill-llama-70b": { input: 0.00075, output: 0.00099 }, + "gpt-oss-120B": { input: 0.00075, output: 0.00099 }, + "gpt-oss-20B": { input: 0.00075, output: 0.00099 } }, gemini: { "gemini-2.5-pro-preview-03-25": { input: 0.00015, output: 0.001 } @@ -41,55 +44,58 @@ export const MODEL_COSTS = { // Models by tier export const MODEL_TIERS = { - "tier1": { - "name": "Basic", - "credits": 1, - "models": [ - "claude-3-5-haiku-latest", - "gpt-oss-20B" - ] + tier1: { + name: "Basic", + credits: 1, + models: [ + "claude-3-5-haiku-latest", + "gpt-oss-20B" + ] }, - "tier2": { - "name": "Standard", - "credits": 3, - "models": [ - - "o1-mini", - "o3-mini", - ] + tier2: { + name: "Standard", + credits: 3, + models: [ + "o1-mini", + "o3-mini", + "gpt-5-nano" // added + ] }, - "tier3": { - "name": "Premium", - "credits": 5, - "models": [ - "o3", - "claude-3-7-sonnet-latest", - "claude-3-5-sonnet-latest", - "claude-sonnet-4-20250514", - "deepseek-r1-distill-llama-70b", - "gpt-oss-120B", - - "gemini-2.5-pro-preview-03-25" - ] + tier3: { + name: "Premium", + credits: 5, + models: [ + "o3", + "claude-3-7-sonnet-latest", + "claude-3-5-sonnet-latest", + "claude-sonnet-4-20250514", + "deepseek-r1-distill-llama-70b", + "gpt-oss-120B", + "gemini-2.5-pro-preview-03-25", + "gpt-5-mini" // added + ] }, - "tier4": { - "name": "Premium Plus", - "credits": 20, - "models": [ - "gpt-4.5-preview", - "o1", - "o1-pro", - "claude-3-opus-latest", - "claude-opus-4-20250514" - ] + tier4: { + name: "Premium Plus", + credits: 20, + models: [ + "gpt-4.5-preview", + "o1", + "o1-pro", + "claude-3-opus-latest", + "claude-opus-4-20250514", + "gpt-5", // moved here + "claude-opus-4-1" // moved here + ] } }; - // Tier colors for UI components + +// Tier colors for UI components export const TIER_COLORS = { tier1: "#10B981", // Green for Basic tier tier2: "#3B82F6", // Blue for Standard tier tier3: "#8B5CF6", // Purple for Premium tier - tier4: "#F59E0B" // Orange for Premium Plus tier + tier4: "#F59E0B" // Orange for Premium Plus tier }; // Model metadata (display name, context window, etc.) @@ -97,10 +103,13 @@ export const MODEL_METADATA: Record; return ( @@ -275,4 +283,4 @@ export function getAllModelsForProvider(provider: string): string[] { */ export function getModelsByTier(tierId: string): string[] { return MODEL_TIERS[tierId as TierId]?.models || []; -} +} From 237dd851bf700f75e28a3125a0fa58a61b48049d Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:30:53 +0800 Subject: [PATCH 27/73] Update app.py --- auto-analyst-backend/app.py | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 23218f18..c1a63b94 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -150,7 +150,7 @@ class DeepAnalysisResponse(BaseModel): # Add near the top of the file, after imports DEFAULT_MODEL_CONFIG = { "provider": os.getenv("MODEL_PROVIDER", "openai"), - "model": os.getenv("MODEL_NAME", "gpt-4o-mini"), + "model": os.getenv("MODEL_NAME", "01"), "api_key": os.getenv("OPENAI_API_KEY"), "temperature": float(os.getenv("TEMPERATURE", 1.0)), "max_tokens": int(os.getenv("MAX_TOKENS", 6000)) @@ -223,13 +223,31 @@ def get_session_lm(session_state): max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) ) else: # OpenAI is the default - logger.log_message(f"Using default model: {model_config.get('model', DEFAULT_MODEL_CONFIG['model'])}", level=logging.INFO) - return dspy.LM( - model=f"openai/{model_config.get("model", DEFAULT_MODEL_CONFIG["model"])}", - api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), - temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) - ) + else: # OpenAI is the default provider + model_name = model_config.get("model", DEFAULT_MODEL_CONFIG["model"]) + max_token_value = model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) + + logger.log_message(f"Using default model: {model_name} with max tokens value: {max_token_value}", level=logging.INFO) + + if model_name in ["gpt-5", "gpt-5-mini", "gpt-5-nano"]: + # For gpt-5 model, use max_completion_token (singular) argument name, + # but its value is what max_tokens used to be + return dspy.LM( + model=f"openai/{model_name}", + api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), + temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), + max_completion_token=max_token_value # note the renamed param here + ) + else: + # For other models, keep using max_tokens as parameter name + return dspy.LM( + model=f"openai/{model_name}", + api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), + temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), + max_tokens=max_token_value + ) + + # If no valid session config, use default return default_lm @@ -1593,4 +1611,4 @@ async def download_html_report( app.include_router(templates_router) if __name__ == "__main__": - uvicorn.run(app, host="0.0.0.0", port=8000) \ No newline at end of file + uvicorn.run(app, host="0.0.0.0", port=8000) From 9439f4d2745f906dc6ff399c3d5ec520ad169202 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:34:09 +0800 Subject: [PATCH 28/73] Update app.py --- auto-analyst-backend/app.py | 1 - 1 file changed, 1 deletion(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index c1a63b94..23b16330 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -223,7 +223,6 @@ def get_session_lm(session_state): max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) ) else: # OpenAI is the default - else: # OpenAI is the default provider model_name = model_config.get("model", DEFAULT_MODEL_CONFIG["model"]) max_token_value = model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) From e843c88b31a5e24252e6d85e943f2355a5492e26 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:35:37 +0800 Subject: [PATCH 29/73] Update app.py --- auto-analyst-backend/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 23b16330..ca141f75 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -235,7 +235,7 @@ def get_session_lm(session_state): model=f"openai/{model_name}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_completion_token=max_token_value # note the renamed param here + max_completion_tokens=max_token_value # note the renamed param here ) else: # For other models, keep using max_tokens as parameter name From 114436478a8c1bd04eb58228bf9ea96df1e12fca Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:43:10 +0800 Subject: [PATCH 30/73] Update app.py --- auto-analyst-backend/app.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index ca141f75..7ec65ba8 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -164,6 +164,7 @@ class DeepAnalysisResponse(BaseModel): temperature=DEFAULT_MODEL_CONFIG["temperature"], max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) + elif DEFAULT_MODEL_CONFIG["provider"].lower() == "gemini": default_lm = dspy.LM( model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", @@ -179,12 +180,20 @@ class DeepAnalysisResponse(BaseModel): max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) else: - default_lm = dspy.LM( - model=f"openai/{DEFAULT_MODEL_CONFIG["model"]}", + if DEFAULT_MODEL_CONFIG['model'] in ['gpt-5','gpt-5-mini','gpt-5-nano']: + default_lm = dspy.LM( + model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], - max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] - ) + max_completion_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + ) + else: + default_lm = dspy.LM( + model=f"openai/{DEFAULT_MODEL_CONFIG["model"]}", + api_key=DEFAULT_MODEL_CONFIG["api_key"], + temperature=DEFAULT_MODEL_CONFIG["temperature"], + max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + ) # lm = dspy.LM('openai/gpt-4o-mini', api_key=os.getenv("OPENAI_API_KEY")) # dspy.configure(lm=lm) From a05002c4b12121c4824e2ec85d2e04e115083777 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:51:28 +0800 Subject: [PATCH 31/73] Update session_routes.py --- .../src/routes/session_routes.py | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index 66f238c0..35de35ba 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -213,14 +213,25 @@ async def update_model_settings( session_state = app_state.get_session_state(session_id) # Create the model config - model_config = { - "provider": settings.provider, - "model": settings.model, - "api_key": settings.api_key, - "temperature": settings.temperature, - "max_tokens": settings.max_tokens - } + if settings.model in ['gpt-5', 'gpt-5-mini','gpt-5-nano']: + model_config = { + "provider": settings.provider, + "model": settings.model, + "api_key": settings.api_key, + "temperature": settings.temperature, + "max_completion_tokens": settings.max_tokens + } + + else: + model_config = { + "provider": settings.provider, + "model": settings.model, + "api_key": settings.api_key, + "temperature": settings.temperature, + "max_tokens": settings.max_tokens + } + # Update only the session's model config session_state["model_config"] = model_config @@ -651,4 +662,4 @@ async def set_message_info( } except Exception as e: logger.log_message(f"Error setting message info: {str(e)}", level=logging.ERROR) - raise HTTPException(status_code=500, detail=str(e)) \ No newline at end of file + raise HTTPException(status_code=500, detail=str(e)) From ef7f4104ec7b82567d2ed7dbb601f2fa8586ac60 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 15:55:08 +0800 Subject: [PATCH 32/73] Update session_routes.py --- .../src/routes/session_routes.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index 35de35ba..d75702cb 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -270,12 +270,20 @@ async def update_model_settings( ) else: # OpenAI is the default logger.log_message(f"OpenAI Model: {settings.model}", level=logging.INFO) - lm = dspy.LM( - model=f"openai/{settings.model}", - api_key=settings.api_key, - temperature=settings.temperature, - max_tokens=settings.max_tokens - ) + if settings.model in ['gpt-5','gpt-5-mini','gpt-5-nano']: + lm = dspy.LM( + model=f"openai/{settings.model}", + api_key=settings.api_key, + temperature=settings.temperature, + max_completion_tokens=settings.max_tokens + ) + else: + lm = dspy.LM( + model=f"openai/{settings.model}", + api_key=settings.api_key, + temperature=settings.temperature, + max_tokens=settings.max_tokens + ) # Test the model configuration without setting it globally From 90d6718469e4406075d6c9c0bef22be1a7679ca7 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:02:04 +0800 Subject: [PATCH 33/73] Update format_response.py --- auto-analyst-backend/scripts/format_response.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/auto-analyst-backend/scripts/format_response.py b/auto-analyst-backend/scripts/format_response.py index 7f2af8e6..6bc04e7c 100644 --- a/auto-analyst-backend/scripts/format_response.py +++ b/auto-analyst-backend/scripts/format_response.py @@ -856,7 +856,7 @@ def format_plan_instructions(plan_instructions): else: raise TypeError(f"Unsupported plan instructions type: {type(plan_instructions)}") except Exception as e: - raise ValueError(f"Error processing plan instructions: {str(e)}") + raise ValueError(f"Error processing plan instructions: {str(e)} + {dspy.settings.lm} ") # logger.log_message(f"Plan instructions: {instructions}", level=logging.INFO) @@ -1059,7 +1059,7 @@ def format_response_to_markdown(api_response, agent_name = None, dataframe=None) except Exception as e: logger.log_message(f"Error in format_response_to_markdown: {str(e)}", level=logging.ERROR) - return f"{str(e)}" + return f"error formating markdown {str(e)}" # logger.log_message(f"Generated markdown content for agent '{agent_name}' at {time.strftime('%Y-%m-%d %H:%M:%S')}: {markdown}, length: {len(markdown)}", level=logging.INFO) @@ -1070,7 +1070,7 @@ def format_response_to_markdown(api_response, agent_name = None, dataframe=None) f"API Response: {api_response}", level=logging.ERROR ) - return " " + return "" return '\n'.join(markdown) @@ -1100,4 +1100,4 @@ def format_response_to_markdown(api_response, agent_name = None, dataframe=None) } } - formatted_md = format_response_to_markdown(sample_response) \ No newline at end of file + formatted_md = format_response_to_markdown(sample_response) From 2131ff7680d02f7b832cf764ad4f116156b59b11 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:05:49 +0800 Subject: [PATCH 34/73] Update agents.py --- auto-analyst-backend/src/agents/agents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/src/agents/agents.py b/auto-analyst-backend/src/agents/agents.py index dcb44c8f..1ac878c0 100644 --- a/auto-analyst-backend/src/agents/agents.py +++ b/auto-analyst-backend/src/agents/agents.py @@ -708,7 +708,7 @@ async def forward(self, goal, dataset, Agent_desc): return { "complexity": "error", "plan": "basic_qa_agent", - "plan_instructions": {"error": f"Planning error: {str(e)}"} + "plan_instructions": {"error": f"Planning error in agents: {str(e)} + {dspy.settings.lm}"} } return output From beaa615df5fbef9e9ffb5d3da3a20afd187ea11f Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:07:36 +0800 Subject: [PATCH 35/73] Update agents.py --- auto-analyst-backend/src/agents/agents.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/src/agents/agents.py b/auto-analyst-backend/src/agents/agents.py index 1ac878c0..c7f7449f 100644 --- a/auto-analyst-backend/src/agents/agents.py +++ b/auto-analyst-backend/src/agents/agents.py @@ -708,7 +708,7 @@ async def forward(self, goal, dataset, Agent_desc): return { "complexity": "error", "plan": "basic_qa_agent", - "plan_instructions": {"error": f"Planning error in agents: {str(e)} + {dspy.settings.lm}"} + "plan_instructions": {"error": f"Planning error in agents: {str(e)} + {dspy.settings.lm.model}"} } return output From 424a6a13d1b385a0725847cfa9907626903c8de3 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:12:01 +0800 Subject: [PATCH 36/73] Update app.py --- auto-analyst-backend/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 7ec65ba8..2681d927 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -180,7 +180,7 @@ class DeepAnalysisResponse(BaseModel): max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) else: - if DEFAULT_MODEL_CONFIG['model'] in ['gpt-5','gpt-5-mini','gpt-5-nano']: + if DEFAULT_MODEL_CONFIG['model'] in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: default_lm = dspy.LM( model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", api_key=DEFAULT_MODEL_CONFIG["api_key"], @@ -237,7 +237,7 @@ def get_session_lm(session_state): logger.log_message(f"Using default model: {model_name} with max tokens value: {max_token_value}", level=logging.INFO) - if model_name in ["gpt-5", "gpt-5-mini", "gpt-5-nano"]: + if model_name in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: # For gpt-5 model, use max_completion_token (singular) argument name, # but its value is what max_tokens used to be return dspy.LM( From c6fc3a03b97f3df940e0be3581f30ccc2e8cd2bc Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:12:54 +0800 Subject: [PATCH 37/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index d75702cb..8157b646 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -213,7 +213,7 @@ async def update_model_settings( session_state = app_state.get_session_state(session_id) # Create the model config - if settings.model in ['gpt-5', 'gpt-5-mini','gpt-5-nano']: + if settings.model in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: model_config = { "provider": settings.provider, "model": settings.model, From 3f1b8b4d3fcbacbcd966cb201d7df7daafd6d4d2 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:17:29 +0800 Subject: [PATCH 38/73] Update app.py --- auto-analyst-backend/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 2681d927..3d42ddec 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -180,7 +180,7 @@ class DeepAnalysisResponse(BaseModel): max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) else: - if DEFAULT_MODEL_CONFIG['model'] in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: + if DEFAULT_MODEL_CONFIG['model'].lower() in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: default_lm = dspy.LM( model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", api_key=DEFAULT_MODEL_CONFIG["api_key"], @@ -237,7 +237,7 @@ def get_session_lm(session_state): logger.log_message(f"Using default model: {model_name} with max tokens value: {max_token_value}", level=logging.INFO) - if model_name in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: + if 'gpt-5' in model_name: # For gpt-5 model, use max_completion_token (singular) argument name, # but its value is what max_tokens used to be return dspy.LM( From 75de4b07de8ccc8898b92309e78760c5dadb599f Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:18:53 +0800 Subject: [PATCH 39/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index 8157b646..cc439cfb 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -213,7 +213,7 @@ async def update_model_settings( session_state = app_state.get_session_state(session_id) # Create the model config - if settings.model in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: + if 'gpt-5' in str(settings.model): model_config = { "provider": settings.provider, "model": settings.model, @@ -270,7 +270,7 @@ async def update_model_settings( ) else: # OpenAI is the default logger.log_message(f"OpenAI Model: {settings.model}", level=logging.INFO) - if settings.model in ['gpt-5','gpt-5-mini','gpt-5-nano']: + if 'gpt-5' in settings.model: lm = dspy.LM( model=f"openai/{settings.model}", api_key=settings.api_key, From 6b6903b40eafd13e251a78becd43a165a56287e5 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:20:13 +0800 Subject: [PATCH 40/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index cc439cfb..67f1871e 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -329,7 +329,7 @@ async def get_model_settings( # Use values from model_config with fallbacks to defaults return { "provider": model_config.get("provider", "openai"), - "model": model_config.get("model", "gpt-4o-mini"), + "model": model_config.get("model", "o1"), "hasCustomKey": bool(model_config.get("api_key")) or bool(os.getenv("CUSTOM_API_KEY")), "temperature": model_config.get("temperature", 0.7), "maxTokens": model_config.get("max_tokens", 6000) From 32bc3ffb3a64235a6b05d5ff4a8bb72219f1ced7 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:27:37 +0800 Subject: [PATCH 41/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index 67f1871e..ac1c117f 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -268,9 +268,10 @@ async def update_model_settings( temperature=settings.temperature, max_tokens=settings.max_tokens ) - else: # OpenAI is the default + elif settings.provider.lower() == "openai": # OpenAI is the default logger.log_message(f"OpenAI Model: {settings.model}", level=logging.INFO) - if 'gpt-5' in settings.model: + print(settings.model.lower()) + if 'gpt-5' in settings.model.lower(): lm = dspy.LM( model=f"openai/{settings.model}", api_key=settings.api_key, From 9f62e7d4accd815be24ec27ecc1bb156165db509 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:34:40 +0800 Subject: [PATCH 42/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 7b5fa813..4cf0608f 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -1,6 +1,7 @@ aiofiles==24.1.0 beautifulsoup4==4.13.4 dspy==2.6.14 +litellm==1.75.2 email_validator==2.2.0 fastapi==0.111.1 fastapi-cli==0.0.7 @@ -60,4 +61,4 @@ pymc==5.23.0 lightgbm==4.6.0 arviz==0.21.0 optuna==4.3.0 -shap==0.45.1 \ No newline at end of file +shap==0.45.1 From bca0a68e8712f4152f40dfa973e20d28c7683177 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:35:50 +0800 Subject: [PATCH 43/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 4cf0608f..893be9c4 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -11,7 +11,6 @@ groq==0.18.0 gunicorn==22.0.0 huggingface-hub==0.30.2 joblib==1.4.2 -litellm==1.63.7 llama-cloud==0.1.19 llama-cloud-services==0.6.21 llama-index==0.12.14 From f9fd3f6a52fa15a2824b37d6a14a05230746c574 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:37:14 +0800 Subject: [PATCH 44/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 893be9c4..fad84511 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -1,6 +1,6 @@ aiofiles==24.1.0 beautifulsoup4==4.13.4 -dspy==2.6.14 +dspy==2.6.27 litellm==1.75.2 email_validator==2.2.0 fastapi==0.111.1 From 10b250e8f91b32a150bfee650c23c69105c6056a Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 16:39:03 +0800 Subject: [PATCH 45/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index fad84511..e1fbab85 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -29,7 +29,7 @@ matplotlib-inline==0.1.7 numpy==2.2.2 openpyxl==3.1.2 xlrd==2.0.1 -openai==1.61.0 +openai==1.97.0 pandas==2.2.3 polars==1.30.0 pillow==11.1.0 From f7efece6e92ddf2ba688413175e3925db1cef6ac Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 17:49:16 +0800 Subject: [PATCH 46/73] Update app.py --- auto-analyst-backend/app.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 3d42ddec..61f0d48c 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -185,6 +185,7 @@ class DeepAnalysisResponse(BaseModel): model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], + max_tokens=None, max_completion_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) else: @@ -244,7 +245,8 @@ def get_session_lm(session_state): model=f"openai/{model_name}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_completion_tokens=max_token_value # note the renamed param here + max_tokens=None, + max_completion_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] ) else: # For other models, keep using max_tokens as parameter name From 3f4255cc5bf3fd04bfc28ceb06e69d9cf4a12074 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 17:50:28 +0800 Subject: [PATCH 47/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index ac1c117f..f7089849 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -219,6 +219,7 @@ async def update_model_settings( "model": settings.model, "api_key": settings.api_key, "temperature": settings.temperature, + "max_tokens":None, "max_completion_tokens": settings.max_tokens } @@ -276,6 +277,7 @@ async def update_model_settings( model=f"openai/{settings.model}", api_key=settings.api_key, temperature=settings.temperature, + max_tokens = None, max_completion_tokens=settings.max_tokens ) else: From b45c380a83a8db28ddd4092cf3dda39e28d7ee24 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 17:56:01 +0800 Subject: [PATCH 48/73] Update session_routes.py set max_completion_tokens to 20K --- auto-analyst-backend/src/routes/session_routes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index f7089849..534f3160 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -220,7 +220,7 @@ async def update_model_settings( "api_key": settings.api_key, "temperature": settings.temperature, "max_tokens":None, - "max_completion_tokens": settings.max_tokens + "max_completion_tokens": 20000 } @@ -278,7 +278,7 @@ async def update_model_settings( api_key=settings.api_key, temperature=settings.temperature, max_tokens = None, - max_completion_tokens=settings.max_tokens + max_completion_tokens= 20000 ) else: lm = dspy.LM( From 05db289ea9e4ca61468217224dae2781eb79c4a5 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 17:56:53 +0800 Subject: [PATCH 49/73] Update app.py --- auto-analyst-backend/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 61f0d48c..e889aff4 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -186,7 +186,7 @@ class DeepAnalysisResponse(BaseModel): api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], max_tokens=None, - max_completion_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_completion_tokens=20000 ) else: default_lm = dspy.LM( @@ -246,7 +246,7 @@ def get_session_lm(session_state): api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), max_tokens=None, - max_completion_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_completion_tokens=20000 ) else: # For other models, keep using max_tokens as parameter name From f80d3400533db080c5c2e5bc6f5103e960cc8e88 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:18:27 +0800 Subject: [PATCH 50/73] Update app.py --- auto-analyst-backend/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index e889aff4..c621537a 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -246,7 +246,7 @@ def get_session_lm(session_state): api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), max_tokens=None, - max_completion_tokens=20000 + max_completion_tokens=500 ) else: # For other models, keep using max_tokens as parameter name From a90d98eda576b7028364442dc7f01866277c38b2 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:18:55 +0800 Subject: [PATCH 51/73] Update app.py --- auto-analyst-backend/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index c621537a..61b4d237 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -186,7 +186,7 @@ class DeepAnalysisResponse(BaseModel): api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], max_tokens=None, - max_completion_tokens=20000 + max_completion_tokens=10000 ) else: default_lm = dspy.LM( @@ -246,7 +246,7 @@ def get_session_lm(session_state): api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), max_tokens=None, - max_completion_tokens=500 + max_completion_tokens=10000 ) else: # For other models, keep using max_tokens as parameter name From 02ebd6f06c64832ed07d39343b8fd25b5f9ad195 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:19:34 +0800 Subject: [PATCH 52/73] Update session_routes.py --- auto-analyst-backend/src/routes/session_routes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-backend/src/routes/session_routes.py b/auto-analyst-backend/src/routes/session_routes.py index 534f3160..2847cfb2 100644 --- a/auto-analyst-backend/src/routes/session_routes.py +++ b/auto-analyst-backend/src/routes/session_routes.py @@ -220,7 +220,7 @@ async def update_model_settings( "api_key": settings.api_key, "temperature": settings.temperature, "max_tokens":None, - "max_completion_tokens": 20000 + "max_completion_tokens": 10000 } @@ -278,7 +278,7 @@ async def update_model_settings( api_key=settings.api_key, temperature=settings.temperature, max_tokens = None, - max_completion_tokens= 20000 + max_completion_tokens= 10000 ) else: lm = dspy.LM( From f7c926a8fdd1380e2cc192910d5740fbc8f7ff37 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:38:02 +0800 Subject: [PATCH 53/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index e1fbab85..a05ef970 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -61,3 +61,4 @@ lightgbm==4.6.0 arviz==0.21.0 optuna==4.3.0 shap==0.45.1 +litellm[proxy] From aacbfd75b60420724585bb23bc3387600d2894f2 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:39:32 +0800 Subject: [PATCH 54/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index a05ef970..f88e2137 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -3,7 +3,7 @@ beautifulsoup4==4.13.4 dspy==2.6.27 litellm==1.75.2 email_validator==2.2.0 -fastapi==0.111.1 +fastapi==0.115.5 fastapi-cli==0.0.7 FastAPI-SQLAlchemy==0.2.1 fastapi-sso==0.10.0 From 918329bcb726c02c4911f471d8604f8f8582e400 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:40:45 +0800 Subject: [PATCH 55/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index f88e2137..096a2852 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -6,7 +6,7 @@ email_validator==2.2.0 fastapi==0.115.5 fastapi-cli==0.0.7 FastAPI-SQLAlchemy==0.2.1 -fastapi-sso==0.10.0 +fastapi-sso==0.16.0 groq==0.18.0 gunicorn==22.0.0 huggingface-hub==0.30.2 From 558f5cd1bc0390ba35e121411fc6777c1fefb440 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:42:17 +0800 Subject: [PATCH 56/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 096a2852..778e6b07 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -8,7 +8,7 @@ fastapi-cli==0.0.7 FastAPI-SQLAlchemy==0.2.1 fastapi-sso==0.16.0 groq==0.18.0 -gunicorn==22.0.0 +gunicorn==23.0.0 huggingface-hub==0.30.2 joblib==1.4.2 llama-cloud==0.1.19 From 51b98affdcd4cd931093099956b8d68f061cbb53 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:43:43 +0800 Subject: [PATCH 57/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 778e6b07..19356df7 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -31,7 +31,7 @@ openpyxl==3.1.2 xlrd==2.0.1 openai==1.97.0 pandas==2.2.3 -polars==1.30.0 +polars==1.31.0 pillow==11.1.0 plotly==5.24.1 psycopg2==2.9.10 From 11f10cc5d9d37c32c20ad8a04eac103b3e66518f Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:44:58 +0800 Subject: [PATCH 58/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 19356df7..5e5000d1 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -37,7 +37,6 @@ plotly==5.24.1 psycopg2==2.9.10 python-dateutil==2.9.0.post0 python-dotenv==1.0.1 -python-multipart==0.0.9 requests==2.32.3 scikit-learn==1.6.1 scipy==1.15.1 From 5978947d8662ddd94d1751ca6afae7342dd5ec51 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:47:27 +0800 Subject: [PATCH 59/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 5e5000d1..7b6450eb 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -50,7 +50,7 @@ tiktoken==0.8.0 tokenizers==0.21.0 tqdm==4.67.1 urllib3==2.4.0 -uvicorn==0.22.0 +uvicorn==0.29.0 websockets==14.2 wheel==0.45.1 xgboost-cpu==3.0.2 From 02c6c57c6f7a1710267ba49bb5d69d262c54dfd3 Mon Sep 17 00:00:00 2001 From: arslanfbt Date: Fri, 8 Aug 2025 18:49:18 +0800 Subject: [PATCH 60/73] Update requirements.txt --- auto-analyst-backend/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-backend/requirements.txt b/auto-analyst-backend/requirements.txt index 7b6450eb..f84443c8 100644 --- a/auto-analyst-backend/requirements.txt +++ b/auto-analyst-backend/requirements.txt @@ -51,7 +51,7 @@ tokenizers==0.21.0 tqdm==4.67.1 urllib3==2.4.0 uvicorn==0.29.0 -websockets==14.2 +websockets>=13.1.0 wheel==0.45.1 xgboost-cpu==3.0.2 bokeh==3.7.3 From dc52e0761dd0f8fd72db09aff2b5556944a4f960 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 12:36:37 +0500 Subject: [PATCH 61/73] Update route.ts --- auto-analyst-frontend/app/api/credits/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/api/credits/route.ts b/auto-analyst-frontend/app/api/credits/route.ts index ec6cd68e..bedf1367 100644 --- a/auto-analyst-frontend/app/api/credits/route.ts +++ b/auto-analyst-frontend/app/api/credits/route.ts @@ -40,7 +40,7 @@ export async function POST(request: Request) { if (action === 'reset') { // Reset credits to the monthly allowance using centralized config - const defaultCredits = 0 // No free credits anymore + const defaultCredits = 20 // No free credits anymore await creditUtils.initializeTrialCredits(userIdentifier, 'manual-init', new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString()) return NextResponse.json({ success: true, credits: defaultCredits }) } else if (action === 'deduct') { @@ -68,4 +68,4 @@ export async function POST(request: Request) { { status: 500 } ) } -} \ No newline at end of file +} From 76eab20485e1d917ac3e95caec187bd6a56e7db0 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 12:44:17 +0500 Subject: [PATCH 62/73] Update redis.ts --- auto-analyst-frontend/lib/redis.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/lib/redis.ts b/auto-analyst-frontend/lib/redis.ts index c292c9b3..3b698d6b 100644 --- a/auto-analyst-frontend/lib/redis.ts +++ b/auto-analyst-frontend/lib/redis.ts @@ -43,7 +43,7 @@ export const creditUtils = { const creditsHash = await redis.hgetall(KEYS.USER_CREDITS(userId)) if (!creditsHash || !creditsHash.total || !creditsHash.used) { // No more free credits - users must have 0 credits if no subscription - return 0 + return 20 } const total = parseInt(creditsHash.total as string) @@ -570,4 +570,4 @@ export const profileUtils = { return null; } } -}; \ No newline at end of file +}; From b4042fa8872e993fc4ee27476512b894986380c2 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:04:37 +0500 Subject: [PATCH 63/73] Update route.ts --- .../app/api/user/deduct-credits/route.ts | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts index 20916e2d..77af7dc3 100644 --- a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts +++ b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts @@ -19,15 +19,28 @@ export async function POST(request: NextRequest) { const creditsHash = await redis.hgetall(KEYS.USER_CREDITS(userId)) if (!creditsHash || !creditsHash.total) { + const defaultCredits = CreditConfig.getDefaultInitialCredits() + await redis.hset(KEYS.USER_CREDITS(userId), { + total: '20', + used: '0', + resetDate: CreditConfig.getNextResetDate(), + lastUpdate: new Date().toISOString() + }) + return NextResponse.json({ + success: true, + remaining: defaultCredits, + deducted: 0 + }) + // No credits for users without subscription - require upgrade - return NextResponse.json({ - success: false, - error: 'UPGRADE_REQUIRED', - message: 'Please start your trial or upgrade your plan to continue.', - remaining: 0, - needsUpgrade: true - }, { status: 402 }) // Payment Required status code - } + // return NextResponse.json({ + // success: false, + // error: 'UPGRADE_REQUIRED', + // message: 'Please start your trial or upgrade your plan to continue.', + // remaining: 0, + // needsUpgrade: true + // }, { status: 402 }) // Payment Required status code + // } // Calculate new used amount const total = parseInt(creditsHash.total as string) @@ -67,4 +80,4 @@ export async function POST(request: NextRequest) { console.error('Error deducting credits:', error) return NextResponse.json({ error: error.message || 'Failed to deduct credits' }, { status: 500 }) } -} \ No newline at end of file +} From 45ee6a3610c988a14d2e57b891035c20fc6e78b3 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:09:24 +0500 Subject: [PATCH 64/73] Update route.ts --- auto-analyst-frontend/app/api/user/deduct-credits/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts index 77af7dc3..e63cbeff 100644 --- a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts +++ b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts @@ -19,7 +19,7 @@ export async function POST(request: NextRequest) { const creditsHash = await redis.hgetall(KEYS.USER_CREDITS(userId)) if (!creditsHash || !creditsHash.total) { - const defaultCredits = CreditConfig.getDefaultInitialCredits() + const defaultCredits = 20 await redis.hset(KEYS.USER_CREDITS(userId), { total: '20', used: '0', @@ -28,7 +28,7 @@ export async function POST(request: NextRequest) { }) return NextResponse.json({ success: true, - remaining: defaultCredits, + remaining: 20, deducted: 0 }) From 181011ddebdd795651ee8ba15b3421f8137f7d13 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:11:32 +0500 Subject: [PATCH 65/73] Update route.ts --- auto-analyst-frontend/app/api/user/deduct-credits/route.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts index e63cbeff..a35baa94 100644 --- a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts +++ b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts @@ -31,7 +31,7 @@ export async function POST(request: NextRequest) { remaining: 20, deducted: 0 }) - + } // No credits for users without subscription - require upgrade // return NextResponse.json({ // success: false, @@ -40,8 +40,9 @@ export async function POST(request: NextRequest) { // remaining: 0, // needsUpgrade: true // }, { status: 402 }) // Payment Required status code - // } - + // + } +} // Calculate new used amount const total = parseInt(creditsHash.total as string) const currentUsed = creditsHash.used ? parseInt(creditsHash.used as string) : 0 From c323621116885eaf1c2f7b3d9353997ee74bf857 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Sun, 10 Aug 2025 13:13:14 +0500 Subject: [PATCH 66/73] Update route.ts --- auto-analyst-frontend/app/api/user/deduct-credits/route.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts index a35baa94..72ebe745 100644 --- a/auto-analyst-frontend/app/api/user/deduct-credits/route.ts +++ b/auto-analyst-frontend/app/api/user/deduct-credits/route.ts @@ -41,8 +41,8 @@ export async function POST(request: NextRequest) { // needsUpgrade: true // }, { status: 402 }) // Payment Required status code // - } -} + + // Calculate new used amount const total = parseInt(creditsHash.total as string) const currentUsed = creditsHash.used ? parseInt(creditsHash.used as string) : 0 From 0b8d20256abec4dd602a8769bcf447515daa7283 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:57:27 +0500 Subject: [PATCH 67/73] Update route.ts --- .../app/api/initialize-credits/route.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/initialize-credits/route.ts b/auto-analyst-frontend/app/api/initialize-credits/route.ts index 840f3110..a7f08c30 100644 --- a/auto-analyst-frontend/app/api/initialize-credits/route.ts +++ b/auto-analyst-frontend/app/api/initialize-credits/route.ts @@ -10,6 +10,18 @@ export async function GET(request: NextRequest) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } + + const userId = token.sub; + + // Allow custom amount via query param for testing + const searchParams = request.nextUrl.searchParams; + const amount = searchParams.get('amount') + ? parseInt(searchParams.get('amount') as string) + : parseInt(process.env.NEXT_PUBLIC_CREDITS_INITIAL_AMOUNT || '20'); + + // Initialize credits for the user + await creditUtils.initializeCredits(userId, amount); + const userId = token.sub; // This endpoint is for debugging/testing only @@ -35,4 +47,4 @@ export async function GET(request: NextRequest) { { status: 500 } ); } -} \ No newline at end of file +} From 0a3e047186de4140be7b935cafbf3931e3289fa5 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Mon, 11 Aug 2025 16:59:07 +0500 Subject: [PATCH 68/73] Update redis.ts --- auto-analyst-frontend/lib/redis.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/auto-analyst-frontend/lib/redis.ts b/auto-analyst-frontend/lib/redis.ts index 3b698d6b..da1aa17b 100644 --- a/auto-analyst-frontend/lib/redis.ts +++ b/auto-analyst-frontend/lib/redis.ts @@ -35,6 +35,22 @@ export const KEYS = { USER_CREDITS: (userId: string) => `user:${userId}:credits`, }; +async initializeCredits(userId: string, credits: number = parseInt(process.env.NEXT_PUBLIC_CREDITS_INITIAL_AMOUNT || '20')): Promise { + try { + // Only use hash-based approach + await redis.hset(KEYS.USER_CREDITS(userId), { + total: credits.toString(), + used: '0', + lastUpdate: new Date().toISOString(), + resetDate: this.getNextMonthFirstDay() + }); + + logger.log(`Credits initialized successfully for ${userId}: ${credits}`); + } catch (error) { + console.error('Error initializing credits:', error); + } + }, + // Credits management utilities with consolidated hash-based storage export const creditUtils = { // Get remaining credits for a user From 0e2eb442b290f0934cf02113ef0664ac0ac851b2 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Mon, 11 Aug 2025 17:03:05 +0500 Subject: [PATCH 69/73] Update redis.ts --- auto-analyst-frontend/lib/redis.ts | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/auto-analyst-frontend/lib/redis.ts b/auto-analyst-frontend/lib/redis.ts index da1aa17b..98058c0c 100644 --- a/auto-analyst-frontend/lib/redis.ts +++ b/auto-analyst-frontend/lib/redis.ts @@ -35,21 +35,7 @@ export const KEYS = { USER_CREDITS: (userId: string) => `user:${userId}:credits`, }; -async initializeCredits(userId: string, credits: number = parseInt(process.env.NEXT_PUBLIC_CREDITS_INITIAL_AMOUNT || '20')): Promise { - try { - // Only use hash-based approach - await redis.hset(KEYS.USER_CREDITS(userId), { - total: credits.toString(), - used: '0', - lastUpdate: new Date().toISOString(), - resetDate: this.getNextMonthFirstDay() - }); - - logger.log(`Credits initialized successfully for ${userId}: ${credits}`); - } catch (error) { - console.error('Error initializing credits:', error); - } - }, + // Credits management utilities with consolidated hash-based storage export const creditUtils = { @@ -76,6 +62,21 @@ export const creditUtils = { return 0 } }, + async initializeCredits(userId: string, credits: number = parseInt(process.env.NEXT_PUBLIC_CREDITS_INITIAL_AMOUNT || '20')): Promise { + try { + // Only use hash-based approach + await redis.hset(KEYS.USER_CREDITS(userId), { + total: credits.toString(), + used: '0', + lastUpdate: new Date().toISOString(), + resetDate: this.getNextMonthFirstDay() + }); + + logger.log(`Credits initialized successfully for ${userId}: ${credits}`); + } catch (error) { + console.error('Error initializing credits:', error); + } + }, // Initialize credits for a trial user (500 credits) async initializeTrialCredits(userId: string, paymentIntentId: string, trialEndDate: string): Promise { @@ -147,6 +148,8 @@ export const creditUtils = { } }, + + // Check if a user has enough credits async hasEnoughCredits(userId: string, amount: number): Promise { const remainingCredits = await this.getRemainingCredits(userId); From 19d5690505c44c66826461dac42981606ff6d612 Mon Sep 17 00:00:00 2001 From: Arslan Shahid <49631998+ArslanS1997@users.noreply.github.com> Date: Mon, 11 Aug 2025 17:05:19 +0500 Subject: [PATCH 70/73] Update route.ts --- auto-analyst-frontend/app/api/initialize-credits/route.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/initialize-credits/route.ts b/auto-analyst-frontend/app/api/initialize-credits/route.ts index a7f08c30..05190f51 100644 --- a/auto-analyst-frontend/app/api/initialize-credits/route.ts +++ b/auto-analyst-frontend/app/api/initialize-credits/route.ts @@ -22,7 +22,6 @@ export async function GET(request: NextRequest) { // Initialize credits for the user await creditUtils.initializeCredits(userId, amount); - const userId = token.sub; // This endpoint is for debugging/testing only // Don't automatically initialize credits anymore since we removed free plan From 77e650391c836f561d0cb80c52c08115e52ccd9d Mon Sep 17 00:00:00 2001 From: Arslan Date: Tue, 26 Aug 2025 07:45:42 +0500 Subject: [PATCH 71/73] made some creds changes --- auto-analyst-frontend/app/api/user/credits/route.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auto-analyst-frontend/app/api/user/credits/route.ts b/auto-analyst-frontend/app/api/user/credits/route.ts index b6874342..89154edc 100644 --- a/auto-analyst-frontend/app/api/user/credits/route.ts +++ b/auto-analyst-frontend/app/api/user/credits/route.ts @@ -28,7 +28,7 @@ export async function GET(request: NextRequest) { planName = subscriptionHash?.plan || 'Free Plan' } else { // Initialize default values for new users using centralized config - creditsTotal = 0 // No free credits anymore + creditsTotal = 20 // No free credits anymore creditsUsed = 0 resetDate = CreditConfig.getNextResetDate() lastUpdate = new Date().toISOString() From 4a246c82e3adca1bd35b170a6f0ca4ca9db4a5b2 Mon Sep 17 00:00:00 2001 From: Arslan Date: Wed, 3 Sep 2025 21:18:54 +0500 Subject: [PATCH 72/73] added agent is done stuff --- auto-analyst-backend/app.py | 270 ++++++++++++---------- auto-analyst-backend/src/agents/agents.py | 266 ++++++++++----------- auto-analyst-frontend/.env | 43 ++++ 3 files changed, 330 insertions(+), 249 deletions(-) create mode 100644 auto-analyst-frontend/.env diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index 61b4d237..a781599e 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -153,7 +153,7 @@ class DeepAnalysisResponse(BaseModel): "model": os.getenv("MODEL_NAME", "01"), "api_key": os.getenv("OPENAI_API_KEY"), "temperature": float(os.getenv("TEMPERATURE", 1.0)), - "max_tokens": int(os.getenv("MAX_TOKENS", 6000)) + "max_tokens": int(os.getenv("MAX_TOKENS", 6000)), "cache": False } # Create default LM config but don't set it globally @@ -162,7 +162,7 @@ class DeepAnalysisResponse(BaseModel): model=f"groq/{DEFAULT_MODEL_CONFIG["model"]}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], - max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"], cache=False ) elif DEFAULT_MODEL_CONFIG["provider"].lower() == "gemini": @@ -170,14 +170,14 @@ class DeepAnalysisResponse(BaseModel): model=f"gemini/{DEFAULT_MODEL_CONFIG['model']}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], - max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"], cache=False ) elif DEFAULT_MODEL_CONFIG["provider"].lower() == "anthropic": default_lm = dspy.LM( model=f"anthropic/{DEFAULT_MODEL_CONFIG["model"]}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], - max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"], cache=False ) else: if DEFAULT_MODEL_CONFIG['model'].lower() in ['openai/gpt-5', 'openai/gpt-5-mini','openai/gpt-5-nano']: @@ -186,14 +186,14 @@ class DeepAnalysisResponse(BaseModel): api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], max_tokens=None, - max_completion_tokens=10000 + max_completion_tokens= DEFAULT_MODEL_CONFIG["max_tokens"], cache=False ) else: default_lm = dspy.LM( model=f"openai/{DEFAULT_MODEL_CONFIG["model"]}", api_key=DEFAULT_MODEL_CONFIG["api_key"], temperature=DEFAULT_MODEL_CONFIG["temperature"], - max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"] + max_tokens=DEFAULT_MODEL_CONFIG["max_tokens"], cache=False ) # lm = dspy.LM('openai/gpt-4o-mini', api_key=os.getenv("OPENAI_API_KEY")) @@ -214,7 +214,7 @@ def get_session_lm(session_state): model=f"groq/{model_config.get("model", DEFAULT_MODEL_CONFIG["model"])}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) + max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]), cache=False ) elif provider == "anthropic": logger.log_message(f"Using anthropic model: {model_config.get('model', DEFAULT_MODEL_CONFIG['model'])}", level=logging.INFO) @@ -222,7 +222,7 @@ def get_session_lm(session_state): model=f"anthropic/{model_config.get("model", DEFAULT_MODEL_CONFIG["model"])}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) + max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]), cache=False ) elif provider == "gemini": logger.log_message(f"Using gemini model: {model_config.get('model', DEFAULT_MODEL_CONFIG['model'])}", level=logging.INFO) @@ -230,7 +230,7 @@ def get_session_lm(session_state): model=f"gemini/{model_config.get('model', DEFAULT_MODEL_CONFIG['model'])}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]) + max_tokens=model_config.get("max_tokens", DEFAULT_MODEL_CONFIG["max_tokens"]), cache=False ) else: # OpenAI is the default model_name = model_config.get("model", DEFAULT_MODEL_CONFIG["model"]) @@ -246,7 +246,7 @@ def get_session_lm(session_state): api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), max_tokens=None, - max_completion_tokens=10000 + max_completion_tokens=model_config.get("max_tokens", 3000), cache=False ) else: # For other models, keep using max_tokens as parameter name @@ -254,7 +254,7 @@ def get_session_lm(session_state): model=f"openai/{model_name}", api_key=model_config.get("api_key", DEFAULT_MODEL_CONFIG["api_key"]), temperature=model_config.get("temperature", DEFAULT_MODEL_CONFIG["temperature"]), - max_tokens=max_token_value + max_tokens=max_token_value, cache=False ) @@ -482,7 +482,7 @@ async def verify_origin_middleware(request: Request, call_next): RESPONSE_ERROR_INVALID_QUERY = "Please provide a valid query..." RESPONSE_ERROR_NO_DATASET = "No dataset is currently loaded. Please link a dataset before proceeding with your analysis." DEFAULT_TOKEN_RATIO = 1.5 -REQUEST_TIMEOUT_SECONDS = 120 # Timeout for LLM requests +REQUEST_TIMEOUT_SECONDS = 30 # Timeout for LLM requests MAX_RECENT_MESSAGES = 3 DB_BATCH_SIZE = 10 # For future batch DB operations @@ -923,115 +923,159 @@ async def _generate_streaming_responses(session_state: dict, query: str, session # Add chat context from previous messages enhanced_query = _prepare_query_with_context(query, session_state) - # Use the session model for this specific request - with dspy.context(lm=session_lm): - try: - # Get the plan - planner is now async, so we need to await it - plan_response = await session_state["ai_system"].get_plan(enhanced_query) - - plan_description = format_response_to_markdown( - {"analytical_planner": plan_response}, - dataframe=session_state["current_df"] - ) - - # Check if plan is valid - if plan_description == RESPONSE_ERROR_INVALID_QUERY: - yield json.dumps({ - "agent": "Analytical Planner", - "content": plan_description, - "status": "error" - }) + "\n" - return - + try: + # Get the plan - planner is now async, so we need to await it + plan_response = await session_state["ai_system"].get_plan(enhanced_query) + + plan_description = format_response_to_markdown( + {"analytical_planner": plan_response}, + dataframe=session_state["current_df"] + ) + + # Check if plan is valid + if plan_description == RESPONSE_ERROR_INVALID_QUERY: yield json.dumps({ "agent": "Analytical Planner", "content": plan_description, - "status": "success" if plan_description else "error" + "status": "error" }) + "\n" + return + + yield json.dumps({ + "agent": "Analytical Planner", + "content": plan_description, + "status": "success" if plan_description else "error" + }) + "\n" + + # Track planner usage + if session_state.get("user_id"): + planner_tokens = _estimate_tokens(ai_manager=app.state.ai_manager, + input_text=enhanced_query, + output_text=plan_description) - # Track planner usage - if session_state.get("user_id"): - planner_tokens = _estimate_tokens(ai_manager=app.state.ai_manager, - input_text=enhanced_query, - output_text=plan_description) - - usage_records.append(_create_usage_record( - session_state=session_state, - model_name=session_state.get("model_config", DEFAULT_MODEL_CONFIG)["model"], - prompt_tokens=planner_tokens["prompt"], - completion_tokens=planner_tokens["completion"], - query_size=len(enhanced_query), - response_size=len(plan_description), - processing_time_ms=int((time.time() - overall_start_time) * 1000), - is_streaming=False - )) - - # Execute the plan with well-managed concurrency - async for agent_name, inputs, response in _execute_plan_with_timeout( - session_state["ai_system"], enhanced_query, plan_response): - - if agent_name == "plan_not_found": - yield json.dumps({ - "agent": "Analytical Planner", - "content": "**No plan found**\n\nPlease try again with a different query or try using a different model.", - "status": "error" - }) + "\n" - return + usage_records.append(_create_usage_record( + session_state=session_state, + model_name=session_state.get("model_config", DEFAULT_MODEL_CONFIG)["model"], + prompt_tokens=planner_tokens["prompt"], + completion_tokens=planner_tokens["completion"], + query_size=len(enhanced_query), + response_size=len(plan_description), + processing_time_ms=int((time.time() - overall_start_time) * 1000), + is_streaming=False + )) + + logger.log_message(f"Plan response: {plan_response}", level=logging.INFO) + logger.log_message(f"Plan response type: {type(plan_response)}", level=logging.INFO) + + # Check if plan_response is valid + # if not plan_response or not isinstance(plan_response, dict): + # yield json.dumps({ + # "agent": "Analytical Planner", + # "content": "**Error: Invalid plan response**\n\nResponse: " + str(plan_response), + # "status": "error" + # }) + "\n" + # return + + # Execute the plan with well-managed concurrency + with dspy.context(lm = session_lm): + try: - formatted_response = format_response_to_markdown( - {agent_name: response}, - dataframe=session_state["current_df"] - ) or "No response generated" + async for agent_name, inputs, response in session_state["ai_system"].execute_plan(enhanced_query, plan_response): + + if agent_name == "plan_not_found": + yield json.dumps({ + "agent": "Analytical Planner", + "content": "**No plan found**\n\nPlease try again with a different query or try using a different model.", + "status": "error" + }) + "\n" + return + + if agent_name == "plan_not_formated_correctly": + yield json.dumps({ + "agent": "Analytical Planner", + "content": "**Something went wrong with formatting, retry the query!**", + "status": "error" + }) + "\n" + return + + + formatted_response = format_response_to_markdown( + {agent_name: response}, + dataframe=session_state["current_df"] + ) - if formatted_response == RESPONSE_ERROR_INVALID_QUERY: yield json.dumps({ - "agent": agent_name, + "agent": agent_name.split("__")[0] if "__" in agent_name else agent_name, "content": formatted_response, - "status": "error" + "status": "success" if response else "error" }) + "\n" - return - # Send response chunk + # Handle agent errors + if isinstance(response, dict) and "error" in response: + yield json.dumps({ + "agent": agent_name, + "content": f"**Error in {agent_name}**: {response['error']}", + "status": "error" + }) + "\n" + continue # Continue with next agent instead of returning + + + + if formatted_response == RESPONSE_ERROR_INVALID_QUERY: + yield json.dumps({ + "agent": agent_name, + "content": formatted_response, + "status": "error" + }) + "\n" + continue # Continue with next agent instead of returning + + # Send response chunk + + + # Track agent usage for future batch DB write + if session_state.get("user_id"): + agent_tokens = _estimate_tokens( + ai_manager=app.state.ai_manager, + input_text=str(inputs), + output_text=str(response) + ) + + # Get appropriate model name for code combiner + if "code_combiner_agent" in agent_name and "__" in agent_name: + provider = agent_name.split("__")[1] + model_name = _get_model_name_for_provider(provider) + else: + model_name = session_state.get("model_config", DEFAULT_MODEL_CONFIG)["model"] + + usage_records.append(_create_usage_record( + session_state=session_state, + model_name=model_name, + prompt_tokens=agent_tokens["prompt"], + completion_tokens=agent_tokens["completion"], + query_size=len(str(inputs)), + response_size=len(str(response)), + processing_time_ms=int((time.time() - overall_start_time) * 1000), + is_streaming=True + )) + + except asyncio.TimeoutError: yield json.dumps({ - "agent": agent_name.split("__")[0] if "__" in agent_name else agent_name, - "content": formatted_response, - "status": "success" if response else "error" + "agent": "planner", + "content": "The request timed out. Please try a simpler query.", + "status": "error" }) + "\n" + return - # Track agent usage for future batch DB write - if session_state.get("user_id"): - agent_tokens = _estimate_tokens( - ai_manager=app.state.ai_manager, - input_text=str(inputs), - output_text=str(response) - ) - - # Get appropriate model name for code combiner - if "code_combiner_agent" in agent_name and "__" in agent_name: - provider = agent_name.split("__")[1] - model_name = _get_model_name_for_provider(provider) - else: - model_name = session_state.get("model_config", DEFAULT_MODEL_CONFIG)["model"] - - usage_records.append(_create_usage_record( - session_state=session_state, - model_name=model_name, - prompt_tokens=agent_tokens["prompt"], - completion_tokens=agent_tokens["completion"], - query_size=len(str(inputs)), - response_size=len(str(response)), - processing_time_ms=int((time.time() - overall_start_time) * 1000), - is_streaming=True - )) - - except asyncio.TimeoutError: - yield json.dumps({ - "agent": "planner", - "content": "The request timed out. Please try a simpler query.", - "status": "error" - }) + "\n" - return - except Exception as e: + except Exception as e: + logger.log_message(f"Error executing plan: {str(e)}", level=logging.ERROR) + yield json.dumps({ + "agent": "planner", + "content": f"An error occurred while executing the plan: {str(e)}", + "status": "error" + }) + "\n" + return + + except Exception as e: logger.log_message(f"Error in streaming response: {str(e)}", level=logging.ERROR) yield json.dumps({ "agent": "planner", @@ -1094,18 +1138,6 @@ def _get_model_name_for_provider(provider: str) -> str: return provider_model_map.get(provider, "o3-mini") -async def _execute_plan_with_timeout(ai_system, enhanced_query, plan_response): - """Execute the plan with timeout handling for each step""" - try: - logger.log_message(f"Plan response: {plan_response}", level=logging.INFO) - # Use the async generator from execute_plan directly - async for agent_name, inputs, response in ai_system.execute_plan(enhanced_query, plan_response): - # Yield results as they come - yield agent_name, inputs, response - except Exception as e: - logger.log_message(f"Error executing plan: {str(e)}", level=logging.ERROR) - yield "error", None, {"error": "An error occurred during plan execution"} - # Add an endpoint to list available agents @app.get("/agents", response_model=dict) diff --git a/auto-analyst-backend/src/agents/agents.py b/auto-analyst-backend/src/agents/agents.py index c7f7449f..fd27ffd3 100644 --- a/auto-analyst-backend/src/agents/agents.py +++ b/auto-analyst-backend/src/agents/agents.py @@ -4,6 +4,8 @@ from dotenv import load_dotenv import logging from src.utils.logger import Logger +import json + load_dotenv() logger = Logger("agents", see_time=True, console_log=False) @@ -626,9 +628,9 @@ def __init__(self): self.planners = { - "advanced":dspy.asyncify(dspy.ChainOfThought(advanced_query_planner)), - "intermediate":dspy.asyncify(dspy.ChainOfThought(intermediate_query_planner)), - "basic":dspy.asyncify(dspy.ChainOfThought(basic_query_planner)), + "advanced":dspy.asyncify(dspy.Predict(advanced_query_planner)), + "intermediate":dspy.asyncify(dspy.Predict(intermediate_query_planner)), + "basic":dspy.asyncify(dspy.Predict(basic_query_planner)), # "unrelated":dspy.Predict(self.basic_qa_agent) } self.planner_desc = { @@ -642,76 +644,89 @@ def __init__(self): self.allocator = dspy.Predict("goal,planner_desc,dataset->exact_word_complexity,reasoning") async def forward(self, goal, dataset, Agent_desc): - # Check if we have any agents available - if not Agent_desc or Agent_desc == "[]" or len(str(Agent_desc).strip()) < 10: + + if not Agent_desc or Agent_desc == "[]": logger.log_message("No agents available for planning", level=logging.WARNING) return { "complexity": "no_agents_available", "plan": "no_agents_available", "plan_instructions": {"message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis."} } - - try: - complexity = self.allocator(goal=goal, planner_desc=str(self.planner_desc), dataset=str(dataset)) - # If complexity is unrelated, return basic_qa_agent - if complexity.exact_word_complexity.strip() == "unrelated": - return { - "complexity": complexity.exact_word_complexity.strip(), - "plan": "basic_qa_agent", - "plan_instructions": "{'basic_qa_agent':'Not a data related query, please ask a data related-query'}" - } + lm = dspy.LM('openai/gpt-4o-mini',max_tokens=400) + with dspy.context(lm= lm): + + # Check if we have any agents available + - # Try to get plan with determined complexity try: - logger.log_message(f"Attempting to plan with complexity: {complexity.exact_word_complexity.strip()}", level=logging.DEBUG) - plan = await self.planners[complexity.exact_word_complexity.strip()](goal=goal, dataset=dataset, Agent_desc=Agent_desc) - logger.log_message(f"Plan generated successfully: {plan}", level=logging.DEBUG) - - # Check if the planner returned no_agents_available - if hasattr(plan, 'plan') and 'no_agents_available' in str(plan.plan): - logger.log_message("Planner returned no_agents_available", level=logging.WARNING) - output = { - "complexity": "no_agents_available", - "plan": "no_agents_available", - "plan_instructions": {"message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis."} - } - else: - output = { + + complexity = self.allocator(goal=goal, planner_desc=str(self.planner_desc), dataset=str(dataset)) + # If complexity is unrelated, return basic_qa_agent + if complexity.exact_word_complexity.strip() == "unrelated": + return { "complexity": complexity.exact_word_complexity.strip(), - "plan": dict(plan) + "plan": "basic_qa_agent", + "plan_instructions": "{'basic_qa_agent':'Not a data related query, please ask a data related-query'}" } - - except Exception as e: - logger.log_message(f"Error with {complexity.exact_word_complexity.strip()} planner, falling back to intermediate: {str(e)}", level=logging.WARNING) - # Fallback to intermediate planner - plan = await self.planners["intermediate"](goal=goal, dataset=dataset, Agent_desc=Agent_desc) - logger.log_message(f"Fallback plan generated: {plan}", level=logging.DEBUG) - # Check if the fallback planner also returned no_agents_available - if hasattr(plan, 'plan') and 'no_agents_available' in str(plan.plan): - logger.log_message("Fallback planner also returned no_agents_available", level=logging.WARNING) - output = { - "complexity": "no_agents_available", - "plan": "no_agents_available", - "plan_instructions": {"message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis."} - } - else: - output = { - "complexity": "intermediate", - "plan": dict(plan) - } - - except Exception as e: - logger.log_message(f"Error in planner forward: {str(e)}", level=logging.ERROR) - # Return error response - return { - "complexity": "error", - "plan": "basic_qa_agent", - "plan_instructions": {"error": f"Planning error in agents: {str(e)} + {dspy.settings.lm.model}"} - } + except Exception as e: + logger.log_message(f"Error in planner forward: {str(e)}", level=logging.ERROR) + # Return error response + return { + "complexity": "error", + "plan": "basic_qa_agent", + "plan_instructions": {"error": f"Planning error in agents: {str(e)} + {dspy.settings.lm.model}"} + } + + # Try to get plan with determined complexity + # try: + logger.log_message(f"Attempting to plan with complexity: {complexity.exact_word_complexity.strip()}", level=logging.DEBUG) + with dspy.context(lm = dspy.LM('openai/gpt-4o-mini',max_tokens=3000)): + plan = await self.planners[complexity.exact_word_complexity.strip()](goal=goal, dataset=dataset, Agent_desc=Agent_desc) + logger.log_message(f"Plan generated successfully: {plan}", level=logging.DEBUG) - return output + # Check if the planner returned no_agents_available + if hasattr(plan, 'plan') and 'no_agents_available' in str(plan.plan): + logger.log_message("Planner returned no_agents_available", level=logging.WARNING) + output = { + "complexity": "no_agents_available", + "plan": "no_agents_available", + "plan_instructions": {"message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis."} + } + else: + output = { + "complexity": complexity.exact_word_complexity.strip(), + "plan": plan.plan, + "plan_instructions": plan.plan_instructions + } + + # except Exception as e: + # logger.log_message(f"Error with {complexity.exact_word_complexity.strip()} planner, falling back to basic: {str(e)}", level=logging.WARNING) + + # # Fallback to basic planner + # with dspy.context(lm = dspy.LM('openai/gpt-4o-mini',max_tokens=3000)): + # plan = await self.planners["basic"](goal=goal, dataset=dataset, Agent_desc=Agent_desc) + # logger.log_message(f"Fallback plan generated: {plan}", level=logging.DEBUG) + + # # Check if the fallback planner also returned no_agents_available + # if hasattr(plan, 'plan') and 'no_agents_available' in str(plan.plan): + # logger.log_message("Fallback planner also returned no_agents_available", level=logging.WARNING) + # output = { + # "complexity": "no_agents_available", + # "plan": "no_agents_available", + # "plan_instructions": {"message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis."} + # } + # else: + # output = { + # "complexity": "basic", + # "plan": plan.plan, + # "plan_instructions":plan.plan_instructions + # } + + + + return output @@ -1399,7 +1414,7 @@ async def execute_agent(self, specified_agent, inputs): except Exception as e: # logger.log_message(f"[EXECUTE] Error executing agent {specified_agent}: {str(e)}", level=logging.ERROR) - import traceback + # logger.log_message(f"[EXECUTE] Full traceback: {traceback.format_exc()}", level=logging.ERROR) return specified_agent.strip(), {"error": str(e)} @@ -1580,7 +1595,7 @@ def __init__(self, agents, retrievers, user_id=None, db_session=None): continue # Add template agent to agents dict - self.agents[template_name] = dspy.asyncify(dspy.ChainOfThought(signature)) + self.agents[template_name] = dspy.asyncify(dspy.Predict(signature)) # Determine if this is a visualization agent based on database category is_viz_agent = False @@ -1861,20 +1876,7 @@ async def _track_agent_usage(self, agent_name): except Exception as e: logger.log_message(f"Error in _track_agent_usage for {agent_name}: {str(e)}", level=logging.ERROR) - async def execute_agent(self, agent_name, inputs): - """Execute a single agent with given inputs""" - - try: - result = await self.agents[agent_name.strip()](**inputs) - - # Track usage for custom agents and templates - await self._track_agent_usage(agent_name.strip()) - - logger.log_message(f"Agent {agent_name} execution completed", level=logging.DEBUG) - return agent_name.strip(), dict(result) - except Exception as e: - logger.log_message(f"Error in execute_agent for {agent_name}: {str(e)}", level=logging.ERROR) - return agent_name.strip(), {"error": str(e)} + async def get_plan(self, query): """Get the analysis plan""" @@ -1885,51 +1887,51 @@ async def get_plan(self, query): dict_['Agent_desc'] = str(self.agent_desc) - try: - module_return = await self.planner( - goal=dict_['goal'], - dataset=dict_['dataset'], - Agent_desc=dict_['Agent_desc'] - ) - logger.log_message(f"Module return: {module_return}", level=logging.INFO) - - # Handle different plan formats - plan = module_return['plan'] - logger.log_message(f"Plan from module_return: {plan}, type: {type(plan)}", level=logging.INFO) - - # If plan is a string (agent name), convert to proper format - if isinstance(plan, str): - if 'complexity' in module_return: - complexity = module_return['complexity'] - else: - complexity = 'basic' - - plan_dict = { - 'plan': plan, - 'complexity': complexity - } - - # Add plan_instructions if available - if 'plan_instructions' in module_return: - plan_dict['plan_instructions'] = module_return['plan_instructions'] - else: - plan_dict['plan_instructions'] = {} + # try: + module_return = await self.planner( + goal=dict_['goal'], + dataset=dict_['dataset'], + Agent_desc=dict_['Agent_desc'] + ) + logger.log_message(f"Module return: {module_return}", level=logging.INFO) + + # Handle different plan formats + plan = module_return['plan'] + logger.log_message(f"Plan from module_return: {plan}, type: {type(plan)}", level=logging.INFO) + + # If plan is a string (agent name), convert to proper format + if isinstance(plan, str): + if 'complexity' in module_return: + complexity = module_return['complexity'] else: - # If plan is already a dict, use it directly - plan_dict = dict(plan) if not isinstance(plan, dict) else plan - if 'complexity' in module_return: - complexity = module_return['complexity'] - else: - complexity = 'basic' - plan_dict['complexity'] = complexity + complexity = 'basic' - logger.log_message(f"Final plan dict: {plan_dict}", level=logging.INFO) + plan_dict = { + 'plan': plan, + 'complexity': complexity + } + + # Add plan_instructions if available + if 'plan_instructions' in module_return: + plan_dict['plan_instructions'] = module_return['plan_instructions'] + else: + plan_dict['plan_instructions'] = {} + else: + # If plan is already a dict, use it directly + plan_dict = dict(plan) if not isinstance(plan, dict) else plan + if 'complexity' in module_return: + complexity = module_return['complexity'] + else: + complexity = 'basic' + plan_dict['complexity'] = complexity + + logger.log_message(f"Final plan dict: {plan_dict}", level=logging.INFO) - return plan_dict + return plan_dict - except Exception as e: - logger.log_message(f"Error in get_plan: {str(e)}", level=logging.ERROR) - raise + # except Exception as e: + # logger.log_message(f"Error in get_plan: {str(e)}", level=logging.ERROR) + # raise async def execute_plan(self, query, plan): """Execute the plan and yield results as they complete""" @@ -1940,7 +1942,6 @@ async def execute_plan(self, query, plan): dict_['hint'] = [] dict_['goal'] = query - import json # Clean and split the plan string into agent names plan_text = plan.get("plan", "").lower().replace("plan:", "").strip() @@ -1953,6 +1954,7 @@ async def execute_plan(self, query, plan): return plan_list = [agent.strip() for agent in plan_text.split("->") if agent.strip()] + logger.log_message(f"Plan list: {plan_list}", level=logging.INFO) # Parse the attached plan_instructions into a dict raw_instr = plan.get("plan_instructions", {}) @@ -1969,15 +1971,14 @@ async def execute_plan(self, query, plan): # Check if we have no valid agents to execute - if not plan_list or all(agent not in self.agents for agent in plan_list): - yield "plan_not_found", None, {"error": "No valid agents found in plan"} + if not plan_list: + if len(plan_text) != 0: + yield "plan_not_formatted_correctly", str(plan_text), {'error': "There was a error in the formatting"} + return - + # Execute agents in sequence for agent_name in plan_list: - if agent_name not in self.agents: - yield agent_name, {}, {"error": f"Agent '{agent_name}' not available"} - continue try: # Prepare inputs for the agent @@ -1985,18 +1986,23 @@ async def execute_plan(self, query, plan): # Add plan instructions if available for this agent if agent_name in plan_instructions: - inputs['plan_instructions'] = json.dumps(plan_instructions[agent_name]) + inputs['plan_instructions'] = plan_instructions[agent_name] else: - inputs['plan_instructions'] = "" + inputs['plan_instructions'] = str(plan_instructions).split(agent_name)[1].split('agent')[0] # logger.log_message(f"Agent inputs for {agent_name}: {inputs}", level=logging.INFO) + + + result = await self.agents[agent_name.strip()](**inputs) + # Track usage for custom agents and templates + await self._track_agent_usage(agent_name.strip()) # Execute the agent - agent_result_name, response = await self.execute_agent(agent_name, inputs) + - yield agent_result_name, inputs, response + yield agent_name, inputs, result except Exception as e: - logger.log_message(f"Error executing agent {agent_name}: {str(e)}", level=logging.ERROR) - yield agent_name, {}, {"error": f"Error executing {agent_name}: {str(e)}"} + logger.log_message(f"Error executing agent {agent_name}: {str(e)}", level=logging.ERROR) + yield agent_name, {}, {"error": f"Error executing {agent_name}: {str(e)}"} diff --git a/auto-analyst-frontend/.env b/auto-analyst-frontend/.env new file mode 100644 index 00000000..00ada3b9 --- /dev/null +++ b/auto-analyst-frontend/.env @@ -0,0 +1,43 @@ +# Sample .env file for the frontend + +NEXTAUTH_URL=http://localhost:3000 +NEXTAUTH_SECRET="Dp..." + +GOOGLE_CLIENT_ID=561649614725-fck7d0fss66eqmmjvk9p9rls2nrileob.apps.googleusercontent.com +GOOGLE_CLIENT_SECRET=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 + +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_USER=... +SMTP_PASS=... +SMTP_FROM=... + +SALES_EMAIL=... + +# NEXT_PUBLIC_API_URL=http://localhost:8000 +# NEXT_PUBLIC_API_URL=https://auto-analyst-test-67f323333dd2.herokuapp.com +NEXT_PUBLIC_API_URL=https://firebird-tech-auto-analyst-test.hf.space +NEXT_PUBLIC_ANALYTICS_ADMIN_PASSWORD=... +NEXT_PUBLIC_ADMIN_EMAIL=... +NEXT_PUBLIC_FREE_TRIAL_LIMIT=0 + +ADMIN_API_KEY=admin123 + + +UPSTASH_REDIS_REST_URL=https://ideal-robin-15637.upstash.io +UPSTASH_REDIS_REST_TOKEN=AT0VAAIjcDFhNmYwZjJhNjk3ZWQ0YjkzOWI2ZWU3ODE5NDBkZDZkMnAxMA + +NEXT_PUBLIC_UPSTASH_REDIS_REST_URL=... +NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN= + +NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=... +STRIPE_SECRET_KEY=whsec_zXA1YFHXLmN3iqOUmcZmRgwIU0SVOp8A + +NEXT_PUBLIC_STRIPE_BASIC_YEARLY_PRICE_ID=... +NEXT_PUBLIC_STRIPE_STANDARD_YEARLY_PRICE_ID=... +NEXT_PUBLIC_STRIPE_PREMIUM_YEARLY_PRICE_ID=... + +NEXT_PUBLIC_STRIPE_BASIC_PRICE_ID=... +NEXT_PUBLIC_STRIPE_STANDARD_PRICE_ID=... +NEXT_PUBLIC_STRIPE_PREMIUM_PRICE_ID=... +NODE_ENV=development From 92ea5ec2f95e58ab784121ece1009b7138a0677a Mon Sep 17 00:00:00 2001 From: Arslan Date: Wed, 3 Sep 2025 21:19:41 +0500 Subject: [PATCH 73/73] added agent is done stuff --- auto-analyst-backend/Dockerfile | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/auto-analyst-backend/Dockerfile b/auto-analyst-backend/Dockerfile index 480e44ca..0f77d7c1 100644 --- a/auto-analyst-backend/Dockerfile +++ b/auto-analyst-backend/Dockerfile @@ -10,4 +10,23 @@ COPY --chown=user ./requirements.txt requirements.txt RUN pip install --no-cache-dir --upgrade -r requirements.txt COPY --chown=user . /app -CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"] \ No newline at end of file + +# Verify agents_config.json was copied (it should be in the backend directory) +RUN if [ -f "/app/agents_config.json" ]; then \ + echo "✅ agents_config.json found in container"; \ + ls -la /app/agents_config.json; \ + else \ + echo "⚠️ agents_config.json not found in container - will use fallback templates"; \ + ls -la /app/ | grep -E "agents|config" || echo "No config files found"; \ + fi + +# Make entrypoint script executable +USER root +RUN chmod +x /app/entrypoint_local.sh +# Make populate script executable +RUN chmod +x /app/scripts/populate_agent_templates.py + +USER user + +# Use the entrypoint script instead of directly running uvicorn +CMD ["/app/entrypoint_local.sh"] \ No newline at end of file