Base code
This commit is contained in:
264
backend/docs/ASSET_TRACKING_IMPLEMENTATION.md
Normal file
264
backend/docs/ASSET_TRACKING_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,264 @@
|
||||
# Asset Tracking Implementation Guide
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the production-ready implementation of asset tracking across all ALwrity modules. The unified Content Asset Library automatically tracks all AI-generated content (images, videos, audio, text) for easy management and organization.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Core Components
|
||||
|
||||
1. **Database Models** (`backend/models/content_asset_models.py`)
|
||||
- `ContentAsset`: Main model for tracking assets
|
||||
- `AssetCollection`: Collections/albums for organizing assets
|
||||
- `AssetType`: Enum (text, image, video, audio)
|
||||
- `AssetSource`: Enum (all ALwrity modules)
|
||||
|
||||
2. **Service Layer** (`backend/services/content_asset_service.py`)
|
||||
- CRUD operations for assets
|
||||
- Search, filter, pagination
|
||||
- Usage tracking
|
||||
|
||||
3. **Utility Functions**
|
||||
- `backend/utils/asset_tracker.py`: `save_asset_to_library()` helper
|
||||
- `backend/utils/file_storage.py`: Robust file saving utilities
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### ✅ Completed Integrations
|
||||
|
||||
#### 1. Story Writer (`backend/api/story_writer/router.py`)
|
||||
- **Images**: Tracks all scene images with metadata
|
||||
- **Audio**: Tracks all scene audio files with narration details
|
||||
- **Videos**: Tracks individual scene videos and complete story videos
|
||||
- **Location**: After generation in `/generate-images`, `/generate-audio`, `/generate-video`, `/generate-complete-video`
|
||||
- **Metadata**: Includes prompts, scene numbers, providers, models, costs, status
|
||||
|
||||
#### 2. Image Studio (`backend/api/images.py`)
|
||||
- **Image Generation**: Tracks all generated images
|
||||
- **Image Editing**: Tracks all edited images
|
||||
- **Location**: After generation in `/api/images/generate` and `/api/images/edit`
|
||||
- **Features**:
|
||||
- Robust file saving with validation
|
||||
- Atomic file writes
|
||||
- Proper error handling (non-blocking)
|
||||
- File serving endpoint at `/api/images/image-studio/images/{filename}`
|
||||
|
||||
### 📝 Notes on Other Modules
|
||||
|
||||
#### Main Generation Services
|
||||
- **Text Generation** (`main_text_generation.py`): Returns strings, not files. If text content needs tracking, save to `.txt` or `.md` files first.
|
||||
- **Video Generation** (`main_video_generation.py`): Already integrated via Story Writer
|
||||
- **Audio Generation** (`main_audio_generation.py`): Already integrated via Story Writer
|
||||
|
||||
#### Social Writers
|
||||
- **LinkedIn Writer**: Generates text content (posts, articles). No file generation currently.
|
||||
- **Facebook Writer**: Generates text content (posts, stories, reels). No file generation currently.
|
||||
- **Blog Writer**: Generates blog content. May generate images in future.
|
||||
|
||||
**Note**: If these modules generate files in the future, follow the integration pattern below.
|
||||
|
||||
## Integration Pattern
|
||||
|
||||
### For Image Generation
|
||||
|
||||
```python
|
||||
from utils.asset_tracker import save_asset_to_library
|
||||
from utils.file_storage import save_file_safely, generate_unique_filename
|
||||
from sqlalchemy.orm import Session
|
||||
from pathlib import Path
|
||||
|
||||
# After successful image generation
|
||||
try:
|
||||
base_dir = Path(__file__).parent.parent
|
||||
output_dir = base_dir / "module_images"
|
||||
|
||||
image_filename = generate_unique_filename(
|
||||
prefix="img_prompt",
|
||||
extension=".png",
|
||||
include_uuid=True
|
||||
)
|
||||
|
||||
# Save file safely
|
||||
image_path, save_error = save_file_safely(
|
||||
content=result.image_bytes,
|
||||
directory=output_dir,
|
||||
filename=image_filename,
|
||||
max_file_size=50 * 1024 * 1024 # 50MB
|
||||
)
|
||||
|
||||
if image_path and not save_error:
|
||||
image_url = f"/api/module/images/{image_path.name}"
|
||||
|
||||
# Track in asset library (non-blocking)
|
||||
try:
|
||||
asset_id = save_asset_to_library(
|
||||
db=db,
|
||||
user_id=user_id,
|
||||
asset_type="image",
|
||||
source_module="module_name",
|
||||
filename=image_path.name,
|
||||
file_url=image_url,
|
||||
file_path=str(image_path),
|
||||
file_size=len(result.image_bytes),
|
||||
mime_type="image/png",
|
||||
title="Image Title",
|
||||
description="Image description",
|
||||
prompt=prompt,
|
||||
tags=["tag1", "tag2"],
|
||||
provider=result.provider,
|
||||
model=result.model,
|
||||
metadata={"status": "completed"}
|
||||
)
|
||||
logger.info(f"✅ Asset saved: ID={asset_id}")
|
||||
except Exception as e:
|
||||
logger.error(f"Asset tracking failed: {e}", exc_info=True)
|
||||
# Don't fail the request
|
||||
except Exception as e:
|
||||
logger.error(f"File save failed: {e}", exc_info=True)
|
||||
# Continue - base64 is still available
|
||||
```
|
||||
|
||||
### For Video Generation
|
||||
|
||||
```python
|
||||
# After successful video generation
|
||||
try:
|
||||
asset_id = save_asset_to_library(
|
||||
db=db,
|
||||
user_id=user_id,
|
||||
asset_type="video",
|
||||
source_module="module_name",
|
||||
filename=video_filename,
|
||||
file_url=video_url,
|
||||
file_path=str(video_path),
|
||||
file_size=file_size,
|
||||
mime_type="video/mp4",
|
||||
title="Video Title",
|
||||
description="Video description",
|
||||
prompt=prompt,
|
||||
tags=["video", "tag"],
|
||||
provider=provider,
|
||||
model=model,
|
||||
cost=cost,
|
||||
metadata={"duration": duration, "status": "completed"}
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Asset tracking failed: {e}", exc_info=True)
|
||||
```
|
||||
|
||||
### For Audio Generation
|
||||
|
||||
```python
|
||||
# After successful audio generation
|
||||
try:
|
||||
asset_id = save_asset_to_library(
|
||||
db=db,
|
||||
user_id=user_id,
|
||||
asset_type="audio",
|
||||
source_module="module_name",
|
||||
filename=audio_filename,
|
||||
file_url=audio_url,
|
||||
file_path=str(audio_path),
|
||||
file_size=file_size,
|
||||
mime_type="audio/mpeg",
|
||||
title="Audio Title",
|
||||
description="Audio description",
|
||||
prompt=text,
|
||||
tags=["audio", "tag"],
|
||||
provider=provider,
|
||||
model=model,
|
||||
cost=cost,
|
||||
metadata={"status": "completed"}
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"Asset tracking failed: {e}", exc_info=True)
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### 1. Error Handling
|
||||
- **Always non-blocking**: Asset tracking failures should never break the main request
|
||||
- **Log errors**: Use `logger.error()` with `exc_info=True` for debugging
|
||||
- **Graceful degradation**: Continue with base64/file response even if tracking fails
|
||||
|
||||
### 2. File Management
|
||||
- **Use `save_file_safely()`**: Handles validation, atomic writes, directory creation
|
||||
- **Sanitize filenames**: Use `sanitize_filename()` to prevent path traversal
|
||||
- **Unique filenames**: Use `generate_unique_filename()` with UUIDs
|
||||
- **File size limits**: Enforce reasonable limits (50MB for images, 100MB for videos)
|
||||
|
||||
### 3. Database Sessions
|
||||
- **Pass session explicitly**: Use `db: Session = Depends(get_db)` in endpoints
|
||||
- **Handle session lifecycle**: Let FastAPI manage session cleanup
|
||||
- **Background tasks**: Get new session in background tasks
|
||||
|
||||
### 4. Metadata
|
||||
- **Rich metadata**: Include provider, model, dimensions, cost, status
|
||||
- **Searchable tags**: Use consistent tag naming (e.g., "image_studio", "generated")
|
||||
- **Status tracking**: Always include `"status": "completed"` in metadata
|
||||
|
||||
### 5. File URLs
|
||||
- **Consistent patterns**: Use `/api/{module}/images/{filename}` format
|
||||
- **Serving endpoints**: Create corresponding GET endpoints to serve files
|
||||
- **Authentication**: Protect file serving endpoints with `get_current_user`
|
||||
|
||||
## File Storage Utilities
|
||||
|
||||
### `save_file_safely()`
|
||||
- Validates file size
|
||||
- Creates directories automatically
|
||||
- Atomic writes (temp file + rename)
|
||||
- Returns `(file_path, error_message)` tuple
|
||||
|
||||
### `sanitize_filename()`
|
||||
- Removes dangerous characters
|
||||
- Prevents path traversal
|
||||
- Limits filename length
|
||||
- Handles empty filenames
|
||||
|
||||
### `generate_unique_filename()`
|
||||
- Creates unique filenames with UUIDs
|
||||
- Sanitizes prefix
|
||||
- Handles extensions properly
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
- [ ] Images are saved to disk correctly
|
||||
- [ ] Files are accessible via serving endpoints
|
||||
- [ ] Asset tracking works (check database)
|
||||
- [ ] Errors don't break main requests
|
||||
- [ ] File size limits are enforced
|
||||
- [ ] Filenames are sanitized properly
|
||||
- [ ] Metadata is complete and accurate
|
||||
- [ ] Asset Library UI displays assets correctly
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
1. **Text Content Tracking**: Save text content as files when needed
|
||||
2. **Batch Operations**: Track multiple assets in single transaction
|
||||
3. **File Cleanup**: Automatic cleanup of orphaned files
|
||||
4. **Storage Backends**: Support S3, GCS for production
|
||||
5. **Thumbnail Generation**: Auto-generate thumbnails for videos/images
|
||||
6. **Compression**: Compress large files before storage
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Assets not appearing in library
|
||||
1. Check database: `SELECT * FROM content_assets WHERE user_id = '...'`
|
||||
2. Check logs for asset tracking errors
|
||||
3. Verify `save_asset_to_library()` returns asset ID
|
||||
4. Check file URLs are correct
|
||||
|
||||
### File serving fails
|
||||
1. Verify file exists on disk
|
||||
2. Check serving endpoint is registered
|
||||
3. Verify authentication is working
|
||||
4. Check file permissions
|
||||
|
||||
### Performance issues
|
||||
1. Use background tasks for heavy operations
|
||||
2. Batch database operations
|
||||
3. Consider async file I/O for large files
|
||||
4. Monitor database query performance
|
||||
|
||||
Reference in New Issue
Block a user