MOPC-App/docs/architecture/ai-services.md

250 lines
5.6 KiB
Markdown

# AI Services Reference
## 1. AI Filtering Service
**File:** `src/server/services/ai-filtering.ts`
**Purpose:** Evaluate projects against admin-defined criteria text
### Input
- List of projects (anonymized)
- Criteria text (e.g., "Projects must be based in Mediterranean region")
- Rule configuration (PASS/REJECT/FLAG actions)
### Output
Per-project result:
- `meets_criteria` - Boolean
- `confidence` - 0-1 score
- `reasoning` - Explanation
- `quality_score` - 1-10 rating
- `spam_risk` - Boolean flag
### Configuration
- **Batch Size:** 20 projects per API call
- **Description Limit:** 500 characters
- **Token Usage:** ~1500-2500 tokens per batch
### Example Criteria
- "Filter out any project without a description"
- "Only include projects founded after 2020"
- "Reject projects with fewer than 2 team members"
- "Projects must be based in Mediterranean region"
### Usage
```typescript
import { aiFilterProjects } from '@/server/services/ai-filtering'
const results = await aiFilterProjects(
projects,
'Only include projects with ocean conservation focus',
userId,
roundId
)
```
---
## 2. AI Assignment Service
**File:** `src/server/services/ai-assignment.ts`
**Purpose:** Match jurors to projects based on expertise alignment
### Input
- List of jurors with expertise tags
- List of projects with tags/category
- Constraints:
- Required reviews per project
- Max assignments per juror
- Existing assignments (to avoid duplicates)
### Output
Suggested assignments:
- `jurorId` - Juror to assign
- `projectId` - Project to assign
- `confidenceScore` - 0-1 match confidence
- `expertiseMatchScore` - 0-1 expertise overlap
- `reasoning` - Explanation
### Configuration
- **Batch Size:** 15 projects per batch (all jurors included)
- **Description Limit:** 300 characters
- **Token Usage:** ~2000-3500 tokens per batch
### Fallback Algorithm
When AI is unavailable, uses:
1. Tag overlap scoring (60% weight)
2. Load balancing (40% weight)
3. Constraint satisfaction
### Usage
```typescript
import { generateAIAssignments } from '@/server/services/ai-assignment'
const result = await generateAIAssignments(
jurors,
projects,
{
requiredReviewsPerProject: 3,
maxAssignmentsPerJuror: 10,
existingAssignments: [],
},
userId,
roundId
)
```
---
## 3. Award Eligibility Service
**File:** `src/server/services/ai-award-eligibility.ts`
**Purpose:** Determine which projects qualify for special awards
### Input
- Award criteria text (plain language)
- List of projects (anonymized)
- Optional: Auto-tag rules (field-based matching)
### Output
Per-project:
- `eligible` - Boolean
- `confidence` - 0-1 score
- `reasoning` - Explanation
- `method` - 'AI' or 'AUTO'
### Configuration
- **Batch Size:** 20 projects per API call
- **Description Limit:** 400 characters
- **Token Usage:** ~1500-2500 tokens per batch
### Auto-Tag Rules
Deterministic rules can be combined with AI:
```typescript
const rules: AutoTagRule[] = [
{ field: 'country', operator: 'equals', value: 'Italy' },
{ field: 'competitionCategory', operator: 'equals', value: 'STARTUP' },
]
```
### Usage
```typescript
import { aiInterpretCriteria, applyAutoTagRules } from '@/server/services/ai-award-eligibility'
// Deterministic matching
const autoResults = applyAutoTagRules(rules, projects)
// AI-based criteria interpretation
const aiResults = await aiInterpretCriteria(
'Projects focusing on marine biodiversity',
projects,
userId,
awardId
)
```
---
## 4. Mentor Matching Service
**File:** `src/server/services/mentor-matching.ts`
**Purpose:** Recommend mentors for projects based on expertise
### Input
- Project details (single or batch)
- Available mentors with expertise tags and availability
### Output
Ranked list of mentor matches:
- `mentorId` - Mentor ID
- `confidenceScore` - 0-1 overall match
- `expertiseMatchScore` - 0-1 expertise overlap
- `reasoning` - Explanation
### Configuration
- **Batch Size:** 15 projects per batch
- **Description Limit:** 350 characters
- **Token Usage:** ~1500-2500 tokens per batch
### Fallback Algorithm
Keyword-based matching when AI unavailable:
1. Extract keywords from project tags/description
2. Match against mentor expertise tags
3. Factor in availability (assignments vs max)
### Usage
```typescript
import {
getAIMentorSuggestions,
getAIMentorSuggestionsBatch
} from '@/server/services/mentor-matching'
// Single project
const matches = await getAIMentorSuggestions(prisma, projectId, 5, userId)
// Batch processing
const batchResults = await getAIMentorSuggestionsBatch(
prisma,
projectIds,
5,
userId
)
```
---
## Common Patterns
### Token Logging
All services log usage to `AIUsageLog`:
```typescript
await logAIUsage({
userId,
action: 'FILTERING',
entityType: 'Round',
entityId: roundId,
model,
promptTokens: usage.promptTokens,
completionTokens: usage.completionTokens,
totalTokens: usage.totalTokens,
batchSize: projects.length,
itemsProcessed: projects.length,
status: 'SUCCESS',
})
```
### Error Handling
All services use unified error classification:
```typescript
try {
// AI call
} catch (error) {
const classified = classifyAIError(error)
logAIError('ServiceName', 'functionName', classified)
if (classified.retryable) {
// Retry logic
} else {
// Fall back to algorithm
}
}
```
### Anonymization
All services anonymize before sending to AI:
```typescript
const { anonymized, mappings } = anonymizeProjectsForAI(projects, 'FILTERING')
if (!validateAnonymizedProjects(anonymized)) {
throw new Error('GDPR compliance check failed')
}
```
## See Also
- [AI System Architecture](./ai-system.md)
- [AI Configuration Guide](./ai-configuration.md)
- [AI Error Handling](./ai-errors.md)