Spaces:
Running
Running
Update services/geminiService.ts
Browse files- services/geminiService.ts +134 -6
services/geminiService.ts
CHANGED
|
@@ -4,6 +4,38 @@ import { NodeData, LayerType } from '../types';
|
|
| 4 |
import { LAYER_DEFINITIONS } from '../constants';
|
| 5 |
|
| 6 |
// --- SCHEMAS ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
const graphResponseSchema = {
|
| 8 |
type: Type.OBJECT,
|
| 9 |
properties: {
|
|
@@ -94,7 +126,7 @@ const getAiClient = () => {
|
|
| 94 |
|
| 95 |
export const DEFAULT_MODEL = 'gemini-2.5-flash';
|
| 96 |
|
| 97 |
-
export type AgentStatus = 'idle' | 'architect' | 'critic' | 'refiner' | 'debugger' | 'patcher' | 'complete' | 'error';
|
| 98 |
|
| 99 |
/**
|
| 100 |
* Internal helper to build the raw specification string.
|
|
@@ -539,15 +571,95 @@ Return ONLY the final JSON object.`;
|
|
| 539 |
}
|
| 540 |
};
|
| 541 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 542 |
/**
|
| 543 |
* Multi-agent code generation.
|
| 544 |
* Uses the detailed prompt to write, review, and polish PyTorch code.
|
| 545 |
*/
|
| 546 |
export const generateCodeWithAgents = async (
|
| 547 |
-
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
): Promise<string> => {
|
| 551 |
const ai = getAiClient();
|
| 552 |
|
| 553 |
// --- Step 1: Coder ---
|
|
@@ -563,6 +675,9 @@ Coding Standards:
|
|
| 563 |
4. Use descriptive variable names.
|
| 564 |
5. Include a robust 'if __name__ == "__main__":' block that instantiates the model and runs a dummy forward pass with torch.randn.
|
| 565 |
6. Handle custom layer logic or external imports if specified.
|
|
|
|
|
|
|
|
|
|
| 566 |
|
| 567 |
Return ONLY the Python code. No markdown backticks.`;
|
| 568 |
|
|
@@ -639,8 +754,21 @@ Return ONLY the final Python code. No markdown backticks.`;
|
|
| 639 |
config: { systemInstruction: polisherSystemInstruction }
|
| 640 |
});
|
| 641 |
let finalCode = cleanJsonString(response.text);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 642 |
onStatusUpdate('complete', 'Code generation complete!');
|
| 643 |
-
return finalCode;
|
| 644 |
} catch(e) {
|
| 645 |
throw new Error("Polisher agent failed to generate code.");
|
| 646 |
}
|
|
|
|
| 4 |
import { LAYER_DEFINITIONS } from '../constants';
|
| 5 |
|
| 6 |
// --- SCHEMAS ---
|
| 7 |
+
const patchSchema = {
|
| 8 |
+
type: Type.OBJECT,
|
| 9 |
+
properties: {
|
| 10 |
+
reasoning: { type: Type.STRING, description: "Why these changes are being made." },
|
| 11 |
+
summary: { type: Type.STRING, description: "A concise summary of what was updated (e.g., 'Added dropout to encoder')." },
|
| 12 |
+
files_changed: { type: Type.ARRAY, items: { type: Type.STRING }, description: "List of files modified." },
|
| 13 |
+
patches: {
|
| 14 |
+
type: Type.ARRAY,
|
| 15 |
+
items: {
|
| 16 |
+
type: Type.OBJECT,
|
| 17 |
+
properties: {
|
| 18 |
+
search: { type: Type.STRING, description: "The exact code block to find. Must be unique." },
|
| 19 |
+
replace: { type: Type.STRING, description: "The code to replace it with." }
|
| 20 |
+
},
|
| 21 |
+
required: ["search", "replace"]
|
| 22 |
+
}
|
| 23 |
+
}
|
| 24 |
+
},
|
| 25 |
+
required: ["patches", "summary", "files_changed"]
|
| 26 |
+
};
|
| 27 |
+
|
| 28 |
+
const evaluationSchema = {
|
| 29 |
+
type: Type.OBJECT,
|
| 30 |
+
properties: {
|
| 31 |
+
score: { type: Type.NUMBER, description: "0-100 score of how well requirements were met." },
|
| 32 |
+
missing_components: { type: Type.ARRAY, items: { type: Type.STRING } },
|
| 33 |
+
bugs: { type: Type.ARRAY, items: { type: Type.STRING } },
|
| 34 |
+
improvement_tasks: { type: Type.ARRAY, items: { type: Type.STRING } }
|
| 35 |
+
},
|
| 36 |
+
required: ["score", "improvement_tasks"]
|
| 37 |
+
};
|
| 38 |
+
|
| 39 |
const graphResponseSchema = {
|
| 40 |
type: Type.OBJECT,
|
| 41 |
properties: {
|
|
|
|
| 126 |
|
| 127 |
export const DEFAULT_MODEL = 'gemini-2.5-flash';
|
| 128 |
|
| 129 |
+
export type AgentStatus = 'idle' | 'architect' | 'critic' | 'refiner' | 'evaluator' | 'debugger' | 'patcher' | 'complete' | 'error';
|
| 130 |
|
| 131 |
/**
|
| 132 |
* Internal helper to build the raw specification string.
|
|
|
|
| 571 |
}
|
| 572 |
};
|
| 573 |
|
| 574 |
+
/**
|
| 575 |
+
* Helper: Applies a list of patches to a code string.
|
| 576 |
+
*/
|
| 577 |
+
export const applyPatches = (code: string, patches: { search: string, replace: string }[]): string => {
|
| 578 |
+
let updatedCode = code;
|
| 579 |
+
for (const patch of patches) {
|
| 580 |
+
if (updatedCode.includes(patch.search)) {
|
| 581 |
+
updatedCode = updatedCode.replace(patch.search, patch.replace);
|
| 582 |
+
} else {
|
| 583 |
+
console.warn("Patch failed: Search block not found.", patch.search);
|
| 584 |
+
}
|
| 585 |
+
}
|
| 586 |
+
return updatedCode;
|
| 587 |
+
};
|
| 588 |
+
|
| 589 |
+
/**
|
| 590 |
+
* Evaluates generated code against the original prompt.
|
| 591 |
+
*/
|
| 592 |
+
export const evaluateCode = async (
|
| 593 |
+
prompt: string,
|
| 594 |
+
code: string,
|
| 595 |
+
model: string = DEFAULT_MODEL
|
| 596 |
+
): Promise<{ score: number, missing_components: string[], bugs: string[], improvement_tasks: string[] }> => {
|
| 597 |
+
const ai = getAiClient();
|
| 598 |
+
try {
|
| 599 |
+
const response = await ai.models.generateContent({
|
| 600 |
+
model: model,
|
| 601 |
+
contents: `Original Prompt: "${prompt}"\n\nGenerated Code:\n${code}`,
|
| 602 |
+
config: {
|
| 603 |
+
systemInstruction: `You are a Senior QA Engineer. Compare the generated PyTorch code against the original prompt.
|
| 604 |
+
Identify any missing requirements, logical bugs, or incomplete components.
|
| 605 |
+
Generate a list of targeted improvement tasks.
|
| 606 |
+
Return the evaluation in JSON format.`,
|
| 607 |
+
responseMimeType: "application/json",
|
| 608 |
+
responseSchema: evaluationSchema
|
| 609 |
+
}
|
| 610 |
+
});
|
| 611 |
+
return JSON.parse(cleanJsonString(response.text));
|
| 612 |
+
} catch (error) {
|
| 613 |
+
console.error("Evaluation failed:", error);
|
| 614 |
+
return { score: 0, missing_components: [], bugs: [], improvement_tasks: ["Manual review required."] };
|
| 615 |
+
}
|
| 616 |
+
};
|
| 617 |
+
|
| 618 |
+
/**
|
| 619 |
+
* Generates patches for code based on instructions.
|
| 620 |
+
*/
|
| 621 |
+
export const generateCodePatches = async (
|
| 622 |
+
code: string,
|
| 623 |
+
instructions: string,
|
| 624 |
+
model: string = DEFAULT_MODEL
|
| 625 |
+
): Promise<{ reasoning: string, summary: string, files_changed: string[], patches: { search: string, replace: string }[] }> => {
|
| 626 |
+
const ai = getAiClient();
|
| 627 |
+
try {
|
| 628 |
+
const response = await ai.models.generateContent({
|
| 629 |
+
model: model,
|
| 630 |
+
contents: `Current Code:\n${code}\n\nInstructions for Modification:\n${instructions}`,
|
| 631 |
+
config: {
|
| 632 |
+
systemInstruction: `You are a Principal Software Engineer. Instead of rewriting the entire file, you provide targeted patches.
|
| 633 |
+
A patch consists of a 'search' block (the exact code to find) and a 'replace' block (the new code).
|
| 634 |
+
The 'search' block MUST be a unique, contiguous substring from the current code.
|
| 635 |
+
Include all necessary imports if they are missing.
|
| 636 |
+
|
| 637 |
+
Output Requirements:
|
| 638 |
+
1. 'summary': A concise one-line description of the update.
|
| 639 |
+
2. 'files_changed': An array of filenames (e.g., ["model.py"]).
|
| 640 |
+
3. 'patches': The search/replace pairs.
|
| 641 |
+
|
| 642 |
+
Return the patches in JSON format.`,
|
| 643 |
+
responseMimeType: "application/json",
|
| 644 |
+
responseSchema: patchSchema
|
| 645 |
+
}
|
| 646 |
+
});
|
| 647 |
+
return JSON.parse(cleanJsonString(response.text));
|
| 648 |
+
} catch (error) {
|
| 649 |
+
console.error("Patch generation failed:", error);
|
| 650 |
+
throw error;
|
| 651 |
+
}
|
| 652 |
+
};
|
| 653 |
+
|
| 654 |
/**
|
| 655 |
* Multi-agent code generation.
|
| 656 |
* Uses the detailed prompt to write, review, and polish PyTorch code.
|
| 657 |
*/
|
| 658 |
export const generateCodeWithAgents = async (
|
| 659 |
+
promptText: string,
|
| 660 |
+
onStatusUpdate: (status: AgentStatus, log: string) => void,
|
| 661 |
+
model: string = DEFAULT_MODEL
|
| 662 |
+
): Promise<{ code: string, evaluation?: any, initialPatches?: any }> => {
|
| 663 |
const ai = getAiClient();
|
| 664 |
|
| 665 |
// --- Step 1: Coder ---
|
|
|
|
| 675 |
4. Use descriptive variable names.
|
| 676 |
5. Include a robust 'if __name__ == "__main__":' block that instantiates the model and runs a dummy forward pass with torch.randn.
|
| 677 |
6. Handle custom layer logic or external imports if specified.
|
| 678 |
+
7. Initialization Strategy:
|
| 679 |
+
- Use Kaiming initialization (nn.init.kaiming_normal_) for Conv2d and Linear layers.
|
| 680 |
+
- CRITICAL: If using SiLU (nn.SiLU) as the activation, use nonlinearity='linear' (gain=1) in the Kaiming initialization instead of 'relu'. This better preserves feature variance for SiLU.
|
| 681 |
|
| 682 |
Return ONLY the Python code. No markdown backticks.`;
|
| 683 |
|
|
|
|
| 754 |
config: { systemInstruction: polisherSystemInstruction }
|
| 755 |
});
|
| 756 |
let finalCode = cleanJsonString(response.text);
|
| 757 |
+
|
| 758 |
+
// --- Step 4: Evaluator (New Step) ---
|
| 759 |
+
onStatusUpdate('evaluator', 'Evaluator Agent is verifying requirements...');
|
| 760 |
+
const evaluation = await evaluateCode(promptText, finalCode, model);
|
| 761 |
+
|
| 762 |
+
let initialPatches = null;
|
| 763 |
+
if (evaluation.score < 90 && evaluation.improvement_tasks.length > 0) {
|
| 764 |
+
onStatusUpdate('refiner', 'Applying automated improvements based on evaluation...');
|
| 765 |
+
const patchResult = await generateCodePatches(finalCode, evaluation.improvement_tasks.join("\n"), model);
|
| 766 |
+
finalCode = applyPatches(finalCode, patchResult.patches);
|
| 767 |
+
initialPatches = patchResult;
|
| 768 |
+
}
|
| 769 |
+
|
| 770 |
onStatusUpdate('complete', 'Code generation complete!');
|
| 771 |
+
return { code: finalCode, evaluation, initialPatches };
|
| 772 |
} catch(e) {
|
| 773 |
throw new Error("Polisher agent failed to generate code.");
|
| 774 |
}
|