Spaces:
Configuration error
Configuration error
File size: 7,147 Bytes
971b4ea | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | # Data Model: Content Personalization API
**Feature Branch**: `005-content-personalize`
**Created**: 2025-12-14
**Status**: Complete
## Overview
This feature uses the **existing User model** and introduces **request/response schemas** only. No new database tables are required.
---
## Existing Entity: User
The User entity already contains all fields needed for personalization.
**Location**: `app/models/user.py`
```
βββββββββββββββββββββββββββββββββββββββββββββββ
β User β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β id: Integer (PK) β
β username: String (nullable, unique) β
β email: String(255) (unique, not null) β
β hashed_password: String(60) (not null) β
β software_level: String(20) (default: "beginner") β
β hardware_level: String(20) (default: "none") β
β learning_goals: Text (default: "") β
β created_at: DateTime (auto) β
βββββββββββββββββββββββββββββββββββββββββββββββ
```
### Relevant Fields for Personalization
| Field | Type | Values | Usage |
|-------|------|--------|-------|
| `software_level` | String(20) | "beginner", "intermediate", "advanced" | Determines code/software content complexity |
| `hardware_level` | String(20) | "none", "basic", "experienced" | Determines hardware concept explanation depth |
| `learning_goals` | Text | Free-form | Used to emphasize relevant topics |
### Enums (Reference)
```python
class SoftwareLevel(str, Enum):
beginner = "beginner"
intermediate = "intermediate"
advanced = "advanced"
class HardwareLevel(str, Enum):
none = "none"
basic = "basic"
experienced = "experienced"
```
---
## New Schema: PersonalizeRequest
**Purpose**: Validate incoming personalization requests
**Location**: `app/schemas/personalize.py`
```
βββββββββββββββββββββββββββββββββββββββββββββββ
β PersonalizeRequest β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β content: str (required, non-empty) β
β user_id: int (required, positive) β
βββββββββββββββββββββββββββββββββββββββββββββββ
```
### Validation Rules
| Field | Rule | Error |
|-------|------|-------|
| `content` | Non-empty after strip | "Content cannot be empty" |
| `content` | Max 50,000 characters | "Content exceeds maximum length of 50000 characters" |
| `user_id` | Positive integer | "User ID must be a positive integer" |
---
## New Schema: PersonalizeResponse
**Purpose**: Structure the API response
**Location**: `app/schemas/personalize.py`
```
βββββββββββββββββββββββββββββββββββββββββββββββ
β PersonalizeResponse β
βββββββββββββββββββββββββββββββββββββββββββββββ€
β personalized_content: str β
β adjustments_made: str β
βββββββββββββββββββββββββββββββββββββββββββββββ
```
### Field Descriptions
| Field | Description | Example |
|-------|-------------|---------|
| `personalized_content` | The content adapted for the user's level | Full adapted text |
| `adjustments_made` | Human-readable description of changes | "Simplified technical terminology, added explanations for variables and loops, included beginner-friendly examples" |
---
## Entity Relationships
```
βββββββββββββββββββ βββββββββββββββββββββββββββ
β User β ββββββββ β PersonalizeRequest β
β β user_id β β
β id (PK) β β content β
β software_level β β user_id β
β hardware_level β βββββββββββββββββββββββββββ
β learning_goals β
βββββββββββββββββββ
β
β Profile data used for
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββ
β OpenAI API Call β
β β
β System: Personalization rules + user profileβ
β User: Original content β
β β
β Returns: Adapted content + adjustments β
βββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββ
β PersonalizeResponse β
β β
β personalized_content β
β adjustments_made β
βββββββββββββββββββββββββββ
```
---
## Data Flow
1. **Request** arrives with `content` and `user_id`
2. **Validation** ensures content is non-empty and within limits
3. **User lookup** retrieves profile from database by `user_id`
4. **Personalization** sends content + profile to OpenAI
5. **Response** returns adapted content and adjustment description
---
## No Database Migrations Required
This feature:
- Uses existing User table (no schema changes)
- Does not persist personalized content (per spec - out of scope)
- Only requires Pydantic schemas for request/response validation
---
## Schema Implementation
```python
# app/schemas/personalize.py
from pydantic import BaseModel, field_validator
class PersonalizeRequest(BaseModel):
content: str
user_id: int
@field_validator('content')
@classmethod
def content_not_empty(cls, v):
if not v or not v.strip():
raise ValueError('Content cannot be empty')
v = v.strip()
if len(v) > 50000:
raise ValueError('Content exceeds maximum length of 50000 characters')
return v
@field_validator('user_id')
@classmethod
def user_id_positive(cls, v):
if v <= 0:
raise ValueError('User ID must be a positive integer')
return v
class PersonalizeResponse(BaseModel):
personalized_content: str
adjustments_made: str
```
|