MAJOR: Added a GUI app for simulations

This commit is contained in:
2026-07-09 18:14:26 +05:30
parent 0c59756c08
commit 4ef52f926e
22 changed files with 2996 additions and 13 deletions

View File

@@ -11,6 +11,21 @@ export interface LLMResponse<T> {
success: boolean;
data?: T;
error?: string;
usage?: {
inputTokens: number;
outputTokens: number;
totalTokens: number;
};
}
export interface LLMCallRecord {
systemPrompt: string;
userContext: string;
usage?: {
inputTokens: number;
outputTokens: number;
totalTokens: number;
};
}
export interface ILLMProvider {
@@ -19,4 +34,5 @@ export interface ILLMProvider {
generateStructuredResponse<T extends z.ZodTypeAny>(
request: LLMRequest<T>,
): Promise<LLMResponse<z.infer<T>>>;
lastCalls?: LLMCallRecord[];
}

View File

@@ -1,11 +1,12 @@
import { z } from "zod";
import { ChatGoogleGenerativeAI } from "@langchain/google-genai";
import { ILLMProvider, LLMRequest, LLMResponse } from "../llm.js";
import { ILLMProvider, LLMRequest, LLMResponse, LLMCallRecord } from "../llm.js";
import { llmConfig } from "../config.js";
export class GeminiProvider implements ILLMProvider {
providerName = "Gemini";
private model: ChatGoogleGenerativeAI;
lastCalls: LLMCallRecord[] = [];
constructor(apiKey?: string) {
const key = apiKey || llmConfig.GOOGLE_API_KEY;
@@ -21,11 +22,36 @@ export class GeminiProvider implements ILLMProvider {
async generateStructuredResponse<T extends z.ZodTypeAny>(
request: LLMRequest<T>,
): Promise<LLMResponse<z.infer<T>>> {
const structuredModel = this.model.withStructuredOutput(request.schema);
const result = await structuredModel.invoke([
const structuredModel = this.model.withStructuredOutput(request.schema, { includeRaw: true });
const result = (await structuredModel.invoke([
{ role: "system", content: request.systemPrompt },
{ role: "user", content: request.userContext },
]);
return { success: true, data: result as z.infer<T> };
])) as unknown as {
parsed?: z.infer<T>;
raw?: {
usage_metadata?: {
input_tokens?: number;
output_tokens?: number;
total_tokens?: number;
};
};
};
const parsed = result?.parsed;
const raw = result?.raw;
const usage = raw?.usage_metadata ? {
inputTokens: raw.usage_metadata.input_tokens || 0,
outputTokens: raw.usage_metadata.output_tokens || 0,
totalTokens: raw.usage_metadata.total_tokens || 0,
} : undefined;
this.lastCalls.push({
systemPrompt: request.systemPrompt,
userContext: request.userContext,
usage,
});
return { success: true, data: parsed, usage };
}
}

View File

@@ -1,9 +1,10 @@
import { z } from "zod";
import { ILLMProvider, LLMRequest, LLMResponse } from "../llm.js";
import { ILLMProvider, LLMRequest, LLMResponse, LLMCallRecord } from "../llm.js";
export class MockLLMProvider implements ILLMProvider {
providerName = "mock";
private callCount = 0;
lastCalls: LLMCallRecord[] = [];
constructor(private responses: unknown[]) {}
@@ -14,9 +15,15 @@ export class MockLLMProvider implements ILLMProvider {
if (next === undefined) {
return { success: false, error: "Mock responses exhausted" };
}
const usage = { inputTokens: 100, outputTokens: 50, totalTokens: 150 };
this.lastCalls.push({
systemPrompt: request.systemPrompt,
userContext: request.userContext,
usage,
});
try {
const parsed = request.schema.parse(next);
return { success: true, data: parsed };
return { success: true, data: parsed, usage };
} catch (e) {
return { success: false, error: e instanceof Error ? e.message : String(e) };
}