Date: 2026-03-16 Author: Sisyphus AI Agent Status: Draft for Review
Enhance the existing talent assessment system with comprehensive management functionality allowing administrators to configure assessment generation through keywords, question counts, and style requirements. The system will extract relevant content from knowledge bases and generate customized assessments based on these configurations.
User selects knowledge base → System generates 3-5 questions → User answers → AI grades → Report generated
User selects template/inline config → System filters content by keywords → Generates N questions with specified style → User answers → AI grades → Report generated
@Entity('assessment_configs')
export class AssessmentConfig {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
name: string;
@Column({ nullable: true })
description: string;
@Column({ name: 'tenant_id', nullable: true })
tenantId: string;
@Column({ type: 'simple-json' })
configuration: AssessmentConfigSettings;
@Column({ default: true })
isActive: boolean;
@CreateDateColumn({ name: 'created_at' })
createdAt: Date;
@UpdateDateColumn({ name: 'updated_at' })
updatedAt: Date;
}
interface AssessmentConfigSettings {
// Keywords for content filtering and AI focus
keywords: string[];
// Question generation parameters
questionCount: number; // 1-20
difficultyDistribution: {
standard: number; // 0-100%
advanced: number; // 0-100%
specialist: number; // 0-100%
};
// Style requirements
style: {
tone: 'formal' | 'conversational' | 'technical' | 'business';
questionTypes: ('multiple-choice' | 'open-ended' | 'scenario-based' | 'technical')[];
assessmentGoals: ('knowledge-check' | 'problem-solving' | 'critical-thinking' | 'application')[];
};
// Content filtering
contentFilter: {
minContentLength: number; // Minimum characters for content to be considered
maxContextChunks: number; // Max chunks to include in context
};
}
Add reference to assessment config:
@Entity('assessment_sessions')
export class AssessmentSession {
// ... existing fields ...
@Column({ name: 'config_id', nullable: true })
configId: string | null;
@ManyToOne(() => AssessmentConfig, { nullable: true })
@JoinColumn({ name: 'config_id' })
config: AssessmentConfig;
// Inline configuration (when no template used)
@Column({ type: 'simple-json', nullable: true, name: 'inline_config' })
inlineConfig: AssessmentConfigSettings | null;
}
@Injectable()
export class AssessmentConfigService {
async createConfig(tenantId: string, settings: AssessmentConfigSettings): Promise<AssessmentConfig>
async getConfigs(tenantId: string): Promise<AssessmentConfig[]>
async getConfig(id: string, tenantId: string): Promise<AssessmentConfig>
async updateConfig(id: string, tenantId: string, settings: Partial<AssessmentConfigSettings>): Promise<AssessmentConfig>
async deleteConfig(id: string, tenantId: string): Promise<void>
async getActiveConfigs(tenantId: string): Promise<AssessmentConfig[]>
}
@Injectable()
export class ContentFilterService {
async filterByKeywords(
content: string,
keywords: string[],
method: 'exact' | 'semantic' | 'hybrid' = 'hybrid'
): Promise<string> {
// Extract relevant sections based on keywords
// Use semantic similarity for broader matching
// Return filtered content for question generation
}
}
Modify generator.node.ts to accept configuration:
interface GeneratorConfig {
keywords?: string[];
questionCount?: number;
difficultyDistribution?: AssessmentConfigSettings['difficultyDistribution'];
style?: AssessmentConfigSettings['style'];
}
export const questionGeneratorNode = async (
state: EvaluationState,
config?: RunnableConfig & { generatorConfig?: GeneratorConfig }
): Promise<Partial<EvaluationState>> {
// 1. Filter knowledge base content by keywords if provided
// 2. Generate questions based on configuration
// 3. Enforce question count and difficulty distribution
// 4. Apply style requirements to question generation
}
POST /api/v1/assessment/configs - Create assessment config
GET /api/v1/assessment/configs - List configs
GET /api/v1/assessment/configs/:id - Get config details
PUT /api/v1/assessment/configs/:id - Update config
DELETE /api/v1/assessment/configs/:id - Delete config
// Existing: POST /assessment/start
// New parameters supported:
interface StartSessionRequest {
knowledgeBaseId: string;
language?: string;
configId?: string; // Use template
inlineConfig?: AssessmentConfigSettings; // Or use inline config
}
Location: web/src/pages/workspace/AssessmentTemplatePage.tsx
Features:
Location: web/components/views/AssessmentView.tsx
New UI Elements:
// KeywordsInput.tsx
- Tag-based input for keywords
- Suggestions from knowledge base content
- Visual feedback for keyword matching
// QuestionCountSlider.tsx
- Slider from 1-20 questions
- Smart defaults based on content size
// DifficultyDistribution.tsx
- Interactive pie chart
- Drag to adjust percentages
- Real-time validation (must sum to 100%)
// StylePresets.tsx
- Pre-defined style combinations
- Custom style builder
1. Load knowledge base content
2. Apply keyword filtering (semantic similarity)
3. Chunk content into manageable segments
4. Rank segments by relevance to keywords
5. Select top N segments for context
6. Pass filtered content to question generator
1. Receive configuration + filtered content
2. Analyze content for key concepts
3. Generate questions matching:
- Specified count
- Difficulty distribution
- Question types
- Style requirements
4. Validate question quality
5. Return structured question set
// Keywords validation
@ValidateNested()
@ArrayMaxSize(50)
keywords: string[];
// Question count validation
@IsInt()
@Min(1)
@Max(20)
questionCount: number;
// Difficulty distribution validation
@ValidateNested()
@IsNotEmpty()
difficultyDistribution: {
@IsInt()
@Min(0)
@Max(100)
standard: number;
// ... similar for advanced, specialist
};
// Validate sum equals 100
@ValidatorConstraint({ name: 'difficultySum', async: false })
export class DifficultySumConstraint implements ValidatorConstraintInterface {
validate(value: any) {
return (value.standard + value.advanced + value.specialist) === 100;
}
}
| Error | Cause | Resolution |
|---|---|---|
INSUFFICIENT_CONTENT |
Filtered content too short | Relax keyword constraints or select broader keywords |
INVALID_CONFIG |
Config validation failed | Return validation errors with specific field issues |
CONFIG_NOT_FOUND |
Template ID doesn't exist | Return 404 with config ID |
KEYWORD_TOO_SPECIFIC |
No content matches keywords | Suggest broader keywords or use all content |
{
"error": {
"code": "INSUFFICIENT_CONTENT",
"message": "Filtered content is too short for question generation",
"details": {
"minLength": 1000,
"actualLength": 250,
"suggestedKeywords": ["technology", "software"]
}
}
}
Backend:
AssessmentConfigService - CRUD operationsContentFilterService - Keyword filtering logicquestionGeneratorNode - Question generation with configFrontend:
assessment_configs tableconfig_id and inline_config to assessment_sessionsAssessmentConfigService| Risk | Impact | Mitigation |
|---|---|---|
| Keyword filtering too restrictive | Low quality questions | Implement semantic matching + fallback |
| Config complexity overwhelms users | Poor adoption | Progressive disclosure + presets |
| Performance degradation with large KB | Slow generation | Content chunking + caching |
| Breaking existing assessments | System disruption | Feature flag + gradual rollout |
{
"name": "Senior Developer Interview",
"keywords": ["system design", "algorithms", "database", "API", "security"],
"questionCount": 8,
"difficultyDistribution": {
"standard": 25,
"advanced": 50,
"specialist": 25
},
"style": {
"tone": "technical",
"questionTypes": ["technical", "scenario-based"],
"assessmentGoals": ["problem-solving", "critical-thinking"]
}
}
{
"name": "Weekly Training Quiz",
"keywords": [],
"questionCount": 5,
"difficultyDistribution": {
"standard": 70,
"advanced": 30,
"specialist": 0
},
"style": {
"tone": "formal",
"questionTypes": ["multiple-choice", "open-ended"],
"assessmentGoals": ["knowledge-check"]
}
}
Document Status: Ready for review Next Steps: