Skip to content

Commit

Permalink
chore(backend): optimization handler output content (#86)
Browse files Browse the repository at this point in the history
before 
<img width="691" alt="image"
src="https://github.com/user-attachments/assets/f2d3694e-ab06-4b37-a8b1-52225671a1c7"
/>

after
<img width="535" alt="image"
src="https://github.com/user-attachments/assets/58bd2822-b9f3-4554-8a92-7e54e5689a15"
/>

- updating chat api call with new chat api
- remove embedding request in llm-server
- optimization log prompt format for if log output is not only string


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

Based on the comprehensive summary of changes, here are the high-level
release notes:

- **Model Interaction Updates**
- Updated chat model interaction to use a more structured message
format.
  - Added support for system and assistant roles in message handling.

- **Utility Function Enhancements**
  - Introduced new utility functions for processing model responses.
- Improved content extraction and formatting methods, including the
removal of code block fences.

- **Configuration and Logging**
- Enhanced configuration loading with additional logging for better
visibility.

- **Embedding and Provider Changes**
- Removed embedding-related functionality and providers, simplifying the
overall architecture.

- **Minor Improvements**
  - Code formatting and readability enhancements.
  - Streamlined import statements and method signatures.

These changes primarily focus on improving the robustness and
flexibility of the model interaction and response processing mechanisms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: NarwhalChen <[email protected]>
Co-authored-by: ZHallen122 <[email protected]>
  • Loading branch information
4 people authored Jan 8, 2025
1 parent f9b0ed5 commit f20ec64
Show file tree
Hide file tree
Showing 33 changed files with 1,204 additions and 1,317 deletions.
49 changes: 0 additions & 49 deletions backend/src/build-system/__tests__/test-database-schemas.spec.ts

This file was deleted.

80 changes: 18 additions & 62 deletions backend/src/build-system/__tests__/test-generate-doc.spec.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
/* eslint-disable no-console */
import { BuilderContext } from 'src/build-system/context';
import { BuildSequence } from '../types';
import * as fs from 'fs';
import * as path from 'path';
import { writeToFile } from './utils';
import { executeBuildSequence } from './utils';

// TODO: adding integration flag
describe('Sequence: PRD -> UXSD -> UXDD -> UXSS', () => {
// Generate a unique folder with a timestamp
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const logFolderPath = `./logs/generate-docs-${timestamp}`;
fs.mkdirSync(logFolderPath, { recursive: true });

it('should execute the full sequence and log results to individual files', async () => {
const sequence: BuildSequence = {
id: 'test-sequence',
id: 'test-backend-sequence',
version: '1.0.0',
name: 'Test PRD to UX Sequence',
description: 'Testing PRD to UX sequence execution',
name: 'Spotify-like Music Web',
description: 'Users can play music',
databaseType: 'SQLite',
steps: [
{
id: 'step-1',
Expand All @@ -35,7 +28,6 @@ describe('Sequence: PRD -> UXSD -> UXDD -> UXSS', () => {
{
id: 'op:UX:SMD',
name: 'UX Sitemap Document Node',
requires: ['op:PRD'],
},
],
},
Expand All @@ -46,7 +38,6 @@ describe('Sequence: PRD -> UXSD -> UXDD -> UXSS', () => {
{
id: 'op:UX:SMS',
name: 'UX Sitemap Structure Node',
requires: ['op:UX:SMD'],
},
],
},
Expand All @@ -57,73 +48,38 @@ describe('Sequence: PRD -> UXSD -> UXDD -> UXSS', () => {
{
id: 'op:UX:DATAMAP:DOC',
name: 'UX Data Map Document node',
requires: ['op:UX:SMD'],
},
],
},
{
id: 'step-5',
name: 'file structure generation',
nodes: [
{
id: 'op:FILE:STRUCT',
name: 'file structure generation',
requires: ['op:UX:SMD', 'op:UX:DATAMAP:DOC'],
options: {
projectPart: 'frontend',
},
},
],
},
{
id: 'step-6',
name: 'File_Arch Document',
name: 'UX SMD LEVEL 2 Page Details',
nodes: [
{
id: 'op:FILE:ARCH',
name: 'File_Arch',
requires: [
'op:FILE:STRUCT',
//TODO: here use datamap doc rather than datamap struct, we have to change this
'op:UX:DATAMAP:DOC',
],
id: 'op:UX:SMS:LEVEL2',
name: 'UX SMD LEVEL 2 Page Details Node',
},
],
},
],
};

const context = new BuilderContext(sequence, 'test');

// Set input data for context
context.setGlobalContext('projectName', 'spotify like music web');
context.setGlobalContext('description', 'user can play music');
context.setGlobalContext('platform', 'web');

try {
await context.execute();

for (const step of sequence.steps) {
for (const node of step.nodes) {
const resultData = await context.getNodeData(node.id);
console.log(resultData);
if (resultData) {
writeToFile(logFolderPath, node.id, resultData);
}
}
}
const result = await executeBuildSequence(
'test-generate-all-ux-part',
sequence,
);

console.log(
'Sequence completed successfully. Logs stored in:',
logFolderPath,
result.logFolderPath,
);

if (!result.success) {
throw result.error;
}
} catch (error) {
console.error('Error during sequence execution:', error);
fs.writeFileSync(
path.join(logFolderPath, 'error.txt'),
`Error: ${error.message}\n${error.stack}`,
'utf8',
);
throw error;
}
}, 600000);
Expand Down
136 changes: 18 additions & 118 deletions backend/src/build-system/__tests__/test.fullstack-gen.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,8 @@
/* eslint-disable no-console */
import { BuilderContext } from 'src/build-system/context';
import { BuildSequence } from '../types';
import * as fs from 'fs';
import * as path from 'path';
import { writeToFile } from './utils';
import { BuildMonitor } from '../monitor';
import { executeBuildSequence, objectToMarkdown, writeToFile } from './utils';

describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas -> Frontend_File_struct -> Frontend_File_arch -> BackendCodeGenerator', () => {
// Generate a unique folder with a timestamp
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const logFolderPath = `./logs/Fullstack_code_generator-${timestamp}`;
fs.mkdirSync(logFolderPath, { recursive: true });

it('should execute the frontend and backend code generation sequence and log results to individual files', async () => {
// Define the build sequence up to Backend Code Generator
describe('Build Sequence Test', () => {
it('should execute build sequence successfully', async () => {
const sequence: BuildSequence = {
id: 'test-backend-sequence',
version: '1.0.0',
Expand All @@ -28,7 +17,7 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
nodes: [
{
id: 'op:PROJECT::STATE:SETUP',
name: 'set up project folders',
name: 'Project Folders Setup',
},
],
},
Expand All @@ -39,7 +28,7 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
nodes: [
{
id: 'op:PRD',
name: 'PRD Generation Node',
name: 'Project Requirements Document Node',
},
],
},
Expand Down Expand Up @@ -67,7 +56,7 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
},
{
id: 'op:UX:DATAMAP:DOC',
name: 'UX Data Map Document Node',
name: 'UX DataMap Document Node',
requires: ['op:UX:SMD'],
},
],
Expand All @@ -84,12 +73,17 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
},
{
id: 'op:FILE:STRUCT',
name: 'file structure generation',
name: 'File Structure Generation',
requires: ['op:UX:SMD', 'op:UX:DATAMAP:DOC'],
options: {
projectPart: 'frontend',
},
},
{
id: 'op:UX:SMS:LEVEL2',
name: 'Level 2 UX Sitemap Structure Node details',
requires: ['op:UX:SMS'],
},
],
},
{
Expand All @@ -104,7 +98,7 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
},
{
id: 'op:FILE:ARCH',
name: 'File_Arch',
name: 'File Arch',
requires: ['op:FILE:STRUCT', 'op:UX:DATAMAP:DOC'],
},
{
Expand Down Expand Up @@ -145,104 +139,10 @@ describe('Sequence: PRD -> UXSD -> UXSS -> UXDD -> DATABASE_REQ -> DBSchemas ->
},
],
};
const context = new BuilderContext(sequence, 'test-env');
const monitor = BuildMonitor.getInstance();

try {
console.time('Total Execution Time');

await context.execute();

console.timeEnd('Total Execution Time');

const monitorReport = monitor.generateTextReport(sequence.id);
fs.writeFileSync(
path.join(logFolderPath, 'execution-metrics.txt'),
monitorReport,
'utf8',
);

const sequenceMetrics = monitor.getSequenceMetrics(sequence.id);
if (sequenceMetrics) {
const metricsJson = {
totalDuration: `${sequenceMetrics.duration}ms`,
successRate: `${sequenceMetrics.successRate.toFixed(2)}%`,
totalSteps: sequenceMetrics.totalSteps,
completedSteps: sequenceMetrics.completedSteps,
failedSteps: sequenceMetrics.failedSteps,
totalNodes: sequenceMetrics.totalNodes,
startTime: new Date(sequenceMetrics.startTime).toISOString(),
endTime: new Date(sequenceMetrics.endTime).toISOString(),
};

fs.writeFileSync(
path.join(logFolderPath, 'metrics.json'),
JSON.stringify(metricsJson, null, 2),
'utf8',
);

console.log('\nSequence Metrics:');
console.table(metricsJson);
}

for (const step of sequence.steps) {
const stepMetrics = sequenceMetrics?.stepMetrics.get(step.id);
for (const node of step.nodes) {
const resultData = await context.getNodeData(node.id);
const nodeMetrics = stepMetrics?.nodeMetrics.get(node.id);
if (resultData) {
writeToFile(logFolderPath, `${node.name}`, resultData);
} else {
console.error(
` Error: Handler ${node.name} failed to produce result data`,
);
writeToFile(logFolderPath, `${node.name}-error`, {
error: 'No result data',
metrics: nodeMetrics,
});
}
}
}

const summary = {
timestamp: new Date().toISOString(),
sequenceId: sequence.id,
sequenceName: sequence.name,
totalExecutionTime: `${sequenceMetrics?.duration}ms`,
successRate: `${sequenceMetrics?.successRate.toFixed(2)}%`,
nodesExecuted: sequenceMetrics?.totalNodes,
completedNodes: sequenceMetrics?.stepMetrics.size,
logFolder: logFolderPath,
};

fs.writeFileSync(
path.join(logFolderPath, 'execution-summary.json'),
JSON.stringify(summary, null, 2),
'utf8',
);
} catch (error) {
const errorReport = {
error: {
message: error.message,
stack: error.stack,
},
metrics: monitor.getSequenceMetrics(sequence.id),
timestamp: new Date().toISOString(),
};

fs.writeFileSync(
path.join(logFolderPath, 'error-with-metrics.json'),
JSON.stringify(errorReport, null, 2),
'utf8',
);

console.error('\nError during sequence execution:');
console.error(error);
console.error(
'\nError report saved to:',
path.join(logFolderPath, 'error-with-metrics.json'),
);
throw new Error('Sequence execution failed.');
}
}, 300000); // Timeout set to 10 minutes
const result = await executeBuildSequence('fullstack-code-gen', sequence);
expect(result.success).toBe(true);
expect(result.metrics).toBeDefined();
console.log(`Logs saved to: ${result.logFolderPath}`);
}, 300000);
});
17 changes: 10 additions & 7 deletions backend/src/build-system/__tests__/test.model-provider.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { EmbeddingProvider } from "src/common/embedding-provider";
import { EmbeddingProvider } from 'src/common/embedding-provider';

describe('Model Provider Test', () => {
let embProvider = EmbeddingProvider.getInstance();
it('should generate a response from the model provider', async () => {
let res = await embProvider.generateEmbResponse("Your text string goes here", "text-embedding-3-small");
console.log(res);
});
});
const embProvider = EmbeddingProvider.getInstance();
it('should generate a response from the model provider', async () => {
const res = await embProvider.generateEmbResponse(
'Your text string goes here',
'text-embedding-3-small',
);
console.log(res);
});
});
Loading

0 comments on commit f20ec64

Please sign in to comment.