diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..69f2b07c96be70d58cbe275096ba5fff3192e775 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,54 @@ +# Environments +venv/ +.venv/ +env/ +.env + +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg + +# Data & Models (not baked into image — loaded at runtime) +model_cache/ +tests/ +.ipynb_checkpoints/ + +# Version Control +.git/ +.github/ +.gitignore + +# IDEs +.vscode/ +.idea/ + +# OS files +.DS_Store +Thumbs.db + +# HF Spaces — README is required at repo root, not in image +# README.md is NOT excluded so HF can read the frontmatter + + +model_cache/ +__pycache__/ +*.pyc +.env \ No newline at end of file diff --git a/.env b/.env new file mode 100644 index 0000000000000000000000000000000000000000..734a3ee2fd8779b3999cddc5044cc1003c12fd59 --- /dev/null +++ b/.env @@ -0,0 +1,47 @@ +# Server +HOST=0.0.0.0 +PORT=8000 +ENV=development +LOG_LEVEL=INFO + +# JWT Authentication +JWT_ACCESS_SECRET=hubble-access-secret-change-in-production-32chars +JWT_REFRESH_SECRET=hubble-refresh-secret-change-in-production-32chars +JWT_ACCESS_EXPIRES_MINUTES=15 +JWT_REFRESH_EXPIRES_DAYS=7 + +# Security +BCRYPT_ROUNDS=12 +CORS_ORIGINS=http://localhost:3000,http://localhost:3001 + +# MongoDB (Atlas Cloud) +MONGODB_URI=mongodb+srv://sajithjaganathan7_db_user:Winter_bear_07@cluster0.jxdvukx.mongodb.net/hubble?appName=Cluster0 +MONGODB_DB_NAME=hubble + +# Redis (Redis Cloud) +REDIS_URL=redis://default:dongH74t41QfBN0TO0e5ylWAVThXZoLR@redis-13470.crce281.ap-south-1-3.ec2.cloud.redislabs.com:13470 +REDIS_CACHE_TTL=300 + +# Gemini API Keys (User should provide real keys for this) +GEMINI_API_KEYS=AIzaSyBL6onsP6Z-wG32nFgy8Bi7uGDGIopbRDE +GEMINI_MODEL=gemini-2.5-flash + +# LangSmith Tracing +LANGSMITH_API_KEY=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 +LANGSMITH_PROJECT=hubble-moderation +LANGSMITH_TRACING_V2=true + +# Model Configuration +MODEL_CACHE_DIR=./model_cache +ONNX_ENABLED=false +TEXT_MODEL_NAME=unitary/toxic-bert +IMAGE_MODEL_NAME=google/efficientnet-b0 +CLIP_MODEL_NAME=openai/clip-vit-base-patch32 + +# Risk Thresholds +RISK_LOW_MAX=30 +RISK_MEDIUM_MAX=65 + +# Video Processing +VIDEO_MAX_FRAMES=10 +VIDEO_FPS_SAMPLE=1 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000000000000000000000000000000000000..55841f6b9bc852ad214a4d79e0106db877cdba67 --- /dev/null +++ b/.env.example @@ -0,0 +1,48 @@ +# ============================================ +# Hubble AI Engine - Environment Configuration +# ============================================ +# On Hugging Face Spaces, set these as Secrets +# in the Space settings (Settings > Secrets). +# They are injected as environment variables at runtime. + +# Server +HOST=0.0.0.0 +PORT=7860 +ENV=production +LOG_LEVEL=INFO + +# MongoDB (async via motor) +MONGODB_URI=mongodb+srv://:@.mongodb.net/hubble +MONGODB_DB_NAME=hubble + +# Redis +REDIS_URL=redis://default:@: +REDIS_CACHE_TTL=300 + +# Gemini API Keys (comma-separated for rotation) +GEMINI_API_KEYS=your-key-1,your-key-2,your-key-3 +GEMINI_MODEL=gemini-2.5-flash + +# LangSmith Observability (optional) +LANGSMITH_API_KEY=your-langsmith-api-key +LANGSMITH_PROJECT=hubble-moderation +LANGSMITH_TRACING_V2=true + +# JWT Secrets (use long random strings) +JWT_ACCESS_SECRET=your-access-secret-at-least-32-chars +JWT_REFRESH_SECRET=your-refresh-secret-at-least-32-chars + +# Model Configuration +MODEL_CACHE_DIR=/tmp/model_cache +ONNX_ENABLED=false +TEXT_MODEL_NAME=unitary/toxic-bert +IMAGE_MODEL_NAME=google/efficientnet-b0 +CLIP_MODEL_NAME=openai/clip-vit-base-patch32 + +# Risk Thresholds +RISK_LOW_MAX=30 +RISK_MEDIUM_MAX=65 + +# Video Processing +VIDEO_MAX_FRAMES=10 +VIDEO_FPS_SAMPLE=1 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000000000000000000000000000000000..7e971af47b1c01a8a18d62a3c55a4e20c71aabfc --- /dev/null +++ b/.gitattributes @@ -0,0 +1,36 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ckpt filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.mlmodel filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.npy filter=lfs diff=lfs merge=lfs -text +*.npz filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pickle filter=lfs diff=lfs merge=lfs -text +*.pkl filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +*.safetensors filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tar filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.wasm filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text +*.onnx.data filter=lfs diff=lfs merge=lfs -text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..9216e331b17b13585480c27b13efd6a78aac67a9 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,34 @@ +# Hugging Face Spaces — Hubble AI Engine +FROM python:3.12-slim + +# HF Spaces requires port 7860 +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 +ENV HOST=0.0.0.0 +ENV PORT=7860 + +WORKDIR /app + +# System dependencies for OpenCV and native builds +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + libgl1 \ + libglib2.0-0 \ + && rm -rf /var/lib/apt/lists/* + +# Install Python dependencies +COPY requirements.txt . +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir torch torchvision --index-url https://download.pytorch.org/whl/cpu && \ + pip install --no-cache-dir -r requirements.txt --extra-index-url https://download.pytorch.org/whl/cpu + +COPY . . + +# HF Spaces runs containers as a non-root user (UID 1000) +RUN useradd -m -u 1000 user +RUN mkdir -p /tmp/model_cache && chown -R user:user /tmp/model_cache && chown -R user:user /app +USER user + +EXPOSE 7860 + +CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860"] diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5e13972c031c158114dddd9523a30f6a9cb46e6d --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +--- +title: SentinelAI +emoji: 📈 +colorFrom: green +colorTo: blue +sdk: docker +pinned: false +license: mit +--- + +Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..95e89c22246d659d2689cefe05d5e85e7291cda4 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,2 @@ +# app/__init__.py +"""Hubble AI Engine — Production-grade cyberbullying detection pipeline.""" diff --git a/app/api/__init__.py b/app/api/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..267ebfd2794d5c4cb6732667656357d7d40fbb0f --- /dev/null +++ b/app/api/__init__.py @@ -0,0 +1,2 @@ +# app/api/__init__.py +"""API layer: routes, schemas, and versioning.""" diff --git a/app/api/router.py b/app/api/router.py new file mode 100644 index 0000000000000000000000000000000000000000..bbc78fe97ae5dd47f795e3bcc07dcc7626866f1e --- /dev/null +++ b/app/api/router.py @@ -0,0 +1,27 @@ +# app/api/router.py +# Root router — aggregates all versioned API routes + +from fastapi import APIRouter +from app.api.v1.health import router as health_router +from app.api.v1.analyze import router as analyze_router +from app.api.v1.history import router as history_router +from app.api.v1.auth import router as auth_router +from app.api.v1.users import router as users_router +from app.api.v1.scan import router as scan_router +from app.api.v1.alerts import router as alerts_router + +# Main API router +api_router = APIRouter() + +# ── Unauthenticated: health + raw AI pipeline ── +api_router.include_router(health_router, prefix="") +api_router.include_router(analyze_router, prefix="/api/v1") +api_router.include_router(history_router, prefix="/api/v1") + +# ── Auth ── +api_router.include_router(auth_router, prefix="/api/v1") + +# ── Authenticated business logic ── +api_router.include_router(users_router, prefix="/api/v1") +api_router.include_router(scan_router, prefix="/api/v1") +api_router.include_router(alerts_router, prefix="/api/v1") diff --git a/app/api/schemas/__init__.py b/app/api/schemas/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c0f27466760d03da5d18abc44b85160e7bd388e5 --- /dev/null +++ b/app/api/schemas/__init__.py @@ -0,0 +1,2 @@ +# app/api/schemas/__init__.py +"""Pydantic request/response schemas.""" diff --git a/app/api/schemas/requests.py b/app/api/schemas/requests.py new file mode 100644 index 0000000000000000000000000000000000000000..b603fb07febbd09bd8c9548819c49cdf6854f32a --- /dev/null +++ b/app/api/schemas/requests.py @@ -0,0 +1,43 @@ +# app/api/schemas/requests.py +# Pydantic request models for API endpoints + +from pydantic import BaseModel, Field +from typing import Optional + + +class TextAnalysisRequest(BaseModel): + """Request body for text analysis.""" + text: str = Field(..., min_length=1, max_length=10000, description="Text content to analyze") + user_id: Optional[str] = Field(None, description="Optional user ID for history tracking") + source_app: Optional[str] = Field(None, description="Source application (e.g., 'instagram', 'whatsapp')") + metadata: Optional[dict] = Field(None, description="Additional metadata") + + model_config = { + "json_schema_extra": { + "examples": [ + { + "text": "You are so ugly nobody likes you", + "user_id": "user_123", + "source_app": "instagram", + } + ] + } + } + + +class ImageAnalysisRequest(BaseModel): + """Metadata for image analysis (file sent as multipart).""" + user_id: Optional[str] = Field(None, description="Optional user ID for history tracking") + source_app: Optional[str] = Field(None, description="Source application") + + +class VideoAnalysisRequest(BaseModel): + """Metadata for video analysis (file sent as multipart).""" + user_id: Optional[str] = Field(None, description="Optional user ID for history tracking") + source_app: Optional[str] = Field(None, description="Source application") + + +class HistoryRequest(BaseModel): + """Parameters for history queries.""" + limit: int = Field(20, ge=1, le=100, description="Maximum results to return") + skip: int = Field(0, ge=0, description="Number of results to skip") diff --git a/app/api/schemas/responses.py b/app/api/schemas/responses.py new file mode 100644 index 0000000000000000000000000000000000000000..898bca8741a4218eb7e071e69ba625f2171d28f0 --- /dev/null +++ b/app/api/schemas/responses.py @@ -0,0 +1,136 @@ +# app/api/schemas/responses.py +# Pydantic response models for API endpoints + +from pydantic import BaseModel, Field +from typing import Optional, Literal, Any +from datetime import datetime + + +class DecisionDetail(BaseModel): + """Details of the moderation decision.""" + action: Literal["ALLOWED", "WARNING", "BLOCKED"] + reason: str + severity: str + should_alert_parent: bool = False + escalation_notes: Optional[str] = None + + +class DeepAnalysisDetail(BaseModel): + """Details from the deep analysis stage (only present for HIGH risk).""" + is_confirmed: bool + severity: str + reasoning: str + categories: list[str] = [] + recommended_action: str + confidence: float + clip_scores: dict = {} + + +class RiskDetail(BaseModel): + """Breakdown of risk scoring.""" + score: float + level: Literal["LOW", "MEDIUM", "HIGH"] + components: dict = {} + repeat_offender: bool = False + + +class FilterDetail(BaseModel): + """Fast filter stage output.""" + is_flagged: bool + scores: dict[str, float] = {} + max_score: float + max_label: str + categories: list[str] = [] + + +class AnalysisResponse(BaseModel): + """ + Unified response for all /analyze/* endpoints. + + This is the primary contract between the AI engine + and the Node.js backend (and any external consumers). + """ + request_id: str = Field(..., description="Unique request identifier") + input_type: Literal["text", "image", "video"] + status: Literal["ALLOWED", "WARNING", "BLOCKED"] + risk_level: Literal["LOW", "MEDIUM", "HIGH"] + risk_score: float = Field(..., ge=0, le=100, description="Composite risk score 0-100") + categories: list[str] = Field(default_factory=list, description="Detected abuse categories") + confidence: float = Field(..., ge=0, le=1, description="Overall confidence 0-1") + + # Detailed breakdowns + decision: DecisionDetail + risk_detail: RiskDetail + filter_detail: FilterDetail + deep_analysis: Optional[DeepAnalysisDetail] = None + + # Metadata + processing_time_ms: int = Field(..., description="Total processing time in milliseconds") + trace_id: Optional[str] = Field(None, description="LangSmith trace ID for observability") + cached: bool = Field(False, description="Whether this result was served from cache") + + model_config = { + "json_schema_extra": { + "examples": [ + { + "request_id": "req_abc123", + "input_type": "text", + "status": "WARNING", + "risk_level": "MEDIUM", + "risk_score": 45.2, + "categories": ["insult", "toxic"], + "confidence": 0.82, + "decision": { + "action": "WARNING", + "reason": "Content flagged as potentially harmful", + "severity": "medium", + "should_alert_parent": False, + }, + "risk_detail": { + "score": 45.2, + "level": "MEDIUM", + "components": { + "base_score": 42.0, + "multi_category_penalty": 3.2, + "repeat_offender_boost": 0.0, + }, + "repeat_offender": False, + }, + "filter_detail": { + "is_flagged": True, + "scores": {"toxic": 0.78, "insult": 0.65}, + "max_score": 0.78, + "max_label": "toxic", + "categories": ["toxic", "insult"], + }, + "deep_analysis": None, + "processing_time_ms": 156, + "trace_id": None, + "cached": False, + } + ] + } + } + + +class HealthResponse(BaseModel): + """Health check response.""" + status: str + version: str + models: dict[str, bool] + services: dict[str, bool] + uptime_seconds: float + + +class HistoryResponse(BaseModel): + """Moderation history response.""" + user_id: str + total: int + results: list[dict[str, Any]] + + +class ErrorResponse(BaseModel): + """Standard error response.""" + error: str + detail: str + request_id: Optional[str] = None diff --git a/app/api/v1/__init__.py b/app/api/v1/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ebf214282c3a32a48888b941035000250c58671b --- /dev/null +++ b/app/api/v1/__init__.py @@ -0,0 +1,2 @@ +# app/api/v1/__init__.py +"""API v1 endpoints.""" diff --git a/app/api/v1/alerts.py b/app/api/v1/alerts.py new file mode 100644 index 0000000000000000000000000000000000000000..89eb1c24f2580a9bbb83b9f8d26e42fda55ec0a8 --- /dev/null +++ b/app/api/v1/alerts.py @@ -0,0 +1,151 @@ +# app/api/v1/alerts.py +# Alert endpoints for parents and children + +from fastapi import APIRouter, HTTPException, Depends +from pydantic import BaseModel +from typing import Optional +from app.core.dependencies import get_current_user +from app.db.models.user import UserDocument, UserRole +from app.db.models.alert import AlertDocument, AlertStatus +from app.observability.logging import get_logger +from datetime import datetime + +logger = get_logger(__name__) +router = APIRouter(prefix="/alerts", tags=["Alerts"]) + + +@router.get("") +async def list_alerts( + page: int = 1, + limit: int = 20, + status: Optional[str] = None, + severity: Optional[str] = None, + user: UserDocument = Depends(get_current_user), +): + """List alerts. Parents see all their children's alerts; children see their own.""" + skip = (page - 1) * limit + + if user.role == UserRole.PARENT: + query = AlertDocument.find(AlertDocument.parent_id == str(user.id)) + else: + query = AlertDocument.find(AlertDocument.child_id == str(user.id)) + + if status: + query = query.find(AlertDocument.status == AlertStatus(status)) + if severity: + from app.db.models.alert import AlertSeverity + query = query.find(AlertDocument.severity == AlertSeverity(severity)) + + alerts = await query.sort(-AlertDocument.created_at).skip(skip).limit(limit).to_list() + return { + "success": True, + "page": page, + "limit": limit, + "alerts": [_fmt(a) for a in alerts], + } + + +@router.get("/{alert_id}") +async def get_alert( + alert_id: str, + user: UserDocument = Depends(get_current_user), +): + alert = await AlertDocument.get(alert_id) + if not alert: + raise HTTPException(status_code=404, detail="Alert not found") + _check_access(alert, user) + return {"success": True, "alert": _fmt(alert)} + + +class AcknowledgeRequest(BaseModel): + resolution_notes: Optional[str] = None + + +@router.post("/{alert_id}/acknowledge") +async def acknowledge_alert( + alert_id: str, + user: UserDocument = Depends(get_current_user), +): + alert = await AlertDocument.get(alert_id) + if not alert: + raise HTTPException(status_code=404, detail="Alert not found") + _check_access(alert, user) + alert.status = AlertStatus.ACKNOWLEDGED + alert.acknowledged_at = datetime.utcnow() + alert.updated_at = datetime.utcnow() + await alert.save() + return {"success": True, "alert": _fmt(alert)} + + +@router.post("/{alert_id}/resolve") +async def resolve_alert( + alert_id: str, + body: AcknowledgeRequest, + user: UserDocument = Depends(get_current_user), +): + if user.role != UserRole.PARENT: + raise HTTPException(status_code=403, detail="Only parents can resolve alerts") + alert = await AlertDocument.get(alert_id) + if not alert: + raise HTTPException(status_code=404, detail="Alert not found") + if alert.parent_id != str(user.id): + raise HTTPException(status_code=403, detail="Cannot resolve this alert") + alert.status = AlertStatus.RESOLVED + alert.resolved_at = datetime.utcnow() + alert.resolved_by = str(user.id) + alert.resolution_notes = body.resolution_notes + alert.updated_at = datetime.utcnow() + await alert.save() + return {"success": True, "alert": _fmt(alert)} + + +@router.get("/stats/summary") +async def alert_stats(user: UserDocument = Depends(get_current_user)): + if user.role != UserRole.PARENT: + raise HTTPException(status_code=403, detail="Only parents can view stats") + alerts = await AlertDocument.find( + AlertDocument.parent_id == str(user.id) + ).to_list() + + by_severity: dict = {} + by_status: dict = {} + by_category: dict = {} + for a in alerts: + by_severity[a.severity.value] = by_severity.get(a.severity.value, 0) + 1 + by_status[a.status.value] = by_status.get(a.status.value, 0) + 1 + for c in a.categories: + by_category[c] = by_category.get(c, 0) + 1 + + return { + "success": True, + "total": len(alerts), + "by_severity": by_severity, + "by_status": by_status, + "by_category": by_category, + } + + +# ────────────────────────────────────────────── +# Helpers +# ────────────────────────────────────────────── + +def _check_access(alert: AlertDocument, user: UserDocument): + if alert.parent_id != str(user.id) and alert.child_id != str(user.id): + raise HTTPException(status_code=403, detail="Cannot access this alert") + + +def _fmt(a: AlertDocument) -> dict: + return { + "id": str(a.id), + "child_id": a.child_id, + "parent_id": a.parent_id, + "title": a.title, + "message": a.message, + "guidance": a.guidance, + "severity": a.severity.value, + "categories": a.categories, + "status": a.status.value, + "created_at": a.created_at.isoformat(), + "acknowledged_at": a.acknowledged_at.isoformat() if a.acknowledged_at else None, + "resolved_at": a.resolved_at.isoformat() if a.resolved_at else None, + } diff --git a/app/api/v1/analyze.py b/app/api/v1/analyze.py new file mode 100644 index 0000000000000000000000000000000000000000..5f03e8314bdb99176647af9e632b2c0653b40253 --- /dev/null +++ b/app/api/v1/analyze.py @@ -0,0 +1,330 @@ +# app/api/v1/analyze.py +# Core analysis endpoints — text, image, video + +import time +import uuid +from dataclasses import asdict +from fastapi import APIRouter, UploadFile, File, Form, HTTPException + +from app.api.schemas.requests import TextAnalysisRequest +from app.api.schemas.responses import ( + AnalysisResponse, + DecisionDetail, + RiskDetail, + FilterDetail, + DeepAnalysisDetail, + ErrorResponse, +) +from app.services.mongo_service import mongo_service +from app.services.redis_service import redis_service +from app.pipeline.workflow import get_workflow, PipelineState +from app.observability.logging import get_logger +from app.config import get_settings + +logger = get_logger(__name__) +settings = get_settings() + +router = APIRouter(tags=["Analysis"]) + + +# ────────────────────────────────────────────── +# Helper: Convert pipeline state to API response +# ────────────────────────────────────────────── + +def _build_response( + state: dict, + input_type: str, + request_id: str, + start_time: float, + cached: bool = False, +) -> AnalysisResponse: + """Convert pipeline output state into the unified AnalysisResponse.""" + + risk = state.get("risk_score") + decision = state.get("decision") + filter_result = state.get("filter_result") + deep_result = state.get("deep_result") + + # Build nested models + decision_detail = DecisionDetail( + action=decision.action if decision else "WARNING", + reason=decision.reason if decision else "Pipeline incomplete", + severity=decision.severity if decision else "medium", + should_alert_parent=decision.should_alert_parent if decision else False, + escalation_notes=decision.escalation_notes if decision else None, + ) + + risk_detail = RiskDetail( + score=risk.score if risk else 0.0, + level=risk.level if risk else "LOW", + components=risk.components if risk else {}, + repeat_offender=risk.repeat_offender if risk else False, + ) + + filter_detail = FilterDetail( + is_flagged=filter_result.is_flagged if filter_result else False, + scores=filter_result.scores if filter_result else {}, + max_score=filter_result.max_score if filter_result else 0.0, + max_label=filter_result.max_label if filter_result else "", + categories=filter_result.categories if filter_result else [], + ) + + deep_analysis = None + if deep_result: + deep_analysis = DeepAnalysisDetail( + is_confirmed=deep_result.is_confirmed, + severity=deep_result.severity, + reasoning=deep_result.reasoning, + categories=deep_result.categories, + recommended_action=deep_result.recommended_action, + confidence=deep_result.confidence, + clip_scores=deep_result.clip_scores, + ) + + processing_time = int((time.time() - start_time) * 1000) + + return AnalysisResponse( + request_id=request_id, + input_type=input_type, + status=decision_detail.action, + risk_level=risk_detail.level, + risk_score=risk_detail.score, + categories=filter_detail.categories, + confidence=filter_detail.max_score, + decision=decision_detail, + risk_detail=risk_detail, + filter_detail=filter_detail, + deep_analysis=deep_analysis, + processing_time_ms=processing_time, + trace_id=None, # TODO: capture from LangSmith + cached=cached, + ) + + +# ────────────────────────────────────────────── +# POST /analyze/text +# ────────────────────────────────────────────── + +@router.post( + "/analyze/text", + response_model=AnalysisResponse, + responses={400: {"model": ErrorResponse}, 503: {"model": ErrorResponse}}, + summary="Analyze text content for cyberbullying", +) +async def analyze_text(request: TextAnalysisRequest): + """ + Full moderation pipeline for text content. + + Pipeline: Preprocess → RoBERTa Filter → Risk Score → [Deep Analysis] → Decision + """ + request_id = f"req_{uuid.uuid4().hex[:12]}" + start_time = time.time() + + logger.info("analyze_text_started", request_id=request_id, text_length=len(request.text)) + + # Validate text length + if len(request.text) > settings.max_text_length: + raise HTTPException(status_code=400, detail=f"Text too long (max {settings.max_text_length} chars)") + + # Check cache + cached_result = await redis_service.get_cached_result(request.text, "text") + if cached_result: + logger.info("analyze_text_cached", request_id=request_id) + cached_result["request_id"] = request_id + cached_result["cached"] = True + cached_result["processing_time_ms"] = int((time.time() - start_time) * 1000) + return AnalysisResponse(**cached_result) + + # Run pipeline + try: + workflow = get_workflow() + initial_state: PipelineState = { + "input_type": "text", + "raw_content": request.text, + "user_id": request.user_id, + } + + result_state = await workflow.ainvoke(initial_state) + + # Check for pipeline errors + if result_state.get("error"): + raise HTTPException(status_code=500, detail=result_state["error"]) + + response = _build_response(result_state, "text", request_id, start_time) + + # Cache the result + await redis_service.cache_result( + request.text, "text", response.model_dump() + ) + + # Log to MongoDB + await _log_moderation(request_id, "text", request.user_id, response) + + return response + + except HTTPException: + raise + except Exception as e: + logger.error("analyze_text_failed", request_id=request_id, error=str(e)) + raise HTTPException(status_code=500, detail=f"Analysis failed: {str(e)}") + + +# ────────────────────────────────────────────── +# POST /analyze/image +# ────────────────────────────────────────────── + +@router.post( + "/analyze/image", + response_model=AnalysisResponse, + responses={400: {"model": ErrorResponse}, 503: {"model": ErrorResponse}}, + summary="Analyze image content for harmful material", +) +async def analyze_image( + file: UploadFile = File(..., description="Image file to analyze"), + user_id: str | None = Form(None, description="Optional user ID"), + source_app: str | None = Form(None, description="Source application"), +): + """ + Full moderation pipeline for image content. + + Pipeline: Preprocess → EfficientNet Filter → Risk Score → [CLIP + Gemini] → Decision + """ + request_id = f"req_{uuid.uuid4().hex[:12]}" + start_time = time.time() + + # Validate file type + if not file.content_type or not file.content_type.startswith("image/"): + raise HTTPException(status_code=400, detail="File must be an image (JPEG, PNG, etc.)") + + logger.info("analyze_image_started", request_id=request_id, filename=file.filename) + + # Validate file size + if file.size and file.size > settings.max_image_size: + raise HTTPException(status_code=400, detail=f"Image too large (max {settings.max_image_size / 1024 / 1024}MB)") + + try: + image_bytes = await file.read() + + workflow = get_workflow() + initial_state: PipelineState = { + "input_type": "image", + "raw_content": image_bytes, + "user_id": user_id, + } + + result_state = await workflow.ainvoke(initial_state) + + if result_state.get("error"): + raise HTTPException(status_code=500, detail=result_state["error"]) + + response = _build_response(result_state, "image", request_id, start_time) + + # Log to MongoDB + await _log_moderation(request_id, "image", user_id, response) + + return response + + except HTTPException: + raise + except Exception as e: + logger.error("analyze_image_failed", request_id=request_id, error=str(e)) + raise HTTPException(status_code=500, detail=f"Image analysis failed: {str(e)}") + + +# ────────────────────────────────────────────── +# POST /analyze/video +# ────────────────────────────────────────────── + +@router.post( + "/analyze/video", + response_model=AnalysisResponse, + responses={400: {"model": ErrorResponse}, 503: {"model": ErrorResponse}}, + summary="Analyze video content for harmful material", +) +async def analyze_video( + file: UploadFile = File(..., description="Video file to analyze"), + user_id: str | None = Form(None, description="Optional user ID"), + source_app: str | None = Form(None, description="Source application"), +): + """ + Full moderation pipeline for video content. + + Pipeline: Extract frames → Per-frame EfficientNet → Aggregate risk → [Deep Analysis] → Decision + """ + request_id = f"req_{uuid.uuid4().hex[:12]}" + start_time = time.time() + + # Validate file type + if not file.content_type or not file.content_type.startswith("video/"): + raise HTTPException(status_code=400, detail="File must be a video (MP4, AVI, etc.)") + + logger.info("analyze_video_started", request_id=request_id, filename=file.filename) + + # Validate file size + if file.size and file.size > settings.max_video_size: + raise HTTPException(status_code=400, detail=f"Video too large (max {settings.max_video_size / 1024 / 1024}MB)") + + try: + video_bytes = await file.read() + + workflow = get_workflow() + initial_state: PipelineState = { + "input_type": "video", + "raw_content": video_bytes, + "user_id": user_id, + } + + result_state = await workflow.ainvoke(initial_state) + + if result_state.get("error"): + raise HTTPException(status_code=500, detail=result_state["error"]) + + response = _build_response(result_state, "video", request_id, start_time) + + # Log to MongoDB + await _log_moderation(request_id, "video", user_id, response) + + return response + + except HTTPException: + raise + except Exception as e: + logger.error("analyze_video_failed", request_id=request_id, error=str(e)) + raise HTTPException(status_code=500, detail=f"Video analysis failed: {str(e)}") + + +# ────────────────────────────────────────────── +# Helper: Log moderation result to MongoDB +# ────────────────────────────────────────────── + +async def _log_moderation( + request_id: str, + input_type: str, + user_id: str | None, + response: AnalysisResponse, +) -> None: + """Log the moderation result and update user history.""" + try: + log_entry = { + "request_id": request_id, + "input_type": input_type, + "user_id": user_id, + "status": response.status, + "risk_level": response.risk_level, + "risk_score": response.risk_score, + "categories": response.categories, + "processing_time_ms": response.processing_time_ms, + } + await mongo_service.log_moderation(log_entry) + + # Update user history + if user_id: + await mongo_service.update_user_history(user_id, { + "risk_level": response.risk_level, + "categories": response.categories, + }) + # Invalidate cached history + await redis_service.invalidate_user_history(user_id) + + except Exception as e: + logger.warning("moderation_logging_failed", error=str(e)) diff --git a/app/api/v1/auth.py b/app/api/v1/auth.py new file mode 100644 index 0000000000000000000000000000000000000000..377c06f1f9cb2036b1b545d0db599257cad4de34 --- /dev/null +++ b/app/api/v1/auth.py @@ -0,0 +1,217 @@ +# app/api/v1/auth.py +# Auth endpoints: register (parent), create-child, login, refresh, logout + +from datetime import datetime +from fastapi import APIRouter, HTTPException, status, Depends +from pydantic import BaseModel, EmailStr, field_validator +from app.db.models.user import UserDocument, UserRole +from app.core.security import hash_password, verify_password, create_access_token, create_refresh_token, decode_refresh_token +from app.core.dependencies import get_current_user +from app.observability.logging import get_logger + +logger = get_logger(__name__) +router = APIRouter(prefix="/auth", tags=["Auth"]) + + +# ────────────────────────────────────────────── +# Request / Response Schemas +# ────────────────────────────────────────────── + +class RegisterParentRequest(BaseModel): + email: EmailStr + username: str + password: str + first_name: str + last_name: str + phone: str | None = None + consent_given: bool = True + + @field_validator("username") + @classmethod + def username_length(cls, v: str) -> str: + if len(v) < 3 or len(v) > 30: + raise ValueError("Username must be 3–30 characters") + return v.strip() + + @field_validator("password") + @classmethod + def password_length(cls, v: str) -> str: + if len(v) < 8: + raise ValueError("Password must be at least 8 characters") + return v + + +class CreateChildRequest(BaseModel): + username: str + password: str + first_name: str + last_name: str + + +class LoginRequest(BaseModel): + login: str # email or username + password: str + + +class RefreshRequest(BaseModel): + refresh_token: str + + +class TokenResponse(BaseModel): + access_token: str + refresh_token: str + token_type: str = "bearer" + expires_in: int # seconds + + +def _token_response(user: UserDocument) -> dict: + access = create_access_token(str(user.id), user.role.value) + refresh = create_refresh_token(str(user.id), user.role.value) + return { + "access_token": access, + "refresh_token": refresh, + "token_type": "bearer", + "expires_in": 15 * 60, + "user": user.to_public(), + } + + +# ────────────────────────────────────────────── +# Endpoints +# ────────────────────────────────────────────── + +@router.post("/register", status_code=status.HTTP_201_CREATED) +async def register_parent(body: RegisterParentRequest): + """Register a new parent account.""" + # Email uniqueness + existing = await UserDocument.find_one(UserDocument.email == body.email) + if existing: + raise HTTPException(status_code=409, detail="Email already registered") + + # Username uniqueness + existing_u = await UserDocument.find_one(UserDocument.username == body.username) + if existing_u: + raise HTTPException(status_code=409, detail="Username already taken") + + user = UserDocument( + email=body.email, + username=body.username, + password_hash=hash_password(body.password), + role=UserRole.PARENT, + first_name=body.first_name, + last_name=body.last_name, + phone=body.phone, + consent_given=body.consent_given, + consent_date=datetime.utcnow() if body.consent_given else None, + ) + await user.insert() + + resp = _token_response(user) + # Save refresh token + user.refresh_tokens.append(resp["refresh_token"]) + await user.save() + + logger.info("parent_registered", user_id=str(user.id)) + return {"success": True, **resp} + + +@router.post("/create-child", status_code=status.HTTP_201_CREATED) +async def create_child( + body: CreateChildRequest, + current_user: UserDocument = Depends(get_current_user), +): + """Parent creates a child account linked to their account.""" + if current_user.role != UserRole.PARENT: + raise HTTPException(status_code=403, detail="Only parents can create child accounts") + + existing_u = await UserDocument.find_one(UserDocument.username == body.username) + if existing_u: + raise HTTPException(status_code=409, detail="Username already taken") + + child = UserDocument( + username=body.username, + password_hash=hash_password(body.password), + role=UserRole.CHILD, + first_name=body.first_name, + last_name=body.last_name, + parent_id=str(current_user.id), + parental_consent=True, + consent_given=True, + ) + await child.insert() + + # Link child to parent + current_user.children.append(str(child.id)) + await current_user.save() + + logger.info("child_created", child_id=str(child.id), parent_id=str(current_user.id)) + return {"success": True, "user": child.to_public()} + + +@router.post("/login") +async def login(body: LoginRequest): + """Login with email or username + password.""" + login_val = body.login.strip().lower() + + # Try email first, then username + if "@" in login_val: + user = await UserDocument.find_one(UserDocument.email == login_val) + else: + user = await UserDocument.find_one(UserDocument.username == login_val) + + if not user or not verify_password(body.password, user.password_hash): + raise HTTPException(status_code=401, detail="Invalid credentials") + + if not user.is_active: + raise HTTPException(status_code=403, detail="Account is deactivated") + + resp = _token_response(user) + user.refresh_tokens.append(resp["refresh_token"]) + user.last_login_at = datetime.utcnow() + await user.save() + + logger.info("user_logged_in", user_id=str(user.id)) + return {"success": True, **resp} + + +@router.post("/refresh") +async def refresh_token(body: RefreshRequest): + """Exchange a valid refresh token for a new token pair.""" + payload = decode_refresh_token(body.refresh_token) + if not payload: + raise HTTPException(status_code=401, detail="Invalid or expired refresh token") + + user = await UserDocument.get(payload["sub"]) + if not user or not user.is_active: + raise HTTPException(status_code=401, detail="User not found") + + if body.refresh_token not in user.refresh_tokens: + raise HTTPException(status_code=401, detail="Refresh token revoked") + + # Rotate: remove old, add new + user.refresh_tokens.remove(body.refresh_token) + resp = _token_response(user) + user.refresh_tokens.append(resp["refresh_token"]) + await user.save() + + return {"success": True, **resp} + + +@router.post("/logout") +async def logout( + body: RefreshRequest | None = None, + current_user: UserDocument = Depends(get_current_user), +): + """Revoke refresh token(s). Omit body to logout all devices.""" + if body and body.refresh_token in current_user.refresh_tokens: + current_user.refresh_tokens.remove(body.refresh_token) + else: + current_user.refresh_tokens.clear() + await current_user.save() + return {"success": True, "message": "Logged out"} + + +@router.get("/me") +async def get_me(current_user: UserDocument = Depends(get_current_user)): + """Return current authenticated user's profile.""" + return {"success": True, "user": current_user.to_public()} diff --git a/app/api/v1/health.py b/app/api/v1/health.py new file mode 100644 index 0000000000000000000000000000000000000000..698f461921f2a424cd196f81e2c1eb759b1a51cc --- /dev/null +++ b/app/api/v1/health.py @@ -0,0 +1,51 @@ +# app/api/v1/health.py +# Health check endpoints + +import time +from fastapi import APIRouter +from app.api.schemas.responses import HealthResponse +from app.models.model_registry import model_registry +from app.services.redis_service import redis_service +from app.services.mongo_service import mongo_service +from app.services.gemini_service import gemini_service + +router = APIRouter(tags=["Health"]) + +_startup_time = time.time() + + +@router.get("/health", response_model=HealthResponse) +async def health_check(): + """ + Full health check — reports status of all models and services. + """ + model_status = model_registry.get_status() + all_models_ok = all(model_status.values()) + + service_status = { + "mongodb": mongo_service.is_connected, + "redis": redis_service.is_connected, + "gemini": gemini_service.is_initialized, + } + + overall = "healthy" if all_models_ok else "degraded" + + return HealthResponse( + status=overall, + version="4.0.0", + models=model_status, + services=service_status, + uptime_seconds=round(time.time() - _startup_time, 1), + ) + + +@router.get("/health/models") +async def model_health(): + """Detailed model status.""" + return model_registry.get_status() + + +@router.get("/health/ping") +async def ping(): + """Lightweight liveness probe.""" + return {"status": "ok"} diff --git a/app/api/v1/history.py b/app/api/v1/history.py new file mode 100644 index 0000000000000000000000000000000000000000..923f5f6082dbdb87032b7824d7c57f6a2154c024 --- /dev/null +++ b/app/api/v1/history.py @@ -0,0 +1,68 @@ +# app/api/v1/history.py +# Moderation history endpoints + +from fastapi import APIRouter, HTTPException, Query +from app.api.schemas.responses import HistoryResponse +from app.services.mongo_service import mongo_service +from app.observability.logging import get_logger + +logger = get_logger(__name__) + +router = APIRouter(tags=["History"]) + + +@router.get( + "/history/{user_id}", + response_model=HistoryResponse, + summary="Get moderation history for a user", +) +async def get_user_history( + user_id: str, + limit: int = Query(20, ge=1, le=100, description="Max results"), + skip: int = Query(0, ge=0, description="Results to skip"), +): + """ + Retrieve moderation history for a specific user. + + Returns past moderation decisions with timestamps, + risk scores, and categories. + """ + if not mongo_service.is_connected: + raise HTTPException( + status_code=503, + detail="MongoDB not available — history querying disabled", + ) + + results = await mongo_service.get_moderation_history(user_id, limit=limit, skip=skip) + + return HistoryResponse( + user_id=user_id, + total=len(results), + results=results, + ) + + +@router.get( + "/history/{user_id}/summary", + summary="Get aggregated user stats", +) +async def get_user_summary(user_id: str): + """ + Get aggregated moderation statistics for a user. + + Includes total scans, violations, warnings, and category breakdown. + """ + if not mongo_service.is_connected: + raise HTTPException(status_code=503, detail="MongoDB not available") + + history = await mongo_service.get_user_history(user_id) + if not history: + return { + "user_id": user_id, + "total_scans": 0, + "total_violations": 0, + "total_warnings": 0, + "violation_categories": {}, + } + + return history diff --git a/app/api/v1/scan.py b/app/api/v1/scan.py new file mode 100644 index 0000000000000000000000000000000000000000..93d67a7f0a59b751064a45105dacf678c01cc569 --- /dev/null +++ b/app/api/v1/scan.py @@ -0,0 +1,166 @@ +# app/api/v1/scan.py +# Authenticated scan endpoints — wraps the AI pipeline and persists results + +import time +import uuid +from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Depends +from pydantic import BaseModel +from app.core.dependencies import get_current_user, require_role +from app.db.models.user import UserDocument, UserRole +from app.db.models.scan_result import ScanResultDocument, RiskLevel +from app.db.models.alert import AlertDocument, AlertSeverity, AlertStatus +from app.pipeline.workflow import get_workflow, PipelineState +from app.observability.logging import get_logger + +logger = get_logger(__name__) +router = APIRouter(prefix="/scan", tags=["Scan"]) + +_SEVERITY_MAP = { + "LOW": AlertSeverity.LOW, + "MEDIUM": AlertSeverity.MEDIUM, + "HIGH": AlertSeverity.HIGH, + "CRITICAL": AlertSeverity.CRITICAL, +} + + +async def _run_pipeline_and_persist( + input_type: str, + raw_content, + user: UserDocument, +) -> dict: + """Run the AI pipeline, persist ScanResult and optional Alert, return result dict.""" + start = time.time() + + workflow = get_workflow() + state: PipelineState = { + "input_type": input_type, + "raw_content": raw_content, + "user_id": str(user.id), + } + result = await workflow.ainvoke(state) + + if result.get("error"): + raise HTTPException(status_code=500, detail=result["error"]) + + risk = result.get("risk_score") + decision = result.get("decision") + filter_result = result.get("filter_result") + deep_result = result.get("deep_result") + + risk_level_str = risk.level if risk else "LOW" + risk_score = risk.score if risk else 0.0 + action = decision.action if decision else "ALLOWED" + categories = filter_result.categories if filter_result else [] + is_flagged = filter_result.is_flagged if filter_result else False + reasoning = deep_result.reasoning if deep_result else None + processing_ms = int((time.time() - start) * 1000) + + # Persist ScanResult + scan_doc = ScanResultDocument( + user_id=str(user.id), + input_type=input_type, + content_preview=(raw_content[:200] if isinstance(raw_content, str) else None), + risk_level=RiskLevel(risk_level_str), + risk_score=risk_score, + categories=categories, + is_flagged=is_flagged, + action=action, + reasoning=reasoning, + processing_time_ms=processing_ms, + deep_analysis_used=deep_result is not None, + ) + await scan_doc.insert() + + # Create Alert if child account and content is flagged + if is_flagged and user.role == UserRole.CHILD and user.parent_id: + severity = _SEVERITY_MAP.get(risk_level_str, AlertSeverity.LOW) + alert = AlertDocument( + child_id=str(user.id), + parent_id=user.parent_id, + scan_result_id=str(scan_doc.id), + severity=severity, + categories=categories, + severity_score=risk_score, + ) + alert.generate_content() + await alert.insert() + logger.info("alert_created", alert_id=str(alert.id), child_id=str(user.id)) + + return { + "request_id": f"req_{uuid.uuid4().hex[:12]}", + "input_type": input_type, + "scan_id": str(scan_doc.id), + "status": action, + "risk_level": risk_level_str, + "risk_score": risk_score, + "categories": categories, + "is_flagged": is_flagged, + "reasoning": reasoning, + "processing_time_ms": processing_ms, + } + + +# ────────────────────────────────────────────── +# Endpoints +# ────────────────────────────────────────────── + +class ScanTextRequest(BaseModel): + text: str + + +@router.post("/text") +async def scan_text( + body: ScanTextRequest, + user: UserDocument = Depends(get_current_user), +): + """Scan text content. Requires authentication.""" + if not body.text.strip(): + raise HTTPException(status_code=400, detail="Text cannot be empty") + result = await _run_pipeline_and_persist("text", body.text, user) + return {"success": True, **result} + + +@router.post("/image") +async def scan_image( + file: UploadFile = File(...), + user: UserDocument = Depends(get_current_user), +): + """Scan image content. Requires authentication.""" + if not file.content_type or not file.content_type.startswith("image/"): + raise HTTPException(status_code=400, detail="File must be an image") + + image_bytes = await file.read() + result = await _run_pipeline_and_persist("image", image_bytes, user) + return {"success": True, **result} + + +@router.get("/history") +async def get_scan_history( + page: int = 1, + limit: int = 20, + user: UserDocument = Depends(get_current_user), +): + """Get scan history for the current user.""" + skip = (page - 1) * limit + scans = await ScanResultDocument.find( + ScanResultDocument.user_id == str(user.id) + ).sort(-ScanResultDocument.created_at).skip(skip).limit(limit).to_list() + + return { + "success": True, + "page": page, + "limit": limit, + "results": [ + { + "id": str(s.id), + "input_type": s.input_type, + "risk_level": s.risk_level.value, + "risk_score": s.risk_score, + "action": s.action, + "is_flagged": s.is_flagged, + "categories": s.categories, + "created_at": s.created_at.isoformat(), + } + for s in scans + ], + } diff --git a/app/api/v1/users.py b/app/api/v1/users.py new file mode 100644 index 0000000000000000000000000000000000000000..d7b36553686cdbcdb0345c6cafa74857f47ce19a --- /dev/null +++ b/app/api/v1/users.py @@ -0,0 +1,61 @@ +# app/api/v1/users.py +# User profile and parent-child management endpoints + +from fastapi import APIRouter, HTTPException, Depends +from pydantic import BaseModel +from typing import Optional +from app.core.dependencies import get_current_user +from app.db.models.user import UserDocument, UserRole + +router = APIRouter(prefix="/users", tags=["Users"]) + + +@router.get("/me") +async def get_profile(user: UserDocument = Depends(get_current_user)): + return {"success": True, "user": user.to_public()} + + +class UpdateProfileRequest(BaseModel): + first_name: Optional[str] = None + last_name: Optional[str] = None + phone: Optional[str] = None + + +@router.patch("/me") +async def update_profile( + body: UpdateProfileRequest, + user: UserDocument = Depends(get_current_user), +): + if body.first_name: + user.first_name = body.first_name + if body.last_name: + user.last_name = body.last_name + if body.phone is not None: + user.phone = body.phone + await user.save() + return {"success": True, "user": user.to_public()} + + +@router.get("/children") +async def list_children(user: UserDocument = Depends(get_current_user)): + """Parent: list all linked child accounts.""" + if user.role != UserRole.PARENT: + raise HTTPException(status_code=403, detail="Only parents can list children") + children = await UserDocument.find( + UserDocument.parent_id == str(user.id) + ).to_list() + return {"success": True, "children": [c.to_public() for c in children]} + + +@router.get("/children/{child_id}") +async def get_child( + child_id: str, + user: UserDocument = Depends(get_current_user), +): + """Parent: get a specific child's profile.""" + if user.role != UserRole.PARENT: + raise HTTPException(status_code=403, detail="Only parents can view child profiles") + child = await UserDocument.get(child_id) + if not child or child.parent_id != str(user.id): + raise HTTPException(status_code=404, detail="Child not found") + return {"success": True, "child": child.to_public()} diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000000000000000000000000000000000000..ccca497cc4a4d9e3a9238c56b0665b9d391b6780 --- /dev/null +++ b/app/config.py @@ -0,0 +1,99 @@ +# app/config.py +# Centralized configuration via Pydantic Settings + +from pathlib import Path +from functools import lru_cache +from pydantic_settings import BaseSettings +from pydantic import Field + + +class Settings(BaseSettings): + """Application settings loaded from environment variables.""" + + # --- Server --- + host: str = "0.0.0.0" + port: int = 7860 + env: str = "production" + log_level: str = "INFO" + + # --- JWT --- + jwt_access_secret: str = Field(default="change-me-in-production-at-least-32-chars!!") + jwt_refresh_secret: str = Field(default="change-me-in-production-at-least-32-chars!!") + jwt_access_expires_minutes: int = 15 + jwt_refresh_expires_days: int = 7 + + # --- Security --- + bcrypt_rounds: int = 12 + cors_origins: str = "*" + + # --- MongoDB --- + mongodb_uri: str = Field(default="") + mongodb_db_name: str = "hubble" + + # --- Redis --- + redis_url: str = Field(default="") + redis_cache_ttl: int = 300 # seconds + + # --- Gemini --- + gemini_api_keys: str = "" # comma-separated + gemini_model: str = "gemini-2.5-flash" + + # --- LangSmith --- + langsmith_api_key: str = "" + langsmith_project: str = "hubble-moderation" + langsmith_tracing_v2: bool = True + + # --- Models --- + model_cache_dir: str = "/tmp/model_cache" + onnx_enabled: bool = False + text_model_name: str = "unitary/toxic-bert" + image_model_name: str = "google/efficientnet-b0" + clip_model_name: str = "openai/clip-vit-base-patch32" + + # --- Risk Thresholds --- + risk_low_max: int = 30 + risk_medium_max: int = 65 + + # --- Content Limits --- + max_text_length: int = 10000 + max_image_size: int = 10 * 1024 * 1024 # 10MB + max_video_size: int = 50 * 1024 * 1024 # 50MB + + # --- Video Processing --- + video_max_frames: int = 10 + video_fps_sample: int = 1 + + model_config = { + "env_file": ".env", + "env_file_encoding": "utf-8", + "extra": "ignore", + } + + @property + def gemini_keys_list(self) -> list[str]: + """Parse comma-separated Gemini API keys.""" + if not self.gemini_api_keys: + return [] + return [k.strip() for k in self.gemini_api_keys.split(",") if k.strip()] + + @property + def cors_origins_list(self) -> list[str]: + """Parse comma-separated CORS origins.""" + return [o.strip() for o in self.cors_origins.split(",") if o.strip()] + + @property + def model_cache_path(self) -> Path: + """Resolved path for model cache directory.""" + path = Path(self.model_cache_dir) + path.mkdir(parents=True, exist_ok=True) + return path + + @property + def is_production(self) -> bool: + return self.env == "production" + + +@lru_cache() +def get_settings() -> Settings: + """Cached settings singleton.""" + return Settings() diff --git a/app/core/__init__.py b/app/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..524bd7632bba8dc9722e2e27aa8900eb750bef12 --- /dev/null +++ b/app/core/__init__.py @@ -0,0 +1 @@ +# app/core/__init__.py diff --git a/app/core/dependencies.py b/app/core/dependencies.py new file mode 100644 index 0000000000000000000000000000000000000000..8a91fbb1ad60130f0f2a936bf9b6085009c0e9e8 --- /dev/null +++ b/app/core/dependencies.py @@ -0,0 +1,48 @@ +# app/core/dependencies.py +# FastAPI dependency injection — auth guards, role checks, shared helpers + +from fastapi import Depends, HTTPException, status +from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials +from app.core.security import decode_access_token +from app.db.models.user import UserDocument, UserRole + +_bearer = HTTPBearer(auto_error=False) + + +async def get_current_user( + credentials: HTTPAuthorizationCredentials | None = Depends(_bearer), +) -> UserDocument: + """Extract and validate JWT; return the authenticated UserDocument.""" + if not credentials: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Not authenticated", + headers={"WWW-Authenticate": "Bearer"}, + ) + + payload = decode_access_token(credentials.credentials) + if not payload: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="Invalid or expired token", + ) + + user = await UserDocument.get(payload["sub"]) + if not user or not user.is_active: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail="User not found or deactivated", + ) + return user + + +def require_role(*roles: UserRole): + """Factory that returns a dependency requiring one of the given roles.""" + async def _check(user: UserDocument = Depends(get_current_user)) -> UserDocument: + if user.role not in roles: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=f"Role '{user.role}' is not permitted for this action", + ) + return user + return _check diff --git a/app/core/security.py b/app/core/security.py new file mode 100644 index 0000000000000000000000000000000000000000..e19ebd738f7ad8dbb7b2f78be9fed0e10373065b --- /dev/null +++ b/app/core/security.py @@ -0,0 +1,79 @@ +# app/core/security.py +# Password hashing (argon2-cffi) + JWT creation/verification (python-jose) + +from datetime import datetime, timedelta, timezone +from typing import Optional +from argon2 import PasswordHasher +from argon2.exceptions import VerifyMismatchError, VerificationError, InvalidHashError +from jose import JWTError, jwt +from app.config import get_settings + +settings = get_settings() + +# ────────────────────────────────────────────── +# Password hashing — Argon2id (modern, OWASP recommended) +# ────────────────────────────────────────────── + +_ph = PasswordHasher() + + +def hash_password(plain: str) -> str: + return _ph.hash(plain) + + +def verify_password(plain: str, hashed: str) -> bool: + try: + return _ph.verify(hashed, plain) + except (VerifyMismatchError, VerificationError, InvalidHashError): + return False + + +# ────────────────────────────────────────────── +# JWT — HS256 access + refresh tokens +# ────────────────────────────────────────────── + +ALGORITHM = "HS256" + + +def _create_token(data: dict, secret: str, expires_delta: timedelta) -> str: + payload = data.copy() + payload["exp"] = datetime.now(timezone.utc) + expires_delta + return jwt.encode(payload, secret, algorithm=ALGORITHM) + + +def create_access_token(user_id: str, role: str) -> str: + return _create_token( + {"sub": user_id, "role": role, "type": "access"}, + settings.jwt_access_secret, + timedelta(minutes=settings.jwt_access_expires_minutes), + ) + + +def create_refresh_token(user_id: str, role: str) -> str: + return _create_token( + {"sub": user_id, "role": role, "type": "refresh"}, + settings.jwt_refresh_secret, + timedelta(days=settings.jwt_refresh_expires_days), + ) + + +def decode_access_token(token: str) -> Optional[dict]: + """Returns payload dict or None on failure.""" + try: + payload = jwt.decode(token, settings.jwt_access_secret, algorithms=[ALGORITHM]) + if payload.get("type") != "access": + return None + return payload + except JWTError: + return None + + +def decode_refresh_token(token: str) -> Optional[dict]: + """Returns payload dict or None on failure.""" + try: + payload = jwt.decode(token, settings.jwt_refresh_secret, algorithms=[ALGORITHM]) + if payload.get("type") != "refresh": + return None + return payload + except JWTError: + return None diff --git a/app/db/__init__.py b/app/db/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..81f8a9c3013140f379cf8712d16bd017d4d9a25b --- /dev/null +++ b/app/db/__init__.py @@ -0,0 +1 @@ +# app/db/__init__.py diff --git a/app/db/connection.py b/app/db/connection.py new file mode 100644 index 0000000000000000000000000000000000000000..cc526d3a9e30266d8a9da04fd91dfcb1e631114f --- /dev/null +++ b/app/db/connection.py @@ -0,0 +1,36 @@ +# app/db/connection.py +# Beanie ODM initialization — reuses the existing mongo_service Motor client + +from beanie import init_beanie +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +async def connect_db() -> None: + """Initialize Beanie ODM using the already-connected mongo_service client.""" + from app.services.mongo_service import mongo_service + from app.db.models.user import UserDocument + from app.db.models.scan_result import ScanResultDocument + from app.db.models.alert import AlertDocument + + if not mongo_service._connected or mongo_service.client is None: + logger.error("beanie_init_skipped", reason="mongo_service not connected") + return + + try: + db = mongo_service.client[mongo_service.settings.mongodb_db_name] + await init_beanie( + database=db, + document_models=[UserDocument, ScanResultDocument, AlertDocument], + allow_index_dropping=False, + ) + logger.info("beanie_initialized", db=mongo_service.settings.mongodb_db_name) + except Exception as e: + logger.error("beanie_init_failed", error=str(e)) + raise + + +async def close_db() -> None: + """No-op — Motor client is closed by mongo_service.disconnect().""" + pass diff --git a/app/db/models/__init__.py b/app/db/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..0aa150afe3338d6697100b82625b7583c445d01f --- /dev/null +++ b/app/db/models/__init__.py @@ -0,0 +1,10 @@ +# app/db/models/__init__.py +from app.db.models.user import UserDocument, UserRole +from app.db.models.scan_result import ScanResultDocument, RiskLevel +from app.db.models.alert import AlertDocument, AlertSeverity, AlertStatus + +__all__ = [ + "UserDocument", "UserRole", + "ScanResultDocument", "RiskLevel", + "AlertDocument", "AlertSeverity", "AlertStatus", +] diff --git a/app/db/models/alert.py b/app/db/models/alert.py new file mode 100644 index 0000000000000000000000000000000000000000..9249c4db2c03acce0def0d130d619a77850ad373 --- /dev/null +++ b/app/db/models/alert.py @@ -0,0 +1,75 @@ +# app/db/models/alert.py +# Alert Beanie document + +from __future__ import annotations +from datetime import datetime +from enum import Enum +from typing import Optional +from beanie import Document +from pydantic import Field + + +class AlertSeverity(str, Enum): + LOW = "low" + MEDIUM = "medium" + HIGH = "high" + CRITICAL = "critical" + + +class AlertStatus(str, Enum): + PENDING = "pending" + ACKNOWLEDGED = "acknowledged" + RESOLVED = "resolved" + + +class AlertDocument(Document): + """Parent alert generated when flagged content is detected for a child.""" + + child_id: str + parent_id: str + scan_result_id: str + + title: str + message: str + guidance: str = "" + + severity: AlertSeverity = AlertSeverity.LOW + categories: list[str] = Field(default_factory=list) + severity_score: float = 0.0 + + status: AlertStatus = AlertStatus.PENDING + parent_notified: bool = False + child_notified: bool = False + + acknowledged_at: Optional[datetime] = None + resolved_at: Optional[datetime] = None + resolved_by: Optional[str] = None + resolution_notes: Optional[str] = None + + created_at: datetime = Field(default_factory=datetime.utcnow) + updated_at: datetime = Field(default_factory=datetime.utcnow) + + class Settings: + name = "alerts" + + def generate_content(self) -> None: + """Populate title, message, guidance based on severity and categories.""" + category_text = ", ".join(self.categories) if self.categories else "potentially harmful content" + score = int(self.severity_score * 100) + + if self.severity == AlertSeverity.LOW: + self.title = "Mild Concern Detected" + self.message = f"Content flagged for: {category_text}. Score: {score}/100." + self.guidance = "This content contains some concerning elements. Consider talking about online safety." + elif self.severity == AlertSeverity.MEDIUM: + self.title = "Moderate Concern Detected" + self.message = f"Concerning content detected: {category_text}. Score: {score}/100." + self.guidance = "This content shows signs of potential cyberbullying. We recommend discussing this with your child." + elif self.severity == AlertSeverity.HIGH: + self.title = "⚠️ High Severity Alert" + self.message = f"Serious concern detected: {category_text}. Score: {score}/100." + self.guidance = "Immediate discussion with your child is recommended. Consider reaching out to school counselors." + else: # CRITICAL + self.title = "🚨 CRITICAL ALERT - Immediate Action Required" + self.message = f"Critical content detected: {category_text}. Score: {score}/100." + self.guidance = "If there are threats of violence or self-harm, please contact emergency services immediately." diff --git a/app/db/models/scan_result.py b/app/db/models/scan_result.py new file mode 100644 index 0000000000000000000000000000000000000000..41669033a9965156dee752a971f0fa5bf62cf651 --- /dev/null +++ b/app/db/models/scan_result.py @@ -0,0 +1,43 @@ +# app/db/models/scan_result.py +# ScanResult Beanie document + +from __future__ import annotations +from datetime import datetime +from enum import Enum +from typing import Optional +from beanie import Document +from pydantic import Field + + +class RiskLevel(str, Enum): + LOW = "LOW" + MEDIUM = "MEDIUM" + HIGH = "HIGH" + CRITICAL = "CRITICAL" + + +class ScanResultDocument(Document): + """Persisted result of a content scan through the AI pipeline.""" + + user_id: str + input_type: str # text | image | video + content_preview: Optional[str] = None # first 200 chars of text, or filename + + # Risk + risk_level: RiskLevel = RiskLevel.LOW + risk_score: float = 0.0 + categories: list[str] = Field(default_factory=list) + is_flagged: bool = False + + # Decision + action: str = "ALLOWED" # ALLOWED | WARNED | BLOCKED | ESCALATED + reasoning: Optional[str] = None + + # Pipeline metadata + processing_time_ms: int = 0 + deep_analysis_used: bool = False + + created_at: datetime = Field(default_factory=datetime.utcnow) + + class Settings: + name = "scan_results" diff --git a/app/db/models/user.py b/app/db/models/user.py new file mode 100644 index 0000000000000000000000000000000000000000..560093ba9d621cf5fa87f84d15099c3cd365072f --- /dev/null +++ b/app/db/models/user.py @@ -0,0 +1,74 @@ +# app/db/models/user.py +# Beanie User document — mirrors the Mongoose User model from Backend/ + +from __future__ import annotations +from datetime import datetime +from enum import Enum +from typing import Optional +from beanie import Document, Indexed +from pydantic import EmailStr, Field + + +class UserRole(str, Enum): + PARENT = "parent" + CHILD = "child" + ADMIN = "admin" + + +class UserDocument(Document): + """ + User document stored in MongoDB. + Supports Parent → Child relationship for monitoring. + """ + + email: Optional[EmailStr] = None + username: Indexed(str, unique=True) # type: ignore[valid-type] + password_hash: str # bcrypt hash — never returned in API responses + role: UserRole = UserRole.PARENT + first_name: str + last_name: str + phone: Optional[str] = None + date_of_birth: Optional[datetime] = None + + # Parent-Child relationship + parent_id: Optional[str] = None # set for child accounts + children: list[str] = Field(default_factory=list) # set for parent accounts + + # Consent & Privacy + consent_given: bool = False + consent_date: Optional[datetime] = None + parental_consent: Optional[bool] = None # for child accounts + + # Account status + is_active: bool = True + is_verified: bool = False + last_login_at: Optional[datetime] = None + + # Security — refresh tokens stored for rotation/revocation + refresh_tokens: list[str] = Field(default_factory=list) + password_changed_at: Optional[datetime] = None + + created_at: datetime = Field(default_factory=datetime.utcnow) + updated_at: datetime = Field(default_factory=datetime.utcnow) + + class Settings: + name = "users" + # Atlas already has the correct indexes from the Mongoose model. + # Beanie will use the field-level Indexed() annotations and won't + # try to re-create conflicting ones when allow_index_dropping=False. + + def to_public(self) -> dict: + """Return safe user dict without sensitive fields.""" + return { + "id": str(self.id), + "email": self.email, + "username": self.username, + "role": self.role.value, + "first_name": self.first_name, + "last_name": self.last_name, + "is_active": self.is_active, + "is_verified": self.is_verified, + "parent_id": self.parent_id, + "children": self.children, + "created_at": self.created_at.isoformat(), + } diff --git a/app/dependencies.py b/app/dependencies.py new file mode 100644 index 0000000000000000000000000000000000000000..57684c6ab847812b5a8a98f7315717ffcdb52aa4 --- /dev/null +++ b/app/dependencies.py @@ -0,0 +1,29 @@ +# app/dependencies.py +# FastAPI dependency injection + +from app.models.model_registry import model_registry +from app.services.redis_service import redis_service +from app.services.mongo_service import mongo_service + + +async def require_models(): + """Dependency: ensure models are loaded.""" + status = model_registry.get_status() + if not status.get("text_model") and not status.get("image_model"): + from fastapi import HTTPException + raise HTTPException( + status_code=503, + detail="AI models not loaded. Server is starting up.", + ) + return model_registry + + +async def require_mongo(): + """Dependency: ensure MongoDB is connected.""" + if not mongo_service.is_connected: + from fastapi import HTTPException + raise HTTPException( + status_code=503, + detail="MongoDB not available.", + ) + return mongo_service diff --git a/app/main.py b/app/main.py new file mode 100644 index 0000000000000000000000000000000000000000..ab930417e367faf75e376977a3c50d751fb7b269 --- /dev/null +++ b/app/main.py @@ -0,0 +1,154 @@ +# app/main.py +# FastAPI application factory — entry point for the Hubble AI Engine + +from contextlib import asynccontextmanager +from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse + +from app.config import get_settings +from app.observability.logging import setup_logging, get_logger +from app.observability.langsmith import setup_langsmith +from app.models.model_registry import model_registry +from app.services.redis_service import redis_service +from app.services.mongo_service import mongo_service +from app.services.gemini_service import gemini_service +from app.pipeline.workflow import get_workflow +from app.api.router import api_router +from app.db.connection import connect_db, close_db + + +@asynccontextmanager +async def lifespan(app: FastAPI): + """ + Application lifespan manager. + + Startup: + 1. Configure logging + 2. Setup LangSmith tracing + 3. Connect MongoDB & Redis + 4. Initialize Gemini service + 5. Load all ML models + 6. Compile LangGraph workflow + + Shutdown: + 1. Disconnect MongoDB & Redis + """ + logger = get_logger(__name__) + settings = get_settings() + + # ── Startup ── + logger.info("=" * 60) + logger.info("[STARTUP] HUBBLE AI ENGINE — Starting up...") + logger.info("=" * 60) + + # 1. LangSmith + langsmith_ok = setup_langsmith() + logger.info("langsmith", enabled=langsmith_ok) + + # 2. MongoDB (legacy motor service + Beanie ODM) + logger.info("connecting_mongodb") + await mongo_service.connect() + await connect_db() # initializes Beanie document models + + # 3. Redis + logger.info("connecting_redis") + await redis_service.connect() + + # 4. Gemini + logger.info("initializing_gemini") + gemini_service.initialize() + + # 5. ML Models + logger.info("loading_models") + model_status = await model_registry.load_all() + logger.info("models_loaded", status=model_status) + + # 6. LangGraph Workflow + logger.info("compiling_workflow") + get_workflow() + + logger.info("=" * 60) + logger.info("[READY] HUBBLE AI ENGINE — Ready!") + logger.info(f" Environment: {settings.env}") + logger.info(f" Port: {settings.port}") + logger.info(f" Docs: http://localhost:{settings.port}/docs") + logger.info("=" * 60) + + yield # ── Application runs here ── + + # ── Shutdown ── + logger.info("[SHUTDOWN] HUBBLE — Shutting down...") + await redis_service.disconnect() + await mongo_service.disconnect() + await close_db() + logger.info("Shutdown complete") + + +def create_app() -> FastAPI: + """Create and configure the FastAPI application.""" + settings = get_settings() + + # Configure logging first + setup_logging() + + app = FastAPI( + title="Hubble AI Engine — Cyberbullying Detection API", + description=( + "Production-grade content moderation pipeline with layered AI analysis. " + "Supports text, image, and video inputs with risk-based routing." + ), + version="4.0.0", + docs_url="/docs", + redoc_url="/redoc", + lifespan=lifespan, + ) + + # CORS — use origins from config + app.add_middleware( + CORSMiddleware, + allow_origins=settings.cors_origins_list if settings.is_production else ["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + # Mount routes + app.include_router(api_router) + + @app.get("/", include_in_schema=False) + async def root(): + return JSONResponse({ + "name": "Hubble Unified API", + "version": "5.0.0", + "docs": "/docs", + "health": "/health", + "endpoints": { + "auth": "POST /api/v1/auth/{register|login|refresh|logout}", + "users": "GET /api/v1/users/me", + "scan_text": "POST /api/v1/scan/text", + "scan_image": "POST /api/v1/scan/image", + "scan_history": "GET /api/v1/scan/history", + "alerts": "GET /api/v1/alerts", + "analyze_text": "POST /api/v1/analyze/text (raw, no auth)", + "analyze_image": "POST /api/v1/analyze/image (raw, no auth)", + }, + }) + + return app + + +# Create the app instance +app = create_app() + + +if __name__ == "__main__": + import uvicorn + + settings = get_settings() + uvicorn.run( + "app.main:app", + host=settings.host, + port=settings.port, + reload=not settings.is_production, + ) diff --git a/app/models/__init__.py b/app/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..c88302071dd65ad2827e2a95baf8ea0074b78989 --- /dev/null +++ b/app/models/__init__.py @@ -0,0 +1,2 @@ +# app/models/__init__.py +"""Model loading, ONNX optimization, and inference.""" diff --git a/app/models/clip_model.py b/app/models/clip_model.py new file mode 100644 index 0000000000000000000000000000000000000000..ab1f35f3fc5d84cc685265cde7449fb783b27151 --- /dev/null +++ b/app/models/clip_model.py @@ -0,0 +1,145 @@ +# app/models/clip_model.py +# CLIP model for multimodal text-image alignment (deep analysis only) + +from PIL import Image +import numpy as np +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class CLIPModel: + """ + CLIP (Contrastive Language-Image Pre-Training) model. + + Used in the deep analysis path to compute semantic alignment + between text descriptions and image content. This helps detect + subtle multimodal threats (e.g., threatening text overlaid on images). + """ + + def __init__(self): + self.settings = get_settings() + self.model = None + self.preprocess = None + self.tokenizer = None + self._loaded = False + self.device = None + + def load(self) -> None: + """Load the CLIP model and preprocessor.""" + import torch + try: + import open_clip + + model_name = self.settings.clip_model_name + cache_dir = self.settings.model_cache_path / "clip" + cache_dir.mkdir(parents=True, exist_ok=True) + + self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + + logger.info("loading_clip_model", model=model_name) + + # Use OpenCLIP for flexibility + self.model, _, self.preprocess = open_clip.create_model_and_transforms( + "ViT-B-32", + pretrained="laion2b_s34b_b79k", + ) + self.model = self.model.to(self.device) + self.model.eval() + + self.tokenizer = open_clip.get_tokenizer("ViT-B-32") + + self._loaded = True + logger.info("clip_model_loaded") + + except ImportError: + logger.warning("clip_not_available", reason="open_clip not installed") + self._loaded = False + except Exception as e: + logger.error("clip_load_failed", error=str(e)) + self._loaded = False + + def compute_similarity(self, image: Image.Image, texts: list[str]) -> dict: + """ + Compute cosine similarity between an image and a list of text descriptions. + + Args: + image: PIL Image. + texts: List of text descriptions to compare against. + + Returns: + Dict with similarities, best_match, and best_score. + """ + if not self._loaded: + return {"error": "CLIP model not loaded", "similarities": []} + + import torch + + # Preprocess image + image_input = self.preprocess(image).unsqueeze(0).to(self.device) + + # Tokenize texts + text_tokens = self.tokenizer(texts).to(self.device) + + with torch.no_grad(): + image_features = self.model.encode_image(image_input) + text_features = self.model.encode_text(text_tokens) + + # Normalize + image_features = image_features / image_features.norm(dim=-1, keepdim=True) + text_features = text_features / text_features.norm(dim=-1, keepdim=True) + + # Cosine similarity + similarities = (image_features @ text_features.T).squeeze(0).cpu().numpy() + + sim_list = similarities.tolist() + best_idx = int(np.argmax(sim_list)) + + return { + "similarities": dict(zip(texts, sim_list)), + "best_match": texts[best_idx], + "best_score": sim_list[best_idx], + } + + def align_content(self, image: Image.Image, context_text: str | None = None) -> dict: + """ + Analyze image alignment with harmful content categories. + + Args: + image: Image to analyze. + context_text: Optional surrounding text context. + + Returns: + Dict with category alignment scores. + """ + harmful_descriptions = [ + "a photo containing violence, fighting, or physical harm", + "a photo containing nudity or sexual content", + "a photo containing self-harm or suicide imagery", + "a photo containing hate symbols or extremist content", + "a photo containing drugs or substance abuse", + "a safe and appropriate photo for children", + ] + + result = self.compute_similarity(image, harmful_descriptions) + + if "error" in result: + return result + + # Also check text-image alignment if context provided + text_alignment = None + if context_text: + text_result = self.compute_similarity(image, [context_text, "unrelated content"]) + text_alignment = text_result["similarities"].get(context_text, 0.0) + + return { + "category_scores": result["similarities"], + "most_aligned": result["best_match"], + "alignment_score": result["best_score"], + "text_image_alignment": text_alignment, + } + + @property + def is_loaded(self) -> bool: + return self._loaded diff --git a/app/models/image_model.py b/app/models/image_model.py new file mode 100644 index 0000000000000000000000000000000000000000..e95d5dd0e1a4afb0e373f7c3bbc09eff79ead099 --- /dev/null +++ b/app/models/image_model.py @@ -0,0 +1,180 @@ +# app/models/image_model.py +# EfficientNet-based image classification model with ONNX optimization + +from pathlib import Path +import numpy as np +from PIL import Image +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class ImageClassificationModel: + """ + Image content classifier using EfficientNet. + + Detects violence, NSFW content, and other harmful imagery. + Supports ONNX (fast) and PyTorch (fallback) inference. + """ + + LABELS = ["safe", "violence", "nsfw", "self_harm", "hate_symbol"] + + def __init__(self): + self.settings = get_settings() + self.processor = None + self.onnx_session = None + self.pt_model = None + self.device = None + self._loaded = False + self._num_labels = len(self.LABELS) + + def load(self) -> None: + """Load the image processor and model.""" + from transformers import AutoImageProcessor, AutoModelForImageClassification + + model_name = self.settings.image_model_name + cache_dir = self.settings.model_cache_path / "efficientnet" + onnx_path = cache_dir / "image_classifier.onnx" + + logger.info("loading_image_model", model=model_name) + + # Load image processor + try: + self.processor = AutoImageProcessor.from_pretrained( + model_name, cache_dir=cache_dir + ) + except Exception: + # Fallback: use a generic processor + from transformers import AutoImageProcessor + self.processor = AutoImageProcessor.from_pretrained( + "google/efficientnet-b0", cache_dir=cache_dir + ) + + if self.settings.onnx_enabled and onnx_path.exists(): + from app.models.onnx_utils import load_onnx_session + self.onnx_session = load_onnx_session(onnx_path) + logger.info("image_model_loaded", backend="onnx") + else: + self._load_pytorch(model_name, cache_dir) + if self.settings.onnx_enabled: + try: + self._export_onnx(onnx_path) + from app.models.onnx_utils import load_onnx_session + self.onnx_session = load_onnx_session(onnx_path) + self.pt_model = None + logger.info("image_model_loaded", backend="onnx", note="exported") + except Exception as e: + logger.warning("onnx_export_failed", error=str(e), fallback="pytorch") + else: + logger.info("image_model_loaded", backend="pytorch") + + self._loaded = True + + def _load_pytorch(self, model_name: str, cache_dir: Path) -> None: + """Load PyTorch model.""" + import torch + from transformers import AutoModelForImageClassification + + self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + try: + self.pt_model = AutoModelForImageClassification.from_pretrained( + model_name, cache_dir=cache_dir + ) + except Exception: + # If the model doesn't exist as a pretrained classifier, load base EfficientNet + self.pt_model = AutoModelForImageClassification.from_pretrained( + "google/efficientnet-b0", cache_dir=cache_dir + ) + self.pt_model.to(self.device) + self.pt_model.eval() + + # Update labels from model config if available + if hasattr(self.pt_model.config, "id2label"): + model_labels = list(self.pt_model.config.id2label.values()) + if model_labels: + self._num_labels = len(model_labels) + + def _export_onnx(self, onnx_path: Path) -> None: + """Export to ONNX.""" + import torch + from app.models.onnx_utils import export_to_onnx + + dummy_input = torch.randn(1, 3, 224, 224).to(self.device) + export_to_onnx( + model=self.pt_model, + sample_input={"pixel_values": dummy_input}, + output_path=onnx_path, + input_names=["pixel_values"], + output_names=["logits"], + ) + + def predict(self, image: Image.Image) -> dict: + """ + Classify an image for harmful content. + + Args: + image: PIL Image (RGB). + + Returns: + Dict with labels, scores, is_harmful, max_score, max_label. + """ + if not self._loaded: + raise RuntimeError("Image model not loaded. Call load() first.") + + # Preprocess with the model's processor + inputs = self.processor(images=image, return_tensors="np" if self.onnx_session else "pt") + + if self.onnx_session: + return self._predict_onnx(inputs) + else: + return self._predict_pytorch(inputs) + + def _predict_onnx(self, inputs) -> dict: + """ONNX inference.""" + from app.models.onnx_utils import onnx_inference + + pixel_values = inputs["pixel_values"].astype(np.float32) + outputs = onnx_inference(self.onnx_session, {"pixel_values": pixel_values}) + logits = outputs[0][0] + return self._format_output(logits) + + def _predict_pytorch(self, inputs) -> dict: + """PyTorch inference.""" + import torch + + inputs = {k: v.to(self.device) for k, v in inputs.items()} + with torch.no_grad(): + outputs = self.pt_model(**inputs) + logits = outputs.logits[0].cpu().numpy() + return self._format_output(logits) + + def _format_output(self, logits: np.ndarray) -> dict: + """Convert logits to prediction dict.""" + # Softmax for single-label classification + exp_logits = np.exp(logits - np.max(logits)) + scores = (exp_logits / exp_logits.sum()).tolist() + + # Map to our labels (or use model's own labels) + if self.pt_model and hasattr(self.pt_model.config, "id2label"): + labels = [self.pt_model.config.id2label.get(i, f"class_{i}") for i in range(len(scores))] + else: + labels = [f"class_{i}" for i in range(len(scores))] + + max_idx = int(np.argmax(scores)) + + # Determine if harmful (anything not classified as safe/non-violent) + safe_keywords = {"safe", "non-violence", "non_violence", "normal", "neutral"} + is_harmful = labels[max_idx].lower().replace("-", "_").replace(" ", "_") not in safe_keywords + + return { + "labels": labels, + "scores": scores, + "is_harmful": is_harmful, + "max_score": scores[max_idx], + "max_label": labels[max_idx], + } + + @property + def is_loaded(self) -> bool: + return self._loaded diff --git a/app/models/model_registry.py b/app/models/model_registry.py new file mode 100644 index 0000000000000000000000000000000000000000..34150d474330362c6f5b5bb41b8d5c81db60039c --- /dev/null +++ b/app/models/model_registry.py @@ -0,0 +1,99 @@ +# app/models/model_registry.py +# Singleton model registry — loads and manages all ML models + +from app.models.text_model import TextToxicityModel +from app.models.image_model import ImageClassificationModel +from app.models.clip_model import CLIPModel +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class ModelRegistry: + """ + Central registry for all ML models. + + Provides lazy-loading and lifecycle management. + Models are loaded once and reused across requests. + """ + + def __init__(self): + self._text_model: TextToxicityModel | None = None + self._image_model: ImageClassificationModel | None = None + self._clip_model: CLIPModel | None = None + + async def load_all(self) -> dict[str, bool]: + """ + Load all models. Called during application startup. + + Returns: + Dict of model name → loaded status. + """ + results = {} + + # Text model (required) + logger.info("registry_loading", model="text_toxicity") + try: + self._text_model = TextToxicityModel() + self._text_model.load() + results["text"] = True + except Exception as e: + logger.error("text_model_load_failed", error=str(e)) + results["text"] = False + + # Image model (required) + logger.info("registry_loading", model="image_classifier") + try: + self._image_model = ImageClassificationModel() + self._image_model.load() + results["image"] = True + except Exception as e: + logger.error("image_model_load_failed", error=str(e)) + results["image"] = False + + # CLIP model (optional — only for deep analysis) + logger.info("registry_loading", model="clip") + try: + self._clip_model = CLIPModel() + self._clip_model.load() + results["clip"] = self._clip_model.is_loaded + except Exception as e: + logger.warning("clip_model_load_failed", error=str(e)) + results["clip"] = False + + logger.info("registry_loaded", results=results) + return results + + @property + def text_model(self) -> TextToxicityModel: + if self._text_model is None or not self._text_model.is_loaded: + raise RuntimeError("Text model not available") + return self._text_model + + @property + def image_model(self) -> ImageClassificationModel: + if self._image_model is None or not self._image_model.is_loaded: + raise RuntimeError("Image model not available") + return self._image_model + + @property + def clip_model(self) -> CLIPModel: + if self._clip_model is None: + raise RuntimeError("CLIP model not available") + return self._clip_model + + @property + def clip_available(self) -> bool: + return self._clip_model is not None and self._clip_model.is_loaded + + def get_status(self) -> dict: + """Get health status of all models.""" + return { + "text_model": self._text_model.is_loaded if self._text_model else False, + "image_model": self._image_model.is_loaded if self._image_model else False, + "clip_model": self._clip_model.is_loaded if self._clip_model else False, + } + + +# Global singleton +model_registry = ModelRegistry() diff --git a/app/models/onnx_utils.py b/app/models/onnx_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..a251fa4f62667234ab269b6e9c68106f54fb99b8 --- /dev/null +++ b/app/models/onnx_utils.py @@ -0,0 +1,120 @@ +# app/models/onnx_utils.py +# ONNX export and inference utilities + +from pathlib import Path +import numpy as np +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +def export_to_onnx( + model, + sample_input: dict, + output_path: Path, + input_names: list[str] | None = None, + output_names: list[str] | None = None, + dynamic_axes: dict | None = None, + opset_version: int = 14, +) -> Path: + """ + Export a PyTorch model to ONNX format. + + Args: + model: PyTorch model (eval mode). + sample_input: Dict of tensor inputs for tracing. + output_path: Where to save the .onnx file. + input_names: Names for input tensors. + output_names: Names for output tensors. + dynamic_axes: Dynamic axes specification. + opset_version: ONNX opset version. + + Returns: + Path to the exported ONNX model. + """ + import torch + + output_path = Path(output_path) + output_path.parent.mkdir(parents=True, exist_ok=True) + + if input_names is None: + input_names = list(sample_input.keys()) + if output_names is None: + output_names = ["logits"] + if dynamic_axes is None: + dynamic_axes = {name: {0: "batch_size"} for name in input_names + output_names} + + # Prepare ordered tuple of inputs + input_tuple = tuple(sample_input[name] for name in input_names) + + model.eval() + with torch.no_grad(): + torch.onnx.export( + model, + input_tuple, + str(output_path), + input_names=input_names, + output_names=output_names, + dynamic_axes=dynamic_axes, + opset_version=opset_version, + do_constant_folding=True, + ) + + logger.info("onnx_export_complete", path=str(output_path), size_mb=round(output_path.stat().st_size / 1e6, 1)) + return output_path + + +def load_onnx_session(model_path: Path, providers: list[str] | None = None): + """ + Load an ONNX model as an InferenceSession. + + Args: + model_path: Path to .onnx file. + providers: ONNX Runtime execution providers (defaults to CPU). + + Returns: + ort.InferenceSession instance. + """ + import onnxruntime as ort + + if providers is None: + available = ort.get_available_providers() + # Prefer CUDA if available, else CPU + if "CUDAExecutionProvider" in available: + providers = ["CUDAExecutionProvider", "CPUExecutionProvider"] + else: + providers = ["CPUExecutionProvider"] + + session = ort.InferenceSession(str(model_path), providers=providers) + logger.info( + "onnx_session_loaded", + path=str(model_path), + providers=providers, + ) + return session + + +def onnx_inference(session, inputs: dict[str, np.ndarray]) -> list[np.ndarray]: + """ + Run inference on an ONNX session. + + Args: + session: ONNX InferenceSession. + inputs: Dict mapping input names to numpy arrays. + + Returns: + List of output numpy arrays. + """ + # Ensure proper dtypes + feed = {} + for inp in session.get_inputs(): + if inp.name in inputs: + arr = inputs[inp.name] + # Match expected dtype + if "int" in inp.type: + arr = arr.astype(np.int64) + else: + arr = arr.astype(np.float32) + feed[inp.name] = arr + + return session.run(None, feed) diff --git a/app/models/text_model.py b/app/models/text_model.py new file mode 100644 index 0000000000000000000000000000000000000000..423912860d2660d6723b852b4ebf7827d6fa4bd4 --- /dev/null +++ b/app/models/text_model.py @@ -0,0 +1,178 @@ +# app/models/text_model.py +# RoBERTa-based text toxicity model with ONNX optimization + +from pathlib import Path +import numpy as np +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class TextToxicityModel: + """ + Text toxicity classifier using a RoBERTa-based model. + + Supports both ONNX (fast) and PyTorch (fallback) inference. + Model: unitary/toxic-bert (multi-label toxicity detection). + + Labels: toxic, severe_toxic, obscene, threat, insult, identity_hate + """ + + LABELS = ["toxic", "severe_toxic", "obscene", "threat", "insult", "identity_hate"] + + def __init__(self): + self.settings = get_settings() + self.tokenizer = None + self.onnx_session = None + self.pt_model = None + self.device = None + self._loaded = False + + def load(self) -> None: + """Load the tokenizer and model (ONNX preferred, PyTorch fallback).""" + from transformers import AutoTokenizer + + model_name = self.settings.text_model_name + cache_dir = self.settings.model_cache_path / "roberta" + onnx_path = cache_dir / "text_toxicity.onnx" + + logger.info("loading_text_model", model=model_name) + + # Load tokenizer + self.tokenizer = AutoTokenizer.from_pretrained(model_name, cache_dir=cache_dir) + + if self.settings.onnx_enabled and onnx_path.exists(): + # Use existing ONNX model + from app.models.onnx_utils import load_onnx_session + self.onnx_session = load_onnx_session(onnx_path) + logger.info("text_model_loaded", backend="onnx") + elif self.settings.onnx_enabled: + # Load PyTorch, export to ONNX, then use ONNX + self._load_pytorch(model_name, cache_dir) + self._export_onnx(onnx_path) + # Switch to ONNX session + from app.models.onnx_utils import load_onnx_session + self.onnx_session = load_onnx_session(onnx_path) + self.pt_model = None # Free PyTorch memory + logger.info("text_model_loaded", backend="onnx", note="exported_from_pytorch") + else: + # PyTorch only + self._load_pytorch(model_name, cache_dir) + logger.info("text_model_loaded", backend="pytorch") + + self._loaded = True + + def _load_pytorch(self, model_name: str, cache_dir: Path) -> None: + """Load the PyTorch model.""" + import torch + from transformers import AutoModelForSequenceClassification + + self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + self.pt_model = AutoModelForSequenceClassification.from_pretrained( + model_name, cache_dir=cache_dir + ) + self.pt_model.to(self.device) + self.pt_model.eval() + + def _export_onnx(self, onnx_path: Path) -> None: + """Export current PyTorch model to ONNX.""" + import torch + from app.models.onnx_utils import export_to_onnx + + sample = self.tokenizer( + "test input for export", + return_tensors="pt", + padding="max_length", + truncation=True, + max_length=128, + ) + sample = {k: v.to(self.device) for k, v in sample.items()} + + export_to_onnx( + model=self.pt_model, + sample_input=sample, + output_path=onnx_path, + input_names=["input_ids", "attention_mask"], + output_names=["logits"], + ) + + def predict(self, text: str) -> dict: + """ + Predict toxicity scores for input text. + + Args: + text: Input text to classify. + + Returns: + Dict with: + - labels: list of label names + - scores: list of per-label probabilities + - is_toxic: bool (any label > 0.5) + - max_score: float (highest toxicity probability) + - max_label: str (label with highest probability) + """ + if not self._loaded: + raise RuntimeError("Text model not loaded. Call load() first.") + + # Tokenize + encoding = self.tokenizer( + text, + return_tensors="np" if self.onnx_session else "pt", + padding="max_length", + truncation=True, + max_length=128, + ) + + if self.onnx_session: + return self._predict_onnx(encoding) + else: + return self._predict_pytorch(encoding) + + def _predict_onnx(self, encoding: dict) -> dict: + """Run ONNX inference.""" + from app.models.onnx_utils import onnx_inference + + inputs = { + "input_ids": encoding["input_ids"].astype(np.int64), + "attention_mask": encoding["attention_mask"].astype(np.int64), + } + outputs = onnx_inference(self.onnx_session, inputs) + logits = outputs[0][0] # (num_labels,) + return self._format_output(logits) + + def _predict_pytorch(self, encoding: dict) -> dict: + """Run PyTorch inference.""" + import torch + + inputs = {k: v.to(self.device) for k, v in encoding.items()} + with torch.no_grad(): + outputs = self.pt_model(**inputs) + logits = outputs.logits[0].cpu().numpy() + return self._format_output(logits) + + def _format_output(self, logits: np.ndarray) -> dict: + """Convert raw logits to formatted prediction dict.""" + # Sigmoid for multi-label classification + scores = 1 / (1 + np.exp(-logits)) + scores = scores.tolist() + + # Handle case where model has fewer outputs than expected labels + labels = self.LABELS[: len(scores)] + + label_scores = dict(zip(labels, scores)) + max_idx = int(np.argmax(scores)) + is_toxic = any(s > 0.5 for s in scores) + + return { + "labels": labels, + "scores": scores, + "label_scores": label_scores, + "is_toxic": is_toxic, + "max_score": scores[max_idx], + "max_label": labels[max_idx], + } + + @property + def is_loaded(self) -> bool: + return self._loaded diff --git a/app/observability/__init__.py b/app/observability/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2e1a9233fb6471fd89a0b95d4d7f774e37167dba --- /dev/null +++ b/app/observability/__init__.py @@ -0,0 +1,2 @@ +# app/observability/__init__.py +"""Observability: structured logging and LangSmith tracing.""" diff --git a/app/observability/langsmith.py b/app/observability/langsmith.py new file mode 100644 index 0000000000000000000000000000000000000000..1412d1f285c0b03391efe8fe133ee61222fb78e5 --- /dev/null +++ b/app/observability/langsmith.py @@ -0,0 +1,59 @@ +# app/observability/langsmith.py +# LangSmith tracing integration for pipeline observability + +import os +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +def setup_langsmith() -> bool: + """ + Configure LangSmith tracing via environment variables. + LangChain/LangGraph automatically pick up these env vars. + + Returns: + True if LangSmith is configured, False otherwise. + """ + settings = get_settings() + + if not settings.langsmith_api_key: + logger.info("langsmith_disabled", reason="No API key provided") + return False + + os.environ["LANGCHAIN_TRACING_V2"] = str(settings.langsmith_tracing_v2).lower() + os.environ["LANGCHAIN_API_KEY"] = settings.langsmith_api_key + os.environ["LANGCHAIN_PROJECT"] = settings.langsmith_project + + logger.info( + "langsmith_enabled", + project=settings.langsmith_project, + ) + return True + + +def get_trace_config( + run_name: str, + input_type: str, + metadata: dict | None = None, +) -> dict: + """ + Build configuration dict for LangGraph invoke calls. + This attaches metadata and tags to the LangSmith trace. + + Args: + run_name: Human-readable name for this trace run. + input_type: The content type being analyzed (text/image/video). + metadata: Additional key-value metadata. + + Returns: + Config dict to pass to workflow.invoke(). + """ + tags = [f"input:{input_type}", "hubble-moderation"] + config = { + "run_name": run_name, + "tags": tags, + "metadata": metadata or {}, + } + return {"configurable": config} diff --git a/app/observability/logging.py b/app/observability/logging.py new file mode 100644 index 0000000000000000000000000000000000000000..21138e66c7c7b095be3fa07ed4219aa9df3267fc --- /dev/null +++ b/app/observability/logging.py @@ -0,0 +1,41 @@ +# app/observability/logging.py +# Structured logging with structlog + +import sys +import logging +import structlog +from app.config import get_settings + + +def setup_logging() -> None: + """Configure structured logging for the application.""" + settings = get_settings() + + # Configure structlog + structlog.configure( + processors=[ + structlog.contextvars.merge_contextvars, + structlog.processors.add_log_level, + structlog.processors.StackInfoRenderer(), + structlog.dev.set_exc_info, + structlog.processors.TimeStamper(fmt="iso"), + structlog.processors.JSONRenderer() + if settings.is_production + else structlog.dev.ConsoleRenderer(colors=True), + ], + wrapper_class=structlog.make_filtering_bound_logger( + logging.getLevelName(settings.log_level) + ), + context_class=dict, + logger_factory=structlog.PrintLoggerFactory(), + cache_logger_on_first_use=True, + ) + + # Silence noisy third-party loggers + for logger_name in ["uvicorn.access", "httpx", "httpcore"]: + logging.getLogger(logger_name).setLevel(logging.WARNING) + + +def get_logger(name: str | None = None) -> structlog.BoundLogger: + """Get a structured logger instance.""" + return structlog.get_logger(name or __name__) diff --git a/app/pipeline/__init__.py b/app/pipeline/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5ef6e8e8021963eda3618760ba3ce1df099ac2e8 --- /dev/null +++ b/app/pipeline/__init__.py @@ -0,0 +1,2 @@ +# app/pipeline/__init__.py +"""Core moderation pipeline: preprocess → filter → score → route → decide.""" diff --git a/app/pipeline/decision_engine.py b/app/pipeline/decision_engine.py new file mode 100644 index 0000000000000000000000000000000000000000..66b87636137e2ec307dc91c260811fd335df438f --- /dev/null +++ b/app/pipeline/decision_engine.py @@ -0,0 +1,142 @@ +# app/pipeline/decision_engine.py +# Rule-based decision engine: final moderation verdict + +from dataclasses import dataclass, field +from app.pipeline.risk_scorer import RiskScore +from app.pipeline.deep_analyzer import DeepAnalysisResult +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +@dataclass +class Decision: + """Final moderation decision.""" + action: str # ALLOWED, WARNING, BLOCKED + reason: str + severity: str # low, medium, high, critical + categories: list[str] = field(default_factory=list) + should_alert_parent: bool = False + should_log: bool = True + escalation_notes: str | None = None + + +class DecisionEngine: + """ + Rule-based final decision engine. + + Takes risk score + optional deep analysis and produces a final verdict. + + Rules: + - LOW risk → ALLOWED (no action) + - MEDIUM risk → WARNING (increment user warning count, log) + - HIGH risk + deep_confirmed → BLOCKED (alert parent, log, escalate if critical) + - HIGH risk + deep_not_confirmed → WARNING (false positive recovery) + - Repeat offender with MEDIUM → BLOCKED (escalate) + """ + + def decide( + self, + risk: RiskScore, + deep_result: DeepAnalysisResult | None = None, + user_history: dict | None = None, + ) -> Decision: + """ + Produce final moderation decision. + + Args: + risk: Composite risk score from the scoring engine. + deep_result: Optional deep analysis result (only for HIGH risk). + user_history: Optional user moderation history. + + Returns: + Decision with action, reason, and metadata. + """ + + # === LOW RISK === + if risk.level == "LOW": + decision = Decision( + action="ALLOWED", + reason="Content passed all safety checks", + severity="low", + should_log=False, # Don't clutter logs with safe content + ) + + # === MEDIUM RISK === + elif risk.level == "MEDIUM": + # Check for repeat offender escalation + if risk.repeat_offender: + decision = Decision( + action="BLOCKED", + reason="Repeat offender with moderately harmful content — escalated to block", + severity="high", + should_alert_parent=True, + escalation_notes="User has repeated violation history. Medium-risk content escalated.", + ) + else: + decision = Decision( + action="WARNING", + reason=f"Content flagged as potentially harmful (risk score: {risk.score})", + severity="medium", + should_alert_parent=False, + ) + + # === HIGH RISK === + elif risk.level == "HIGH": + if deep_result and deep_result.is_confirmed: + # Deep analysis confirms the threat + severity = deep_result.severity + should_escalate = severity == "critical" + + decision = Decision( + action="BLOCKED", + reason=deep_result.reasoning, + severity=severity, + categories=deep_result.categories, + should_alert_parent=True, + escalation_notes=( + "CRITICAL: Immediate review required. " + f"Recommended action: {deep_result.recommended_action}" + if should_escalate + else None + ), + ) + elif deep_result and not deep_result.is_confirmed: + # Deep analysis says it's a false positive + decision = Decision( + action="WARNING", + reason=( + f"Content initially flagged as high-risk (score: {risk.score}) " + f"but deep analysis did not confirm threat. " + f"Reasoning: {deep_result.reasoning}" + ), + severity="low", + should_alert_parent=False, + ) + else: + # No deep analysis available — err on caution + decision = Decision( + action="BLOCKED", + reason=f"High-risk content detected (score: {risk.score}). Deep analysis unavailable.", + severity="high", + should_alert_parent=True, + escalation_notes="Deep analysis was not performed. Manual review recommended.", + ) + + else: + # Fallback + decision = Decision( + action="WARNING", + reason="Unclassified risk level", + severity="medium", + ) + + logger.info( + "decision_made", + action=decision.action, + severity=decision.severity, + alert_parent=decision.should_alert_parent, + risk_score=risk.score, + risk_level=risk.level, + ) + return decision diff --git a/app/pipeline/deep_analyzer.py b/app/pipeline/deep_analyzer.py new file mode 100644 index 0000000000000000000000000000000000000000..ec92bdf3f7a39d2f39f9159c85fa299d860f1566 --- /dev/null +++ b/app/pipeline/deep_analyzer.py @@ -0,0 +1,153 @@ +# app/pipeline/deep_analyzer.py +# Deep analysis layer: CLIP + Gemini reasoning (HIGH risk only) + +from dataclasses import dataclass, field +from PIL import Image +from app.models.model_registry import model_registry +from app.services.gemini_service import gemini_service +from app.pipeline.fast_filter import FilterResult +from app.utils.image_utils import image_to_base64 +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +@dataclass +class DeepAnalysisResult: + """Output from the deep analysis stage.""" + is_confirmed: bool # Does deep analysis confirm the threat? + severity: str # low, medium, high, critical + reasoning: str # Explanation from Gemini + categories: list[str] = field(default_factory=list) + recommended_action: str = "warn" # allow, warn, block, escalate + confidence: float = 0.0 + clip_scores: dict = field(default_factory=dict) + gemini_raw: dict = field(default_factory=dict) + + +class DeepAnalyzer: + """ + Deep analysis layer invoked only for HIGH-risk content. + + Pipeline: + 1. CLIP multimodal alignment (if image present) + 2. Gemini reasoning via LangChain + 3. Combine signals into final assessment + + This layer trades speed for accuracy — expected latency: 1-3 seconds. + """ + + async def analyze_text( + self, + text: str, + filter_result: FilterResult, + ) -> DeepAnalysisResult: + """ + Deep analysis for flagged text content. + + Args: + text: Original text content. + filter_result: Results from the fast filter stage. + + Returns: + DeepAnalysisResult with Gemini reasoning. + """ + logger.info("deep_analysis_text_started") + + # Prepare context from fast filter + context = { + "flagged_categories": filter_result.categories, + "max_score": filter_result.max_score, + "max_label": filter_result.max_label, + "all_scores": filter_result.scores, + } + + # Invoke Gemini for contextual reasoning + gemini_result = await gemini_service.analyze_text(text, context) + + result = self._build_result(gemini_result) + + logger.info( + "deep_analysis_text_complete", + confirmed=result.is_confirmed, + severity=result.severity, + action=result.recommended_action, + ) + return result + + async def analyze_image( + self, + image: Image.Image, + filter_result: FilterResult, + context_text: str | None = None, + ) -> DeepAnalysisResult: + """ + Deep analysis for flagged image content. + + Args: + image: PIL Image. + filter_result: Results from the fast filter. + context_text: Optional text accompanying the image. + + Returns: + DeepAnalysisResult with CLIP alignment + Gemini reasoning. + """ + logger.info("deep_analysis_image_started") + + # Step 1: CLIP multimodal alignment + clip_scores = {} + if model_registry.clip_available: + try: + clip_result = model_registry.clip_model.align_content(image, context_text) + clip_scores = clip_result + logger.info("clip_alignment_complete", most_aligned=clip_result.get("most_aligned")) + except Exception as e: + logger.warning("clip_alignment_failed", error=str(e)) + + # Step 2: Gemini image reasoning + context = { + "flagged_categories": filter_result.categories, + "max_score": filter_result.max_score, + "clip_alignment": clip_scores.get("most_aligned", "unknown"), + } + + image_b64 = image_to_base64(image) + gemini_result = await gemini_service.analyze_image(image_b64, context) + + result = self._build_result(gemini_result, clip_scores) + + logger.info( + "deep_analysis_image_complete", + confirmed=result.is_confirmed, + severity=result.severity, + ) + return result + + def _build_result( + self, + gemini_result: dict, + clip_scores: dict | None = None, + ) -> DeepAnalysisResult: + """Build DeepAnalysisResult from Gemini response.""" + if "error" in gemini_result: + # Gemini failed — err on the side of caution + return DeepAnalysisResult( + is_confirmed=True, # Assume harmful if we can't verify + severity="medium", + reasoning=f"Deep analysis unavailable: {gemini_result['error']}. Defaulting to caution.", + recommended_action="warn", + confidence=0.3, + clip_scores=clip_scores or {}, + gemini_raw=gemini_result, + ) + + return DeepAnalysisResult( + is_confirmed=gemini_result.get("is_confirmed", False), + severity=gemini_result.get("severity", "medium"), + reasoning=gemini_result.get("reasoning", "No reasoning provided"), + categories=gemini_result.get("categories", []), + recommended_action=gemini_result.get("recommended_action", "warn"), + confidence=gemini_result.get("confidence", 0.5), + clip_scores=clip_scores or {}, + gemini_raw=gemini_result, + ) diff --git a/app/pipeline/fast_filter.py b/app/pipeline/fast_filter.py new file mode 100644 index 0000000000000000000000000000000000000000..73e6a2e956c7782fbcca6e2cb68c6006d64f1cb6 --- /dev/null +++ b/app/pipeline/fast_filter.py @@ -0,0 +1,124 @@ +# app/pipeline/fast_filter.py +# First-pass AI classification using ONNX-optimized models + +from dataclasses import dataclass, field +from PIL import Image +from app.models.model_registry import model_registry +from app.pipeline.preprocessor import ProcessedText, ProcessedImage +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +@dataclass +class FilterResult: + """Output from the fast filter stage.""" + input_type: str # "text", "image" + is_flagged: bool + scores: dict[str, float] = field(default_factory=dict) + max_score: float = 0.0 + max_label: str = "" + categories: list[str] = field(default_factory=list) + confidence: float = 0.0 + + +class FastFilter: + """ + Fast AI filter using ONNX-optimized models. + + - RoBERTa for text toxicity (multi-label) + - EfficientNet for image classification + + This is the first gate in the pipeline. Designed for speed (<200ms). + """ + + # Toxicity threshold for flagging + TEXT_FLAG_THRESHOLD = 0.4 + IMAGE_FLAG_THRESHOLD = 0.5 + + def filter_text(self, processed: ProcessedText) -> FilterResult: + """ + Run RoBERTa text toxicity inference. + + Args: + processed: Preprocessed text input. + + Returns: + FilterResult with per-category toxicity scores. + """ + text_model = model_registry.text_model + prediction = text_model.predict(processed.cleaned) + + # Determine which categories are flagged + flagged_categories = [] + label_scores = prediction.get("label_scores", {}) + for label, score in label_scores.items(): + if score > self.TEXT_FLAG_THRESHOLD: + flagged_categories.append(label) + + is_flagged = len(flagged_categories) > 0 + + result = FilterResult( + input_type="text", + is_flagged=is_flagged, + scores=label_scores, + max_score=prediction["max_score"], + max_label=prediction["max_label"], + categories=flagged_categories, + confidence=prediction["max_score"], + ) + + logger.info( + "fast_filter_text", + flagged=is_flagged, + max_label=result.max_label, + max_score=round(result.max_score, 3), + categories=flagged_categories, + ) + return result + + def filter_image(self, processed: ProcessedImage) -> FilterResult: + """ + Run EfficientNet image classification inference. + + Args: + processed: Preprocessed image input. + + Returns: + FilterResult with image classification scores. + """ + image_model = model_registry.image_model + prediction = image_model.predict(processed.image) + + # Map model output to categories + scores = {} + for label, score in zip(prediction["labels"], prediction["scores"]): + scores[label] = score + + flagged_categories = [] + for label, score in scores.items(): + if score > self.IMAGE_FLAG_THRESHOLD: + # Check if this is a harmful category + safe_labels = {"safe", "non-violence", "non_violence", "normal", "neutral"} + if label.lower().replace("-", "_").replace(" ", "_") not in safe_labels: + flagged_categories.append(label) + + is_flagged = prediction["is_harmful"] + + result = FilterResult( + input_type="image", + is_flagged=is_flagged, + scores=scores, + max_score=prediction["max_score"], + max_label=prediction["max_label"], + categories=flagged_categories, + confidence=prediction["max_score"], + ) + + logger.info( + "fast_filter_image", + flagged=is_flagged, + max_label=result.max_label, + max_score=round(result.max_score, 3), + ) + return result diff --git a/app/pipeline/preprocessor.py b/app/pipeline/preprocessor.py new file mode 100644 index 0000000000000000000000000000000000000000..4a7957a0cffc3351f9bc50ed0d848f889b31b52a --- /dev/null +++ b/app/pipeline/preprocessor.py @@ -0,0 +1,141 @@ +# app/pipeline/preprocessor.py +# Input preprocessing: normalization, frame extraction, cleaning + +import re +from dataclasses import dataclass, field +from PIL import Image +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +@dataclass +class ProcessedText: + """Preprocessed text content.""" + original: str + cleaned: str + word_count: int + char_count: int + language: str = "en" # placeholder for language detection + + +@dataclass +class ProcessedImage: + """Preprocessed image content.""" + image: Image.Image + width: int + height: int + format: str = "RGB" + + +@dataclass +class ProcessedVideo: + """Preprocessed video — a list of extracted frames.""" + frames: list[ProcessedImage] = field(default_factory=list) + frame_count: int = 0 + duration_seconds: float = 0.0 + metadata: dict = field(default_factory=dict) + + +class Preprocessor: + """ + Input preprocessing for all content types. + + - Text: cleaning, normalization + - Image: resize, format conversion + - Video: frame extraction + per-frame preprocessing + """ + + def __init__(self): + self.settings = get_settings() + + def process_text(self, text: str) -> ProcessedText: + """ + Clean and normalize input text. + + - Strip excessive whitespace + - Remove zero-width characters + - Normalize unicode + """ + import unicodedata + + # Remove zero-width characters often used for obfuscation + cleaned = re.sub(r"[\u200b\u200c\u200d\ufeff]", "", text) + + # Normalize unicode + cleaned = unicodedata.normalize("NFKC", cleaned) + + # Collapse excessive whitespace + cleaned = re.sub(r"\s+", " ", cleaned).strip() + + result = ProcessedText( + original=text, + cleaned=cleaned, + word_count=len(cleaned.split()), + char_count=len(cleaned), + ) + + logger.debug( + "text_preprocessed", + word_count=result.word_count, + char_count=result.char_count, + ) + return result + + def process_image(self, image_bytes: bytes) -> ProcessedImage: + """ + Load and preprocess image from bytes. + + - Convert to RGB + - Record dimensions + """ + from app.utils.image_utils import load_image_from_bytes + + image = load_image_from_bytes(image_bytes) + width, height = image.size + + result = ProcessedImage( + image=image, + width=width, + height=height, + ) + + logger.debug("image_preprocessed", width=width, height=height) + return result + + def process_video(self, video_bytes: bytes) -> ProcessedVideo: + """ + Extract key frames from video. + + Uses OpenCV to sample frames at configured intervals. + """ + from app.utils.video_utils import extract_frames, get_video_metadata + + metadata = get_video_metadata(video_bytes) + frames_pil = extract_frames( + video_bytes, + max_frames=self.settings.video_max_frames, + fps_sample=self.settings.video_fps_sample, + ) + + processed_frames = [] + for frame in frames_pil: + w, h = frame.size + processed_frames.append( + ProcessedImage(image=frame, width=w, height=h) + ) + + result = ProcessedVideo( + frames=processed_frames, + frame_count=len(processed_frames), + duration_seconds=metadata.get("duration_seconds", 0.0), + metadata=metadata, + ) + + logger.debug( + "video_preprocessed", + frames_extracted=result.frame_count, + duration=result.duration_seconds, + ) + return result diff --git a/app/pipeline/risk_scorer.py b/app/pipeline/risk_scorer.py new file mode 100644 index 0000000000000000000000000000000000000000..39e70484a0e0c3bab26b6f14e9abda0eec7b75b2 --- /dev/null +++ b/app/pipeline/risk_scorer.py @@ -0,0 +1,166 @@ +# app/pipeline/risk_scorer.py +# Composite risk scoring engine + +from dataclasses import dataclass +from app.config import get_settings +from app.pipeline.fast_filter import FilterResult +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +@dataclass +class RiskScore: + """Composite risk assessment.""" + score: float # 0-100 + level: str # LOW, MEDIUM, HIGH + components: dict # breakdown of scoring factors + repeat_offender: bool = False + + +class RiskScorer: + """ + Computes a composite risk score (0-100) from multiple signals. + + Scoring formula: + - Base score from model confidence (weighted by category severity) + - Repeat offender boost (user history) + - Multi-category penalty (multiple harmful categories = higher risk) + + Thresholds (configurable via env): + - 0-30: LOW → Allow + - 31-65: MEDIUM → Warning + - 66-100: HIGH → Deep Analysis + """ + + # Category severity weights (how dangerous each type is) + CATEGORY_WEIGHTS = { + # Text categories (from RoBERTa toxic-bert) + "toxic": 0.6, + "severe_toxic": 1.0, + "obscene": 0.5, + "threat": 1.0, + "insult": 0.5, + "identity_hate": 0.9, + # Image categories + "violence": 0.9, + "nsfw": 0.8, + "self_harm": 1.0, + "hate_symbol": 0.9, + # Generic fallback + "harassment": 0.7, + "bullying": 0.7, + } + + # Repeat offender thresholds + REPEAT_OFFENDER_VIOLATIONS = 3 + REPEAT_OFFENDER_BOOST = 15 # points added + + def __init__(self): + self.settings = get_settings() + + def score( + self, + filter_result: FilterResult, + user_history: dict | None = None, + ) -> RiskScore: + """ + Compute composite risk score. + + Args: + filter_result: Output from fast filter stage. + user_history: Optional user moderation history. + + Returns: + RiskScore with level classification. + """ + # 1. Base score from model confidence + base_score = self._compute_base_score(filter_result) + + # 2. Multi-category penalty + multi_cat_penalty = self._multi_category_penalty(filter_result) + + # 3. Repeat offender boost + repeat_boost, is_repeat = self._repeat_offender_boost(user_history) + + # 4. Combine + raw_score = base_score + multi_cat_penalty + repeat_boost + final_score = min(100.0, max(0.0, raw_score)) + + # 5. Classify level + level = self._classify_level(final_score) + + result = RiskScore( + score=round(final_score, 1), + level=level, + components={ + "base_score": round(base_score, 1), + "multi_category_penalty": round(multi_cat_penalty, 1), + "repeat_offender_boost": round(repeat_boost, 1), + }, + repeat_offender=is_repeat, + ) + + logger.info( + "risk_scored", + score=result.score, + level=result.level, + components=result.components, + repeat_offender=is_repeat, + ) + return result + + def _compute_base_score(self, result: FilterResult) -> float: + """ + Compute base score from model predictions. + + Uses weighted sum of flagged category scores. + """ + if not result.is_flagged: + # Even unflagged content gets a small score based on max prediction + return result.max_score * 20 # Scale 0-1 → 0-20 + + # Weighted sum of flagged category scores + weighted_sum = 0.0 + weight_total = 0.0 + + for category, score in result.scores.items(): + weight = self.CATEGORY_WEIGHTS.get(category.lower(), 0.5) + weighted_sum += score * weight * 100 + weight_total += weight + + if weight_total > 0: + return weighted_sum / weight_total + return result.max_score * 60 + + def _multi_category_penalty(self, result: FilterResult) -> float: + """Add penalty when multiple harmful categories are detected.""" + num_categories = len(result.categories) + if num_categories <= 1: + return 0.0 + # Each additional category adds 5 points + return (num_categories - 1) * 5.0 + + def _repeat_offender_boost(self, user_history: dict | None) -> tuple[float, bool]: + """Boost score for users with violation history.""" + if not user_history: + return 0.0, False + + total_violations = user_history.get("total_violations", 0) + is_repeat = total_violations >= self.REPEAT_OFFENDER_VIOLATIONS + + if is_repeat: + return self.REPEAT_OFFENDER_BOOST, True + elif total_violations > 0: + # Smaller boost for users with some history + return total_violations * 3.0, False + return 0.0, False + + def _classify_level(self, score: float) -> str: + """Map numeric score to risk level.""" + if score <= self.settings.risk_low_max: + return "LOW" + elif score <= self.settings.risk_medium_max: + return "MEDIUM" + else: + return "HIGH" diff --git a/app/pipeline/workflow.py b/app/pipeline/workflow.py new file mode 100644 index 0000000000000000000000000000000000000000..ec34159b860aee221e8720c3a70a0b5030b96041 --- /dev/null +++ b/app/pipeline/workflow.py @@ -0,0 +1,327 @@ +# app/pipeline/workflow.py +# LangGraph state machine — orchestrates the full moderation pipeline + +from __future__ import annotations +from typing import Any, TypedDict, Literal +from dataclasses import asdict + +from langgraph.graph import StateGraph, END + +from app.pipeline.preprocessor import ( + Preprocessor, + ProcessedText, + ProcessedImage, + ProcessedVideo, +) +from app.pipeline.fast_filter import FastFilter, FilterResult +from app.pipeline.risk_scorer import RiskScorer, RiskScore +from app.pipeline.deep_analyzer import DeepAnalyzer, DeepAnalysisResult +from app.pipeline.decision_engine import DecisionEngine, Decision +from app.services.mongo_service import mongo_service +from app.services.redis_service import redis_service +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +# ────────────────────────────────────────────── +# Pipeline State Schema +# ────────────────────────────────────────────── + +class PipelineState(TypedDict, total=False): + """State that flows through the LangGraph pipeline.""" + # Input + input_type: str # "text", "image", "video" + raw_content: Any # str for text, bytes for image/video + user_id: str | None + + # Preprocessed + processed_text: ProcessedText | None + processed_image: ProcessedImage | None + processed_video: ProcessedVideo | None + + # Pipeline stages + filter_result: FilterResult | None + filter_results: list[FilterResult] # For video (multiple frames) + risk_score: RiskScore | None + deep_result: DeepAnalysisResult | None + decision: Decision | None + + # Context + user_history: dict | None + + # Metadata + error: str | None + + +# ────────────────────────────────────────────── +# Pipeline Node Functions +# ────────────────────────────────────────────── + +preprocessor = Preprocessor() +fast_filter = FastFilter() +risk_scorer = RiskScorer() +deep_analyzer = DeepAnalyzer() +decision_engine = DecisionEngine() + + +async def preprocess_node(state: PipelineState) -> dict: + """Node 1: Preprocess the raw input.""" + input_type = state["input_type"] + raw = state["raw_content"] + + try: + if input_type == "text": + processed = preprocessor.process_text(raw) + return {"processed_text": processed} + + elif input_type == "image": + processed = preprocessor.process_image(raw) + return {"processed_image": processed} + + elif input_type == "video": + processed = preprocessor.process_video(raw) + return {"processed_video": processed} + + else: + return {"error": f"Unknown input type: {input_type}"} + + except Exception as e: + logger.error("preprocess_failed", error=str(e)) + return {"error": f"Preprocessing failed: {str(e)}"} + + +async def fetch_user_history_node(state: PipelineState) -> dict: + """Node 1b: Fetch user moderation history (parallel with preprocess).""" + user_id = state.get("user_id") + if not user_id: + return {"user_history": None} + + # Try Redis cache first + cached = await redis_service.get_user_history(user_id) + if cached: + return {"user_history": cached} + + # Fall back to MongoDB + history = await mongo_service.get_user_history(user_id) + if history: + await redis_service.cache_user_history(user_id, history) + return {"user_history": history} + + +async def fast_filter_node(state: PipelineState) -> dict: + """Node 2: Run fast AI filter.""" + input_type = state["input_type"] + + try: + if input_type == "text" and state.get("processed_text"): + result = fast_filter.filter_text(state["processed_text"]) + return {"filter_result": result} + + elif input_type == "image" and state.get("processed_image"): + result = fast_filter.filter_image(state["processed_image"]) + return {"filter_result": result} + + elif input_type == "video" and state.get("processed_video"): + # Analyze each frame, take the worst result + video = state["processed_video"] + frame_results = [] + for frame in video.frames: + result = fast_filter.filter_image(frame) + frame_results.append(result) + + # Use the highest-risk frame as the representative result + if frame_results: + worst = max(frame_results, key=lambda r: r.max_score) + return { + "filter_result": worst, + "filter_results": frame_results, + } + else: + return { + "filter_result": FilterResult( + input_type="video", + is_flagged=False, + max_score=0.0, + ) + } + + return {"error": "No processed content available for filtering"} + + except Exception as e: + logger.error("fast_filter_failed", error=str(e)) + return {"error": f"Fast filter failed: {str(e)}"} + + +async def risk_score_node(state: PipelineState) -> dict: + """Node 3: Compute composite risk score.""" + filter_result = state.get("filter_result") + if not filter_result: + return {"error": "No filter result to score"} + + try: + user_history = state.get("user_history") + score = risk_scorer.score(filter_result, user_history) + return {"risk_score": score} + except Exception as e: + logger.error("risk_score_failed", error=str(e)) + return {"error": f"Risk scoring failed: {str(e)}"} + + +def route_by_risk(state: PipelineState) -> str: + """ + Conditional router: decides whether to do deep analysis or skip to decision. + + - LOW / MEDIUM → skip directly to decision + - HIGH → go to deep analysis + """ + risk = state.get("risk_score") + if risk and risk.level == "HIGH": + return "deep_analysis" + return "decide" + + +async def deep_analysis_node(state: PipelineState) -> dict: + """Node 4 (conditional): Deep analysis with CLIP + Gemini.""" + input_type = state["input_type"] + filter_result = state.get("filter_result") + + try: + if input_type == "text" and state.get("processed_text"): + result = await deep_analyzer.analyze_text( + state["processed_text"].cleaned, + filter_result, + ) + return {"deep_result": result} + + elif input_type in ("image", "video") and state.get("processed_image"): + result = await deep_analyzer.analyze_image( + state["processed_image"].image, + filter_result, + ) + return {"deep_result": result} + + elif input_type == "video" and state.get("processed_video"): + # Use the worst frame for deep analysis + video = state["processed_video"] + if video.frames: + # Find the worst frame based on filter_results + worst_frame = video.frames[0] + filter_results = state.get("filter_results", []) + if filter_results: + worst_idx = max( + range(len(filter_results)), + key=lambda i: filter_results[i].max_score, + ) + if worst_idx < len(video.frames): + worst_frame = video.frames[worst_idx] + + result = await deep_analyzer.analyze_image( + worst_frame.image, + filter_result, + ) + return {"deep_result": result} + + return {"deep_result": None} + + except Exception as e: + logger.error("deep_analysis_failed", error=str(e)) + return {"deep_result": None} + + +async def decision_node(state: PipelineState) -> dict: + """Node 5: Final decision.""" + risk = state.get("risk_score") + if not risk: + # Emergency fallback + return { + "decision": Decision( + action="WARNING", + reason="Pipeline error: no risk score available", + severity="medium", + ) + } + + try: + deep_result = state.get("deep_result") + user_history = state.get("user_history") + decision = decision_engine.decide(risk, deep_result, user_history) + return {"decision": decision} + except Exception as e: + logger.error("decision_failed", error=str(e)) + return { + "decision": Decision( + action="WARNING", + reason=f"Decision engine error: {str(e)}", + severity="medium", + ) + } + + +# ────────────────────────────────────────────── +# Build the LangGraph Workflow +# ────────────────────────────────────────────── + +def build_moderation_workflow(): + """ + Construct and compile the LangGraph moderation pipeline. + + Flow: + preprocess → fast_filter → risk_score + ├─ LOW/MEDIUM → decide + └─ HIGH → deep_analysis → decide + + Returns: + Compiled LangGraph workflow. + """ + graph = StateGraph(PipelineState) + + # Add nodes + graph.add_node("preprocess", preprocess_node) + graph.add_node("fetch_history", fetch_user_history_node) + graph.add_node("fast_filter", fast_filter_node) + graph.add_node("risk_score", risk_score_node) + graph.add_node("deep_analysis", deep_analysis_node) + graph.add_node("decide", decision_node) + + # Define edges + graph.set_entry_point("preprocess") + + # After preprocess, run fast filter + graph.add_edge("preprocess", "fast_filter") + + # After fast filter, compute risk score + graph.add_edge("fast_filter", "risk_score") + + # Conditional routing based on risk level + graph.add_conditional_edges( + "risk_score", + route_by_risk, + { + "deep_analysis": "deep_analysis", + "decide": "decide", + }, + ) + + # Deep analysis flows to decision + graph.add_edge("deep_analysis", "decide") + + # Decision is the terminal node + graph.add_edge("decide", END) + + # Compile + workflow = graph.compile() + logger.info("moderation_workflow_compiled") + return workflow + + +# Global compiled workflow (initialized at startup) +moderation_workflow = None + + +def get_workflow(): + """Get or create the compiled moderation workflow.""" + global moderation_workflow + if moderation_workflow is None: + moderation_workflow = build_moderation_workflow() + return moderation_workflow diff --git a/app/services/__init__.py b/app/services/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..6ea918852b79f05ba98666a73349871160a8b545 --- /dev/null +++ b/app/services/__init__.py @@ -0,0 +1,2 @@ +# app/services/__init__.py +"""External service integrations: MongoDB, Redis, Gemini.""" diff --git a/app/services/gemini_service.py b/app/services/gemini_service.py new file mode 100644 index 0000000000000000000000000000000000000000..9cc4771d530535287e07f9cb5f2b66d6aa3cf512 --- /dev/null +++ b/app/services/gemini_service.py @@ -0,0 +1,247 @@ +# app/services/gemini_service.py +# Gemini API integration via LangChain for deep analysis reasoning + +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class GeminiService: + """ + Google Gemini API client powered by LangChain. + + Used in the deep analysis path for contextual reasoning + about flagged content. Replaces the old raw REST calls + with structured LangChain invocations for: + - Reliable structured output (JSON) + - Automatic retry and fallback + - LangSmith trace integration + """ + + def __init__(self): + self.settings = get_settings() + self.llm = None + self._current_key_idx = 0 + self._initialized = False + + def initialize(self) -> None: + """Initialize the LangChain Gemini client.""" + keys = self.settings.gemini_keys_list + if not keys: + logger.warning("gemini_no_keys", reason="No API keys configured") + return + + try: + from langchain_google_genai import ChatGoogleGenerativeAI + + self.llm = ChatGoogleGenerativeAI( + model=self.settings.gemini_model, + google_api_key=keys[self._current_key_idx], + temperature=0.1, + max_output_tokens=1024, + convert_system_message_to_human=True, + ) + self._initialized = True + logger.info("gemini_initialized", model=self.settings.gemini_model) + except Exception as e: + logger.error("gemini_init_failed", error=str(e)) + + def _rotate_key(self) -> bool: + """Rotate to the next API key. Returns False if all keys exhausted.""" + keys = self.settings.gemini_keys_list + if not keys: + return False + + self._current_key_idx = (self._current_key_idx + 1) % len(keys) + try: + from langchain_google_genai import ChatGoogleGenerativeAI + + self.llm = ChatGoogleGenerativeAI( + model=self.settings.gemini_model, + google_api_key=keys[self._current_key_idx], + temperature=0.1, + max_output_tokens=1024, + convert_system_message_to_human=True, + ) + logger.info("gemini_key_rotated", key_index=self._current_key_idx) + return True + except Exception: + return False + + async def analyze_text(self, text: str, context: dict | None = None) -> dict: + """ + Perform deep contextual analysis of flagged text. + + Args: + text: The flagged text content. + context: Additional context (fast filter results, categories, etc.). + + Returns: + Structured analysis with verdict, reasoning, and severity. + """ + if not self._initialized: + return {"error": "Gemini not initialized", "is_confirmed": False} + + from langchain_core.messages import SystemMessage, HumanMessage + + system_prompt = """You are an expert content moderator specializing in cyberbullying detection. +You are analyzing content that has been flagged as potentially harmful by automated filters. + +Your task: Provide a detailed, contextual analysis. Consider: +- Intent and context (sarcasm, jokes, genuine threats) +- Severity level (mild rudeness vs. serious threats) +- Whether this constitutes cyberbullying +- Impact on minors (under 18) + +Respond in this exact JSON format: +{ + "is_confirmed": true/false, + "severity": "low" | "medium" | "high" | "critical", + "categories": ["category1", "category2"], + "reasoning": "Detailed explanation of your analysis", + "recommended_action": "allow" | "warn" | "block" | "escalate", + "confidence": 0.0-1.0 +}""" + + context_str = "" + if context: + context_str = f"\n\nPre-filter context: {context}" + + human_message = f"""Analyze this flagged content:{context_str} + +Content: "{text}" + +Provide your JSON analysis:""" + + return await self._invoke(system_prompt, human_message) + + async def analyze_image(self, image_base64: str, context: dict | None = None) -> dict: + """ + Perform deep analysis of a flagged image. + + Args: + image_base64: Base64-encoded image. + context: Additional context from fast filter. + + Returns: + Structured analysis dict. + """ + if not self._initialized: + return {"error": "Gemini not initialized", "is_confirmed": False} + + from langchain_core.messages import SystemMessage, HumanMessage + + system_prompt = """You are an expert content moderator analyzing images for content harmful to minors. + +Analyze the image for: +- Violence, gore, weapons +- Nudity, sexual content +- Drug/alcohol imagery +- Self-harm or suicide content +- Hate symbols, extremist content +- Cyberbullying imagery (humiliating photos, etc.) + +Respond in this exact JSON format: +{ + "is_confirmed": true/false, + "severity": "low" | "medium" | "high" | "critical", + "categories": ["category1", "category2"], + "reasoning": "Description of what was found", + "recommended_action": "allow" | "warn" | "block" | "escalate", + "confidence": 0.0-1.0 +}""" + + context_str = f"\nPre-filter flags: {context}" if context else "" + + human_content = [ + {"type": "text", "text": f"Analyze this flagged image:{context_str}\n\nProvide your JSON analysis:"}, + { + "type": "image_url", + "image_url": {"url": f"data:image/jpeg;base64,{image_base64}"}, + }, + ] + + return await self._invoke_multimodal(system_prompt, human_content) + + async def _invoke(self, system_prompt: str, human_message: str) -> dict: + """Invoke Gemini with retry on rate limits.""" + from langchain_core.messages import SystemMessage, HumanMessage + import json + + keys = self.settings.gemini_keys_list + attempts = max(len(keys), 1) + + for attempt in range(attempts): + try: + messages = [ + SystemMessage(content=system_prompt), + HumanMessage(content=human_message), + ] + response = await self.llm.ainvoke(messages) + return self._parse_response(response.content) + + except Exception as e: + error_str = str(e) + if "429" in error_str or "quota" in error_str.lower(): + logger.warning("gemini_rate_limited", attempt=attempt) + if not self._rotate_key(): + break + else: + logger.error("gemini_invoke_failed", error=error_str) + return {"error": error_str, "is_confirmed": False} + + return {"error": "All Gemini API keys exhausted", "is_confirmed": False} + + async def _invoke_multimodal(self, system_prompt: str, human_content: list) -> dict: + """Invoke Gemini with multimodal content.""" + from langchain_core.messages import SystemMessage, HumanMessage + + keys = self.settings.gemini_keys_list + attempts = max(len(keys), 1) + + for attempt in range(attempts): + try: + messages = [ + SystemMessage(content=system_prompt), + HumanMessage(content=human_content), + ] + response = await self.llm.ainvoke(messages) + return self._parse_response(response.content) + + except Exception as e: + error_str = str(e) + if "429" in error_str or "quota" in error_str.lower(): + if not self._rotate_key(): + break + else: + return {"error": error_str, "is_confirmed": False} + + return {"error": "All Gemini API keys exhausted", "is_confirmed": False} + + def _parse_response(self, text: str) -> dict: + """Parse JSON from Gemini response text.""" + import json, re + + try: + # Extract JSON block (handle markdown code fences) + json_match = re.search(r"\{[\s\S]*\}", text) + if json_match: + return json.loads(json_match.group()) + except json.JSONDecodeError: + pass + + logger.warning("gemini_parse_failed", raw_text=text[:200]) + return { + "error": "Failed to parse Gemini response", + "is_confirmed": False, + "raw_response": text[:500], + } + + @property + def is_initialized(self) -> bool: + return self._initialized + + +# Global singleton +gemini_service = GeminiService() diff --git a/app/services/mongo_service.py b/app/services/mongo_service.py new file mode 100644 index 0000000000000000000000000000000000000000..eab4e1776b223368014ad277de4c16595a48698f --- /dev/null +++ b/app/services/mongo_service.py @@ -0,0 +1,185 @@ +# app/services/mongo_service.py +# Async MongoDB client for moderation logs and user history + +from datetime import datetime, timezone +from typing import Any +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class MongoService: + """ + Async MongoDB client using Motor. + + Collections: + - moderation_logs: Full pipeline run traces + - user_history: Aggregated user moderation stats + """ + + def __init__(self): + self.settings = get_settings() + self.client = None + self.db = None + self._connected = False + + async def connect(self) -> None: + """Establish MongoDB connection.""" + try: + from motor.motor_asyncio import AsyncIOMotorClient + + self.client = AsyncIOMotorClient( + self.settings.mongodb_uri, + serverSelectionTimeoutMS=5000, + ) + # Verify connection + await self.client.server_info() + + self.db = self.client[self.settings.mongodb_db_name] + self._connected = True + logger.info("mongodb_connected", db=self.settings.mongodb_db_name) + + # Create indexes + await self._create_indexes() + except Exception as e: + logger.warning("mongodb_connection_failed", error=str(e)) + self._connected = False + + async def _create_indexes(self) -> None: + """Create necessary indexes for performance.""" + try: + # moderation_logs indexes + logs = self.db["moderation_logs"] + await logs.create_index("user_id") + await logs.create_index("created_at") + await logs.create_index([("user_id", 1), ("created_at", -1)]) + + # user_history indexes + history = self.db["user_history"] + await history.create_index("user_id", unique=True) + + logger.info("mongodb_indexes_created") + except Exception as e: + logger.warning("mongodb_index_creation_failed", error=str(e)) + + async def disconnect(self) -> None: + """Close MongoDB connection.""" + if self.client: + self.client.close() + self._connected = False + logger.info("mongodb_disconnected") + + # ---- Moderation Logs ---- + + async def log_moderation(self, log_entry: dict) -> str | None: + """ + Store a complete moderation pipeline run. + + Args: + log_entry: Full pipeline result including input, scores, decisions. + + Returns: + Inserted document ID or None. + """ + if not self._connected: + return None + + try: + log_entry["created_at"] = datetime.now(timezone.utc) + result = await self.db["moderation_logs"].insert_one(log_entry) + logger.debug("moderation_logged", doc_id=str(result.inserted_id)) + return str(result.inserted_id) + except Exception as e: + logger.error("moderation_log_failed", error=str(e)) + return None + + async def get_moderation_history( + self, + user_id: str, + limit: int = 20, + skip: int = 0, + ) -> list[dict]: + """Get moderation history for a user.""" + if not self._connected: + return [] + + try: + cursor = ( + self.db["moderation_logs"] + .find({"user_id": user_id}) + .sort("created_at", -1) + .skip(skip) + .limit(limit) + ) + results = [] + async for doc in cursor: + doc["_id"] = str(doc["_id"]) + results.append(doc) + return results + except Exception as e: + logger.error("history_fetch_failed", error=str(e)) + return [] + + # ---- User History (aggregated stats) ---- + + async def get_user_history(self, user_id: str) -> dict | None: + """Get aggregated moderation stats for a user.""" + if not self._connected: + return None + + try: + doc = await self.db["user_history"].find_one({"user_id": user_id}) + if doc: + doc["_id"] = str(doc["_id"]) + return doc + except Exception as e: + logger.error("user_history_fetch_failed", error=str(e)) + return None + + async def update_user_history(self, user_id: str, moderation_result: dict) -> None: + """ + Update aggregated user history after a moderation event. + + Tracks: + - total_scans, total_violations, total_warnings + - violation_categories (count per category) + - last_violation_at + - risk_trend (recent violation rate) + """ + if not self._connected: + return + + try: + risk_level = moderation_result.get("risk_level", "LOW") + categories = moderation_result.get("categories", []) + + update_ops: dict[str, Any] = { + "$inc": {"total_scans": 1}, + "$set": {"last_scan_at": datetime.now(timezone.utc)}, + "$setOnInsert": {"user_id": user_id, "created_at": datetime.now(timezone.utc)}, + } + + if risk_level == "HIGH": + update_ops["$inc"]["total_violations"] = 1 + update_ops["$set"]["last_violation_at"] = datetime.now(timezone.utc) + for cat in categories: + update_ops["$inc"][f"violation_categories.{cat}"] = 1 + elif risk_level == "MEDIUM": + update_ops["$inc"]["total_warnings"] = 1 + + await self.db["user_history"].update_one( + {"user_id": user_id}, + update_ops, + upsert=True, + ) + except Exception as e: + logger.error("user_history_update_failed", error=str(e)) + + @property + def is_connected(self) -> bool: + return self._connected + + +# Global singleton +mongo_service = MongoService() diff --git a/app/services/redis_service.py b/app/services/redis_service.py new file mode 100644 index 0000000000000000000000000000000000000000..7bea9326e07e78b4e89704a9ba45a667076adc7c --- /dev/null +++ b/app/services/redis_service.py @@ -0,0 +1,145 @@ +# app/services/redis_service.py +# Async Redis client for caching analysis results and user history + +import json +import hashlib +from typing import Any +from app.config import get_settings +from app.observability.logging import get_logger + +logger = get_logger(__name__) + + +class RedisService: + """ + Async Redis client for caching. + + Caches: + - Analysis results by content hash (avoid re-processing identical content) + - User history summaries (avoid repeated MongoDB queries) + """ + + def __init__(self): + self.settings = get_settings() + self.client = None + self._connected = False + + async def connect(self) -> None: + """Establish Redis connection.""" + try: + import redis.asyncio as aioredis + + self.client = aioredis.from_url( + self.settings.redis_url, + decode_responses=True, + socket_connect_timeout=5, + ) + # Test connection + await self.client.ping() + self._connected = True + logger.info("redis_connected", url=self.settings.redis_url) + except Exception as e: + logger.warning("redis_connection_failed", error=str(e)) + self._connected = False + + async def disconnect(self) -> None: + """Close Redis connection.""" + if self.client: + await self.client.close() + self._connected = False + logger.info("redis_disconnected") + + @staticmethod + def _content_hash(content: str) -> str: + """Generate a deterministic hash for content-based cache keys.""" + return hashlib.sha256(content.encode("utf-8")).hexdigest()[:16] + + async def get_cached_result(self, content: str, input_type: str) -> dict | None: + """ + Look up a cached analysis result. + + Args: + content: The raw content (text, or image hash). + input_type: 'text', 'image', or 'video'. + + Returns: + Cached result dict or None. + """ + if not self._connected: + return None + + try: + key = f"hubble:result:{input_type}:{self._content_hash(content)}" + cached = await self.client.get(key) + if cached: + logger.debug("cache_hit", key=key) + return json.loads(cached) + return None + except Exception as e: + logger.warning("cache_get_failed", error=str(e)) + return None + + async def cache_result(self, content: str, input_type: str, result: dict) -> None: + """ + Cache an analysis result. + + Args: + content: The raw content (text, or image hash). + input_type: 'text', 'image', or 'video'. + result: The analysis result dict. + """ + if not self._connected: + return + + try: + key = f"hubble:result:{input_type}:{self._content_hash(content)}" + await self.client.setex( + key, + self.settings.redis_cache_ttl, + json.dumps(result, default=str), + ) + logger.debug("cache_set", key=key, ttl=self.settings.redis_cache_ttl) + except Exception as e: + logger.warning("cache_set_failed", error=str(e)) + + async def get_user_history(self, user_id: str) -> dict | None: + """Get cached user moderation history summary.""" + if not self._connected: + return None + + try: + key = f"hubble:user_history:{user_id}" + cached = await self.client.get(key) + return json.loads(cached) if cached else None + except Exception: + return None + + async def cache_user_history(self, user_id: str, history: dict) -> None: + """Cache user moderation history summary (10 minute TTL).""" + if not self._connected: + return + + try: + key = f"hubble:user_history:{user_id}" + await self.client.setex(key, 600, json.dumps(history, default=str)) + except Exception: + pass + + async def invalidate_user_history(self, user_id: str) -> None: + """Invalidate cached user history after a new moderation event.""" + if not self._connected: + return + + try: + key = f"hubble:user_history:{user_id}" + await self.client.delete(key) + except Exception: + pass + + @property + def is_connected(self) -> bool: + return self._connected + + +# Global singleton +redis_service = RedisService() diff --git a/app/utils/__init__.py b/app/utils/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..fd534897d2e52a77bd2d2c8d450dc193ad35a7f1 --- /dev/null +++ b/app/utils/__init__.py @@ -0,0 +1,2 @@ +# app/utils/__init__.py +"""Shared utility functions.""" diff --git a/app/utils/image_utils.py b/app/utils/image_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..302c723fb40b08ccfb802888ac1a4114e7ede060 --- /dev/null +++ b/app/utils/image_utils.py @@ -0,0 +1,54 @@ +# app/utils/image_utils.py +# Image preprocessing and manipulation utilities + +from io import BytesIO +from PIL import Image +import numpy as np + + +def load_image_from_bytes(data: bytes) -> Image.Image: + """Load a PIL Image from raw bytes.""" + return Image.open(BytesIO(data)).convert("RGB") + + +def resize_image(image: Image.Image, size: tuple[int, int] = (224, 224)) -> Image.Image: + """Resize image to target dimensions, maintaining aspect ratio with center crop.""" + image = image.resize(size, Image.Resampling.LANCZOS) + return image + + +def image_to_numpy(image: Image.Image) -> np.ndarray: + """Convert PIL Image to normalized numpy array (C, H, W) float32.""" + arr = np.array(image, dtype=np.float32) / 255.0 + # HWC → CHW + arr = np.transpose(arr, (2, 0, 1)) + return arr + + +def normalize_image( + arr: np.ndarray, + mean: tuple[float, ...] = (0.485, 0.456, 0.406), + std: tuple[float, ...] = (0.229, 0.224, 0.225), +) -> np.ndarray: + """Apply ImageNet normalization to a CHW numpy array.""" + mean_arr = np.array(mean, dtype=np.float32).reshape(3, 1, 1) + std_arr = np.array(std, dtype=np.float32).reshape(3, 1, 1) + return (arr - mean_arr) / std_arr + + +def preprocess_image_for_model( + image: Image.Image, size: tuple[int, int] = (224, 224) +) -> np.ndarray: + """Full preprocessing pipeline: resize → numpy → normalize → add batch dim.""" + image = resize_image(image, size) + arr = image_to_numpy(image) + arr = normalize_image(arr) + return np.expand_dims(arr, axis=0) # (1, C, H, W) + + +def image_to_base64(image: Image.Image, fmt: str = "JPEG", quality: int = 85) -> str: + """Encode PIL Image as base64 string.""" + import base64 + buffer = BytesIO() + image.save(buffer, format=fmt, quality=quality) + return base64.b64encode(buffer.getvalue()).decode("utf-8") diff --git a/app/utils/video_utils.py b/app/utils/video_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..96e80067d355f456971d4ae789b3dede87776631 --- /dev/null +++ b/app/utils/video_utils.py @@ -0,0 +1,96 @@ +# app/utils/video_utils.py +# Video frame extraction using OpenCV + +import tempfile +from pathlib import Path +from PIL import Image +import numpy as np + + +def extract_frames( + video_bytes: bytes, + max_frames: int = 10, + fps_sample: int = 1, +) -> list[Image.Image]: + """ + Extract key frames from a video file. + + Args: + video_bytes: Raw video file bytes. + max_frames: Maximum number of frames to extract. + fps_sample: Extract 1 frame every N seconds. + + Returns: + List of PIL Images (RGB). + """ + import cv2 + + # Write to temp file (OpenCV needs file path) + with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp: + tmp.write(video_bytes) + tmp_path = tmp.name + + frames: list[Image.Image] = [] + + try: + cap = cv2.VideoCapture(tmp_path) + if not cap.isOpened(): + raise ValueError("Failed to open video file") + + video_fps = cap.get(cv2.CAP_PROP_FPS) or 30.0 + total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + frame_interval = int(video_fps * fps_sample) + + if frame_interval < 1: + frame_interval = 1 + + frame_idx = 0 + while cap.isOpened() and len(frames) < max_frames: + ret, frame = cap.read() + if not ret: + break + + if frame_idx % frame_interval == 0: + # BGR → RGB + rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) + pil_image = Image.fromarray(rgb_frame) + frames.append(pil_image) + + frame_idx += 1 + + cap.release() + finally: + # Clean up temp file + Path(tmp_path).unlink(missing_ok=True) + + return frames + + +def get_video_metadata(video_bytes: bytes) -> dict: + """Extract basic metadata from video file.""" + import cv2 + + with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp: + tmp.write(video_bytes) + tmp_path = tmp.name + + try: + cap = cv2.VideoCapture(tmp_path) + if not cap.isOpened(): + return {"error": "Failed to open video"} + + metadata = { + "fps": cap.get(cv2.CAP_PROP_FPS), + "frame_count": int(cap.get(cv2.CAP_PROP_FRAME_COUNT)), + "width": int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), + "height": int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)), + "duration_seconds": ( + int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) / cap.get(cv2.CAP_PROP_FPS) + if cap.get(cv2.CAP_PROP_FPS) > 0 + else 0 + ), + } + cap.release() + return metadata + finally: + Path(tmp_path).unlink(missing_ok=True) diff --git a/model_cache/efficientnet/CACHEDIR.TAG b/model_cache/efficientnet/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..2b927574f362cc41ca52cb6e863dbf47e664febb --- /dev/null +++ b/model_cache/efficientnet/CACHEDIR.TAG @@ -0,0 +1,4 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by huggingface_hub. +# For information about cache directory tags, see: +# https://bford.info/cachedir/ diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/model.safetensors b/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/model.safetensors.index.json b/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/model.safetensors.index.json new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/processor_config.json b/model_cache/efficientnet/models--google--efficientnet-b0/.no_exist/3d8d75d0812b65064f0151b456f869c6344bf20c/processor_config.json new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/refs/main b/model_cache/efficientnet/models--google--efficientnet-b0/refs/main new file mode 100644 index 0000000000000000000000000000000000000000..7d16616c482a989b06e6de222797649910d84039 --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/refs/main @@ -0,0 +1 @@ +3d8d75d0812b65064f0151b456f869c6344bf20c \ No newline at end of file diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/refs/refs/pr/3 b/model_cache/efficientnet/models--google--efficientnet-b0/refs/refs/pr/3 new file mode 100644 index 0000000000000000000000000000000000000000..4a19d679fc49be2ac5315910135dd08e0e00cb0c --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/refs/refs/pr/3 @@ -0,0 +1 @@ +f86b650049699f1cf772edd370d7ea0382f0941f \ No newline at end of file diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/config.json b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/config.json new file mode 100644 index 0000000000000000000000000000000000000000..b507eeecf90b349090c397ccc6dadf846299b32b --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/config.json @@ -0,0 +1,2091 @@ +{ + "architectures": [ + "EfficientNetForImageClassification" + ], + "batch_norm_eps": 0.001, + "batch_norm_momentum": 0.99, + "depth_coefficient": 1.0, + "depth_divisor": 8, + "depthwise_padding": [], + "drop_connect_rate": 0.2, + "dropout_rate": 0.2, + "expand_ratios": [ + 1, + 6, + 6, + 6, + 6, + 6, + 6 + ], + "hidden_act": "swish", + "hidden_dim": 1280, + "id2label": { + "0": "tench, Tinca tinca", + "1": "goldfish, Carassius auratus", + "2": "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias", + "3": "tiger shark, Galeocerdo cuvieri", + "4": "hammerhead, hammerhead shark", + "5": "electric ray, crampfish, numbfish, torpedo", + "6": "stingray", + "7": "cock", + "8": "hen", + "9": "ostrich, Struthio camelus", + "10": "brambling, Fringilla montifringilla", + "11": "goldfinch, Carduelis carduelis", + "12": "house finch, linnet, Carpodacus mexicanus", + "13": "junco, snowbird", + "14": "indigo bunting, indigo finch, indigo bird, Passerina cyanea", + "15": "robin, American robin, Turdus migratorius", + "16": "bulbul", + "17": "jay", + "18": "magpie", + "19": "chickadee", + "20": "water ouzel, dipper", + "21": "kite", + "22": "bald eagle, American eagle, Haliaeetus leucocephalus", + "23": "vulture", + "24": "great grey owl, great gray owl, Strix nebulosa", + "25": "European fire salamander, Salamandra salamandra", + "26": "common newt, Triturus vulgaris", + "27": "eft", + "28": "spotted salamander, Ambystoma maculatum", + "29": "axolotl, mud puppy, Ambystoma mexicanum", + "30": "bullfrog, Rana catesbeiana", + "31": "tree frog, tree-frog", + "32": "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui", + "33": "loggerhead, loggerhead turtle, Caretta caretta", + "34": "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea", + "35": "mud turtle", + "36": "terrapin", + "37": "box turtle, box tortoise", + "38": "banded gecko", + "39": "common iguana, iguana, Iguana iguana", + "40": "American chameleon, anole, Anolis carolinensis", + "41": "whiptail, whiptail lizard", + "42": "agama", + "43": "frilled lizard, Chlamydosaurus kingi", + "44": "alligator lizard", + "45": "Gila monster, Heloderma suspectum", + "46": "green lizard, Lacerta viridis", + "47": "African chameleon, Chamaeleo chamaeleon", + "48": "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis", + "49": "African crocodile, Nile crocodile, Crocodylus niloticus", + "50": "American alligator, Alligator mississipiensis", + "51": "triceratops", + "52": "thunder snake, worm snake, Carphophis amoenus", + "53": "ringneck snake, ring-necked snake, ring snake", + "54": "hognose snake, puff adder, sand viper", + "55": "green snake, grass snake", + "56": "king snake, kingsnake", + "57": "garter snake, grass snake", + "58": "water snake", + "59": "vine snake", + "60": "night snake, Hypsiglena torquata", + "61": "boa constrictor, Constrictor constrictor", + "62": "rock python, rock snake, Python sebae", + "63": "Indian cobra, Naja naja", + "64": "green mamba", + "65": "sea snake", + "66": "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus", + "67": "diamondback, diamondback rattlesnake, Crotalus adamanteus", + "68": "sidewinder, horned rattlesnake, Crotalus cerastes", + "69": "trilobite", + "70": "harvestman, daddy longlegs, Phalangium opilio", + "71": "scorpion", + "72": "black and gold garden spider, Argiope aurantia", + "73": "barn spider, Araneus cavaticus", + "74": "garden spider, Aranea diademata", + "75": "black widow, Latrodectus mactans", + "76": "tarantula", + "77": "wolf spider, hunting spider", + "78": "tick", + "79": "centipede", + "80": "black grouse", + "81": "ptarmigan", + "82": "ruffed grouse, partridge, Bonasa umbellus", + "83": "prairie chicken, prairie grouse, prairie fowl", + "84": "peacock", + "85": "quail", + "86": "partridge", + "87": "African grey, African gray, Psittacus erithacus", + "88": "macaw", + "89": "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita", + "90": "lorikeet", + "91": "coucal", + "92": "bee eater", + "93": "hornbill", + "94": "hummingbird", + "95": "jacamar", + "96": "toucan", + "97": "drake", + "98": "red-breasted merganser, Mergus serrator", + "99": "goose", + "100": "black swan, Cygnus atratus", + "101": "tusker", + "102": "echidna, spiny anteater, anteater", + "103": "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus", + "104": "wallaby, brush kangaroo", + "105": "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus", + "106": "wombat", + "107": "jellyfish", + "108": "sea anemone, anemone", + "109": "brain coral", + "110": "flatworm, platyhelminth", + "111": "nematode, nematode worm, roundworm", + "112": "conch", + "113": "snail", + "114": "slug", + "115": "sea slug, nudibranch", + "116": "chiton, coat-of-mail shell, sea cradle, polyplacophore", + "117": "chambered nautilus, pearly nautilus, nautilus", + "118": "Dungeness crab, Cancer magister", + "119": "rock crab, Cancer irroratus", + "120": "fiddler crab", + "121": "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica", + "122": "American lobster, Northern lobster, Maine lobster, Homarus americanus", + "123": "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish", + "124": "crayfish, crawfish, crawdad, crawdaddy", + "125": "hermit crab", + "126": "isopod", + "127": "white stork, Ciconia ciconia", + "128": "black stork, Ciconia nigra", + "129": "spoonbill", + "130": "flamingo", + "131": "little blue heron, Egretta caerulea", + "132": "American egret, great white heron, Egretta albus", + "133": "bittern", + "134": "crane", + "135": "limpkin, Aramus pictus", + "136": "European gallinule, Porphyrio porphyrio", + "137": "American coot, marsh hen, mud hen, water hen, Fulica americana", + "138": "bustard", + "139": "ruddy turnstone, Arenaria interpres", + "140": "red-backed sandpiper, dunlin, Erolia alpina", + "141": "redshank, Tringa totanus", + "142": "dowitcher", + "143": "oystercatcher, oyster catcher", + "144": "pelican", + "145": "king penguin, Aptenodytes patagonica", + "146": "albatross, mollymawk", + "147": "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus", + "148": "killer whale, killer, orca, grampus, sea wolf, Orcinus orca", + "149": "dugong, Dugong dugon", + "150": "sea lion", + "151": "Chihuahua", + "152": "Japanese spaniel", + "153": "Maltese dog, Maltese terrier, Maltese", + "154": "Pekinese, Pekingese, Peke", + "155": "Shih-Tzu", + "156": "Blenheim spaniel", + "157": "papillon", + "158": "toy terrier", + "159": "Rhodesian ridgeback", + "160": "Afghan hound, Afghan", + "161": "basset, basset hound", + "162": "beagle", + "163": "bloodhound, sleuthhound", + "164": "bluetick", + "165": "black-and-tan coonhound", + "166": "Walker hound, Walker foxhound", + "167": "English foxhound", + "168": "redbone", + "169": "borzoi, Russian wolfhound", + "170": "Irish wolfhound", + "171": "Italian greyhound", + "172": "whippet", + "173": "Ibizan hound, Ibizan Podenco", + "174": "Norwegian elkhound, elkhound", + "175": "otterhound, otter hound", + "176": "Saluki, gazelle hound", + "177": "Scottish deerhound, deerhound", + "178": "Weimaraner", + "179": "Staffordshire bullterrier, Staffordshire bull terrier", + "180": "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier", + "181": "Bedlington terrier", + "182": "Border terrier", + "183": "Kerry blue terrier", + "184": "Irish terrier", + "185": "Norfolk terrier", + "186": "Norwich terrier", + "187": "Yorkshire terrier", + "188": "wire-haired fox terrier", + "189": "Lakeland terrier", + "190": "Sealyham terrier, Sealyham", + "191": "Airedale, Airedale terrier", + "192": "cairn, cairn terrier", + "193": "Australian terrier", + "194": "Dandie Dinmont, Dandie Dinmont terrier", + "195": "Boston bull, Boston terrier", + "196": "miniature schnauzer", + "197": "giant schnauzer", + "198": "standard schnauzer", + "199": "Scotch terrier, Scottish terrier, Scottie", + "200": "Tibetan terrier, chrysanthemum dog", + "201": "silky terrier, Sydney silky", + "202": "soft-coated wheaten terrier", + "203": "West Highland white terrier", + "204": "Lhasa, Lhasa apso", + "205": "flat-coated retriever", + "206": "curly-coated retriever", + "207": "golden retriever", + "208": "Labrador retriever", + "209": "Chesapeake Bay retriever", + "210": "German short-haired pointer", + "211": "vizsla, Hungarian pointer", + "212": "English setter", + "213": "Irish setter, red setter", + "214": "Gordon setter", + "215": "Brittany spaniel", + "216": "clumber, clumber spaniel", + "217": "English springer, English springer spaniel", + "218": "Welsh springer spaniel", + "219": "cocker spaniel, English cocker spaniel, cocker", + "220": "Sussex spaniel", + "221": "Irish water spaniel", + "222": "kuvasz", + "223": "schipperke", + "224": "groenendael", + "225": "malinois", + "226": "briard", + "227": "kelpie", + "228": "komondor", + "229": "Old English sheepdog, bobtail", + "230": "Shetland sheepdog, Shetland sheep dog, Shetland", + "231": "collie", + "232": "Border collie", + "233": "Bouvier des Flandres, Bouviers des Flandres", + "234": "Rottweiler", + "235": "German shepherd, German shepherd dog, German police dog, alsatian", + "236": "Doberman, Doberman pinscher", + "237": "miniature pinscher", + "238": "Greater Swiss Mountain dog", + "239": "Bernese mountain dog", + "240": "Appenzeller", + "241": "EntleBucher", + "242": "boxer", + "243": "bull mastiff", + "244": "Tibetan mastiff", + "245": "French bulldog", + "246": "Great Dane", + "247": "Saint Bernard, St Bernard", + "248": "Eskimo dog, husky", + "249": "malamute, malemute, Alaskan malamute", + "250": "Siberian husky", + "251": "dalmatian, coach dog, carriage dog", + "252": "affenpinscher, monkey pinscher, monkey dog", + "253": "basenji", + "254": "pug, pug-dog", + "255": "Leonberg", + "256": "Newfoundland, Newfoundland dog", + "257": "Great Pyrenees", + "258": "Samoyed, Samoyede", + "259": "Pomeranian", + "260": "chow, chow chow", + "261": "keeshond", + "262": "Brabancon griffon", + "263": "Pembroke, Pembroke Welsh corgi", + "264": "Cardigan, Cardigan Welsh corgi", + "265": "toy poodle", + "266": "miniature poodle", + "267": "standard poodle", + "268": "Mexican hairless", + "269": "timber wolf, grey wolf, gray wolf, Canis lupus", + "270": "white wolf, Arctic wolf, Canis lupus tundrarum", + "271": "red wolf, maned wolf, Canis rufus, Canis niger", + "272": "coyote, prairie wolf, brush wolf, Canis latrans", + "273": "dingo, warrigal, warragal, Canis dingo", + "274": "dhole, Cuon alpinus", + "275": "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus", + "276": "hyena, hyaena", + "277": "red fox, Vulpes vulpes", + "278": "kit fox, Vulpes macrotis", + "279": "Arctic fox, white fox, Alopex lagopus", + "280": "grey fox, gray fox, Urocyon cinereoargenteus", + "281": "tabby, tabby cat", + "282": "tiger cat", + "283": "Persian cat", + "284": "Siamese cat, Siamese", + "285": "Egyptian cat", + "286": "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor", + "287": "lynx, catamount", + "288": "leopard, Panthera pardus", + "289": "snow leopard, ounce, Panthera uncia", + "290": "jaguar, panther, Panthera onca, Felis onca", + "291": "lion, king of beasts, Panthera leo", + "292": "tiger, Panthera tigris", + "293": "cheetah, chetah, Acinonyx jubatus", + "294": "brown bear, bruin, Ursus arctos", + "295": "American black bear, black bear, Ursus americanus, Euarctos americanus", + "296": "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus", + "297": "sloth bear, Melursus ursinus, Ursus ursinus", + "298": "mongoose", + "299": "meerkat, mierkat", + "300": "tiger beetle", + "301": "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle", + "302": "ground beetle, carabid beetle", + "303": "long-horned beetle, longicorn, longicorn beetle", + "304": "leaf beetle, chrysomelid", + "305": "dung beetle", + "306": "rhinoceros beetle", + "307": "weevil", + "308": "fly", + "309": "bee", + "310": "ant, emmet, pismire", + "311": "grasshopper, hopper", + "312": "cricket", + "313": "walking stick, walkingstick, stick insect", + "314": "cockroach, roach", + "315": "mantis, mantid", + "316": "cicada, cicala", + "317": "leafhopper", + "318": "lacewing, lacewing fly", + "319": "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk", + "320": "damselfly", + "321": "admiral", + "322": "ringlet, ringlet butterfly", + "323": "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus", + "324": "cabbage butterfly", + "325": "sulphur butterfly, sulfur butterfly", + "326": "lycaenid, lycaenid butterfly", + "327": "starfish, sea star", + "328": "sea urchin", + "329": "sea cucumber, holothurian", + "330": "wood rabbit, cottontail, cottontail rabbit", + "331": "hare", + "332": "Angora, Angora rabbit", + "333": "hamster", + "334": "porcupine, hedgehog", + "335": "fox squirrel, eastern fox squirrel, Sciurus niger", + "336": "marmot", + "337": "beaver", + "338": "guinea pig, Cavia cobaya", + "339": "sorrel", + "340": "zebra", + "341": "hog, pig, grunter, squealer, Sus scrofa", + "342": "wild boar, boar, Sus scrofa", + "343": "warthog", + "344": "hippopotamus, hippo, river horse, Hippopotamus amphibius", + "345": "ox", + "346": "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis", + "347": "bison", + "348": "ram, tup", + "349": "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis", + "350": "ibex, Capra ibex", + "351": "hartebeest", + "352": "impala, Aepyceros melampus", + "353": "gazelle", + "354": "Arabian camel, dromedary, Camelus dromedarius", + "355": "llama", + "356": "weasel", + "357": "mink", + "358": "polecat, fitch, foulmart, foumart, Mustela putorius", + "359": "black-footed ferret, ferret, Mustela nigripes", + "360": "otter", + "361": "skunk, polecat, wood pussy", + "362": "badger", + "363": "armadillo", + "364": "three-toed sloth, ai, Bradypus tridactylus", + "365": "orangutan, orang, orangutang, Pongo pygmaeus", + "366": "gorilla, Gorilla gorilla", + "367": "chimpanzee, chimp, Pan troglodytes", + "368": "gibbon, Hylobates lar", + "369": "siamang, Hylobates syndactylus, Symphalangus syndactylus", + "370": "guenon, guenon monkey", + "371": "patas, hussar monkey, Erythrocebus patas", + "372": "baboon", + "373": "macaque", + "374": "langur", + "375": "colobus, colobus monkey", + "376": "proboscis monkey, Nasalis larvatus", + "377": "marmoset", + "378": "capuchin, ringtail, Cebus capucinus", + "379": "howler monkey, howler", + "380": "titi, titi monkey", + "381": "spider monkey, Ateles geoffroyi", + "382": "squirrel monkey, Saimiri sciureus", + "383": "Madagascar cat, ring-tailed lemur, Lemur catta", + "384": "indri, indris, Indri indri, Indri brevicaudatus", + "385": "Indian elephant, Elephas maximus", + "386": "African elephant, Loxodonta africana", + "387": "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens", + "388": "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca", + "389": "barracouta, snoek", + "390": "eel", + "391": "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch", + "392": "rock beauty, Holocanthus tricolor", + "393": "anemone fish", + "394": "sturgeon", + "395": "gar, garfish, garpike, billfish, Lepisosteus osseus", + "396": "lionfish", + "397": "puffer, pufferfish, blowfish, globefish", + "398": "abacus", + "399": "abaya", + "400": "academic gown, academic robe, judge's robe", + "401": "accordion, piano accordion, squeeze box", + "402": "acoustic guitar", + "403": "aircraft carrier, carrier, flattop, attack aircraft carrier", + "404": "airliner", + "405": "airship, dirigible", + "406": "altar", + "407": "ambulance", + "408": "amphibian, amphibious vehicle", + "409": "analog clock", + "410": "apiary, bee house", + "411": "apron", + "412": "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin", + "413": "assault rifle, assault gun", + "414": "backpack, back pack, knapsack, packsack, rucksack, haversack", + "415": "bakery, bakeshop, bakehouse", + "416": "balance beam, beam", + "417": "balloon", + "418": "ballpoint, ballpoint pen, ballpen, Biro", + "419": "Band Aid", + "420": "banjo", + "421": "bannister, banister, balustrade, balusters, handrail", + "422": "barbell", + "423": "barber chair", + "424": "barbershop", + "425": "barn", + "426": "barometer", + "427": "barrel, cask", + "428": "barrow, garden cart, lawn cart, wheelbarrow", + "429": "baseball", + "430": "basketball", + "431": "bassinet", + "432": "bassoon", + "433": "bathing cap, swimming cap", + "434": "bath towel", + "435": "bathtub, bathing tub, bath, tub", + "436": "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon", + "437": "beacon, lighthouse, beacon light, pharos", + "438": "beaker", + "439": "bearskin, busby, shako", + "440": "beer bottle", + "441": "beer glass", + "442": "bell cote, bell cot", + "443": "bib", + "444": "bicycle-built-for-two, tandem bicycle, tandem", + "445": "bikini, two-piece", + "446": "binder, ring-binder", + "447": "binoculars, field glasses, opera glasses", + "448": "birdhouse", + "449": "boathouse", + "450": "bobsled, bobsleigh, bob", + "451": "bolo tie, bolo, bola tie, bola", + "452": "bonnet, poke bonnet", + "453": "bookcase", + "454": "bookshop, bookstore, bookstall", + "455": "bottlecap", + "456": "bow", + "457": "bow tie, bow-tie, bowtie", + "458": "brass, memorial tablet, plaque", + "459": "brassiere, bra, bandeau", + "460": "breakwater, groin, groyne, mole, bulwark, seawall, jetty", + "461": "breastplate, aegis, egis", + "462": "broom", + "463": "bucket, pail", + "464": "buckle", + "465": "bulletproof vest", + "466": "bullet train, bullet", + "467": "butcher shop, meat market", + "468": "cab, hack, taxi, taxicab", + "469": "caldron, cauldron", + "470": "candle, taper, wax light", + "471": "cannon", + "472": "canoe", + "473": "can opener, tin opener", + "474": "cardigan", + "475": "car mirror", + "476": "carousel, carrousel, merry-go-round, roundabout, whirligig", + "477": "carpenter's kit, tool kit", + "478": "carton", + "479": "car wheel", + "480": "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM", + "481": "cassette", + "482": "cassette player", + "483": "castle", + "484": "catamaran", + "485": "CD player", + "486": "cello, violoncello", + "487": "cellular telephone, cellular phone, cellphone, cell, mobile phone", + "488": "chain", + "489": "chainlink fence", + "490": "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour", + "491": "chain saw, chainsaw", + "492": "chest", + "493": "chiffonier, commode", + "494": "chime, bell, gong", + "495": "china cabinet, china closet", + "496": "Christmas stocking", + "497": "church, church building", + "498": "cinema, movie theater, movie theatre, movie house, picture palace", + "499": "cleaver, meat cleaver, chopper", + "500": "cliff dwelling", + "501": "cloak", + "502": "clog, geta, patten, sabot", + "503": "cocktail shaker", + "504": "coffee mug", + "505": "coffeepot", + "506": "coil, spiral, volute, whorl, helix", + "507": "combination lock", + "508": "computer keyboard, keypad", + "509": "confectionery, confectionary, candy store", + "510": "container ship, containership, container vessel", + "511": "convertible", + "512": "corkscrew, bottle screw", + "513": "cornet, horn, trumpet, trump", + "514": "cowboy boot", + "515": "cowboy hat, ten-gallon hat", + "516": "cradle", + "517": "crane", + "518": "crash helmet", + "519": "crate", + "520": "crib, cot", + "521": "Crock Pot", + "522": "croquet ball", + "523": "crutch", + "524": "cuirass", + "525": "dam, dike, dyke", + "526": "desk", + "527": "desktop computer", + "528": "dial telephone, dial phone", + "529": "diaper, nappy, napkin", + "530": "digital clock", + "531": "digital watch", + "532": "dining table, board", + "533": "dishrag, dishcloth", + "534": "dishwasher, dish washer, dishwashing machine", + "535": "disk brake, disc brake", + "536": "dock, dockage, docking facility", + "537": "dogsled, dog sled, dog sleigh", + "538": "dome", + "539": "doormat, welcome mat", + "540": "drilling platform, offshore rig", + "541": "drum, membranophone, tympan", + "542": "drumstick", + "543": "dumbbell", + "544": "Dutch oven", + "545": "electric fan, blower", + "546": "electric guitar", + "547": "electric locomotive", + "548": "entertainment center", + "549": "envelope", + "550": "espresso maker", + "551": "face powder", + "552": "feather boa, boa", + "553": "file, file cabinet, filing cabinet", + "554": "fireboat", + "555": "fire engine, fire truck", + "556": "fire screen, fireguard", + "557": "flagpole, flagstaff", + "558": "flute, transverse flute", + "559": "folding chair", + "560": "football helmet", + "561": "forklift", + "562": "fountain", + "563": "fountain pen", + "564": "four-poster", + "565": "freight car", + "566": "French horn, horn", + "567": "frying pan, frypan, skillet", + "568": "fur coat", + "569": "garbage truck, dustcart", + "570": "gasmask, respirator, gas helmet", + "571": "gas pump, gasoline pump, petrol pump, island dispenser", + "572": "goblet", + "573": "go-kart", + "574": "golf ball", + "575": "golfcart, golf cart", + "576": "gondola", + "577": "gong, tam-tam", + "578": "gown", + "579": "grand piano, grand", + "580": "greenhouse, nursery, glasshouse", + "581": "grille, radiator grille", + "582": "grocery store, grocery, food market, market", + "583": "guillotine", + "584": "hair slide", + "585": "hair spray", + "586": "half track", + "587": "hammer", + "588": "hamper", + "589": "hand blower, blow dryer, blow drier, hair dryer, hair drier", + "590": "hand-held computer, hand-held microcomputer", + "591": "handkerchief, hankie, hanky, hankey", + "592": "hard disc, hard disk, fixed disk", + "593": "harmonica, mouth organ, harp, mouth harp", + "594": "harp", + "595": "harvester, reaper", + "596": "hatchet", + "597": "holster", + "598": "home theater, home theatre", + "599": "honeycomb", + "600": "hook, claw", + "601": "hoopskirt, crinoline", + "602": "horizontal bar, high bar", + "603": "horse cart, horse-cart", + "604": "hourglass", + "605": "iPod", + "606": "iron, smoothing iron", + "607": "jack-o'-lantern", + "608": "jean, blue jean, denim", + "609": "jeep, landrover", + "610": "jersey, T-shirt, tee shirt", + "611": "jigsaw puzzle", + "612": "jinrikisha, ricksha, rickshaw", + "613": "joystick", + "614": "kimono", + "615": "knee pad", + "616": "knot", + "617": "lab coat, laboratory coat", + "618": "ladle", + "619": "lampshade, lamp shade", + "620": "laptop, laptop computer", + "621": "lawn mower, mower", + "622": "lens cap, lens cover", + "623": "letter opener, paper knife, paperknife", + "624": "library", + "625": "lifeboat", + "626": "lighter, light, igniter, ignitor", + "627": "limousine, limo", + "628": "liner, ocean liner", + "629": "lipstick, lip rouge", + "630": "Loafer", + "631": "lotion", + "632": "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system", + "633": "loupe, jeweler's loupe", + "634": "lumbermill, sawmill", + "635": "magnetic compass", + "636": "mailbag, postbag", + "637": "mailbox, letter box", + "638": "maillot", + "639": "maillot, tank suit", + "640": "manhole cover", + "641": "maraca", + "642": "marimba, xylophone", + "643": "mask", + "644": "matchstick", + "645": "maypole", + "646": "maze, labyrinth", + "647": "measuring cup", + "648": "medicine chest, medicine cabinet", + "649": "megalith, megalithic structure", + "650": "microphone, mike", + "651": "microwave, microwave oven", + "652": "military uniform", + "653": "milk can", + "654": "minibus", + "655": "miniskirt, mini", + "656": "minivan", + "657": "missile", + "658": "mitten", + "659": "mixing bowl", + "660": "mobile home, manufactured home", + "661": "Model T", + "662": "modem", + "663": "monastery", + "664": "monitor", + "665": "moped", + "666": "mortar", + "667": "mortarboard", + "668": "mosque", + "669": "mosquito net", + "670": "motor scooter, scooter", + "671": "mountain bike, all-terrain bike, off-roader", + "672": "mountain tent", + "673": "mouse, computer mouse", + "674": "mousetrap", + "675": "moving van", + "676": "muzzle", + "677": "nail", + "678": "neck brace", + "679": "necklace", + "680": "nipple", + "681": "notebook, notebook computer", + "682": "obelisk", + "683": "oboe, hautboy, hautbois", + "684": "ocarina, sweet potato", + "685": "odometer, hodometer, mileometer, milometer", + "686": "oil filter", + "687": "organ, pipe organ", + "688": "oscilloscope, scope, cathode-ray oscilloscope, CRO", + "689": "overskirt", + "690": "oxcart", + "691": "oxygen mask", + "692": "packet", + "693": "paddle, boat paddle", + "694": "paddlewheel, paddle wheel", + "695": "padlock", + "696": "paintbrush", + "697": "pajama, pyjama, pj's, jammies", + "698": "palace", + "699": "panpipe, pandean pipe, syrinx", + "700": "paper towel", + "701": "parachute, chute", + "702": "parallel bars, bars", + "703": "park bench", + "704": "parking meter", + "705": "passenger car, coach, carriage", + "706": "patio, terrace", + "707": "pay-phone, pay-station", + "708": "pedestal, plinth, footstall", + "709": "pencil box, pencil case", + "710": "pencil sharpener", + "711": "perfume, essence", + "712": "Petri dish", + "713": "photocopier", + "714": "pick, plectrum, plectron", + "715": "pickelhaube", + "716": "picket fence, paling", + "717": "pickup, pickup truck", + "718": "pier", + "719": "piggy bank, penny bank", + "720": "pill bottle", + "721": "pillow", + "722": "ping-pong ball", + "723": "pinwheel", + "724": "pirate, pirate ship", + "725": "pitcher, ewer", + "726": "plane, carpenter's plane, woodworking plane", + "727": "planetarium", + "728": "plastic bag", + "729": "plate rack", + "730": "plow, plough", + "731": "plunger, plumber's helper", + "732": "Polaroid camera, Polaroid Land camera", + "733": "pole", + "734": "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria", + "735": "poncho", + "736": "pool table, billiard table, snooker table", + "737": "pop bottle, soda bottle", + "738": "pot, flowerpot", + "739": "potter's wheel", + "740": "power drill", + "741": "prayer rug, prayer mat", + "742": "printer", + "743": "prison, prison house", + "744": "projectile, missile", + "745": "projector", + "746": "puck, hockey puck", + "747": "punching bag, punch bag, punching ball, punchball", + "748": "purse", + "749": "quill, quill pen", + "750": "quilt, comforter, comfort, puff", + "751": "racer, race car, racing car", + "752": "racket, racquet", + "753": "radiator", + "754": "radio, wireless", + "755": "radio telescope, radio reflector", + "756": "rain barrel", + "757": "recreational vehicle, RV, R.V.", + "758": "reel", + "759": "reflex camera", + "760": "refrigerator, icebox", + "761": "remote control, remote", + "762": "restaurant, eating house, eating place, eatery", + "763": "revolver, six-gun, six-shooter", + "764": "rifle", + "765": "rocking chair, rocker", + "766": "rotisserie", + "767": "rubber eraser, rubber, pencil eraser", + "768": "rugby ball", + "769": "rule, ruler", + "770": "running shoe", + "771": "safe", + "772": "safety pin", + "773": "saltshaker, salt shaker", + "774": "sandal", + "775": "sarong", + "776": "sax, saxophone", + "777": "scabbard", + "778": "scale, weighing machine", + "779": "school bus", + "780": "schooner", + "781": "scoreboard", + "782": "screen, CRT screen", + "783": "screw", + "784": "screwdriver", + "785": "seat belt, seatbelt", + "786": "sewing machine", + "787": "shield, buckler", + "788": "shoe shop, shoe-shop, shoe store", + "789": "shoji", + "790": "shopping basket", + "791": "shopping cart", + "792": "shovel", + "793": "shower cap", + "794": "shower curtain", + "795": "ski", + "796": "ski mask", + "797": "sleeping bag", + "798": "slide rule, slipstick", + "799": "sliding door", + "800": "slot, one-armed bandit", + "801": "snorkel", + "802": "snowmobile", + "803": "snowplow, snowplough", + "804": "soap dispenser", + "805": "soccer ball", + "806": "sock", + "807": "solar dish, solar collector, solar furnace", + "808": "sombrero", + "809": "soup bowl", + "810": "space bar", + "811": "space heater", + "812": "space shuttle", + "813": "spatula", + "814": "speedboat", + "815": "spider web, spider's web", + "816": "spindle", + "817": "sports car, sport car", + "818": "spotlight, spot", + "819": "stage", + "820": "steam locomotive", + "821": "steel arch bridge", + "822": "steel drum", + "823": "stethoscope", + "824": "stole", + "825": "stone wall", + "826": "stopwatch, stop watch", + "827": "stove", + "828": "strainer", + "829": "streetcar, tram, tramcar, trolley, trolley car", + "830": "stretcher", + "831": "studio couch, day bed", + "832": "stupa, tope", + "833": "submarine, pigboat, sub, U-boat", + "834": "suit, suit of clothes", + "835": "sundial", + "836": "sunglass", + "837": "sunglasses, dark glasses, shades", + "838": "sunscreen, sunblock, sun blocker", + "839": "suspension bridge", + "840": "swab, swob, mop", + "841": "sweatshirt", + "842": "swimming trunks, bathing trunks", + "843": "swing", + "844": "switch, electric switch, electrical switch", + "845": "syringe", + "846": "table lamp", + "847": "tank, army tank, armored combat vehicle, armoured combat vehicle", + "848": "tape player", + "849": "teapot", + "850": "teddy, teddy bear", + "851": "television, television system", + "852": "tennis ball", + "853": "thatch, thatched roof", + "854": "theater curtain, theatre curtain", + "855": "thimble", + "856": "thresher, thrasher, threshing machine", + "857": "throne", + "858": "tile roof", + "859": "toaster", + "860": "tobacco shop, tobacconist shop, tobacconist", + "861": "toilet seat", + "862": "torch", + "863": "totem pole", + "864": "tow truck, tow car, wrecker", + "865": "toyshop", + "866": "tractor", + "867": "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi", + "868": "tray", + "869": "trench coat", + "870": "tricycle, trike, velocipede", + "871": "trimaran", + "872": "tripod", + "873": "triumphal arch", + "874": "trolleybus, trolley coach, trackless trolley", + "875": "trombone", + "876": "tub, vat", + "877": "turnstile", + "878": "typewriter keyboard", + "879": "umbrella", + "880": "unicycle, monocycle", + "881": "upright, upright piano", + "882": "vacuum, vacuum cleaner", + "883": "vase", + "884": "vault", + "885": "velvet", + "886": "vending machine", + "887": "vestment", + "888": "viaduct", + "889": "violin, fiddle", + "890": "volleyball", + "891": "waffle iron", + "892": "wall clock", + "893": "wallet, billfold, notecase, pocketbook", + "894": "wardrobe, closet, press", + "895": "warplane, military plane", + "896": "washbasin, handbasin, washbowl, lavabo, wash-hand basin", + "897": "washer, automatic washer, washing machine", + "898": "water bottle", + "899": "water jug", + "900": "water tower", + "901": "whiskey jug", + "902": "whistle", + "903": "wig", + "904": "window screen", + "905": "window shade", + "906": "Windsor tie", + "907": "wine bottle", + "908": "wing", + "909": "wok", + "910": "wooden spoon", + "911": "wool, woolen, woollen", + "912": "worm fence, snake fence, snake-rail fence, Virginia fence", + "913": "wreck", + "914": "yawl", + "915": "yurt", + "916": "web site, website, internet site, site", + "917": "comic book", + "918": "crossword puzzle, crossword", + "919": "street sign", + "920": "traffic light, traffic signal, stoplight", + "921": "book jacket, dust cover, dust jacket, dust wrapper", + "922": "menu", + "923": "plate", + "924": "guacamole", + "925": "consomme", + "926": "hot pot, hotpot", + "927": "trifle", + "928": "ice cream, icecream", + "929": "ice lolly, lolly, lollipop, popsicle", + "930": "French loaf", + "931": "bagel, beigel", + "932": "pretzel", + "933": "cheeseburger", + "934": "hotdog, hot dog, red hot", + "935": "mashed potato", + "936": "head cabbage", + "937": "broccoli", + "938": "cauliflower", + "939": "zucchini, courgette", + "940": "spaghetti squash", + "941": "acorn squash", + "942": "butternut squash", + "943": "cucumber, cuke", + "944": "artichoke, globe artichoke", + "945": "bell pepper", + "946": "cardoon", + "947": "mushroom", + "948": "Granny Smith", + "949": "strawberry", + "950": "orange", + "951": "lemon", + "952": "fig", + "953": "pineapple, ananas", + "954": "banana", + "955": "jackfruit, jak, jack", + "956": "custard apple", + "957": "pomegranate", + "958": "hay", + "959": "carbonara", + "960": "chocolate sauce, chocolate syrup", + "961": "dough", + "962": "meat loaf, meatloaf", + "963": "pizza, pizza pie", + "964": "potpie", + "965": "burrito", + "966": "red wine", + "967": "espresso", + "968": "cup", + "969": "eggnog", + "970": "alp", + "971": "bubble", + "972": "cliff, drop, drop-off", + "973": "coral reef", + "974": "geyser", + "975": "lakeside, lakeshore", + "976": "promontory, headland, head, foreland", + "977": "sandbar, sand bar", + "978": "seashore, coast, seacoast, sea-coast", + "979": "valley, vale", + "980": "volcano", + "981": "ballplayer, baseball player", + "982": "groom, bridegroom", + "983": "scuba diver", + "984": "rapeseed", + "985": "daisy", + "986": "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum", + "987": "corn", + "988": "acorn", + "989": "hip, rose hip, rosehip", + "990": "buckeye, horse chestnut, conker", + "991": "coral fungus", + "992": "agaric", + "993": "gyromitra", + "994": "stinkhorn, carrion fungus", + "995": "earthstar", + "996": "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa", + "997": "bolete", + "998": "ear, spike, capitulum", + "999": "toilet tissue, toilet paper, bathroom tissue" + }, + "image_size": 224, + "in_channels": [ + 32, + 16, + 24, + 40, + 80, + 112, + 192 + ], + "initializer_range": 0.02, + "kernel_sizes": [ + 3, + 3, + 5, + 3, + 5, + 5, + 3 + ], + "label2id": { + "Afghan hound, Afghan": 160, + "African chameleon, Chamaeleo chamaeleon": 47, + "African crocodile, Nile crocodile, Crocodylus niloticus": 49, + "African elephant, Loxodonta africana": 386, + "African grey, African gray, Psittacus erithacus": 87, + "African hunting dog, hyena dog, Cape hunting dog, Lycaon pictus": 275, + "Airedale, Airedale terrier": 191, + "American Staffordshire terrier, Staffordshire terrier, American pit bull terrier, pit bull terrier": 180, + "American alligator, Alligator mississipiensis": 50, + "American black bear, black bear, Ursus americanus, Euarctos americanus": 295, + "American chameleon, anole, Anolis carolinensis": 40, + "American coot, marsh hen, mud hen, water hen, Fulica americana": 137, + "American egret, great white heron, Egretta albus": 132, + "American lobster, Northern lobster, Maine lobster, Homarus americanus": 122, + "Angora, Angora rabbit": 332, + "Appenzeller": 240, + "Arabian camel, dromedary, Camelus dromedarius": 354, + "Arctic fox, white fox, Alopex lagopus": 279, + "Australian terrier": 193, + "Band Aid": 419, + "Bedlington terrier": 181, + "Bernese mountain dog": 239, + "Blenheim spaniel": 156, + "Border collie": 232, + "Border terrier": 182, + "Boston bull, Boston terrier": 195, + "Bouvier des Flandres, Bouviers des Flandres": 233, + "Brabancon griffon": 262, + "Brittany spaniel": 215, + "CD player": 485, + "Cardigan, Cardigan Welsh corgi": 264, + "Chesapeake Bay retriever": 209, + "Chihuahua": 151, + "Christmas stocking": 496, + "Crock Pot": 521, + "Dandie Dinmont, Dandie Dinmont terrier": 194, + "Doberman, Doberman pinscher": 236, + "Dungeness crab, Cancer magister": 118, + "Dutch oven": 544, + "Egyptian cat": 285, + "English foxhound": 167, + "English setter": 212, + "English springer, English springer spaniel": 217, + "EntleBucher": 241, + "Eskimo dog, husky": 248, + "European fire salamander, Salamandra salamandra": 25, + "European gallinule, Porphyrio porphyrio": 136, + "French bulldog": 245, + "French horn, horn": 566, + "French loaf": 930, + "German shepherd, German shepherd dog, German police dog, alsatian": 235, + "German short-haired pointer": 210, + "Gila monster, Heloderma suspectum": 45, + "Gordon setter": 214, + "Granny Smith": 948, + "Great Dane": 246, + "Great Pyrenees": 257, + "Greater Swiss Mountain dog": 238, + "Ibizan hound, Ibizan Podenco": 173, + "Indian cobra, Naja naja": 63, + "Indian elephant, Elephas maximus": 385, + "Irish setter, red setter": 213, + "Irish terrier": 184, + "Irish water spaniel": 221, + "Irish wolfhound": 170, + "Italian greyhound": 171, + "Japanese spaniel": 152, + "Kerry blue terrier": 183, + "Komodo dragon, Komodo lizard, dragon lizard, giant lizard, Varanus komodoensis": 48, + "Labrador retriever": 208, + "Lakeland terrier": 189, + "Leonberg": 255, + "Lhasa, Lhasa apso": 204, + "Loafer": 630, + "Madagascar cat, ring-tailed lemur, Lemur catta": 383, + "Maltese dog, Maltese terrier, Maltese": 153, + "Mexican hairless": 268, + "Model T": 661, + "Newfoundland, Newfoundland dog": 256, + "Norfolk terrier": 185, + "Norwegian elkhound, elkhound": 174, + "Norwich terrier": 186, + "Old English sheepdog, bobtail": 229, + "Pekinese, Pekingese, Peke": 154, + "Pembroke, Pembroke Welsh corgi": 263, + "Persian cat": 283, + "Petri dish": 712, + "Polaroid camera, Polaroid Land camera": 732, + "Pomeranian": 259, + "Rhodesian ridgeback": 159, + "Rottweiler": 234, + "Saint Bernard, St Bernard": 247, + "Saluki, gazelle hound": 176, + "Samoyed, Samoyede": 258, + "Scotch terrier, Scottish terrier, Scottie": 199, + "Scottish deerhound, deerhound": 177, + "Sealyham terrier, Sealyham": 190, + "Shetland sheepdog, Shetland sheep dog, Shetland": 230, + "Shih-Tzu": 155, + "Siamese cat, Siamese": 284, + "Siberian husky": 250, + "Staffordshire bullterrier, Staffordshire bull terrier": 179, + "Sussex spaniel": 220, + "Tibetan mastiff": 244, + "Tibetan terrier, chrysanthemum dog": 200, + "Walker hound, Walker foxhound": 166, + "Weimaraner": 178, + "Welsh springer spaniel": 218, + "West Highland white terrier": 203, + "Windsor tie": 906, + "Yorkshire terrier": 187, + "abacus": 398, + "abaya": 399, + "academic gown, academic robe, judge's robe": 400, + "accordion, piano accordion, squeeze box": 401, + "acorn": 988, + "acorn squash": 941, + "acoustic guitar": 402, + "admiral": 321, + "affenpinscher, monkey pinscher, monkey dog": 252, + "agama": 42, + "agaric": 992, + "aircraft carrier, carrier, flattop, attack aircraft carrier": 403, + "airliner": 404, + "airship, dirigible": 405, + "albatross, mollymawk": 146, + "alligator lizard": 44, + "alp": 970, + "altar": 406, + "ambulance": 407, + "amphibian, amphibious vehicle": 408, + "analog clock": 409, + "anemone fish": 393, + "ant, emmet, pismire": 310, + "apiary, bee house": 410, + "apron": 411, + "armadillo": 363, + "artichoke, globe artichoke": 944, + "ashcan, trash can, garbage can, wastebin, ash bin, ash-bin, ashbin, dustbin, trash barrel, trash bin": 412, + "assault rifle, assault gun": 413, + "axolotl, mud puppy, Ambystoma mexicanum": 29, + "baboon": 372, + "backpack, back pack, knapsack, packsack, rucksack, haversack": 414, + "badger": 362, + "bagel, beigel": 931, + "bakery, bakeshop, bakehouse": 415, + "balance beam, beam": 416, + "bald eagle, American eagle, Haliaeetus leucocephalus": 22, + "balloon": 417, + "ballplayer, baseball player": 981, + "ballpoint, ballpoint pen, ballpen, Biro": 418, + "banana": 954, + "banded gecko": 38, + "banjo": 420, + "bannister, banister, balustrade, balusters, handrail": 421, + "barbell": 422, + "barber chair": 423, + "barbershop": 424, + "barn": 425, + "barn spider, Araneus cavaticus": 73, + "barometer": 426, + "barracouta, snoek": 389, + "barrel, cask": 427, + "barrow, garden cart, lawn cart, wheelbarrow": 428, + "baseball": 429, + "basenji": 253, + "basketball": 430, + "basset, basset hound": 161, + "bassinet": 431, + "bassoon": 432, + "bath towel": 434, + "bathing cap, swimming cap": 433, + "bathtub, bathing tub, bath, tub": 435, + "beach wagon, station wagon, wagon, estate car, beach waggon, station waggon, waggon": 436, + "beacon, lighthouse, beacon light, pharos": 437, + "beagle": 162, + "beaker": 438, + "bearskin, busby, shako": 439, + "beaver": 337, + "bee": 309, + "bee eater": 92, + "beer bottle": 440, + "beer glass": 441, + "bell cote, bell cot": 442, + "bell pepper": 945, + "bib": 443, + "bicycle-built-for-two, tandem bicycle, tandem": 444, + "bighorn, bighorn sheep, cimarron, Rocky Mountain bighorn, Rocky Mountain sheep, Ovis canadensis": 349, + "bikini, two-piece": 445, + "binder, ring-binder": 446, + "binoculars, field glasses, opera glasses": 447, + "birdhouse": 448, + "bison": 347, + "bittern": 133, + "black and gold garden spider, Argiope aurantia": 72, + "black grouse": 80, + "black stork, Ciconia nigra": 128, + "black swan, Cygnus atratus": 100, + "black widow, Latrodectus mactans": 75, + "black-and-tan coonhound": 165, + "black-footed ferret, ferret, Mustela nigripes": 359, + "bloodhound, sleuthhound": 163, + "bluetick": 164, + "boa constrictor, Constrictor constrictor": 61, + "boathouse": 449, + "bobsled, bobsleigh, bob": 450, + "bolete": 997, + "bolo tie, bolo, bola tie, bola": 451, + "bonnet, poke bonnet": 452, + "book jacket, dust cover, dust jacket, dust wrapper": 921, + "bookcase": 453, + "bookshop, bookstore, bookstall": 454, + "borzoi, Russian wolfhound": 169, + "bottlecap": 455, + "bow": 456, + "bow tie, bow-tie, bowtie": 457, + "box turtle, box tortoise": 37, + "boxer": 242, + "brain coral": 109, + "brambling, Fringilla montifringilla": 10, + "brass, memorial tablet, plaque": 458, + "brassiere, bra, bandeau": 459, + "breakwater, groin, groyne, mole, bulwark, seawall, jetty": 460, + "breastplate, aegis, egis": 461, + "briard": 226, + "broccoli": 937, + "broom": 462, + "brown bear, bruin, Ursus arctos": 294, + "bubble": 971, + "bucket, pail": 463, + "buckeye, horse chestnut, conker": 990, + "buckle": 464, + "bulbul": 16, + "bull mastiff": 243, + "bullet train, bullet": 466, + "bulletproof vest": 465, + "bullfrog, Rana catesbeiana": 30, + "burrito": 965, + "bustard": 138, + "butcher shop, meat market": 467, + "butternut squash": 942, + "cab, hack, taxi, taxicab": 468, + "cabbage butterfly": 324, + "cairn, cairn terrier": 192, + "caldron, cauldron": 469, + "can opener, tin opener": 473, + "candle, taper, wax light": 470, + "cannon": 471, + "canoe": 472, + "capuchin, ringtail, Cebus capucinus": 378, + "car mirror": 475, + "car wheel": 479, + "carbonara": 959, + "cardigan": 474, + "cardoon": 946, + "carousel, carrousel, merry-go-round, roundabout, whirligig": 476, + "carpenter's kit, tool kit": 477, + "carton": 478, + "cash machine, cash dispenser, automated teller machine, automatic teller machine, automated teller, automatic teller, ATM": 480, + "cassette": 481, + "cassette player": 482, + "castle": 483, + "catamaran": 484, + "cauliflower": 938, + "cello, violoncello": 486, + "cellular telephone, cellular phone, cellphone, cell, mobile phone": 487, + "centipede": 79, + "chain": 488, + "chain mail, ring mail, mail, chain armor, chain armour, ring armor, ring armour": 490, + "chain saw, chainsaw": 491, + "chainlink fence": 489, + "chambered nautilus, pearly nautilus, nautilus": 117, + "cheeseburger": 933, + "cheetah, chetah, Acinonyx jubatus": 293, + "chest": 492, + "chickadee": 19, + "chiffonier, commode": 493, + "chime, bell, gong": 494, + "chimpanzee, chimp, Pan troglodytes": 367, + "china cabinet, china closet": 495, + "chiton, coat-of-mail shell, sea cradle, polyplacophore": 116, + "chocolate sauce, chocolate syrup": 960, + "chow, chow chow": 260, + "church, church building": 497, + "cicada, cicala": 316, + "cinema, movie theater, movie theatre, movie house, picture palace": 498, + "cleaver, meat cleaver, chopper": 499, + "cliff dwelling": 500, + "cliff, drop, drop-off": 972, + "cloak": 501, + "clog, geta, patten, sabot": 502, + "clumber, clumber spaniel": 216, + "cock": 7, + "cocker spaniel, English cocker spaniel, cocker": 219, + "cockroach, roach": 314, + "cocktail shaker": 503, + "coffee mug": 504, + "coffeepot": 505, + "coho, cohoe, coho salmon, blue jack, silver salmon, Oncorhynchus kisutch": 391, + "coil, spiral, volute, whorl, helix": 506, + "collie": 231, + "colobus, colobus monkey": 375, + "combination lock": 507, + "comic book": 917, + "common iguana, iguana, Iguana iguana": 39, + "common newt, Triturus vulgaris": 26, + "computer keyboard, keypad": 508, + "conch": 112, + "confectionery, confectionary, candy store": 509, + "consomme": 925, + "container ship, containership, container vessel": 510, + "convertible": 511, + "coral fungus": 991, + "coral reef": 973, + "corkscrew, bottle screw": 512, + "corn": 987, + "cornet, horn, trumpet, trump": 513, + "coucal": 91, + "cougar, puma, catamount, mountain lion, painter, panther, Felis concolor": 286, + "cowboy boot": 514, + "cowboy hat, ten-gallon hat": 515, + "coyote, prairie wolf, brush wolf, Canis latrans": 272, + "cradle": 516, + "crane": 517, + "crash helmet": 518, + "crate": 519, + "crayfish, crawfish, crawdad, crawdaddy": 124, + "crib, cot": 520, + "cricket": 312, + "croquet ball": 522, + "crossword puzzle, crossword": 918, + "crutch": 523, + "cucumber, cuke": 943, + "cuirass": 524, + "cup": 968, + "curly-coated retriever": 206, + "custard apple": 956, + "daisy": 985, + "dalmatian, coach dog, carriage dog": 251, + "dam, dike, dyke": 525, + "damselfly": 320, + "desk": 526, + "desktop computer": 527, + "dhole, Cuon alpinus": 274, + "dial telephone, dial phone": 528, + "diamondback, diamondback rattlesnake, Crotalus adamanteus": 67, + "diaper, nappy, napkin": 529, + "digital clock": 530, + "digital watch": 531, + "dingo, warrigal, warragal, Canis dingo": 273, + "dining table, board": 532, + "dishrag, dishcloth": 533, + "dishwasher, dish washer, dishwashing machine": 534, + "disk brake, disc brake": 535, + "dock, dockage, docking facility": 536, + "dogsled, dog sled, dog sleigh": 537, + "dome": 538, + "doormat, welcome mat": 539, + "dough": 961, + "dowitcher": 142, + "dragonfly, darning needle, devil's darning needle, sewing needle, snake feeder, snake doctor, mosquito hawk, skeeter hawk": 319, + "drake": 97, + "drilling platform, offshore rig": 540, + "drum, membranophone, tympan": 541, + "drumstick": 542, + "dugong, Dugong dugon": 149, + "dumbbell": 543, + "dung beetle": 305, + "ear, spike, capitulum": 998, + "earthstar": 995, + "echidna, spiny anteater, anteater": 102, + "eel": 390, + "eft": 27, + "eggnog": 969, + "electric fan, blower": 545, + "electric guitar": 546, + "electric locomotive": 547, + "electric ray, crampfish, numbfish, torpedo": 5, + "entertainment center": 548, + "envelope": 549, + "espresso": 967, + "espresso maker": 550, + "face powder": 551, + "feather boa, boa": 552, + "fiddler crab": 120, + "fig": 952, + "file, file cabinet, filing cabinet": 553, + "fire engine, fire truck": 555, + "fire screen, fireguard": 556, + "fireboat": 554, + "flagpole, flagstaff": 557, + "flamingo": 130, + "flat-coated retriever": 205, + "flatworm, platyhelminth": 110, + "flute, transverse flute": 558, + "fly": 308, + "folding chair": 559, + "football helmet": 560, + "forklift": 561, + "fountain": 562, + "fountain pen": 563, + "four-poster": 564, + "fox squirrel, eastern fox squirrel, Sciurus niger": 335, + "freight car": 565, + "frilled lizard, Chlamydosaurus kingi": 43, + "frying pan, frypan, skillet": 567, + "fur coat": 568, + "gar, garfish, garpike, billfish, Lepisosteus osseus": 395, + "garbage truck, dustcart": 569, + "garden spider, Aranea diademata": 74, + "garter snake, grass snake": 57, + "gas pump, gasoline pump, petrol pump, island dispenser": 571, + "gasmask, respirator, gas helmet": 570, + "gazelle": 353, + "geyser": 974, + "giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca": 388, + "giant schnauzer": 197, + "gibbon, Hylobates lar": 368, + "go-kart": 573, + "goblet": 572, + "golden retriever": 207, + "goldfinch, Carduelis carduelis": 11, + "goldfish, Carassius auratus": 1, + "golf ball": 574, + "golfcart, golf cart": 575, + "gondola": 576, + "gong, tam-tam": 577, + "goose": 99, + "gorilla, Gorilla gorilla": 366, + "gown": 578, + "grand piano, grand": 579, + "grasshopper, hopper": 311, + "great grey owl, great gray owl, Strix nebulosa": 24, + "great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias": 2, + "green lizard, Lacerta viridis": 46, + "green mamba": 64, + "green snake, grass snake": 55, + "greenhouse, nursery, glasshouse": 580, + "grey fox, gray fox, Urocyon cinereoargenteus": 280, + "grey whale, gray whale, devilfish, Eschrichtius gibbosus, Eschrichtius robustus": 147, + "grille, radiator grille": 581, + "grocery store, grocery, food market, market": 582, + "groenendael": 224, + "groom, bridegroom": 982, + "ground beetle, carabid beetle": 302, + "guacamole": 924, + "guenon, guenon monkey": 370, + "guillotine": 583, + "guinea pig, Cavia cobaya": 338, + "gyromitra": 993, + "hair slide": 584, + "hair spray": 585, + "half track": 586, + "hammer": 587, + "hammerhead, hammerhead shark": 4, + "hamper": 588, + "hamster": 333, + "hand blower, blow dryer, blow drier, hair dryer, hair drier": 589, + "hand-held computer, hand-held microcomputer": 590, + "handkerchief, hankie, hanky, hankey": 591, + "hard disc, hard disk, fixed disk": 592, + "hare": 331, + "harmonica, mouth organ, harp, mouth harp": 593, + "harp": 594, + "hartebeest": 351, + "harvester, reaper": 595, + "harvestman, daddy longlegs, Phalangium opilio": 70, + "hatchet": 596, + "hay": 958, + "head cabbage": 936, + "hen": 8, + "hen-of-the-woods, hen of the woods, Polyporus frondosus, Grifola frondosa": 996, + "hermit crab": 125, + "hip, rose hip, rosehip": 989, + "hippopotamus, hippo, river horse, Hippopotamus amphibius": 344, + "hog, pig, grunter, squealer, Sus scrofa": 341, + "hognose snake, puff adder, sand viper": 54, + "holster": 597, + "home theater, home theatre": 598, + "honeycomb": 599, + "hook, claw": 600, + "hoopskirt, crinoline": 601, + "horizontal bar, high bar": 602, + "hornbill": 93, + "horned viper, cerastes, sand viper, horned asp, Cerastes cornutus": 66, + "horse cart, horse-cart": 603, + "hot pot, hotpot": 926, + "hotdog, hot dog, red hot": 934, + "hourglass": 604, + "house finch, linnet, Carpodacus mexicanus": 12, + "howler monkey, howler": 379, + "hummingbird": 94, + "hyena, hyaena": 276, + "iPod": 605, + "ibex, Capra ibex": 350, + "ice bear, polar bear, Ursus Maritimus, Thalarctos maritimus": 296, + "ice cream, icecream": 928, + "ice lolly, lolly, lollipop, popsicle": 929, + "impala, Aepyceros melampus": 352, + "indigo bunting, indigo finch, indigo bird, Passerina cyanea": 14, + "indri, indris, Indri indri, Indri brevicaudatus": 384, + "iron, smoothing iron": 606, + "isopod": 126, + "jacamar": 95, + "jack-o'-lantern": 607, + "jackfruit, jak, jack": 955, + "jaguar, panther, Panthera onca, Felis onca": 290, + "jay": 17, + "jean, blue jean, denim": 608, + "jeep, landrover": 609, + "jellyfish": 107, + "jersey, T-shirt, tee shirt": 610, + "jigsaw puzzle": 611, + "jinrikisha, ricksha, rickshaw": 612, + "joystick": 613, + "junco, snowbird": 13, + "keeshond": 261, + "kelpie": 227, + "killer whale, killer, orca, grampus, sea wolf, Orcinus orca": 148, + "kimono": 614, + "king crab, Alaska crab, Alaskan king crab, Alaska king crab, Paralithodes camtschatica": 121, + "king penguin, Aptenodytes patagonica": 145, + "king snake, kingsnake": 56, + "kit fox, Vulpes macrotis": 278, + "kite": 21, + "knee pad": 615, + "knot": 616, + "koala, koala bear, kangaroo bear, native bear, Phascolarctos cinereus": 105, + "komondor": 228, + "kuvasz": 222, + "lab coat, laboratory coat": 617, + "lacewing, lacewing fly": 318, + "ladle": 618, + "ladybug, ladybeetle, lady beetle, ladybird, ladybird beetle": 301, + "lakeside, lakeshore": 975, + "lampshade, lamp shade": 619, + "langur": 374, + "laptop, laptop computer": 620, + "lawn mower, mower": 621, + "leaf beetle, chrysomelid": 304, + "leafhopper": 317, + "leatherback turtle, leatherback, leathery turtle, Dermochelys coriacea": 34, + "lemon": 951, + "lens cap, lens cover": 622, + "leopard, Panthera pardus": 288, + "lesser panda, red panda, panda, bear cat, cat bear, Ailurus fulgens": 387, + "letter opener, paper knife, paperknife": 623, + "library": 624, + "lifeboat": 625, + "lighter, light, igniter, ignitor": 626, + "limousine, limo": 627, + "limpkin, Aramus pictus": 135, + "liner, ocean liner": 628, + "lion, king of beasts, Panthera leo": 291, + "lionfish": 396, + "lipstick, lip rouge": 629, + "little blue heron, Egretta caerulea": 131, + "llama": 355, + "loggerhead, loggerhead turtle, Caretta caretta": 33, + "long-horned beetle, longicorn, longicorn beetle": 303, + "lorikeet": 90, + "lotion": 631, + "loudspeaker, speaker, speaker unit, loudspeaker system, speaker system": 632, + "loupe, jeweler's loupe": 633, + "lumbermill, sawmill": 634, + "lycaenid, lycaenid butterfly": 326, + "lynx, catamount": 287, + "macaque": 373, + "macaw": 88, + "magnetic compass": 635, + "magpie": 18, + "mailbag, postbag": 636, + "mailbox, letter box": 637, + "maillot": 638, + "maillot, tank suit": 639, + "malamute, malemute, Alaskan malamute": 249, + "malinois": 225, + "manhole cover": 640, + "mantis, mantid": 315, + "maraca": 641, + "marimba, xylophone": 642, + "marmoset": 377, + "marmot": 336, + "mashed potato": 935, + "mask": 643, + "matchstick": 644, + "maypole": 645, + "maze, labyrinth": 646, + "measuring cup": 647, + "meat loaf, meatloaf": 962, + "medicine chest, medicine cabinet": 648, + "meerkat, mierkat": 299, + "megalith, megalithic structure": 649, + "menu": 922, + "microphone, mike": 650, + "microwave, microwave oven": 651, + "military uniform": 652, + "milk can": 653, + "miniature pinscher": 237, + "miniature poodle": 266, + "miniature schnauzer": 196, + "minibus": 654, + "miniskirt, mini": 655, + "minivan": 656, + "mink": 357, + "missile": 657, + "mitten": 658, + "mixing bowl": 659, + "mobile home, manufactured home": 660, + "modem": 662, + "monarch, monarch butterfly, milkweed butterfly, Danaus plexippus": 323, + "monastery": 663, + "mongoose": 298, + "monitor": 664, + "moped": 665, + "mortar": 666, + "mortarboard": 667, + "mosque": 668, + "mosquito net": 669, + "motor scooter, scooter": 670, + "mountain bike, all-terrain bike, off-roader": 671, + "mountain tent": 672, + "mouse, computer mouse": 673, + "mousetrap": 674, + "moving van": 675, + "mud turtle": 35, + "mushroom": 947, + "muzzle": 676, + "nail": 677, + "neck brace": 678, + "necklace": 679, + "nematode, nematode worm, roundworm": 111, + "night snake, Hypsiglena torquata": 60, + "nipple": 680, + "notebook, notebook computer": 681, + "obelisk": 682, + "oboe, hautboy, hautbois": 683, + "ocarina, sweet potato": 684, + "odometer, hodometer, mileometer, milometer": 685, + "oil filter": 686, + "orange": 950, + "orangutan, orang, orangutang, Pongo pygmaeus": 365, + "organ, pipe organ": 687, + "oscilloscope, scope, cathode-ray oscilloscope, CRO": 688, + "ostrich, Struthio camelus": 9, + "otter": 360, + "otterhound, otter hound": 175, + "overskirt": 689, + "ox": 345, + "oxcart": 690, + "oxygen mask": 691, + "oystercatcher, oyster catcher": 143, + "packet": 692, + "paddle, boat paddle": 693, + "paddlewheel, paddle wheel": 694, + "padlock": 695, + "paintbrush": 696, + "pajama, pyjama, pj's, jammies": 697, + "palace": 698, + "panpipe, pandean pipe, syrinx": 699, + "paper towel": 700, + "papillon": 157, + "parachute, chute": 701, + "parallel bars, bars": 702, + "park bench": 703, + "parking meter": 704, + "partridge": 86, + "passenger car, coach, carriage": 705, + "patas, hussar monkey, Erythrocebus patas": 371, + "patio, terrace": 706, + "pay-phone, pay-station": 707, + "peacock": 84, + "pedestal, plinth, footstall": 708, + "pelican": 144, + "pencil box, pencil case": 709, + "pencil sharpener": 710, + "perfume, essence": 711, + "photocopier": 713, + "pick, plectrum, plectron": 714, + "pickelhaube": 715, + "picket fence, paling": 716, + "pickup, pickup truck": 717, + "pier": 718, + "piggy bank, penny bank": 719, + "pill bottle": 720, + "pillow": 721, + "pineapple, ananas": 953, + "ping-pong ball": 722, + "pinwheel": 723, + "pirate, pirate ship": 724, + "pitcher, ewer": 725, + "pizza, pizza pie": 963, + "plane, carpenter's plane, woodworking plane": 726, + "planetarium": 727, + "plastic bag": 728, + "plate": 923, + "plate rack": 729, + "platypus, duckbill, duckbilled platypus, duck-billed platypus, Ornithorhynchus anatinus": 103, + "plow, plough": 730, + "plunger, plumber's helper": 731, + "pole": 733, + "polecat, fitch, foulmart, foumart, Mustela putorius": 358, + "police van, police wagon, paddy wagon, patrol wagon, wagon, black Maria": 734, + "pomegranate": 957, + "poncho": 735, + "pool table, billiard table, snooker table": 736, + "pop bottle, soda bottle": 737, + "porcupine, hedgehog": 334, + "pot, flowerpot": 738, + "potpie": 964, + "potter's wheel": 739, + "power drill": 740, + "prairie chicken, prairie grouse, prairie fowl": 83, + "prayer rug, prayer mat": 741, + "pretzel": 932, + "printer": 742, + "prison, prison house": 743, + "proboscis monkey, Nasalis larvatus": 376, + "projectile, missile": 744, + "projector": 745, + "promontory, headland, head, foreland": 976, + "ptarmigan": 81, + "puck, hockey puck": 746, + "puffer, pufferfish, blowfish, globefish": 397, + "pug, pug-dog": 254, + "punching bag, punch bag, punching ball, punchball": 747, + "purse": 748, + "quail": 85, + "quill, quill pen": 749, + "quilt, comforter, comfort, puff": 750, + "racer, race car, racing car": 751, + "racket, racquet": 752, + "radiator": 753, + "radio telescope, radio reflector": 755, + "radio, wireless": 754, + "rain barrel": 756, + "ram, tup": 348, + "rapeseed": 984, + "recreational vehicle, RV, R.V.": 757, + "red fox, Vulpes vulpes": 277, + "red wine": 966, + "red wolf, maned wolf, Canis rufus, Canis niger": 271, + "red-backed sandpiper, dunlin, Erolia alpina": 140, + "red-breasted merganser, Mergus serrator": 98, + "redbone": 168, + "redshank, Tringa totanus": 141, + "reel": 758, + "reflex camera": 759, + "refrigerator, icebox": 760, + "remote control, remote": 761, + "restaurant, eating house, eating place, eatery": 762, + "revolver, six-gun, six-shooter": 763, + "rhinoceros beetle": 306, + "rifle": 764, + "ringlet, ringlet butterfly": 322, + "ringneck snake, ring-necked snake, ring snake": 53, + "robin, American robin, Turdus migratorius": 15, + "rock beauty, Holocanthus tricolor": 392, + "rock crab, Cancer irroratus": 119, + "rock python, rock snake, Python sebae": 62, + "rocking chair, rocker": 765, + "rotisserie": 766, + "rubber eraser, rubber, pencil eraser": 767, + "ruddy turnstone, Arenaria interpres": 139, + "ruffed grouse, partridge, Bonasa umbellus": 82, + "rugby ball": 768, + "rule, ruler": 769, + "running shoe": 770, + "safe": 771, + "safety pin": 772, + "saltshaker, salt shaker": 773, + "sandal": 774, + "sandbar, sand bar": 977, + "sarong": 775, + "sax, saxophone": 776, + "scabbard": 777, + "scale, weighing machine": 778, + "schipperke": 223, + "school bus": 779, + "schooner": 780, + "scoreboard": 781, + "scorpion": 71, + "screen, CRT screen": 782, + "screw": 783, + "screwdriver": 784, + "scuba diver": 983, + "sea anemone, anemone": 108, + "sea cucumber, holothurian": 329, + "sea lion": 150, + "sea slug, nudibranch": 115, + "sea snake": 65, + "sea urchin": 328, + "seashore, coast, seacoast, sea-coast": 978, + "seat belt, seatbelt": 785, + "sewing machine": 786, + "shield, buckler": 787, + "shoe shop, shoe-shop, shoe store": 788, + "shoji": 789, + "shopping basket": 790, + "shopping cart": 791, + "shovel": 792, + "shower cap": 793, + "shower curtain": 794, + "siamang, Hylobates syndactylus, Symphalangus syndactylus": 369, + "sidewinder, horned rattlesnake, Crotalus cerastes": 68, + "silky terrier, Sydney silky": 201, + "ski": 795, + "ski mask": 796, + "skunk, polecat, wood pussy": 361, + "sleeping bag": 797, + "slide rule, slipstick": 798, + "sliding door": 799, + "slot, one-armed bandit": 800, + "sloth bear, Melursus ursinus, Ursus ursinus": 297, + "slug": 114, + "snail": 113, + "snorkel": 801, + "snow leopard, ounce, Panthera uncia": 289, + "snowmobile": 802, + "snowplow, snowplough": 803, + "soap dispenser": 804, + "soccer ball": 805, + "sock": 806, + "soft-coated wheaten terrier": 202, + "solar dish, solar collector, solar furnace": 807, + "sombrero": 808, + "sorrel": 339, + "soup bowl": 809, + "space bar": 810, + "space heater": 811, + "space shuttle": 812, + "spaghetti squash": 940, + "spatula": 813, + "speedboat": 814, + "spider monkey, Ateles geoffroyi": 381, + "spider web, spider's web": 815, + "spindle": 816, + "spiny lobster, langouste, rock lobster, crawfish, crayfish, sea crawfish": 123, + "spoonbill": 129, + "sports car, sport car": 817, + "spotlight, spot": 818, + "spotted salamander, Ambystoma maculatum": 28, + "squirrel monkey, Saimiri sciureus": 382, + "stage": 819, + "standard poodle": 267, + "standard schnauzer": 198, + "starfish, sea star": 327, + "steam locomotive": 820, + "steel arch bridge": 821, + "steel drum": 822, + "stethoscope": 823, + "stingray": 6, + "stinkhorn, carrion fungus": 994, + "stole": 824, + "stone wall": 825, + "stopwatch, stop watch": 826, + "stove": 827, + "strainer": 828, + "strawberry": 949, + "street sign": 919, + "streetcar, tram, tramcar, trolley, trolley car": 829, + "stretcher": 830, + "studio couch, day bed": 831, + "stupa, tope": 832, + "sturgeon": 394, + "submarine, pigboat, sub, U-boat": 833, + "suit, suit of clothes": 834, + "sulphur butterfly, sulfur butterfly": 325, + "sulphur-crested cockatoo, Kakatoe galerita, Cacatua galerita": 89, + "sundial": 835, + "sunglass": 836, + "sunglasses, dark glasses, shades": 837, + "sunscreen, sunblock, sun blocker": 838, + "suspension bridge": 839, + "swab, swob, mop": 840, + "sweatshirt": 841, + "swimming trunks, bathing trunks": 842, + "swing": 843, + "switch, electric switch, electrical switch": 844, + "syringe": 845, + "tabby, tabby cat": 281, + "table lamp": 846, + "tailed frog, bell toad, ribbed toad, tailed toad, Ascaphus trui": 32, + "tank, army tank, armored combat vehicle, armoured combat vehicle": 847, + "tape player": 848, + "tarantula": 76, + "teapot": 849, + "teddy, teddy bear": 850, + "television, television system": 851, + "tench, Tinca tinca": 0, + "tennis ball": 852, + "terrapin": 36, + "thatch, thatched roof": 853, + "theater curtain, theatre curtain": 854, + "thimble": 855, + "three-toed sloth, ai, Bradypus tridactylus": 364, + "thresher, thrasher, threshing machine": 856, + "throne": 857, + "thunder snake, worm snake, Carphophis amoenus": 52, + "tick": 78, + "tiger beetle": 300, + "tiger cat": 282, + "tiger shark, Galeocerdo cuvieri": 3, + "tiger, Panthera tigris": 292, + "tile roof": 858, + "timber wolf, grey wolf, gray wolf, Canis lupus": 269, + "titi, titi monkey": 380, + "toaster": 859, + "tobacco shop, tobacconist shop, tobacconist": 860, + "toilet seat": 861, + "toilet tissue, toilet paper, bathroom tissue": 999, + "torch": 862, + "totem pole": 863, + "toucan": 96, + "tow truck, tow car, wrecker": 864, + "toy poodle": 265, + "toy terrier": 158, + "toyshop": 865, + "tractor": 866, + "traffic light, traffic signal, stoplight": 920, + "trailer truck, tractor trailer, trucking rig, rig, articulated lorry, semi": 867, + "tray": 868, + "tree frog, tree-frog": 31, + "trench coat": 869, + "triceratops": 51, + "tricycle, trike, velocipede": 870, + "trifle": 927, + "trilobite": 69, + "trimaran": 871, + "tripod": 872, + "triumphal arch": 873, + "trolleybus, trolley coach, trackless trolley": 874, + "trombone": 875, + "tub, vat": 876, + "turnstile": 877, + "tusker": 101, + "typewriter keyboard": 878, + "umbrella": 879, + "unicycle, monocycle": 880, + "upright, upright piano": 881, + "vacuum, vacuum cleaner": 882, + "valley, vale": 979, + "vase": 883, + "vault": 884, + "velvet": 885, + "vending machine": 886, + "vestment": 887, + "viaduct": 888, + "vine snake": 59, + "violin, fiddle": 889, + "vizsla, Hungarian pointer": 211, + "volcano": 980, + "volleyball": 890, + "vulture": 23, + "waffle iron": 891, + "walking stick, walkingstick, stick insect": 313, + "wall clock": 892, + "wallaby, brush kangaroo": 104, + "wallet, billfold, notecase, pocketbook": 893, + "wardrobe, closet, press": 894, + "warplane, military plane": 895, + "warthog": 343, + "washbasin, handbasin, washbowl, lavabo, wash-hand basin": 896, + "washer, automatic washer, washing machine": 897, + "water bottle": 898, + "water buffalo, water ox, Asiatic buffalo, Bubalus bubalis": 346, + "water jug": 899, + "water ouzel, dipper": 20, + "water snake": 58, + "water tower": 900, + "weasel": 356, + "web site, website, internet site, site": 916, + "weevil": 307, + "whippet": 172, + "whiptail, whiptail lizard": 41, + "whiskey jug": 901, + "whistle": 902, + "white stork, Ciconia ciconia": 127, + "white wolf, Arctic wolf, Canis lupus tundrarum": 270, + "wig": 903, + "wild boar, boar, Sus scrofa": 342, + "window screen": 904, + "window shade": 905, + "wine bottle": 907, + "wing": 908, + "wire-haired fox terrier": 188, + "wok": 909, + "wolf spider, hunting spider": 77, + "wombat": 106, + "wood rabbit, cottontail, cottontail rabbit": 330, + "wooden spoon": 910, + "wool, woolen, woollen": 911, + "worm fence, snake fence, snake-rail fence, Virginia fence": 912, + "wreck": 913, + "yawl": 914, + "yellow lady's slipper, yellow lady-slipper, Cypripedium calceolus, Cypripedium parviflorum": 986, + "yurt": 915, + "zebra": 340, + "zucchini, courgette": 939 + }, + "model_type": "efficientnet", + "num_block_repeats": [ + 1, + 2, + 2, + 3, + 3, + 4, + 1 + ], + "num_channels": 3, + "out_channels": [ + 16, + 24, + 40, + 80, + 112, + 192, + 320 + ], + "out_features": null, + "pooling_type": "mean", + "squeeze_expansion_ratio": 0.25, + "stage_names": [ + "stem", + "stage1", + "stage2", + "stage3", + "stage4", + "stage5", + "stage6", + "stage7" + ], + "strides": [ + 1, + 2, + 2, + 2, + 1, + 2, + 1 + ], + "torch_dtype": "float32", + "transformers_version": "4.27.0.dev0", + "width_coefficient": 1.0 +} diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/preprocessor_config.json b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/preprocessor_config.json new file mode 100644 index 0000000000000000000000000000000000000000..12c6f43f6c5f96787eb621f4daf40bed8f1e89c2 --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/preprocessor_config.json @@ -0,0 +1,28 @@ +{ + "crop_size": { + "height": 289, + "width": 289 + }, + "do_center_crop": false, + "do_normalize": true, + "do_rescale": true, + "do_resize": true, + "image_mean": [ + 0.485, + 0.456, + 0.406 + ], + "image_processor_type": "EfficientNetImageProcessor", + "image_std": [ + 0.47853944, + 0.4732864, + 0.47434163 + ], + "resample": 0, + "rescale_factor": 0.00392156862745098, + "rescale_offset": false, + "size": { + "height": 224, + "width": 224 + } +} diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/pytorch_model.bin b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/pytorch_model.bin new file mode 100644 index 0000000000000000000000000000000000000000..1df51f913660559ae3aeb72e43888595838ab2ed --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/3d8d75d0812b65064f0151b456f869c6344bf20c/pytorch_model.bin @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:30753ee4fb7d6ac093423435b2648d8e295b3120f8f3ba00cc714b2c4a34de6f +size 21444205 diff --git a/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/f86b650049699f1cf772edd370d7ea0382f0941f/model.safetensors b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/f86b650049699f1cf772edd370d7ea0382f0941f/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..af783a3758c883ad0b7cf2ff7c20cb996c62498a --- /dev/null +++ b/model_cache/efficientnet/models--google--efficientnet-b0/snapshots/f86b650049699f1cf772edd370d7ea0382f0941f/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c3cd95b350e7867c1947da57988b80b6070deb35c8af719845c964249a842033 +size 21369176 diff --git a/model_cache/roberta/CACHEDIR.TAG b/model_cache/roberta/CACHEDIR.TAG new file mode 100644 index 0000000000000000000000000000000000000000..2b927574f362cc41ca52cb6e863dbf47e664febb --- /dev/null +++ b/model_cache/roberta/CACHEDIR.TAG @@ -0,0 +1,4 @@ +Signature: 8a477f597d28d172789f06886806bc55 +# This file is a cache directory tag created by huggingface_hub. +# For information about cache directory tags, see: +# https://bford.info/cachedir/ diff --git a/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/added_tokens.json b/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/added_tokens.json new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/chat_template.jinja b/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/chat_template.jinja new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/tokenizer.json b/model_cache/roberta/models--unitary--toxic-bert/.no_exist/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/tokenizer.json new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/model_cache/roberta/models--unitary--toxic-bert/refs/main b/model_cache/roberta/models--unitary--toxic-bert/refs/main new file mode 100644 index 0000000000000000000000000000000000000000..08446cfaa46af1077c8a8c8cd7c8d7610ca1f702 --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/refs/main @@ -0,0 +1 @@ +4d6c22e74ba2fdd26bc4f7238f50766b045a0d94 \ No newline at end of file diff --git a/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/config.json b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/config.json new file mode 100644 index 0000000000000000000000000000000000000000..3ec47d6ec6e7142b3d7d0696f7b35f4103794291 --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/config.json @@ -0,0 +1,37 @@ +{ + "architectures": [ + "BertForSequenceClassification" + ], + "attention_probs_dropout_prob": 0.1, + "gradient_checkpointing": false, + "hidden_act": "gelu", + "hidden_dropout_prob": 0.1, + "hidden_size": 768, + "id2label": { + "0": "toxic", + "1": "severe_toxic", + "2": "obscene", + "3": "threat", + "4": "insult", + "5": "identity_hate" + }, + "initializer_range": 0.02, + "intermediate_size": 3072, + "label2id": { + "toxic": 0, + "severe_toxic": 1, + "obscene": 2, + "threat": 3, + "insult": 4, + "identity_hate": 5 + }, + "problem_type": "multi_label_classification", + "layer_norm_eps": 1e-12, + "max_position_embeddings": 512, + "model_type": "bert", + "num_attention_heads": 12, + "num_hidden_layers": 12, + "pad_token_id": 0, + "type_vocab_size": 2, + "vocab_size": 30522 +} \ No newline at end of file diff --git a/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/model.safetensors b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/model.safetensors new file mode 100644 index 0000000000000000000000000000000000000000..f64e19b6eb81b56bab9cb6f625afd9ddd869068f --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/model.safetensors @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2c272885d24138df70bff1b3cd944a999bd6b41dad33209730aa8ba074f6ad09 +size 437975136 diff --git a/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/special_tokens_map.json b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/special_tokens_map.json new file mode 100644 index 0000000000000000000000000000000000000000..e7b0375001f109a6b8873d756ad4f7bbb15fbaa5 --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/special_tokens_map.json @@ -0,0 +1 @@ +{"unk_token": "[UNK]", "sep_token": "[SEP]", "pad_token": "[PAD]", "cls_token": "[CLS]", "mask_token": "[MASK]"} \ No newline at end of file diff --git a/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/tokenizer_config.json b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/tokenizer_config.json new file mode 100644 index 0000000000000000000000000000000000000000..8de608959302012994f35a2646e39cd0b2d9011e --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/tokenizer_config.json @@ -0,0 +1 @@ +{"unk_token": "[UNK]", "sep_token": "[SEP]", "pad_token": "[PAD]", "cls_token": "[CLS]", "mask_token": "[MASK]", "model_max_length": 512, "name_or_path": "bert-base-uncased"} \ No newline at end of file diff --git a/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/vocab.txt b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/vocab.txt new file mode 100644 index 0000000000000000000000000000000000000000..fb140275c155a9c7c5a3b3e0e77a9e839594a938 --- /dev/null +++ b/model_cache/roberta/models--unitary--toxic-bert/snapshots/4d6c22e74ba2fdd26bc4f7238f50766b045a0d94/vocab.txt @@ -0,0 +1,30522 @@ +[PAD] +[unused0] +[unused1] +[unused2] +[unused3] +[unused4] +[unused5] +[unused6] +[unused7] +[unused8] +[unused9] +[unused10] +[unused11] +[unused12] +[unused13] +[unused14] +[unused15] +[unused16] +[unused17] +[unused18] +[unused19] +[unused20] +[unused21] +[unused22] +[unused23] +[unused24] +[unused25] +[unused26] +[unused27] +[unused28] +[unused29] +[unused30] +[unused31] +[unused32] +[unused33] +[unused34] +[unused35] +[unused36] +[unused37] +[unused38] +[unused39] +[unused40] +[unused41] +[unused42] +[unused43] +[unused44] +[unused45] +[unused46] +[unused47] +[unused48] +[unused49] +[unused50] +[unused51] +[unused52] +[unused53] +[unused54] +[unused55] +[unused56] +[unused57] +[unused58] +[unused59] +[unused60] +[unused61] +[unused62] +[unused63] +[unused64] +[unused65] +[unused66] +[unused67] +[unused68] +[unused69] +[unused70] +[unused71] +[unused72] +[unused73] +[unused74] +[unused75] +[unused76] +[unused77] +[unused78] +[unused79] +[unused80] +[unused81] +[unused82] +[unused83] +[unused84] +[unused85] +[unused86] +[unused87] +[unused88] +[unused89] +[unused90] +[unused91] +[unused92] +[unused93] +[unused94] +[unused95] +[unused96] +[unused97] +[unused98] +[UNK] +[CLS] +[SEP] +[MASK] +[unused99] +[unused100] +[unused101] +[unused102] +[unused103] +[unused104] +[unused105] +[unused106] +[unused107] +[unused108] +[unused109] +[unused110] +[unused111] +[unused112] +[unused113] +[unused114] +[unused115] +[unused116] +[unused117] +[unused118] +[unused119] +[unused120] +[unused121] +[unused122] +[unused123] +[unused124] +[unused125] +[unused126] +[unused127] +[unused128] +[unused129] +[unused130] +[unused131] +[unused132] +[unused133] +[unused134] +[unused135] +[unused136] +[unused137] +[unused138] +[unused139] +[unused140] +[unused141] +[unused142] +[unused143] +[unused144] +[unused145] +[unused146] +[unused147] +[unused148] +[unused149] +[unused150] +[unused151] +[unused152] +[unused153] +[unused154] +[unused155] +[unused156] +[unused157] +[unused158] +[unused159] +[unused160] +[unused161] +[unused162] +[unused163] +[unused164] +[unused165] +[unused166] +[unused167] +[unused168] +[unused169] +[unused170] +[unused171] +[unused172] +[unused173] +[unused174] +[unused175] +[unused176] +[unused177] +[unused178] +[unused179] +[unused180] +[unused181] +[unused182] +[unused183] +[unused184] +[unused185] +[unused186] +[unused187] +[unused188] +[unused189] +[unused190] +[unused191] +[unused192] +[unused193] +[unused194] +[unused195] +[unused196] +[unused197] +[unused198] +[unused199] +[unused200] +[unused201] +[unused202] +[unused203] +[unused204] +[unused205] +[unused206] +[unused207] +[unused208] +[unused209] +[unused210] +[unused211] +[unused212] +[unused213] +[unused214] +[unused215] +[unused216] +[unused217] +[unused218] +[unused219] +[unused220] +[unused221] +[unused222] +[unused223] +[unused224] +[unused225] +[unused226] +[unused227] +[unused228] +[unused229] +[unused230] +[unused231] +[unused232] +[unused233] +[unused234] +[unused235] +[unused236] +[unused237] +[unused238] +[unused239] +[unused240] +[unused241] +[unused242] +[unused243] +[unused244] +[unused245] +[unused246] +[unused247] +[unused248] +[unused249] +[unused250] +[unused251] +[unused252] +[unused253] +[unused254] +[unused255] +[unused256] +[unused257] +[unused258] +[unused259] +[unused260] +[unused261] +[unused262] +[unused263] +[unused264] +[unused265] +[unused266] +[unused267] +[unused268] +[unused269] +[unused270] +[unused271] +[unused272] +[unused273] +[unused274] +[unused275] +[unused276] +[unused277] +[unused278] +[unused279] +[unused280] +[unused281] +[unused282] +[unused283] +[unused284] +[unused285] +[unused286] +[unused287] +[unused288] +[unused289] +[unused290] +[unused291] +[unused292] +[unused293] +[unused294] +[unused295] +[unused296] +[unused297] +[unused298] +[unused299] +[unused300] +[unused301] +[unused302] +[unused303] +[unused304] +[unused305] +[unused306] +[unused307] +[unused308] +[unused309] +[unused310] +[unused311] +[unused312] +[unused313] +[unused314] +[unused315] +[unused316] +[unused317] +[unused318] +[unused319] +[unused320] +[unused321] +[unused322] +[unused323] +[unused324] +[unused325] +[unused326] +[unused327] +[unused328] +[unused329] +[unused330] +[unused331] +[unused332] +[unused333] +[unused334] +[unused335] +[unused336] +[unused337] +[unused338] +[unused339] +[unused340] +[unused341] +[unused342] +[unused343] +[unused344] +[unused345] +[unused346] +[unused347] +[unused348] +[unused349] +[unused350] +[unused351] +[unused352] +[unused353] +[unused354] +[unused355] +[unused356] +[unused357] +[unused358] +[unused359] +[unused360] +[unused361] +[unused362] +[unused363] +[unused364] +[unused365] +[unused366] +[unused367] +[unused368] +[unused369] +[unused370] +[unused371] +[unused372] +[unused373] +[unused374] +[unused375] +[unused376] +[unused377] +[unused378] +[unused379] +[unused380] +[unused381] +[unused382] +[unused383] +[unused384] +[unused385] +[unused386] +[unused387] +[unused388] +[unused389] +[unused390] +[unused391] +[unused392] +[unused393] +[unused394] +[unused395] +[unused396] +[unused397] +[unused398] +[unused399] +[unused400] +[unused401] +[unused402] +[unused403] +[unused404] +[unused405] +[unused406] +[unused407] +[unused408] +[unused409] +[unused410] +[unused411] +[unused412] +[unused413] +[unused414] +[unused415] +[unused416] +[unused417] +[unused418] +[unused419] +[unused420] +[unused421] +[unused422] +[unused423] +[unused424] +[unused425] +[unused426] +[unused427] +[unused428] +[unused429] +[unused430] +[unused431] +[unused432] +[unused433] +[unused434] +[unused435] +[unused436] +[unused437] +[unused438] +[unused439] +[unused440] +[unused441] +[unused442] +[unused443] +[unused444] +[unused445] +[unused446] +[unused447] +[unused448] +[unused449] +[unused450] +[unused451] +[unused452] +[unused453] +[unused454] +[unused455] +[unused456] +[unused457] +[unused458] +[unused459] +[unused460] +[unused461] +[unused462] +[unused463] +[unused464] +[unused465] +[unused466] +[unused467] +[unused468] +[unused469] +[unused470] +[unused471] +[unused472] +[unused473] +[unused474] +[unused475] +[unused476] +[unused477] +[unused478] +[unused479] +[unused480] +[unused481] +[unused482] +[unused483] +[unused484] +[unused485] +[unused486] +[unused487] +[unused488] +[unused489] +[unused490] +[unused491] +[unused492] +[unused493] +[unused494] +[unused495] +[unused496] +[unused497] +[unused498] +[unused499] +[unused500] +[unused501] +[unused502] +[unused503] +[unused504] +[unused505] +[unused506] +[unused507] +[unused508] +[unused509] +[unused510] +[unused511] +[unused512] +[unused513] +[unused514] +[unused515] +[unused516] +[unused517] +[unused518] +[unused519] +[unused520] +[unused521] +[unused522] +[unused523] +[unused524] +[unused525] +[unused526] +[unused527] +[unused528] +[unused529] +[unused530] +[unused531] +[unused532] +[unused533] +[unused534] +[unused535] +[unused536] +[unused537] +[unused538] +[unused539] +[unused540] +[unused541] +[unused542] +[unused543] +[unused544] +[unused545] +[unused546] +[unused547] +[unused548] +[unused549] +[unused550] +[unused551] +[unused552] +[unused553] +[unused554] +[unused555] +[unused556] +[unused557] +[unused558] +[unused559] +[unused560] +[unused561] +[unused562] +[unused563] +[unused564] +[unused565] +[unused566] +[unused567] +[unused568] +[unused569] +[unused570] +[unused571] +[unused572] +[unused573] +[unused574] +[unused575] +[unused576] +[unused577] +[unused578] +[unused579] +[unused580] +[unused581] +[unused582] +[unused583] +[unused584] +[unused585] +[unused586] +[unused587] +[unused588] +[unused589] +[unused590] +[unused591] +[unused592] +[unused593] +[unused594] +[unused595] +[unused596] +[unused597] +[unused598] +[unused599] +[unused600] +[unused601] +[unused602] +[unused603] +[unused604] +[unused605] +[unused606] +[unused607] +[unused608] +[unused609] +[unused610] +[unused611] +[unused612] +[unused613] +[unused614] +[unused615] +[unused616] +[unused617] +[unused618] +[unused619] +[unused620] +[unused621] +[unused622] +[unused623] +[unused624] +[unused625] +[unused626] +[unused627] +[unused628] +[unused629] +[unused630] +[unused631] +[unused632] +[unused633] +[unused634] +[unused635] +[unused636] +[unused637] +[unused638] +[unused639] +[unused640] +[unused641] +[unused642] +[unused643] +[unused644] +[unused645] +[unused646] +[unused647] +[unused648] +[unused649] +[unused650] +[unused651] +[unused652] +[unused653] +[unused654] +[unused655] +[unused656] +[unused657] +[unused658] +[unused659] +[unused660] +[unused661] +[unused662] +[unused663] +[unused664] +[unused665] +[unused666] +[unused667] +[unused668] +[unused669] +[unused670] +[unused671] +[unused672] +[unused673] +[unused674] +[unused675] +[unused676] +[unused677] +[unused678] +[unused679] +[unused680] +[unused681] +[unused682] +[unused683] +[unused684] +[unused685] +[unused686] +[unused687] +[unused688] +[unused689] +[unused690] +[unused691] +[unused692] +[unused693] +[unused694] +[unused695] +[unused696] +[unused697] +[unused698] +[unused699] +[unused700] +[unused701] +[unused702] +[unused703] +[unused704] +[unused705] +[unused706] +[unused707] +[unused708] +[unused709] +[unused710] +[unused711] +[unused712] +[unused713] +[unused714] +[unused715] +[unused716] +[unused717] +[unused718] +[unused719] +[unused720] +[unused721] +[unused722] +[unused723] +[unused724] +[unused725] +[unused726] +[unused727] +[unused728] +[unused729] +[unused730] +[unused731] +[unused732] +[unused733] +[unused734] +[unused735] +[unused736] +[unused737] +[unused738] +[unused739] +[unused740] +[unused741] +[unused742] +[unused743] +[unused744] +[unused745] +[unused746] +[unused747] +[unused748] +[unused749] +[unused750] +[unused751] +[unused752] +[unused753] +[unused754] +[unused755] +[unused756] +[unused757] +[unused758] +[unused759] +[unused760] +[unused761] +[unused762] +[unused763] +[unused764] +[unused765] +[unused766] +[unused767] +[unused768] +[unused769] +[unused770] +[unused771] +[unused772] +[unused773] +[unused774] +[unused775] +[unused776] +[unused777] +[unused778] +[unused779] +[unused780] +[unused781] +[unused782] +[unused783] +[unused784] +[unused785] +[unused786] +[unused787] +[unused788] +[unused789] +[unused790] +[unused791] +[unused792] +[unused793] +[unused794] +[unused795] +[unused796] +[unused797] +[unused798] +[unused799] +[unused800] +[unused801] +[unused802] +[unused803] +[unused804] +[unused805] +[unused806] +[unused807] +[unused808] +[unused809] +[unused810] +[unused811] +[unused812] +[unused813] +[unused814] +[unused815] +[unused816] +[unused817] +[unused818] +[unused819] +[unused820] +[unused821] +[unused822] +[unused823] +[unused824] +[unused825] +[unused826] +[unused827] +[unused828] +[unused829] +[unused830] +[unused831] +[unused832] +[unused833] +[unused834] +[unused835] +[unused836] +[unused837] +[unused838] +[unused839] +[unused840] +[unused841] +[unused842] +[unused843] +[unused844] +[unused845] +[unused846] +[unused847] +[unused848] +[unused849] +[unused850] +[unused851] +[unused852] +[unused853] +[unused854] +[unused855] +[unused856] +[unused857] +[unused858] +[unused859] +[unused860] +[unused861] +[unused862] +[unused863] +[unused864] +[unused865] +[unused866] +[unused867] +[unused868] +[unused869] +[unused870] +[unused871] +[unused872] +[unused873] +[unused874] +[unused875] +[unused876] +[unused877] +[unused878] +[unused879] +[unused880] +[unused881] +[unused882] +[unused883] +[unused884] +[unused885] +[unused886] +[unused887] +[unused888] +[unused889] +[unused890] +[unused891] +[unused892] +[unused893] +[unused894] +[unused895] +[unused896] +[unused897] +[unused898] +[unused899] +[unused900] +[unused901] +[unused902] +[unused903] +[unused904] +[unused905] +[unused906] +[unused907] +[unused908] +[unused909] +[unused910] +[unused911] +[unused912] +[unused913] +[unused914] +[unused915] +[unused916] +[unused917] +[unused918] +[unused919] +[unused920] +[unused921] +[unused922] +[unused923] +[unused924] +[unused925] +[unused926] +[unused927] +[unused928] +[unused929] +[unused930] +[unused931] +[unused932] +[unused933] +[unused934] +[unused935] +[unused936] +[unused937] +[unused938] +[unused939] +[unused940] +[unused941] +[unused942] +[unused943] +[unused944] +[unused945] +[unused946] +[unused947] +[unused948] +[unused949] +[unused950] +[unused951] +[unused952] +[unused953] +[unused954] +[unused955] +[unused956] +[unused957] +[unused958] +[unused959] +[unused960] +[unused961] +[unused962] +[unused963] +[unused964] +[unused965] +[unused966] +[unused967] +[unused968] +[unused969] +[unused970] +[unused971] +[unused972] +[unused973] +[unused974] +[unused975] +[unused976] +[unused977] +[unused978] +[unused979] +[unused980] +[unused981] +[unused982] +[unused983] +[unused984] +[unused985] +[unused986] +[unused987] +[unused988] +[unused989] +[unused990] +[unused991] +[unused992] +[unused993] +! +" +# +$ +% +& +' +( +) +* ++ +, +- +. +/ +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +: +; +< += +> +? +@ +[ +\ +] +^ +_ +` +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z +{ +| +} +~ +¡ +¢ +£ +¤ +¥ +¦ +§ +¨ +© +ª +« +¬ +® +° +± +² +³ +´ +µ +¶ +· +¹ +º +» +¼ +½ +¾ +¿ +× +ß +æ +ð +÷ +ø +þ +đ +ħ +ı +ł +ŋ +œ +ƒ +ɐ +ɑ +ɒ +ɔ +ɕ +ə +ɛ +ɡ +ɣ +ɨ +ɪ +ɫ +ɬ +ɯ +ɲ +ɴ +ɹ +ɾ +ʀ +ʁ +ʂ +ʃ +ʉ +ʊ +ʋ +ʌ +ʎ +ʐ +ʑ +ʒ +ʔ +ʰ +ʲ +ʳ +ʷ +ʸ +ʻ +ʼ +ʾ +ʿ +ˈ +ː +ˡ +ˢ +ˣ +ˤ +α +β +γ +δ +ε +ζ +η +θ +ι +κ +λ +μ +ν +ξ +ο +π +ρ +ς +σ +τ +υ +φ +χ +ψ +ω +а +б +в +г +д +е +ж +з +и +к +л +м +н +о +п +р +с +т +у +ф +х +ц +ч +ш +щ +ъ +ы +ь +э +ю +я +ђ +є +і +ј +љ +њ +ћ +ӏ +ա +բ +գ +դ +ե +թ +ի +լ +կ +հ +մ +յ +ն +ո +պ +ս +վ +տ +ր +ւ +ք +־ +א +ב +ג +ד +ה +ו +ז +ח +ט +י +ך +כ +ל +ם +מ +ן +נ +ס +ע +ף +פ +ץ +צ +ק +ר +ש +ת +، +ء +ا +ب +ة +ت +ث +ج +ح +خ +د +ذ +ر +ز +س +ش +ص +ض +ط +ظ +ع +غ +ـ +ف +ق +ك +ل +م +ن +ه +و +ى +ي +ٹ +پ +چ +ک +گ +ں +ھ +ہ +ی +ے +अ +आ +उ +ए +क +ख +ग +च +ज +ट +ड +ण +त +थ +द +ध +न +प +ब +भ +म +य +र +ल +व +श +ष +स +ह +ा +ि +ी +ो +। +॥ +ং +অ +আ +ই +উ +এ +ও +ক +খ +গ +চ +ছ +জ +ট +ড +ণ +ত +থ +দ +ধ +ন +প +ব +ভ +ম +য +র +ল +শ +ষ +স +হ +া +ি +ী +ে +க +ச +ட +த +ந +ன +ப +ம +ய +ர +ல +ள +வ +ா +ி +ு +ே +ை +ನ +ರ +ಾ +ක +ය +ර +ල +ව +ා +ก +ง +ต +ท +น +พ +ม +ย +ร +ล +ว +ส +อ +า +เ +་ +། +ག +ང +ད +ན +པ +བ +མ +འ +ར +ལ +ས +မ +ა +ბ +გ +დ +ე +ვ +თ +ი +კ +ლ +მ +ნ +ო +რ +ს +ტ +უ +ᄀ +ᄂ +ᄃ +ᄅ +ᄆ +ᄇ +ᄉ +ᄊ +ᄋ +ᄌ +ᄎ +ᄏ +ᄐ +ᄑ +ᄒ +ᅡ +ᅢ +ᅥ +ᅦ +ᅧ +ᅩ +ᅪ +ᅭ +ᅮ +ᅯ +ᅲ +ᅳ +ᅴ +ᅵ +ᆨ +ᆫ +ᆯ +ᆷ +ᆸ +ᆼ +ᴬ +ᴮ +ᴰ +ᴵ +ᴺ +ᵀ +ᵃ +ᵇ +ᵈ +ᵉ +ᵍ +ᵏ +ᵐ +ᵒ +ᵖ +ᵗ +ᵘ +ᵢ +ᵣ +ᵤ +ᵥ +ᶜ +ᶠ +‐ +‑ +‒ +– +— +― +‖ +‘ +’ +‚ +“ +” +„ +† +‡ +• +… +‰ +′ +″ +› +‿ +⁄ +⁰ +ⁱ +⁴ +⁵ +⁶ +⁷ +⁸ +⁹ +⁺ +⁻ +ⁿ +₀ +₁ +₂ +₃ +₄ +₅ +₆ +₇ +₈ +₉ +₊ +₍ +₎ +ₐ +ₑ +ₒ +ₓ +ₕ +ₖ +ₗ +ₘ +ₙ +ₚ +ₛ +ₜ +₤ +₩ +€ +₱ +₹ +ℓ +№ +ℝ +™ +⅓ +⅔ +← +↑ +→ +↓ +↔ +↦ +⇄ +⇌ +⇒ +∂ +∅ +∆ +∇ +∈ +− +∗ +∘ +√ +∞ +∧ +∨ +∩ +∪ +≈ +≡ +≤ +≥ +⊂ +⊆ +⊕ +⊗ +⋅ +─ +│ +■ +▪ +● +★ +☆ +☉ +♠ +♣ +♥ +♦ +♭ +♯ +⟨ +⟩ +ⱼ +⺩ +⺼ +⽥ +、 +。 +〈 +〉 +《 +》 +「 +」 +『 +』 +〜 +あ +い +う +え +お +か +き +く +け +こ +さ +し +す +せ +そ +た +ち +っ +つ +て +と +な +に +ぬ +ね +の +は +ひ +ふ +へ +ほ +ま +み +む +め +も +や +ゆ +よ +ら +り +る +れ +ろ +を +ん +ァ +ア +ィ +イ +ウ +ェ +エ +オ +カ +キ +ク +ケ +コ +サ +シ +ス +セ +タ +チ +ッ +ツ +テ +ト +ナ +ニ +ノ +ハ +ヒ +フ +ヘ +ホ +マ +ミ +ム +メ +モ +ャ +ュ +ョ +ラ +リ +ル +レ +ロ +ワ +ン +・ +ー +一 +三 +上 +下 +不 +世 +中 +主 +久 +之 +也 +事 +二 +五 +井 +京 +人 +亻 +仁 +介 +代 +仮 +伊 +会 +佐 +侍 +保 +信 +健 +元 +光 +八 +公 +内 +出 +分 +前 +劉 +力 +加 +勝 +北 +区 +十 +千 +南 +博 +原 +口 +古 +史 +司 +合 +吉 +同 +名 +和 +囗 +四 +国 +國 +土 +地 +坂 +城 +堂 +場 +士 +夏 +外 +大 +天 +太 +夫 +奈 +女 +子 +学 +宀 +宇 +安 +宗 +定 +宣 +宮 +家 +宿 +寺 +將 +小 +尚 +山 +岡 +島 +崎 +川 +州 +巿 +帝 +平 +年 +幸 +广 +弘 +張 +彳 +後 +御 +德 +心 +忄 +志 +忠 +愛 +成 +我 +戦 +戸 +手 +扌 +政 +文 +新 +方 +日 +明 +星 +春 +昭 +智 +曲 +書 +月 +有 +朝 +木 +本 +李 +村 +東 +松 +林 +森 +楊 +樹 +橋 +歌 +止 +正 +武 +比 +氏 +民 +水 +氵 +氷 +永 +江 +沢 +河 +治 +法 +海 +清 +漢 +瀬 +火 +版 +犬 +王 +生 +田 +男 +疒 +発 +白 +的 +皇 +目 +相 +省 +真 +石 +示 +社 +神 +福 +禾 +秀 +秋 +空 +立 +章 +竹 +糹 +美 +義 +耳 +良 +艹 +花 +英 +華 +葉 +藤 +行 +街 +西 +見 +訁 +語 +谷 +貝 +貴 +車 +軍 +辶 +道 +郎 +郡 +部 +都 +里 +野 +金 +鈴 +镇 +長 +門 +間 +阝 +阿 +陳 +陽 +雄 +青 +面 +風 +食 +香 +馬 +高 +龍 +龸 +fi +fl +! +( +) +, +- +. +/ +: +? +~ +the +of +and +in +to +was +he +is +as +for +on +with +that +it +his +by +at +from +her +##s +she +you +had +an +were +but +be +this +are +not +my +they +one +which +or +have +him +me +first +all +also +their +has +up +who +out +been +when +after +there +into +new +two +its +##a +time +would +no +what +about +said +we +over +then +other +so +more +##e +can +if +like +back +them +only +some +could +##i +where +just +##ing +during +before +##n +do +##o +made +school +through +than +now +years +most +world +may +between +down +well +three +##d +year +while +will +##ed +##r +##y +later +##t +city +under +around +did +such +being +used +state +people +part +know +against +your +many +second +university +both +national +##er +these +don +known +off +way +until +re +how +even +get +head +... +didn +##ly +team +american +because +de +##l +born +united +film +since +still +long +work +south +us +became +any +high +again +day +family +see +right +man +eyes +house +season +war +states +including +took +life +north +same +each +called +name +much +place +however +go +four +group +another +found +won +area +here +going +10 +away +series +left +home +music +best +make +hand +number +company +several +never +last +john +000 +very +album +take +end +good +too +following +released +game +played +little +began +district +##m +old +want +those +side +held +own +early +county +ll +league +use +west +##u +face +think +##es +2010 +government +##h +march +came +small +general +town +june +##on +line +based +something +##k +september +thought +looked +along +international +2011 +air +july +club +went +january +october +our +august +april +york +12 +few +2012 +2008 +east +show +member +college +2009 +father +public +##us +come +men +five +set +station +church +##c +next +former +november +room +party +located +december +2013 +age +got +2007 +##g +system +let +love +2006 +though +every +2014 +look +song +water +century +without +body +black +night +within +great +women +single +ve +building +large +population +river +named +band +white +started +##an +once +15 +20 +should +18 +2015 +service +top +built +british +open +death +king +moved +local +times +children +february +book +why +11 +door +need +president +order +final +road +wasn +although +due +major +died +village +third +knew +2016 +asked +turned +st +wanted +say +##p +together +received +main +son +served +different +##en +behind +himself +felt +members +power +football +law +voice +play +##in +near +park +history +30 +having +2005 +16 +##man +saw +mother +##al +army +point +front +help +english +street +art +late +hands +games +award +##ia +young +14 +put +published +country +division +across +told +13 +often +ever +french +london +center +six +red +2017 +led +days +include +light +25 +find +tell +among +species +really +according +central +half +2004 +form +original +gave +office +making +enough +lost +full +opened +must +included +live +given +german +player +run +business +woman +community +cup +might +million +land +2000 +court +development +17 +short +round +ii +km +seen +class +story +always +become +sure +research +almost +director +council +la +##2 +career +things +using +island +##z +couldn +car +##is +24 +close +force +##1 +better +free +support +control +field +students +2003 +education +married +##b +nothing +worked +others +record +big +inside +level +anything +continued +give +james +##3 +military +established +non +returned +feel +does +title +written +thing +feet +william +far +co +association +hard +already +2002 +##ra +championship +human +western +100 +##na +department +hall +role +various +production +21 +19 +heart +2001 +living +fire +version +##ers +##f +television +royal +##4 +produced +working +act +case +society +region +present +radio +period +looking +least +total +keep +england +wife +program +per +brother +mind +special +22 +##le +am +works +soon +##6 +political +george +services +taken +created +##7 +further +able +reached +david +union +joined +upon +done +important +social +information +either +##ic +##x +appeared +position +ground +lead +rock +dark +election +23 +board +france +hair +course +arms +site +police +girl +instead +real +sound +##v +words +moment +##te +someone +##8 +summer +project +announced +san +less +wrote +past +followed +##5 +blue +founded +al +finally +india +taking +records +america +##ne +1999 +design +considered +northern +god +stop +battle +toward +european +outside +described +track +today +playing +language +28 +call +26 +heard +professional +low +australia +miles +california +win +yet +green +##ie +trying +blood +##ton +southern +science +maybe +everything +match +square +27 +mouth +video +race +recorded +leave +above +##9 +daughter +points +space +1998 +museum +change +middle +common +##0 +move +tv +post +##ta +lake +seven +tried +elected +closed +ten +paul +minister +##th +months +start +chief +return +canada +person +sea +release +similar +modern +brought +rest +hit +formed +mr +##la +1997 +floor +event +doing +thomas +1996 +robert +care +killed +training +star +week +needed +turn +finished +railway +rather +news +health +sent +example +ran +term +michael +coming +currently +yes +forces +despite +gold +areas +50 +stage +fact +29 +dead +says +popular +2018 +originally +germany +probably +developed +result +pulled +friend +stood +money +running +mi +signed +word +songs +child +eventually +met +tour +average +teams +minutes +festival +current +deep +kind +1995 +decided +usually +eastern +seemed +##ness +episode +bed +added +table +indian +private +charles +route +available +idea +throughout +centre +addition +appointed +style +1994 +books +eight +construction +press +mean +wall +friends +remained +schools +study +##ch +##um +institute +oh +chinese +sometimes +events +possible +1992 +australian +type +brown +forward +talk +process +food +debut +seat +performance +committee +features +character +arts +herself +else +lot +strong +russian +range +hours +peter +arm +##da +morning +dr +sold +##ry +quickly +directed +1993 +guitar +china +##w +31 +list +##ma +performed +media +uk +players +smile +##rs +myself +40 +placed +coach +province +towards +wouldn +leading +whole +boy +official +designed +grand +census +##el +europe +attack +japanese +henry +1991 +##re +##os +cross +getting +alone +action +lower +network +wide +washington +japan +1990 +hospital +believe +changed +sister +##ar +hold +gone +sir +hadn +ship +##ka +studies +academy +shot +rights +below +base +bad +involved +kept +largest +##ist +bank +future +especially +beginning +mark +movement +section +female +magazine +plan +professor +lord +longer +##ian +sat +walked +hill +actually +civil +energy +model +families +size +thus +aircraft +completed +includes +data +captain +##or +fight +vocals +featured +richard +bridge +fourth +1989 +officer +stone +hear +##ism +means +medical +groups +management +self +lips +competition +entire +lived +technology +leaving +federal +tournament +bit +passed +hot +independent +awards +kingdom +mary +spent +fine +doesn +reported +##ling +jack +fall +raised +itself +stay +true +studio +1988 +sports +replaced +paris +systems +saint +leader +theatre +whose +market +capital +parents +spanish +canadian +earth +##ity +cut +degree +writing +bay +christian +awarded +natural +higher +bill +##as +coast +provided +previous +senior +ft +valley +organization +stopped +onto +countries +parts +conference +queen +security +interest +saying +allowed +master +earlier +phone +matter +smith +winning +try +happened +moving +campaign +los +##ley +breath +nearly +mid +1987 +certain +girls +date +italian +african +standing +fell +artist +##ted +shows +deal +mine +industry +1986 +##ng +everyone +republic +provide +collection +library +student +##ville +primary +owned +older +via +heavy +1st +makes +##able +attention +anyone +africa +##ri +stated +length +ended +fingers +command +staff +skin +foreign +opening +governor +okay +medal +kill +sun +cover +job +1985 +introduced +chest +hell +feeling +##ies +success +meet +reason +standard +meeting +novel +1984 +trade +source +buildings +##land +rose +guy +goal +##ur +chapter +native +husband +previously +unit +limited +entered +weeks +producer +operations +mountain +takes +covered +forced +related +roman +complete +successful +key +texas +cold +##ya +channel +1980 +traditional +films +dance +clear +approximately +500 +nine +van +prince +question +active +tracks +ireland +regional +silver +author +personal +sense +operation +##ine +economic +1983 +holding +twenty +isbn +additional +speed +hour +edition +regular +historic +places +whom +shook +movie +km² +secretary +prior +report +chicago +read +foundation +view +engine +scored +1982 +units +ask +airport +property +ready +immediately +lady +month +listed +contract +##de +manager +themselves +lines +##ki +navy +writer +meant +##ts +runs +##ro +practice +championships +singer +glass +commission +required +forest +starting +culture +generally +giving +access +attended +test +couple +stand +catholic +martin +caught +executive +##less +eye +##ey +thinking +chair +quite +shoulder +1979 +hope +decision +plays +defeated +municipality +whether +structure +offered +slowly +pain +ice +direction +##ion +paper +mission +1981 +mostly +200 +noted +individual +managed +nature +lives +plant +##ha +helped +except +studied +computer +figure +relationship +issue +significant +loss +die +smiled +gun +ago +highest +1972 +##am +male +bring +goals +mexico +problem +distance +commercial +completely +location +annual +famous +drive +1976 +neck +1978 +surface +caused +italy +understand +greek +highway +wrong +hotel +comes +appearance +joseph +double +issues +musical +companies +castle +income +review +assembly +bass +initially +parliament +artists +experience +1974 +particular +walk +foot +engineering +talking +window +dropped +##ter +miss +baby +boys +break +1975 +stars +edge +remember +policy +carried +train +stadium +bar +sex +angeles +evidence +##ge +becoming +assistant +soviet +1977 +upper +step +wing +1970 +youth +financial +reach +##ll +actor +numerous +##se +##st +nodded +arrived +##ation +minute +##nt +believed +sorry +complex +beautiful +victory +associated +temple +1968 +1973 +chance +perhaps +metal +##son +1945 +bishop +##et +lee +launched +particularly +tree +le +retired +subject +prize +contains +yeah +theory +empire +##ce +suddenly +waiting +trust +recording +##to +happy +terms +camp +champion +1971 +religious +pass +zealand +names +2nd +port +ancient +tom +corner +represented +watch +legal +anti +justice +cause +watched +brothers +45 +material +changes +simply +response +louis +fast +##ting +answer +60 +historical +1969 +stories +straight +create +feature +increased +rate +administration +virginia +el +activities +cultural +overall +winner +programs +basketball +legs +guard +beyond +cast +doctor +mm +flight +results +remains +cost +effect +winter +##ble +larger +islands +problems +chairman +grew +commander +isn +1967 +pay +failed +selected +hurt +fort +box +regiment +majority +journal +35 +edward +plans +##ke +##ni +shown +pretty +irish +characters +directly +scene +likely +operated +allow +spring +##j +junior +matches +looks +mike +houses +fellow +##tion +beach +marriage +##ham +##ive +rules +oil +65 +florida +expected +nearby +congress +sam +peace +recent +iii +wait +subsequently +cell +##do +variety +serving +agreed +please +poor +joe +pacific +attempt +wood +democratic +piece +prime +##ca +rural +mile +touch +appears +township +1964 +1966 +soldiers +##men +##ized +1965 +pennsylvania +closer +fighting +claimed +score +jones +physical +editor +##ous +filled +genus +specific +sitting +super +mom +##va +therefore +supported +status +fear +cases +store +meaning +wales +minor +spain +tower +focus +vice +frank +follow +parish +separate +golden +horse +fifth +remaining +branch +32 +presented +stared +##id +uses +secret +forms +##co +baseball +exactly +##ck +choice +note +discovered +travel +composed +truth +russia +ball +color +kiss +dad +wind +continue +ring +referred +numbers +digital +greater +##ns +metres +slightly +direct +increase +1960 +responsible +crew +rule +trees +troops +##no +broke +goes +individuals +hundred +weight +creek +sleep +memory +defense +provides +ordered +code +value +jewish +windows +1944 +safe +judge +whatever +corps +realized +growing +pre +##ga +cities +alexander +gaze +lies +spread +scott +letter +showed +situation +mayor +transport +watching +workers +extended +##li +expression +normal +##ment +chart +multiple +border +##ba +host +##ner +daily +mrs +walls +piano +##ko +heat +cannot +##ate +earned +products +drama +era +authority +seasons +join +grade +##io +sign +difficult +machine +1963 +territory +mainly +##wood +stations +squadron +1962 +stepped +iron +19th +##led +serve +appear +sky +speak +broken +charge +knowledge +kilometres +removed +ships +article +campus +simple +##ty +pushed +britain +##ve +leaves +recently +cd +soft +boston +latter +easy +acquired +poland +##sa +quality +officers +presence +planned +nations +mass +broadcast +jean +share +image +influence +wild +offer +emperor +electric +reading +headed +ability +promoted +yellow +ministry +1942 +throat +smaller +politician +##by +latin +spoke +cars +williams +males +lack +pop +80 +##ier +acting +seeing +consists +##ti +estate +1961 +pressure +johnson +newspaper +jr +chris +olympics +online +conditions +beat +elements +walking +vote +##field +needs +carolina +text +featuring +global +block +shirt +levels +francisco +purpose +females +et +dutch +duke +ahead +gas +twice +safety +serious +turning +highly +lieutenant +firm +maria +amount +mixed +daniel +proposed +perfect +agreement +affairs +3rd +seconds +contemporary +paid +1943 +prison +save +kitchen +label +administrative +intended +constructed +academic +nice +teacher +races +1956 +formerly +corporation +ben +nation +issued +shut +1958 +drums +housing +victoria +seems +opera +1959 +graduated +function +von +mentioned +picked +build +recognized +shortly +protection +picture +notable +exchange +elections +1980s +loved +percent +racing +fish +elizabeth +garden +volume +hockey +1941 +beside +settled +##ford +1940 +competed +replied +drew +1948 +actress +marine +scotland +steel +glanced +farm +steve +1957 +risk +tonight +positive +magic +singles +effects +gray +screen +dog +##ja +residents +bus +sides +none +secondary +literature +polish +destroyed +flying +founder +households +1939 +lay +reserve +usa +gallery +##ler +1946 +industrial +younger +approach +appearances +urban +ones +1950 +finish +avenue +powerful +fully +growth +page +honor +jersey +projects +advanced +revealed +basic +90 +infantry +pair +equipment +visit +33 +evening +search +grant +effort +solo +treatment +buried +republican +primarily +bottom +owner +1970s +israel +gives +jim +dream +bob +remain +spot +70 +notes +produce +champions +contact +ed +soul +accepted +ways +del +##ally +losing +split +price +capacity +basis +trial +questions +##ina +1955 +20th +guess +officially +memorial +naval +initial +##ization +whispered +median +engineer +##ful +sydney +##go +columbia +strength +300 +1952 +tears +senate +00 +card +asian +agent +1947 +software +44 +draw +warm +supposed +com +pro +##il +transferred +leaned +##at +candidate +escape +mountains +asia +potential +activity +entertainment +seem +traffic +jackson +murder +36 +slow +product +orchestra +haven +agency +bbc +taught +website +comedy +unable +storm +planning +albums +rugby +environment +scientific +grabbed +protect +##hi +boat +typically +1954 +1953 +damage +principal +divided +dedicated +mount +ohio +##berg +pick +fought +driver +##der +empty +shoulders +sort +thank +berlin +prominent +account +freedom +necessary +efforts +alex +headquarters +follows +alongside +des +simon +andrew +suggested +operating +learning +steps +1949 +sweet +technical +begin +easily +34 +teeth +speaking +settlement +scale +##sh +renamed +ray +max +enemy +semi +joint +compared +##rd +scottish +leadership +analysis +offers +georgia +pieces +captured +animal +deputy +guest +organized +##lin +tony +combined +method +challenge +1960s +huge +wants +battalion +sons +rise +crime +types +facilities +telling +path +1951 +platform +sit +1990s +##lo +tells +assigned +rich +pull +##ot +commonly +alive +##za +letters +concept +conducted +wearing +happen +bought +becomes +holy +gets +ocean +defeat +languages +purchased +coffee +occurred +titled +##q +declared +applied +sciences +concert +sounds +jazz +brain +##me +painting +fleet +tax +nick +##ius +michigan +count +animals +leaders +episodes +##line +content +##den +birth +##it +clubs +64 +palace +critical +refused +fair +leg +laughed +returning +surrounding +participated +formation +lifted +pointed +connected +rome +medicine +laid +taylor +santa +powers +adam +tall +shared +focused +knowing +yards +entrance +falls +##wa +calling +##ad +sources +chosen +beneath +resources +yard +##ite +nominated +silence +zone +defined +##que +gained +thirty +38 +bodies +moon +##ard +adopted +christmas +widely +register +apart +iran +premier +serves +du +unknown +parties +##les +generation +##ff +continues +quick +fields +brigade +quiet +teaching +clothes +impact +weapons +partner +flat +theater +supreme +1938 +37 +relations +##tor +plants +suffered +1936 +wilson +kids +begins +##age +1918 +seats +armed +internet +models +worth +laws +400 +communities +classes +background +knows +thanks +quarter +reaching +humans +carry +killing +format +kong +hong +setting +75 +architecture +disease +railroad +inc +possibly +wish +arthur +thoughts +harry +doors +density +##di +crowd +illinois +stomach +tone +unique +reports +anyway +##ir +liberal +der +vehicle +thick +dry +drug +faced +largely +facility +theme +holds +creation +strange +colonel +##mi +revolution +bell +politics +turns +silent +rail +relief +independence +combat +shape +write +determined +sales +learned +4th +finger +oxford +providing +1937 +heritage +fiction +situated +designated +allowing +distribution +hosted +##est +sight +interview +estimated +reduced +##ria +toronto +footballer +keeping +guys +damn +claim +motion +sport +sixth +stayed +##ze +en +rear +receive +handed +twelve +dress +audience +granted +brazil +##well +spirit +##ated +noticed +etc +olympic +representative +eric +tight +trouble +reviews +drink +vampire +missing +roles +ranked +newly +household +finals +wave +critics +##ee +phase +massachusetts +pilot +unlike +philadelphia +bright +guns +crown +organizations +roof +42 +respectively +clearly +tongue +marked +circle +fox +korea +bronze +brian +expanded +sexual +supply +yourself +inspired +labour +fc +##ah +reference +vision +draft +connection +brand +reasons +1935 +classic +driving +trip +jesus +cells +entry +1920 +neither +trail +claims +atlantic +orders +labor +nose +afraid +identified +intelligence +calls +cancer +attacked +passing +stephen +positions +imperial +grey +jason +39 +sunday +48 +swedish +avoid +extra +uncle +message +covers +allows +surprise +materials +fame +hunter +##ji +1930 +citizens +figures +davis +environmental +confirmed +shit +titles +di +performing +difference +acts +attacks +##ov +existing +votes +opportunity +nor +shop +entirely +trains +opposite +pakistan +##pa +develop +resulted +representatives +actions +reality +pressed +##ish +barely +wine +conversation +faculty +northwest +ends +documentary +nuclear +stock +grace +sets +eat +alternative +##ps +bag +resulting +creating +surprised +cemetery +1919 +drop +finding +sarah +cricket +streets +tradition +ride +1933 +exhibition +target +ear +explained +rain +composer +injury +apartment +municipal +educational +occupied +netherlands +clean +billion +constitution +learn +1914 +maximum +classical +francis +lose +opposition +jose +ontario +bear +core +hills +rolled +ending +drawn +permanent +fun +##tes +##lla +lewis +sites +chamber +ryan +##way +scoring +height +1934 +##house +lyrics +staring +55 +officials +1917 +snow +oldest +##tic +orange +##ger +qualified +interior +apparently +succeeded +thousand +dinner +lights +existence +fans +heavily +41 +greatest +conservative +send +bowl +plus +enter +catch +##un +economy +duty +1929 +speech +authorities +princess +performances +versions +shall +graduate +pictures +effective +remembered +poetry +desk +crossed +starring +starts +passenger +sharp +##ant +acres +ass +weather +falling +rank +fund +supporting +check +adult +publishing +heads +cm +southeast +lane +##burg +application +bc +##ura +les +condition +transfer +prevent +display +ex +regions +earl +federation +cool +relatively +answered +besides +1928 +obtained +portion +##town +mix +##ding +reaction +liked +dean +express +peak +1932 +##tte +counter +religion +chain +rare +miller +convention +aid +lie +vehicles +mobile +perform +squad +wonder +lying +crazy +sword +##ping +attempted +centuries +weren +philosophy +category +##ize +anna +interested +47 +sweden +wolf +frequently +abandoned +kg +literary +alliance +task +entitled +##ay +threw +promotion +factory +tiny +soccer +visited +matt +fm +achieved +52 +defence +internal +persian +43 +methods +##ging +arrested +otherwise +cambridge +programming +villages +elementary +districts +rooms +criminal +conflict +worry +trained +1931 +attempts +waited +signal +bird +truck +subsequent +programme +##ol +ad +49 +communist +details +faith +sector +patrick +carrying +laugh +##ss +controlled +korean +showing +origin +fuel +evil +1927 +##ent +brief +identity +darkness +address +pool +missed +publication +web +planet +ian +anne +wings +invited +##tt +briefly +standards +kissed +##be +ideas +climate +causing +walter +worse +albert +articles +winners +desire +aged +northeast +dangerous +gate +doubt +1922 +wooden +multi +##ky +poet +rising +funding +46 +communications +communication +violence +copies +prepared +ford +investigation +skills +1924 +pulling +electronic +##ak +##ial +##han +containing +ultimately +offices +singing +understanding +restaurant +tomorrow +fashion +christ +ward +da +pope +stands +5th +flow +studios +aired +commissioned +contained +exist +fresh +americans +##per +wrestling +approved +kid +employed +respect +suit +1925 +angel +asking +increasing +frame +angry +selling +1950s +thin +finds +##nd +temperature +statement +ali +explain +inhabitants +towns +extensive +narrow +51 +jane +flowers +images +promise +somewhere +object +fly +closely +##ls +1912 +bureau +cape +1926 +weekly +presidential +legislative +1921 +##ai +##au +launch +founding +##ny +978 +##ring +artillery +strike +un +institutions +roll +writers +landing +chose +kevin +anymore +pp +##ut +attorney +fit +dan +billboard +receiving +agricultural +breaking +sought +dave +admitted +lands +mexican +##bury +charlie +specifically +hole +iv +howard +credit +moscow +roads +accident +1923 +proved +wear +struck +hey +guards +stuff +slid +expansion +1915 +cat +anthony +##kin +melbourne +opposed +sub +southwest +architect +failure +plane +1916 +##ron +map +camera +tank +listen +regarding +wet +introduction +metropolitan +link +ep +fighter +inch +grown +gene +anger +fixed +buy +dvd +khan +domestic +worldwide +chapel +mill +functions +examples +##head +developing +1910 +turkey +hits +pocket +antonio +papers +grow +unless +circuit +18th +concerned +attached +journalist +selection +journey +converted +provincial +painted +hearing +aren +bands +negative +aside +wondered +knight +lap +survey +ma +##ow +noise +billy +##ium +shooting +guide +bedroom +priest +resistance +motor +homes +sounded +giant +##mer +150 +scenes +equal +comic +patients +hidden +solid +actual +bringing +afternoon +touched +funds +wedding +consisted +marie +canal +sr +kim +treaty +turkish +recognition +residence +cathedral +broad +knees +incident +shaped +fired +norwegian +handle +cheek +contest +represent +##pe +representing +beauty +##sen +birds +advantage +emergency +wrapped +drawing +notice +pink +broadcasting +##ong +somehow +bachelor +seventh +collected +registered +establishment +alan +assumed +chemical +personnel +roger +retirement +jeff +portuguese +wore +tied +device +threat +progress +advance +##ised +banks +hired +manchester +nfl +teachers +structures +forever +##bo +tennis +helping +saturday +sale +applications +junction +hip +incorporated +neighborhood +dressed +ceremony +##ds +influenced +hers +visual +stairs +decades +inner +kansas +hung +hoped +gain +scheduled +downtown +engaged +austria +clock +norway +certainly +pale +protected +1913 +victor +employees +plate +putting +surrounded +##ists +finishing +blues +tropical +##ries +minnesota +consider +philippines +accept +54 +retrieved +1900 +concern +anderson +properties +institution +gordon +successfully +vietnam +##dy +backing +outstanding +muslim +crossing +folk +producing +usual +demand +occurs +observed +lawyer +educated +##ana +kelly +string +pleasure +budget +items +quietly +colorado +philip +typical +##worth +derived +600 +survived +asks +mental +##ide +56 +jake +jews +distinguished +ltd +1911 +sri +extremely +53 +athletic +loud +thousands +worried +shadow +transportation +horses +weapon +arena +importance +users +tim +objects +contributed +dragon +douglas +aware +senator +johnny +jordan +sisters +engines +flag +investment +samuel +shock +capable +clark +row +wheel +refers +session +familiar +biggest +wins +hate +maintained +drove +hamilton +request +expressed +injured +underground +churches +walker +wars +tunnel +passes +stupid +agriculture +softly +cabinet +regarded +joining +indiana +##ea +##ms +push +dates +spend +behavior +woods +protein +gently +chase +morgan +mention +burning +wake +combination +occur +mirror +leads +jimmy +indeed +impossible +singapore +paintings +covering +##nes +soldier +locations +attendance +sell +historian +wisconsin +invasion +argued +painter +diego +changing +egypt +##don +experienced +inches +##ku +missouri +vol +grounds +spoken +switzerland +##gan +reform +rolling +ha +forget +massive +resigned +burned +allen +tennessee +locked +values +improved +##mo +wounded +universe +sick +dating +facing +pack +purchase +user +##pur +moments +##ul +merged +anniversary +1908 +coal +brick +understood +causes +dynasty +queensland +establish +stores +crisis +promote +hoping +views +cards +referee +extension +##si +raise +arizona +improve +colonial +formal +charged +##rt +palm +lucky +hide +rescue +faces +95 +feelings +candidates +juan +##ell +goods +6th +courses +weekend +59 +luke +cash +fallen +##om +delivered +affected +installed +carefully +tries +swiss +hollywood +costs +lincoln +responsibility +##he +shore +file +proper +normally +maryland +assistance +jump +constant +offering +friendly +waters +persons +realize +contain +trophy +800 +partnership +factor +58 +musicians +cry +bound +oregon +indicated +hero +houston +medium +##ure +consisting +somewhat +##ara +57 +cycle +##che +beer +moore +frederick +gotten +eleven +worst +weak +approached +arranged +chin +loan +universal +bond +fifteen +pattern +disappeared +##ney +translated +##zed +lip +arab +capture +interests +insurance +##chi +shifted +cave +prix +warning +sections +courts +coat +plot +smell +feed +golf +favorite +maintain +knife +vs +voted +degrees +finance +quebec +opinion +translation +manner +ruled +operate +productions +choose +musician +discovery +confused +tired +separated +stream +techniques +committed +attend +ranking +kings +throw +passengers +measure +horror +fan +mining +sand +danger +salt +calm +decade +dam +require +runner +##ik +rush +associate +greece +##ker +rivers +consecutive +matthew +##ski +sighed +sq +documents +steam +edited +closing +tie +accused +1905 +##ini +islamic +distributed +directors +organisation +bruce +7th +breathing +mad +lit +arrival +concrete +taste +08 +composition +shaking +faster +amateur +adjacent +stating +1906 +twin +flew +##ran +tokyo +publications +##tone +obviously +ridge +storage +1907 +carl +pages +concluded +desert +driven +universities +ages +terminal +sequence +borough +250 +constituency +creative +cousin +economics +dreams +margaret +notably +reduce +montreal +mode +17th +ears +saved +jan +vocal +##ica +1909 +andy +##jo +riding +roughly +threatened +##ise +meters +meanwhile +landed +compete +repeated +grass +czech +regularly +charges +tea +sudden +appeal +##ung +solution +describes +pierre +classification +glad +parking +##ning +belt +physics +99 +rachel +add +hungarian +participate +expedition +damaged +gift +childhood +85 +fifty +##red +mathematics +jumped +letting +defensive +mph +##ux +##gh +testing +##hip +hundreds +shoot +owners +matters +smoke +israeli +kentucky +dancing +mounted +grandfather +emma +designs +profit +argentina +##gs +truly +li +lawrence +cole +begun +detroit +willing +branches +smiling +decide +miami +enjoyed +recordings +##dale +poverty +ethnic +gay +##bi +gary +arabic +09 +accompanied +##one +##ons +fishing +determine +residential +acid +##ary +alice +returns +starred +mail +##ang +jonathan +strategy +##ue +net +forty +cook +businesses +equivalent +commonwealth +distinct +ill +##cy +seriously +##ors +##ped +shift +harris +replace +rio +imagine +formula +ensure +##ber +additionally +scheme +conservation +occasionally +purposes +feels +favor +##and +##ore +1930s +contrast +hanging +hunt +movies +1904 +instruments +victims +danish +christopher +busy +demon +sugar +earliest +colony +studying +balance +duties +##ks +belgium +slipped +carter +05 +visible +stages +iraq +fifa +##im +commune +forming +zero +07 +continuing +talked +counties +legend +bathroom +option +tail +clay +daughters +afterwards +severe +jaw +visitors +##ded +devices +aviation +russell +kate +##vi +entering +subjects +##ino +temporary +swimming +forth +smooth +ghost +audio +bush +operates +rocks +movements +signs +eddie +##tz +ann +voices +honorary +06 +memories +dallas +pure +measures +racial +promised +66 +harvard +ceo +16th +parliamentary +indicate +benefit +flesh +dublin +louisiana +1902 +1901 +patient +sleeping +1903 +membership +coastal +medieval +wanting +element +scholars +rice +62 +limit +survive +makeup +rating +definitely +collaboration +obvious +##tan +boss +ms +baron +birthday +linked +soil +diocese +##lan +ncaa +##mann +offensive +shell +shouldn +waist +##tus +plain +ross +organ +resolution +manufacturing +adding +relative +kennedy +98 +whilst +moth +marketing +gardens +crash +72 +heading +partners +credited +carlos +moves +cable +##zi +marshall +##out +depending +bottle +represents +rejected +responded +existed +04 +jobs +denmark +lock +##ating +treated +graham +routes +talent +commissioner +drugs +secure +tests +reign +restored +photography +##gi +contributions +oklahoma +designer +disc +grin +seattle +robin +paused +atlanta +unusual +##gate +praised +las +laughing +satellite +hungary +visiting +##sky +interesting +factors +deck +poems +norman +##water +stuck +speaker +rifle +domain +premiered +##her +dc +comics +actors +01 +reputation +eliminated +8th +ceiling +prisoners +script +##nce +leather +austin +mississippi +rapidly +admiral +parallel +charlotte +guilty +tools +gender +divisions +fruit +##bs +laboratory +nelson +fantasy +marry +rapid +aunt +tribe +requirements +aspects +suicide +amongst +adams +bone +ukraine +abc +kick +sees +edinburgh +clothing +column +rough +gods +hunting +broadway +gathered +concerns +##ek +spending +ty +12th +snapped +requires +solar +bones +cavalry +##tta +iowa +drinking +waste +index +franklin +charity +thompson +stewart +tip +flash +landscape +friday +enjoy +singh +poem +listening +##back +eighth +fred +differences +adapted +bomb +ukrainian +surgery +corporate +masters +anywhere +##more +waves +odd +sean +portugal +orleans +dick +debate +kent +eating +puerto +cleared +96 +expect +cinema +97 +guitarist +blocks +electrical +agree +involving +depth +dying +panel +struggle +##ged +peninsula +adults +novels +emerged +vienna +metro +debuted +shoes +tamil +songwriter +meets +prove +beating +instance +heaven +scared +sending +marks +artistic +passage +superior +03 +significantly +shopping +##tive +retained +##izing +malaysia +technique +cheeks +##ola +warren +maintenance +destroy +extreme +allied +120 +appearing +##yn +fill +advice +alabama +qualifying +policies +cleveland +hat +battery +smart +authors +10th +soundtrack +acted +dated +lb +glance +equipped +coalition +funny +outer +ambassador +roy +possibility +couples +campbell +dna +loose +ethan +supplies +1898 +gonna +88 +monster +##res +shake +agents +frequency +springs +dogs +practices +61 +gang +plastic +easier +suggests +gulf +blade +exposed +colors +industries +markets +pan +nervous +electoral +charts +legislation +ownership +##idae +mac +appointment +shield +copy +assault +socialist +abbey +monument +license +throne +employment +jay +93 +replacement +charter +cloud +powered +suffering +accounts +oak +connecticut +strongly +wright +colour +crystal +13th +context +welsh +networks +voiced +gabriel +jerry +##cing +forehead +mp +##ens +manage +schedule +totally +remix +##ii +forests +occupation +print +nicholas +brazilian +strategic +vampires +engineers +76 +roots +seek +correct +instrumental +und +alfred +backed +hop +##des +stanley +robinson +traveled +wayne +welcome +austrian +achieve +67 +exit +rates +1899 +strip +whereas +##cs +sing +deeply +adventure +bobby +rick +jamie +careful +components +cap +useful +personality +knee +##shi +pushing +hosts +02 +protest +ca +ottoman +symphony +##sis +63 +boundary +1890 +processes +considering +considerable +tons +##work +##ft +##nia +cooper +trading +dear +conduct +91 +illegal +apple +revolutionary +holiday +definition +harder +##van +jacob +circumstances +destruction +##lle +popularity +grip +classified +liverpool +donald +baltimore +flows +seeking +honour +approval +92 +mechanical +till +happening +statue +critic +increasingly +immediate +describe +commerce +stare +##ster +indonesia +meat +rounds +boats +baker +orthodox +depression +formally +worn +naked +claire +muttered +sentence +11th +emily +document +77 +criticism +wished +vessel +spiritual +bent +virgin +parker +minimum +murray +lunch +danny +printed +compilation +keyboards +false +blow +belonged +68 +raising +78 +cutting +##board +pittsburgh +##up +9th +shadows +81 +hated +indigenous +jon +15th +barry +scholar +ah +##zer +oliver +##gy +stick +susan +meetings +attracted +spell +romantic +##ver +ye +1895 +photo +demanded +customers +##ac +1896 +logan +revival +keys +modified +commanded +jeans +##ious +upset +raw +phil +detective +hiding +resident +vincent +##bly +experiences +diamond +defeating +coverage +lucas +external +parks +franchise +helen +bible +successor +percussion +celebrated +il +lift +profile +clan +romania +##ied +mills +##su +nobody +achievement +shrugged +fault +1897 +rhythm +initiative +breakfast +carbon +700 +69 +lasted +violent +74 +wound +ken +killer +gradually +filmed +°c +dollars +processing +94 +remove +criticized +guests +sang +chemistry +##vin +legislature +disney +##bridge +uniform +escaped +integrated +proposal +purple +denied +liquid +karl +influential +morris +nights +stones +intense +experimental +twisted +71 +84 +##ld +pace +nazi +mitchell +ny +blind +reporter +newspapers +14th +centers +burn +basin +forgotten +surviving +filed +collections +monastery +losses +manual +couch +description +appropriate +merely +tag +missions +sebastian +restoration +replacing +triple +73 +elder +julia +warriors +benjamin +julian +convinced +stronger +amazing +declined +versus +merchant +happens +output +finland +bare +barbara +absence +ignored +dawn +injuries +##port +producers +##ram +82 +luis +##ities +kw +admit +expensive +electricity +nba +exception +symbol +##ving +ladies +shower +sheriff +characteristics +##je +aimed +button +ratio +effectively +summit +angle +jury +bears +foster +vessels +pants +executed +evans +dozen +advertising +kicked +patrol +1889 +competitions +lifetime +principles +athletics +##logy +birmingham +sponsored +89 +rob +nomination +1893 +acoustic +##sm +creature +longest +##tra +credits +harbor +dust +josh +##so +territories +milk +infrastructure +completion +thailand +indians +leon +archbishop +##sy +assist +pitch +blake +arrangement +girlfriend +serbian +operational +hence +sad +scent +fur +dj +sessions +hp +refer +rarely +##ora +exists +1892 +##ten +scientists +dirty +penalty +burst +portrait +seed +79 +pole +limits +rival +1894 +stable +alpha +grave +constitutional +alcohol +arrest +flower +mystery +devil +architectural +relationships +greatly +habitat +##istic +larry +progressive +remote +cotton +##ics +##ok +preserved +reaches +##ming +cited +86 +vast +scholarship +decisions +cbs +joy +teach +1885 +editions +knocked +eve +searching +partly +participation +gap +animated +fate +excellent +##ett +na +87 +alternate +saints +youngest +##ily +climbed +##ita +##tors +suggest +##ct +discussion +staying +choir +lakes +jacket +revenue +nevertheless +peaked +instrument +wondering +annually +managing +neil +1891 +signing +terry +##ice +apply +clinical +brooklyn +aim +catherine +fuck +farmers +figured +ninth +pride +hugh +evolution +ordinary +involvement +comfortable +shouted +tech +encouraged +taiwan +representation +sharing +##lia +##em +panic +exact +cargo +competing +fat +cried +83 +1920s +occasions +pa +cabin +borders +utah +marcus +##isation +badly +muscles +##ance +victorian +transition +warner +bet +permission +##rin +slave +terrible +similarly +shares +seth +uefa +possession +medals +benefits +colleges +lowered +perfectly +mall +transit +##ye +##kar +publisher +##ened +harrison +deaths +elevation +##ae +asleep +machines +sigh +ash +hardly +argument +occasion +parent +leo +decline +1888 +contribution +##ua +concentration +1000 +opportunities +hispanic +guardian +extent +emotions +hips +mason +volumes +bloody +controversy +diameter +steady +mistake +phoenix +identify +violin +##sk +departure +richmond +spin +funeral +enemies +1864 +gear +literally +connor +random +sergeant +grab +confusion +1865 +transmission +informed +op +leaning +sacred +suspended +thinks +gates +portland +luck +agencies +yours +hull +expert +muscle +layer +practical +sculpture +jerusalem +latest +lloyd +statistics +deeper +recommended +warrior +arkansas +mess +supports +greg +eagle +1880 +recovered +rated +concerts +rushed +##ano +stops +eggs +files +premiere +keith +##vo +delhi +turner +pit +affair +belief +paint +##zing +mate +##ach +##ev +victim +##ology +withdrew +bonus +styles +fled +##ud +glasgow +technologies +funded +nbc +adaptation +##ata +portrayed +cooperation +supporters +judges +bernard +justin +hallway +ralph +##ick +graduating +controversial +distant +continental +spider +bite +##ho +recognize +intention +mixing +##ese +egyptian +bow +tourism +suppose +claiming +tiger +dominated +participants +vi +##ru +nurse +partially +tape +##rum +psychology +##rn +essential +touring +duo +voting +civilian +emotional +channels +##king +apparent +hebrew +1887 +tommy +carrier +intersection +beast +hudson +##gar +##zo +lab +nova +bench +discuss +costa +##ered +detailed +behalf +drivers +unfortunately +obtain +##lis +rocky +##dae +siege +friendship +honey +##rian +1861 +amy +hang +posted +governments +collins +respond +wildlife +preferred +operator +##po +laura +pregnant +videos +dennis +suspected +boots +instantly +weird +automatic +businessman +alleged +placing +throwing +ph +mood +1862 +perry +venue +jet +remainder +##lli +##ci +passion +biological +boyfriend +1863 +dirt +buffalo +ron +segment +fa +abuse +##era +genre +thrown +stroke +colored +stress +exercise +displayed +##gen +struggled +##tti +abroad +dramatic +wonderful +thereafter +madrid +component +widespread +##sed +tale +citizen +todd +monday +1886 +vancouver +overseas +forcing +crying +descent +##ris +discussed +substantial +ranks +regime +1870 +provinces +switch +drum +zane +ted +tribes +proof +lp +cream +researchers +volunteer +manor +silk +milan +donated +allies +venture +principle +delivery +enterprise +##ves +##ans +bars +traditionally +witch +reminded +copper +##uk +pete +inter +links +colin +grinned +elsewhere +competitive +frequent +##oy +scream +##hu +tension +texts +submarine +finnish +defending +defend +pat +detail +1884 +affiliated +stuart +themes +villa +periods +tool +belgian +ruling +crimes +answers +folded +licensed +resort +demolished +hans +lucy +1881 +lion +traded +photographs +writes +craig +##fa +trials +generated +beth +noble +debt +percentage +yorkshire +erected +ss +viewed +grades +confidence +ceased +islam +telephone +retail +##ible +chile +m² +roberts +sixteen +##ich +commented +hampshire +innocent +dual +pounds +checked +regulations +afghanistan +sung +rico +liberty +assets +bigger +options +angels +relegated +tribute +wells +attending +leaf +##yan +butler +romanian +forum +monthly +lisa +patterns +gmina +##tory +madison +hurricane +rev +##ians +bristol +##ula +elite +valuable +disaster +democracy +awareness +germans +freyja +##ins +loop +absolutely +paying +populations +maine +sole +prayer +spencer +releases +doorway +bull +##ani +lover +midnight +conclusion +##sson +thirteen +lily +mediterranean +##lt +nhl +proud +sample +##hill +drummer +guinea +##ova +murphy +climb +##ston +instant +attributed +horn +ain +railways +steven +##ao +autumn +ferry +opponent +root +traveling +secured +corridor +stretched +tales +sheet +trinity +cattle +helps +indicates +manhattan +murdered +fitted +1882 +gentle +grandmother +mines +shocked +vegas +produces +##light +caribbean +##ou +belong +continuous +desperate +drunk +historically +trio +waved +raf +dealing +nathan +bat +murmured +interrupted +residing +scientist +pioneer +harold +aaron +##net +delta +attempting +minority +mini +believes +chorus +tend +lots +eyed +indoor +load +shots +updated +jail +##llo +concerning +connecting +wealth +##ved +slaves +arrive +rangers +sufficient +rebuilt +##wick +cardinal +flood +muhammad +whenever +relation +runners +moral +repair +viewers +arriving +revenge +punk +assisted +bath +fairly +breathe +lists +innings +illustrated +whisper +nearest +voters +clinton +ties +ultimate +screamed +beijing +lions +andre +fictional +gathering +comfort +radar +suitable +dismissed +hms +ban +pine +wrist +atmosphere +voivodeship +bid +timber +##ned +##nan +giants +##ane +cameron +recovery +uss +identical +categories +switched +serbia +laughter +noah +ensemble +therapy +peoples +touching +##off +locally +pearl +platforms +everywhere +ballet +tables +lanka +herbert +outdoor +toured +derek +1883 +spaces +contested +swept +1878 +exclusive +slight +connections +##dra +winds +prisoner +collective +bangladesh +tube +publicly +wealthy +thai +##ys +isolated +select +##ric +insisted +pen +fortune +ticket +spotted +reportedly +animation +enforcement +tanks +110 +decides +wider +lowest +owen +##time +nod +hitting +##hn +gregory +furthermore +magazines +fighters +solutions +##ery +pointing +requested +peru +reed +chancellor +knights +mask +worker +eldest +flames +reduction +1860 +volunteers +##tis +reporting +##hl +wire +advisory +endemic +origins +settlers +pursue +knock +consumer +1876 +eu +compound +creatures +mansion +sentenced +ivan +deployed +guitars +frowned +involves +mechanism +kilometers +perspective +shops +maps +terminus +duncan +alien +fist +bridges +##pers +heroes +fed +derby +swallowed +##ros +patent +sara +illness +characterized +adventures +slide +hawaii +jurisdiction +##op +organised +##side +adelaide +walks +biology +se +##ties +rogers +swing +tightly +boundaries +##rie +prepare +implementation +stolen +##sha +certified +colombia +edwards +garage +##mm +recalled +##ball +rage +harm +nigeria +breast +##ren +furniture +pupils +settle +##lus +cuba +balls +client +alaska +21st +linear +thrust +celebration +latino +genetic +terror +##cia +##ening +lightning +fee +witness +lodge +establishing +skull +##ique +earning +hood +##ei +rebellion +wang +sporting +warned +missile +devoted +activist +porch +worship +fourteen +package +1871 +decorated +##shire +housed +##ock +chess +sailed +doctors +oscar +joan +treat +garcia +harbour +jeremy +##ire +traditions +dominant +jacques +##gon +##wan +relocated +1879 +amendment +sized +companion +simultaneously +volleyball +spun +acre +increases +stopping +loves +belongs +affect +drafted +tossed +scout +battles +1875 +filming +shoved +munich +tenure +vertical +romance +pc +##cher +argue +##ical +craft +ranging +www +opens +honest +tyler +yesterday +virtual +##let +muslims +reveal +snake +immigrants +radical +screaming +speakers +firing +saving +belonging +ease +lighting +prefecture +blame +farmer +hungry +grows +rubbed +beam +sur +subsidiary +##cha +armenian +sao +dropping +conventional +##fer +microsoft +reply +qualify +spots +1867 +sweat +festivals +##ken +immigration +physician +discover +exposure +sandy +explanation +isaac +implemented +##fish +hart +initiated +connect +stakes +presents +heights +householder +pleased +tourist +regardless +slip +closest +##ction +surely +sultan +brings +riley +preparation +aboard +slammed +baptist +experiment +ongoing +interstate +organic +playoffs +##ika +1877 +130 +##tar +hindu +error +tours +tier +plenty +arrangements +talks +trapped +excited +sank +ho +athens +1872 +denver +welfare +suburb +athletes +trick +diverse +belly +exclusively +yelled +1868 +##med +conversion +##ette +1874 +internationally +computers +conductor +abilities +sensitive +hello +dispute +measured +globe +rocket +prices +amsterdam +flights +tigers +inn +municipalities +emotion +references +3d +##mus +explains +airlines +manufactured +pm +archaeological +1873 +interpretation +devon +comment +##ites +settlements +kissing +absolute +improvement +suite +impressed +barcelona +sullivan +jefferson +towers +jesse +julie +##tin +##lu +grandson +hi +gauge +regard +rings +interviews +trace +raymond +thumb +departments +burns +serial +bulgarian +scores +demonstrated +##ix +1866 +kyle +alberta +underneath +romanized +##ward +relieved +acquisition +phrase +cliff +reveals +han +cuts +merger +custom +##dar +nee +gilbert +graduation +##nts +assessment +cafe +difficulty +demands +swung +democrat +jennifer +commons +1940s +grove +##yo +completing +focuses +sum +substitute +bearing +stretch +reception +##py +reflected +essentially +destination +pairs +##ched +survival +resource +##bach +promoting +doubles +messages +tear +##down +##fully +parade +florence +harvey +incumbent +partial +framework +900 +pedro +frozen +procedure +olivia +controls +##mic +shelter +personally +temperatures +##od +brisbane +tested +sits +marble +comprehensive +oxygen +leonard +##kov +inaugural +iranian +referring +quarters +attitude +##ivity +mainstream +lined +mars +dakota +norfolk +unsuccessful +##° +explosion +helicopter +congressional +##sing +inspector +bitch +seal +departed +divine +##ters +coaching +examination +punishment +manufacturer +sink +columns +unincorporated +signals +nevada +squeezed +dylan +dining +photos +martial +manuel +eighteen +elevator +brushed +plates +ministers +ivy +congregation +##len +slept +specialized +taxes +curve +restricted +negotiations +likes +statistical +arnold +inspiration +execution +bold +intermediate +significance +margin +ruler +wheels +gothic +intellectual +dependent +listened +eligible +buses +widow +syria +earn +cincinnati +collapsed +recipient +secrets +accessible +philippine +maritime +goddess +clerk +surrender +breaks +playoff +database +##ified +##lon +ideal +beetle +aspect +soap +regulation +strings +expand +anglo +shorter +crosses +retreat +tough +coins +wallace +directions +pressing +##oon +shipping +locomotives +comparison +topics +nephew +##mes +distinction +honors +travelled +sierra +ibn +##over +fortress +sa +recognised +carved +1869 +clients +##dan +intent +##mar +coaches +describing +bread +##ington +beaten +northwestern +##ona +merit +youtube +collapse +challenges +em +historians +objective +submitted +virus +attacking +drake +assume +##ere +diseases +marc +stem +leeds +##cus +##ab +farming +glasses +##lock +visits +nowhere +fellowship +relevant +carries +restaurants +experiments +101 +constantly +bases +targets +shah +tenth +opponents +verse +territorial +##ira +writings +corruption +##hs +instruction +inherited +reverse +emphasis +##vic +employee +arch +keeps +rabbi +watson +payment +uh +##ala +nancy +##tre +venice +fastest +sexy +banned +adrian +properly +ruth +touchdown +dollar +boards +metre +circles +edges +favour +comments +ok +travels +liberation +scattered +firmly +##ular +holland +permitted +diesel +kenya +den +originated +##ral +demons +resumed +dragged +rider +##rus +servant +blinked +extend +torn +##ias +##sey +input +meal +everybody +cylinder +kinds +camps +##fe +bullet +logic +##wn +croatian +evolved +healthy +fool +chocolate +wise +preserve +pradesh +##ess +respective +1850 +##ew +chicken +artificial +gross +corresponding +convicted +cage +caroline +dialogue +##dor +narrative +stranger +mario +br +christianity +failing +trent +commanding +buddhist +1848 +maurice +focusing +yale +bike +altitude +##ering +mouse +revised +##sley +veteran +##ig +pulls +theology +crashed +campaigns +legion +##ability +drag +excellence +customer +cancelled +intensity +excuse +##lar +liga +participating +contributing +printing +##burn +variable +##rk +curious +bin +legacy +renaissance +##my +symptoms +binding +vocalist +dancer +##nie +grammar +gospel +democrats +ya +enters +sc +diplomatic +hitler +##ser +clouds +mathematical +quit +defended +oriented +##heim +fundamental +hardware +impressive +equally +convince +confederate +guilt +chuck +sliding +##ware +magnetic +narrowed +petersburg +bulgaria +otto +phd +skill +##ama +reader +hopes +pitcher +reservoir +hearts +automatically +expecting +mysterious +bennett +extensively +imagined +seeds +monitor +fix +##ative +journalism +struggling +signature +ranch +encounter +photographer +observation +protests +##pin +influences +##hr +calendar +##all +cruz +croatia +locomotive +hughes +naturally +shakespeare +basement +hook +uncredited +faded +theories +approaches +dare +phillips +filling +fury +obama +##ain +efficient +arc +deliver +min +raid +breeding +inducted +leagues +efficiency +axis +montana +eagles +##ked +supplied +instructions +karen +picking +indicating +trap +anchor +practically +christians +tomb +vary +occasional +electronics +lords +readers +newcastle +faint +innovation +collect +situations +engagement +160 +claude +mixture +##feld +peer +tissue +logo +lean +##ration +°f +floors +##ven +architects +reducing +##our +##ments +rope +1859 +ottawa +##har +samples +banking +declaration +proteins +resignation +francois +saudi +advocate +exhibited +armor +twins +divorce +##ras +abraham +reviewed +jo +temporarily +matrix +physically +pulse +curled +##ena +difficulties +bengal +usage +##ban +annie +riders +certificate +##pi +holes +warsaw +distinctive +jessica +##mon +mutual +1857 +customs +circular +eugene +removal +loaded +mere +vulnerable +depicted +generations +dame +heir +enormous +lightly +climbing +pitched +lessons +pilots +nepal +ram +google +preparing +brad +louise +renowned +##₂ +liam +##ably +plaza +shaw +sophie +brilliant +bills +##bar +##nik +fucking +mainland +server +pleasant +seized +veterans +jerked +fail +beta +brush +radiation +stored +warmth +southeastern +nate +sin +raced +berkeley +joke +athlete +designation +trunk +##low +roland +qualification +archives +heels +artwork +receives +judicial +reserves +##bed +woke +installation +abu +floating +fake +lesser +excitement +interface +concentrated +addressed +characteristic +amanda +saxophone +monk +auto +##bus +releasing +egg +dies +interaction +defender +ce +outbreak +glory +loving +##bert +sequel +consciousness +http +awake +ski +enrolled +##ress +handling +rookie +brow +somebody +biography +warfare +amounts +contracts +presentation +fabric +dissolved +challenged +meter +psychological +lt +elevated +rally +accurate +##tha +hospitals +undergraduate +specialist +venezuela +exhibit +shed +nursing +protestant +fluid +structural +footage +jared +consistent +prey +##ska +succession +reflect +exile +lebanon +wiped +suspect +shanghai +resting +integration +preservation +marvel +variant +pirates +sheep +rounded +capita +sailing +colonies +manuscript +deemed +variations +clarke +functional +emerging +boxing +relaxed +curse +azerbaijan +heavyweight +nickname +editorial +rang +grid +tightened +earthquake +flashed +miguel +rushing +##ches +improvements +boxes +brooks +180 +consumption +molecular +felix +societies +repeatedly +variation +aids +civic +graphics +professionals +realm +autonomous +receiver +delayed +workshop +militia +chairs +trump +canyon +##point +harsh +extending +lovely +happiness +##jan +stake +eyebrows +embassy +wellington +hannah +##ella +sony +corners +bishops +swear +cloth +contents +xi +namely +commenced +1854 +stanford +nashville +courage +graphic +commitment +garrison +##bin +hamlet +clearing +rebels +attraction +literacy +cooking +ruins +temples +jenny +humanity +celebrate +hasn +freight +sixty +rebel +bastard +##art +newton +##ada +deer +##ges +##ching +smiles +delaware +singers +##ets +approaching +assists +flame +##ph +boulevard +barrel +planted +##ome +pursuit +##sia +consequences +posts +shallow +invitation +rode +depot +ernest +kane +rod +concepts +preston +topic +chambers +striking +blast +arrives +descendants +montgomery +ranges +worlds +##lay +##ari +span +chaos +praise +##ag +fewer +1855 +sanctuary +mud +fbi +##ions +programmes +maintaining +unity +harper +bore +handsome +closure +tournaments +thunder +nebraska +linda +facade +puts +satisfied +argentine +dale +cork +dome +panama +##yl +1858 +tasks +experts +##ates +feeding +equation +##las +##ida +##tu +engage +bryan +##ax +um +quartet +melody +disbanded +sheffield +blocked +gasped +delay +kisses +maggie +connects +##non +sts +poured +creator +publishers +##we +guided +ellis +extinct +hug +gaining +##ord +complicated +##bility +poll +clenched +investigate +##use +thereby +quantum +spine +cdp +humor +kills +administered +semifinals +##du +encountered +ignore +##bu +commentary +##maker +bother +roosevelt +140 +plains +halfway +flowing +cultures +crack +imprisoned +neighboring +airline +##ses +##view +##mate +##ec +gather +wolves +marathon +transformed +##ill +cruise +organisations +carol +punch +exhibitions +numbered +alarm +ratings +daddy +silently +##stein +queens +colours +impression +guidance +liu +tactical +##rat +marshal +della +arrow +##ings +rested +feared +tender +owns +bitter +advisor +escort +##ides +spare +farms +grants +##ene +dragons +encourage +colleagues +cameras +##und +sucked +pile +spirits +prague +statements +suspension +landmark +fence +torture +recreation +bags +permanently +survivors +pond +spy +predecessor +bombing +coup +##og +protecting +transformation +glow +##lands +##book +dug +priests +andrea +feat +barn +jumping +##chen +##ologist +##con +casualties +stern +auckland +pipe +serie +revealing +ba +##bel +trevor +mercy +spectrum +yang +consist +governing +collaborated +possessed +epic +comprises +blew +shane +##ack +lopez +honored +magical +sacrifice +judgment +perceived +hammer +mtv +baronet +tune +das +missionary +sheets +350 +neutral +oral +threatening +attractive +shade +aims +seminary +##master +estates +1856 +michel +wounds +refugees +manufacturers +##nic +mercury +syndrome +porter +##iya +##din +hamburg +identification +upstairs +purse +widened +pause +cared +breathed +affiliate +santiago +prevented +celtic +fisher +125 +recruited +byzantine +reconstruction +farther +##mp +diet +sake +au +spite +sensation +##ert +blank +separation +105 +##hon +vladimir +armies +anime +##lie +accommodate +orbit +cult +sofia +archive +##ify +##box +founders +sustained +disorder +honours +northeastern +mia +crops +violet +threats +blanket +fires +canton +followers +southwestern +prototype +voyage +assignment +altered +moderate +protocol +pistol +##eo +questioned +brass +lifting +1852 +math +authored +##ual +doug +dimensional +dynamic +##san +1851 +pronounced +grateful +quest +uncomfortable +boom +presidency +stevens +relating +politicians +chen +barrier +quinn +diana +mosque +tribal +cheese +palmer +portions +sometime +chester +treasure +wu +bend +download +millions +reforms +registration +##osa +consequently +monitoring +ate +preliminary +brandon +invented +ps +eaten +exterior +intervention +ports +documented +log +displays +lecture +sally +favourite +##itz +vermont +lo +invisible +isle +breed +##ator +journalists +relay +speaks +backward +explore +midfielder +actively +stefan +procedures +cannon +blond +kenneth +centered +servants +chains +libraries +malcolm +essex +henri +slavery +##hal +facts +fairy +coached +cassie +cats +washed +cop +##fi +announcement +item +2000s +vinyl +activated +marco +frontier +growled +curriculum +##das +loyal +accomplished +leslie +ritual +kenny +##00 +vii +napoleon +hollow +hybrid +jungle +stationed +friedrich +counted +##ulated +platinum +theatrical +seated +col +rubber +glen +1840 +diversity +healing +extends +id +provisions +administrator +columbus +##oe +tributary +te +assured +org +##uous +prestigious +examined +lectures +grammy +ronald +associations +bailey +allan +essays +flute +believing +consultant +proceedings +travelling +1853 +kit +kerala +yugoslavia +buddy +methodist +##ith +burial +centres +batman +##nda +discontinued +bo +dock +stockholm +lungs +severely +##nk +citing +manga +##ugh +steal +mumbai +iraqi +robot +celebrity +bride +broadcasts +abolished +pot +joel +overhead +franz +packed +reconnaissance +johann +acknowledged +introduce +handled +doctorate +developments +drinks +alley +palestine +##nis +##aki +proceeded +recover +bradley +grain +patch +afford +infection +nationalist +legendary +##ath +interchange +virtually +gen +gravity +exploration +amber +vital +wishes +powell +doctrine +elbow +screenplay +##bird +contribute +indonesian +pet +creates +##com +enzyme +kylie +discipline +drops +manila +hunger +##ien +layers +suffer +fever +bits +monica +keyboard +manages +##hood +searched +appeals +##bad +testament +grande +reid +##war +beliefs +congo +##ification +##dia +si +requiring +##via +casey +1849 +regret +streak +rape +depends +syrian +sprint +pound +tourists +upcoming +pub +##xi +tense +##els +practiced +echo +nationwide +guild +motorcycle +liz +##zar +chiefs +desired +elena +bye +precious +absorbed +relatives +booth +pianist +##mal +citizenship +exhausted +wilhelm +##ceae +##hed +noting +quarterback +urge +hectares +##gue +ace +holly +##tal +blonde +davies +parked +sustainable +stepping +twentieth +airfield +galaxy +nest +chip +##nell +tan +shaft +paulo +requirement +##zy +paradise +tobacco +trans +renewed +vietnamese +##cker +##ju +suggesting +catching +holmes +enjoying +md +trips +colt +holder +butterfly +nerve +reformed +cherry +bowling +trailer +carriage +goodbye +appreciate +toy +joshua +interactive +enabled +involve +##kan +collar +determination +bunch +facebook +recall +shorts +superintendent +episcopal +frustration +giovanni +nineteenth +laser +privately +array +circulation +##ovic +armstrong +deals +painful +permit +discrimination +##wi +aires +retiring +cottage +ni +##sta +horizon +ellen +jamaica +ripped +fernando +chapters +playstation +patron +lecturer +navigation +behaviour +genes +georgian +export +solomon +rivals +swift +seventeen +rodriguez +princeton +independently +sox +1847 +arguing +entity +casting +hank +criteria +oakland +geographic +milwaukee +reflection +expanding +conquest +dubbed +##tv +halt +brave +brunswick +doi +arched +curtis +divorced +predominantly +somerset +streams +ugly +zoo +horrible +curved +buenos +fierce +dictionary +vector +theological +unions +handful +stability +chan +punjab +segments +##lly +altar +ignoring +gesture +monsters +pastor +##stone +thighs +unexpected +operators +abruptly +coin +compiled +associates +improving +migration +pin +##ose +compact +collegiate +reserved +##urs +quarterfinals +roster +restore +assembled +hurry +oval +##cies +1846 +flags +martha +##del +victories +sharply +##rated +argues +deadly +neo +drawings +symbols +performer +##iel +griffin +restrictions +editing +andrews +java +journals +arabia +compositions +dee +pierce +removing +hindi +casino +runway +civilians +minds +nasa +hotels +##zation +refuge +rent +retain +potentially +conferences +suburban +conducting +##tto +##tions +##tle +descended +massacre +##cal +ammunition +terrain +fork +souls +counts +chelsea +durham +drives +cab +##bank +perth +realizing +palestinian +finn +simpson +##dal +betty +##ule +moreover +particles +cardinals +tent +evaluation +extraordinary +##oid +inscription +##works +wednesday +chloe +maintains +panels +ashley +trucks +##nation +cluster +sunlight +strikes +zhang +##wing +dialect +canon +##ap +tucked +##ws +collecting +##mas +##can +##sville +maker +quoted +evan +franco +aria +buying +cleaning +eva +closet +provision +apollo +clinic +rat +##ez +necessarily +ac +##gle +##ising +venues +flipped +cent +spreading +trustees +checking +authorized +##sco +disappointed +##ado +notion +duration +trumpet +hesitated +topped +brussels +rolls +theoretical +hint +define +aggressive +repeat +wash +peaceful +optical +width +allegedly +mcdonald +strict +copyright +##illa +investors +mar +jam +witnesses +sounding +miranda +michelle +privacy +hugo +harmony +##pp +valid +lynn +glared +nina +102 +headquartered +diving +boarding +gibson +##ncy +albanian +marsh +routine +dealt +enhanced +er +intelligent +substance +targeted +enlisted +discovers +spinning +observations +pissed +smoking +rebecca +capitol +visa +varied +costume +seemingly +indies +compensation +surgeon +thursday +arsenal +westminster +suburbs +rid +anglican +##ridge +knots +foods +alumni +lighter +fraser +whoever +portal +scandal +##ray +gavin +advised +instructor +flooding +terrorist +##ale +teenage +interim +senses +duck +teen +thesis +abby +eager +overcome +##ile +newport +glenn +rises +shame +##cc +prompted +priority +forgot +bomber +nicolas +protective +360 +cartoon +katherine +breeze +lonely +trusted +henderson +richardson +relax +banner +candy +palms +remarkable +##rio +legends +cricketer +essay +ordained +edmund +rifles +trigger +##uri +##away +sail +alert +1830 +audiences +penn +sussex +siblings +pursued +indianapolis +resist +rosa +consequence +succeed +avoided +1845 +##ulation +inland +##tie +##nna +counsel +profession +chronicle +hurried +##una +eyebrow +eventual +bleeding +innovative +cure +##dom +committees +accounting +con +scope +hardy +heather +tenor +gut +herald +codes +tore +scales +wagon +##oo +luxury +tin +prefer +fountain +triangle +bonds +darling +convoy +dried +traced +beings +troy +accidentally +slam +findings +smelled +joey +lawyers +outcome +steep +bosnia +configuration +shifting +toll +brook +performers +lobby +philosophical +construct +shrine +aggregate +boot +cox +phenomenon +savage +insane +solely +reynolds +lifestyle +##ima +nationally +holdings +consideration +enable +edgar +mo +mama +##tein +fights +relegation +chances +atomic +hub +conjunction +awkward +reactions +currency +finale +kumar +underwent +steering +elaborate +gifts +comprising +melissa +veins +reasonable +sunshine +chi +solve +trails +inhabited +elimination +ethics +huh +ana +molly +consent +apartments +layout +marines +##ces +hunters +bulk +##oma +hometown +##wall +##mont +cracked +reads +neighbouring +withdrawn +admission +wingspan +damned +anthology +lancashire +brands +batting +forgive +cuban +awful +##lyn +104 +dimensions +imagination +##ade +dante +##ship +tracking +desperately +goalkeeper +##yne +groaned +workshops +confident +burton +gerald +milton +circus +uncertain +slope +copenhagen +sophia +fog +philosopher +portraits +accent +cycling +varying +gripped +larvae +garrett +specified +scotia +mature +luther +kurt +rap +##kes +aerial +750 +ferdinand +heated +es +transported +##shan +safely +nonetheless +##orn +##gal +motors +demanding +##sburg +startled +##brook +ally +generate +caps +ghana +stained +demo +mentions +beds +ap +afterward +diary +##bling +utility +##iro +richards +1837 +conspiracy +conscious +shining +footsteps +observer +cyprus +urged +loyalty +developer +probability +olive +upgraded +gym +miracle +insects +graves +1844 +ourselves +hydrogen +amazon +katie +tickets +poets +##pm +planes +##pan +prevention +witnessed +dense +jin +randy +tang +warehouse +monroe +bang +archived +elderly +investigations +alec +granite +mineral +conflicts +controlling +aboriginal +carlo +##zu +mechanics +stan +stark +rhode +skirt +est +##berry +bombs +respected +##horn +imposed +limestone +deny +nominee +memphis +grabbing +disabled +##als +amusement +aa +frankfurt +corn +referendum +varies +slowed +disk +firms +unconscious +incredible +clue +sue +##zhou +twist +##cio +joins +idaho +chad +developers +computing +destroyer +103 +mortal +tucker +kingston +choices +yu +carson +1800 +os +whitney +geneva +pretend +dimension +staged +plateau +maya +##une +freestyle +##bc +rovers +hiv +##ids +tristan +classroom +prospect +##hus +honestly +diploma +lied +thermal +auxiliary +feast +unlikely +iata +##tel +morocco +pounding +treasury +lithuania +considerably +1841 +dish +1812 +geological +matching +stumbled +destroying +marched +brien +advances +cake +nicole +belle +settling +measuring +directing +##mie +tuesday +bassist +capabilities +stunned +fraud +torpedo +##list +##phone +anton +wisdom +surveillance +ruined +##ulate +lawsuit +healthcare +theorem +halls +trend +aka +horizontal +dozens +acquire +lasting +swim +hawk +gorgeous +fees +vicinity +decrease +adoption +tactics +##ography +pakistani +##ole +draws +##hall +willie +burke +heath +algorithm +integral +powder +elliott +brigadier +jackie +tate +varieties +darker +##cho +lately +cigarette +specimens +adds +##ree +##ensis +##inger +exploded +finalist +cia +murders +wilderness +arguments +nicknamed +acceptance +onwards +manufacture +robertson +jets +tampa +enterprises +blog +loudly +composers +nominations +1838 +ai +malta +inquiry +automobile +hosting +viii +rays +tilted +grief +museums +strategies +furious +euro +equality +cohen +poison +surrey +wireless +governed +ridiculous +moses +##esh +##room +vanished +##ito +barnes +attract +morrison +istanbul +##iness +absent +rotation +petition +janet +##logical +satisfaction +custody +deliberately +observatory +comedian +surfaces +pinyin +novelist +strictly +canterbury +oslo +monks +embrace +ibm +jealous +photograph +continent +dorothy +marina +doc +excess +holden +allegations +explaining +stack +avoiding +lance +storyline +majesty +poorly +spike +dos +bradford +raven +travis +classics +proven +voltage +pillow +fists +butt +1842 +interpreted +##car +1839 +gage +telegraph +lens +promising +expelled +casual +collector +zones +##min +silly +nintendo +##kh +##bra +downstairs +chef +suspicious +afl +flies +vacant +uganda +pregnancy +condemned +lutheran +estimates +cheap +decree +saxon +proximity +stripped +idiot +deposits +contrary +presenter +magnus +glacier +im +offense +edwin +##ori +upright +##long +bolt +##ois +toss +geographical +##izes +environments +delicate +marking +abstract +xavier +nails +windsor +plantation +occurring +equity +saskatchewan +fears +drifted +sequences +vegetation +revolt +##stic +1843 +sooner +fusion +opposing +nato +skating +1836 +secretly +ruin +lease +##oc +edit +##nne +flora +anxiety +ruby +##ological +##mia +tel +bout +taxi +emmy +frost +rainbow +compounds +foundations +rainfall +assassination +nightmare +dominican +##win +achievements +deserve +orlando +intact +armenia +##nte +calgary +valentine +106 +marion +proclaimed +theodore +bells +courtyard +thigh +gonzalez +console +troop +minimal +monte +everyday +##ence +##if +supporter +terrorism +buck +openly +presbyterian +activists +carpet +##iers +rubbing +uprising +##yi +cute +conceived +legally +##cht +millennium +cello +velocity +ji +rescued +cardiff +1835 +rex +concentrate +senators +beard +rendered +glowing +battalions +scouts +competitors +sculptor +catalogue +arctic +ion +raja +bicycle +wow +glancing +lawn +##woman +gentleman +lighthouse +publish +predicted +calculated +##val +variants +##gne +strain +##ui +winston +deceased +##nus +touchdowns +brady +caleb +sinking +echoed +crush +hon +blessed +protagonist +hayes +endangered +magnitude +editors +##tine +estimate +responsibilities +##mel +backup +laying +consumed +sealed +zurich +lovers +frustrated +##eau +ahmed +kicking +mit +treasurer +1832 +biblical +refuse +terrified +pump +agrees +genuine +imprisonment +refuses +plymouth +##hen +lou +##nen +tara +trembling +antarctic +ton +learns +##tas +crap +crucial +faction +atop +##borough +wrap +lancaster +odds +hopkins +erik +lyon +##eon +bros +##ode +snap +locality +tips +empress +crowned +cal +acclaimed +chuckled +##ory +clara +sends +mild +towel +##fl +##day +##а +wishing +assuming +interviewed +##bal +##die +interactions +eden +cups +helena +##lf +indie +beck +##fire +batteries +filipino +wizard +parted +##lam +traces +##born +rows +idol +albany +delegates +##ees +##sar +discussions +##ex +notre +instructed +belgrade +highways +suggestion +lauren +possess +orientation +alexandria +abdul +beats +salary +reunion +ludwig +alright +wagner +intimate +pockets +slovenia +hugged +brighton +merchants +cruel +stole +trek +slopes +repairs +enrollment +politically +underlying +promotional +counting +boeing +##bb +isabella +naming +##и +keen +bacteria +listing +separately +belfast +ussr +450 +lithuanian +anybody +ribs +sphere +martinez +cock +embarrassed +proposals +fragments +nationals +##fs +##wski +premises +fin +1500 +alpine +matched +freely +bounded +jace +sleeve +##af +gaming +pier +populated +evident +##like +frances +flooded +##dle +frightened +pour +trainer +framed +visitor +challenging +pig +wickets +##fold +infected +email +##pes +arose +##aw +reward +ecuador +oblast +vale +ch +shuttle +##usa +bach +rankings +forbidden +cornwall +accordance +salem +consumers +bruno +fantastic +toes +machinery +resolved +julius +remembering +propaganda +iceland +bombardment +tide +contacts +wives +##rah +concerto +macdonald +albania +implement +daisy +tapped +sudan +helmet +angela +mistress +##lic +crop +sunk +finest +##craft +hostile +##ute +##tsu +boxer +fr +paths +adjusted +habit +ballot +supervision +soprano +##zen +bullets +wicked +sunset +regiments +disappear +lamp +performs +app +##gia +##oa +rabbit +digging +incidents +entries +##cion +dishes +##oi +introducing +##ati +##fied +freshman +slot +jill +tackles +baroque +backs +##iest +lone +sponsor +destiny +altogether +convert +##aro +consensus +shapes +demonstration +basically +feminist +auction +artifacts +##bing +strongest +twitter +halifax +2019 +allmusic +mighty +smallest +precise +alexandra +viola +##los +##ille +manuscripts +##illo +dancers +ari +managers +monuments +blades +barracks +springfield +maiden +consolidated +electron +##end +berry +airing +wheat +nobel +inclusion +blair +payments +geography +bee +cc +eleanor +react +##hurst +afc +manitoba +##yu +su +lineup +fitness +recreational +investments +airborne +disappointment +##dis +edmonton +viewing +##row +renovation +##cast +infant +bankruptcy +roses +aftermath +pavilion +##yer +carpenter +withdrawal +ladder +##hy +discussing +popped +reliable +agreements +rochester +##abad +curves +bombers +220 +rao +reverend +decreased +choosing +107 +stiff +consulting +naples +crawford +tracy +ka +ribbon +cops +##lee +crushed +deciding +unified +teenager +accepting +flagship +explorer +poles +sanchez +inspection +revived +skilled +induced +exchanged +flee +locals +tragedy +swallow +loading +hanna +demonstrate +##ela +salvador +flown +contestants +civilization +##ines +wanna +rhodes +fletcher +hector +knocking +considers +##ough +nash +mechanisms +sensed +mentally +walt +unclear +##eus +renovated +madame +##cks +crews +governmental +##hin +undertaken +monkey +##ben +##ato +fatal +armored +copa +caves +governance +grasp +perception +certification +froze +damp +tugged +wyoming +##rg +##ero +newman +##lor +nerves +curiosity +graph +115 +##ami +withdraw +tunnels +dull +meredith +moss +exhibits +neighbors +communicate +accuracy +explored +raiders +republicans +secular +kat +superman +penny +criticised +##tch +freed +update +conviction +wade +ham +likewise +delegation +gotta +doll +promises +technological +myth +nationality +resolve +convent +##mark +sharon +dig +sip +coordinator +entrepreneur +fold +##dine +capability +councillor +synonym +blown +swan +cursed +1815 +jonas +haired +sofa +canvas +keeper +rivalry +##hart +rapper +speedway +swords +postal +maxwell +estonia +potter +recurring +##nn +##ave +errors +##oni +cognitive +1834 +##² +claws +nadu +roberto +bce +wrestler +ellie +##ations +infinite +ink +##tia +presumably +finite +staircase +108 +noel +patricia +nacional +##cation +chill +eternal +tu +preventing +prussia +fossil +limbs +##logist +ernst +frog +perez +rene +##ace +pizza +prussian +##ios +##vy +molecules +regulatory +answering +opinions +sworn +lengths +supposedly +hypothesis +upward +habitats +seating +ancestors +drank +yield +hd +synthesis +researcher +modest +##var +mothers +peered +voluntary +homeland +##the +acclaim +##igan +static +valve +luxembourg +alto +carroll +fe +receptor +norton +ambulance +##tian +johnston +catholics +depicting +jointly +elephant +gloria +mentor +badge +ahmad +distinguish +remarked +councils +precisely +allison +advancing +detection +crowded +##10 +cooperative +ankle +mercedes +dagger +surrendered +pollution +commit +subway +jeffrey +lesson +sculptures +provider +##fication +membrane +timothy +rectangular +fiscal +heating +teammate +basket +particle +anonymous +deployment +##ple +missiles +courthouse +proportion +shoe +sec +##ller +complaints +forbes +blacks +abandon +remind +sizes +overwhelming +autobiography +natalie +##awa +risks +contestant +countryside +babies +scorer +invaded +enclosed +proceed +hurling +disorders +##cu +reflecting +continuously +cruiser +graduates +freeway +investigated +ore +deserved +maid +blocking +phillip +jorge +shakes +dove +mann +variables +lacked +burden +accompanying +que +consistently +organizing +provisional +complained +endless +##rm +tubes +juice +georges +krishna +mick +labels +thriller +##uch +laps +arcade +sage +snail +##table +shannon +fi +laurence +seoul +vacation +presenting +hire +churchill +surprisingly +prohibited +savannah +technically +##oli +170 +##lessly +testimony +suited +speeds +toys +romans +mlb +flowering +measurement +talented +kay +settings +charleston +expectations +shattered +achieving +triumph +ceremonies +portsmouth +lanes +mandatory +loser +stretching +cologne +realizes +seventy +cornell +careers +webb +##ulating +americas +budapest +ava +suspicion +##ison +yo +conrad +##hai +sterling +jessie +rector +##az +1831 +transform +organize +loans +christine +volcanic +warrant +slender +summers +subfamily +newer +danced +dynamics +rhine +proceeds +heinrich +gastropod +commands +sings +facilitate +easter +ra +positioned +responses +expense +fruits +yanked +imported +25th +velvet +vic +primitive +tribune +baldwin +neighbourhood +donna +rip +hay +pr +##uro +1814 +espn +welcomed +##aria +qualifier +glare +highland +timing +##cted +shells +eased +geometry +louder +exciting +slovakia +##sion +##iz +##lot +savings +prairie +##ques +marching +rafael +tonnes +##lled +curtain +preceding +shy +heal +greene +worthy +##pot +detachment +bury +sherman +##eck +reinforced +seeks +bottles +contracted +duchess +outfit +walsh +##sc +mickey +##ase +geoffrey +archer +squeeze +dawson +eliminate +invention +##enberg +neal +##eth +stance +dealer +coral +maple +retire +polo +simplified +##ht +1833 +hid +watts +backwards +jules +##oke +genesis +mt +frames +rebounds +burma +woodland +moist +santos +whispers +drained +subspecies +##aa +streaming +ulster +burnt +correspondence +maternal +gerard +denis +stealing +##load +genius +duchy +##oria +inaugurated +momentum +suits +placement +sovereign +clause +thames +##hara +confederation +reservation +sketch +yankees +lets +rotten +charm +hal +verses +ultra +commercially +dot +salon +citation +adopt +winnipeg +mist +allocated +cairo +##boy +jenkins +interference +objectives +##wind +1820 +portfolio +armoured +sectors +##eh +initiatives +##world +integrity +exercises +robe +tap +ab +gazed +##tones +distracted +rulers +111 +favorable +jerome +tended +cart +factories +##eri +diplomat +valued +gravel +charitable +##try +calvin +exploring +chang +shepherd +terrace +pdf +pupil +##ural +reflects +ups +##rch +governors +shelf +depths +##nberg +trailed +crest +tackle +##nian +##ats +hatred +##kai +clare +makers +ethiopia +longtime +detected +embedded +lacking +slapped +rely +thomson +anticipation +iso +morton +successive +agnes +screenwriter +straightened +philippe +playwright +haunted +licence +iris +intentions +sutton +112 +logical +correctly +##weight +branded +licked +tipped +silva +ricky +narrator +requests +##ents +greeted +supernatural +cow +##wald +lung +refusing +employer +strait +gaelic +liner +##piece +zoe +sabha +##mba +driveway +harvest +prints +bates +reluctantly +threshold +algebra +ira +wherever +coupled +240 +assumption +picks +##air +designers +raids +gentlemen +##ean +roller +blowing +leipzig +locks +screw +dressing +strand +##lings +scar +dwarf +depicts +##nu +nods +##mine +differ +boris +##eur +yuan +flip +##gie +mob +invested +questioning +applying +##ture +shout +##sel +gameplay +blamed +illustrations +bothered +weakness +rehabilitation +##of +##zes +envelope +rumors +miners +leicester +subtle +kerry +##ico +ferguson +##fu +premiership +ne +##cat +bengali +prof +catches +remnants +dana +##rily +shouting +presidents +baltic +ought +ghosts +dances +sailors +shirley +fancy +dominic +##bie +madonna +##rick +bark +buttons +gymnasium +ashes +liver +toby +oath +providence +doyle +evangelical +nixon +cement +carnegie +embarked +hatch +surroundings +guarantee +needing +pirate +essence +##bee +filter +crane +hammond +projected +immune +percy +twelfth +##ult +regent +doctoral +damon +mikhail +##ichi +lu +critically +elect +realised +abortion +acute +screening +mythology +steadily +##fc +frown +nottingham +kirk +wa +minneapolis +##rra +module +algeria +mc +nautical +encounters +surprising +statues +availability +shirts +pie +alma +brows +munster +mack +soup +crater +tornado +sanskrit +cedar +explosive +bordered +dixon +planets +stamp +exam +happily +##bble +carriers +kidnapped +##vis +accommodation +emigrated +##met +knockout +correspondent +violation +profits +peaks +lang +specimen +agenda +ancestry +pottery +spelling +equations +obtaining +ki +linking +1825 +debris +asylum +##20 +buddhism +teddy +##ants +gazette +##nger +##sse +dental +eligibility +utc +fathers +averaged +zimbabwe +francesco +coloured +hissed +translator +lynch +mandate +humanities +mackenzie +uniforms +lin +##iana +##gio +asset +mhz +fitting +samantha +genera +wei +rim +beloved +shark +riot +entities +expressions +indo +carmen +slipping +owing +abbot +neighbor +sidney +##av +rats +recommendations +encouraging +squadrons +anticipated +commanders +conquered +##oto +donations +diagnosed +##mond +divide +##iva +guessed +decoration +vernon +auditorium +revelation +conversations +##kers +##power +herzegovina +dash +alike +protested +lateral +herman +accredited +mg +##gent +freeman +mel +fiji +crow +crimson +##rine +livestock +##pped +humanitarian +bored +oz +whip +##lene +##ali +legitimate +alter +grinning +spelled +anxious +oriental +wesley +##nin +##hole +carnival +controller +detect +##ssa +bowed +educator +kosovo +macedonia +##sin +occupy +mastering +stephanie +janeiro +para +unaware +nurses +noon +135 +cam +hopefully +ranger +combine +sociology +polar +rica +##eer +neill +##sman +holocaust +##ip +doubled +lust +1828 +109 +decent +cooling +unveiled +##card +1829 +nsw +homer +chapman +meyer +##gin +dive +mae +reagan +expertise +##gled +darwin +brooke +sided +prosecution +investigating +comprised +petroleum +genres +reluctant +differently +trilogy +johns +vegetables +corpse +highlighted +lounge +pension +unsuccessfully +elegant +aided +ivory +beatles +amelia +cain +dubai +sunny +immigrant +babe +click +##nder +underwater +pepper +combining +mumbled +atlas +horns +accessed +ballad +physicians +homeless +gestured +rpm +freak +louisville +corporations +patriots +prizes +rational +warn +modes +decorative +overnight +din +troubled +phantom +##ort +monarch +sheer +##dorf +generals +guidelines +organs +addresses +##zon +enhance +curling +parishes +cord +##kie +linux +caesar +deutsche +bavaria +##bia +coleman +cyclone +##eria +bacon +petty +##yama +##old +hampton +diagnosis +1824 +throws +complexity +rita +disputed +##₃ +pablo +##sch +marketed +trafficking +##ulus +examine +plague +formats +##oh +vault +faithful +##bourne +webster +##ox +highlights +##ient +##ann +phones +vacuum +sandwich +modeling +##gated +bolivia +clergy +qualities +isabel +##nas +##ars +wears +screams +reunited +annoyed +bra +##ancy +##rate +differential +transmitter +tattoo +container +poker +##och +excessive +resides +cowboys +##tum +augustus +trash +providers +statute +retreated +balcony +reversed +void +storey +preceded +masses +leap +laughs +neighborhoods +wards +schemes +falcon +santo +battlefield +pad +ronnie +thread +lesbian +venus +##dian +beg +sandstone +daylight +punched +gwen +analog +stroked +wwe +acceptable +measurements +dec +toxic +##kel +adequate +surgical +economist +parameters +varsity +##sberg +quantity +ella +##chy +##rton +countess +generating +precision +diamonds +expressway +ga +##ı +1821 +uruguay +talents +galleries +expenses +scanned +colleague +outlets +ryder +lucien +##ila +paramount +##bon +syracuse +dim +fangs +gown +sweep +##sie +toyota +missionaries +websites +##nsis +sentences +adviser +val +trademark +spells +##plane +patience +starter +slim +##borg +toe +incredibly +shoots +elliot +nobility +##wyn +cowboy +endorsed +gardner +tendency +persuaded +organisms +emissions +kazakhstan +amused +boring +chips +themed +##hand +llc +constantinople +chasing +systematic +guatemala +borrowed +erin +carey +##hard +highlands +struggles +1810 +##ifying +##ced +wong +exceptions +develops +enlarged +kindergarten +castro +##ern +##rina +leigh +zombie +juvenile +##most +consul +##nar +sailor +hyde +clarence +intensive +pinned +nasty +useless +jung +clayton +stuffed +exceptional +ix +apostolic +230 +transactions +##dge +exempt +swinging +cove +religions +##ash +shields +dairy +bypass +190 +pursuing +bug +joyce +bombay +chassis +southampton +chat +interact +redesignated +##pen +nascar +pray +salmon +rigid +regained +malaysian +grim +publicity +constituted +capturing +toilet +delegate +purely +tray +drift +loosely +striker +weakened +trinidad +mitch +itv +defines +transmitted +ming +scarlet +nodding +fitzgerald +fu +narrowly +sp +tooth +standings +virtue +##₁ +##wara +##cting +chateau +gloves +lid +##nel +hurting +conservatory +##pel +sinclair +reopened +sympathy +nigerian +strode +advocated +optional +chronic +discharge +##rc +suck +compatible +laurel +stella +shi +fails +wage +dodge +128 +informal +sorts +levi +buddha +villagers +##aka +chronicles +heavier +summoned +gateway +3000 +eleventh +jewelry +translations +accordingly +seas +##ency +fiber +pyramid +cubic +dragging +##ista +caring +##ops +android +contacted +lunar +##dt +kai +lisbon +patted +1826 +sacramento +theft +madagascar +subtropical +disputes +ta +holidays +piper +willow +mare +cane +itunes +newfoundland +benny +companions +dong +raj +observe +roar +charming +plaque +tibetan +fossils +enacted +manning +bubble +tina +tanzania +##eda +##hir +funk +swamp +deputies +cloak +ufc +scenario +par +scratch +metals +anthem +guru +engaging +specially +##boat +dialects +nineteen +cecil +duet +disability +messenger +unofficial +##lies +defunct +eds +moonlight +drainage +surname +puzzle +honda +switching +conservatives +mammals +knox +broadcaster +sidewalk +cope +##ried +benson +princes +peterson +##sal +bedford +sharks +eli +wreck +alberto +gasp +archaeology +lgbt +teaches +securities +madness +compromise +waving +coordination +davidson +visions +leased +possibilities +eighty +jun +fernandez +enthusiasm +assassin +sponsorship +reviewer +kingdoms +estonian +laboratories +##fy +##nal +applies +verb +celebrations +##zzo +rowing +lightweight +sadness +submit +mvp +balanced +dude +##vas +explicitly +metric +magnificent +mound +brett +mohammad +mistakes +irregular +##hing +##ass +sanders +betrayed +shipped +surge +##enburg +reporters +termed +georg +pity +verbal +bulls +abbreviated +enabling +appealed +##are +##atic +sicily +sting +heel +sweetheart +bart +spacecraft +brutal +monarchy +##tter +aberdeen +cameo +diane +##ub +survivor +clyde +##aries +complaint +##makers +clarinet +delicious +chilean +karnataka +coordinates +1818 +panties +##rst +pretending +ar +dramatically +kiev +bella +tends +distances +113 +catalog +launching +instances +telecommunications +portable +lindsay +vatican +##eim +angles +aliens +marker +stint +screens +bolton +##rne +judy +wool +benedict +plasma +europa +spark +imaging +filmmaker +swiftly +##een +contributor +##nor +opted +stamps +apologize +financing +butter +gideon +sophisticated +alignment +avery +chemicals +yearly +speculation +prominence +professionally +##ils +immortal +institutional +inception +wrists +identifying +tribunal +derives +gains +##wo +papal +preference +linguistic +vince +operative +brewery +##ont +unemployment +boyd +##ured +##outs +albeit +prophet +1813 +bi +##rr +##face +##rad +quarterly +asteroid +cleaned +radius +temper +##llen +telugu +jerk +viscount +menu +##ote +glimpse +##aya +yacht +hawaiian +baden +##rl +laptop +readily +##gu +monetary +offshore +scots +watches +##yang +##arian +upgrade +needle +xbox +lea +encyclopedia +flank +fingertips +##pus +delight +teachings +confirm +roth +beaches +midway +winters +##iah +teasing +daytime +beverly +gambling +bonnie +##backs +regulated +clement +hermann +tricks +knot +##shing +##uring +##vre +detached +ecological +owed +specialty +byron +inventor +bats +stays +screened +unesco +midland +trim +affection +##ander +##rry +jess +thoroughly +feedback +##uma +chennai +strained +heartbeat +wrapping +overtime +pleaded +##sworth +mon +leisure +oclc +##tate +##ele +feathers +angelo +thirds +nuts +surveys +clever +gill +commentator +##dos +darren +rides +gibraltar +##nc +##mu +dissolution +dedication +shin +meals +saddle +elvis +reds +chaired +taller +appreciation +functioning +niece +favored +advocacy +robbie +criminals +suffolk +yugoslav +passport +constable +congressman +hastings +vera +##rov +consecrated +sparks +ecclesiastical +confined +##ovich +muller +floyd +nora +1822 +paved +1827 +cumberland +ned +saga +spiral +##flow +appreciated +yi +collaborative +treating +similarities +feminine +finishes +##ib +jade +import +##nse +##hot +champagne +mice +securing +celebrities +helsinki +attributes +##gos +cousins +phases +ache +lucia +gandhi +submission +vicar +spear +shine +tasmania +biting +detention +constitute +tighter +seasonal +##gus +terrestrial +matthews +##oka +effectiveness +parody +philharmonic +##onic +1816 +strangers +encoded +consortium +guaranteed +regards +shifts +tortured +collision +supervisor +inform +broader +insight +theaters +armour +emeritus +blink +incorporates +mapping +##50 +##ein +handball +flexible +##nta +substantially +generous +thief +##own +carr +loses +1793 +prose +ucla +romeo +generic +metallic +realization +damages +mk +commissioners +zach +default +##ther +helicopters +lengthy +stems +spa +partnered +spectators +rogue +indication +penalties +teresa +1801 +sen +##tric +dalton +##wich +irving +photographic +##vey +dell +deaf +peters +excluded +unsure +##vable +patterson +crawled +##zio +resided +whipped +latvia +slower +ecole +pipes +employers +maharashtra +comparable +va +textile +pageant +##gel +alphabet +binary +irrigation +chartered +choked +antoine +offs +waking +supplement +##wen +quantities +demolition +regain +locate +urdu +folks +alt +114 +##mc +scary +andreas +whites +##ava +classrooms +mw +aesthetic +publishes +valleys +guides +cubs +johannes +bryant +conventions +affecting +##itt +drain +awesome +isolation +prosecutor +ambitious +apology +captive +downs +atmospheric +lorenzo +aisle +beef +foul +##onia +kidding +composite +disturbed +illusion +natives +##ffer +emi +rockets +riverside +wartime +painters +adolf +melted +##ail +uncertainty +simulation +hawks +progressed +meantime +builder +spray +breach +unhappy +regina +russians +##urg +determining +##tation +tram +1806 +##quin +aging +##12 +1823 +garion +rented +mister +diaz +terminated +clip +1817 +depend +nervously +disco +owe +defenders +shiva +notorious +disbelief +shiny +worcester +##gation +##yr +trailing +undertook +islander +belarus +limitations +watershed +fuller +overlooking +utilized +raphael +1819 +synthetic +breakdown +klein +##nate +moaned +memoir +lamb +practicing +##erly +cellular +arrows +exotic +##graphy +witches +117 +charted +rey +hut +hierarchy +subdivision +freshwater +giuseppe +aloud +reyes +qatar +marty +sideways +utterly +sexually +jude +prayers +mccarthy +softball +blend +damien +##gging +##metric +wholly +erupted +lebanese +negro +revenues +tasted +comparative +teamed +transaction +labeled +maori +sovereignty +parkway +trauma +gran +malay +121 +advancement +descendant +2020 +buzz +salvation +inventory +symbolic +##making +antarctica +mps +##gas +##bro +mohammed +myanmar +holt +submarines +tones +##lman +locker +patriarch +bangkok +emerson +remarks +predators +kin +afghan +confession +norwich +rental +emerge +advantages +##zel +rca +##hold +shortened +storms +aidan +##matic +autonomy +compliance +##quet +dudley +atp +##osis +1803 +motto +documentation +summary +professors +spectacular +christina +archdiocese +flashing +innocence +remake +##dell +psychic +reef +scare +employ +rs +sticks +meg +gus +leans +##ude +accompany +bergen +tomas +##iko +doom +wages +pools +##nch +##bes +breasts +scholarly +alison +outline +brittany +breakthrough +willis +realistic +##cut +##boro +competitor +##stan +pike +picnic +icon +designing +commercials +washing +villain +skiing +micro +costumes +auburn +halted +executives +##hat +logistics +cycles +vowel +applicable +barrett +exclaimed +eurovision +eternity +ramon +##umi +##lls +modifications +sweeping +disgust +##uck +torch +aviv +ensuring +rude +dusty +sonic +donovan +outskirts +cu +pathway +##band +##gun +##lines +disciplines +acids +cadet +paired +##40 +sketches +##sive +marriages +##⁺ +folding +peers +slovak +implies +admired +##beck +1880s +leopold +instinct +attained +weston +megan +horace +##ination +dorsal +ingredients +evolutionary +##its +complications +deity +lethal +brushing +levy +deserted +institutes +posthumously +delivering +telescope +coronation +motivated +rapids +luc +flicked +pays +volcano +tanner +weighed +##nica +crowds +frankie +gifted +addressing +granddaughter +winding +##rna +constantine +gomez +##front +landscapes +rudolf +anthropology +slate +werewolf +##lio +astronomy +circa +rouge +dreaming +sack +knelt +drowned +naomi +prolific +tracked +freezing +herb +##dium +agony +randall +twisting +wendy +deposit +touches +vein +wheeler +##bbled +##bor +batted +retaining +tire +presently +compare +specification +daemon +nigel +##grave +merry +recommendation +czechoslovakia +sandra +ng +roma +##sts +lambert +inheritance +sheikh +winchester +cries +examining +##yle +comeback +cuisine +nave +##iv +ko +retrieve +tomatoes +barker +polished +defining +irene +lantern +personalities +begging +tract +swore +1809 +175 +##gic +omaha +brotherhood +##rley +haiti +##ots +exeter +##ete +##zia +steele +dumb +pearson +210 +surveyed +elisabeth +trends +##ef +fritz +##rf +premium +bugs +fraction +calmly +viking +##birds +tug +inserted +unusually +##ield +confronted +distress +crashing +brent +turks +resign +##olo +cambodia +gabe +sauce +##kal +evelyn +116 +extant +clusters +quarry +teenagers +luna +##lers +##ister +affiliation +drill +##ashi +panthers +scenic +libya +anita +strengthen +inscriptions +##cated +lace +sued +judith +riots +##uted +mint +##eta +preparations +midst +dub +challenger +##vich +mock +cf +displaced +wicket +breaths +enables +schmidt +analyst +##lum +ag +highlight +automotive +axe +josef +newark +sufficiently +resembles +50th +##pal +flushed +mum +traits +##ante +commodore +incomplete +warming +titular +ceremonial +ethical +118 +celebrating +eighteenth +cao +lima +medalist +mobility +strips +snakes +##city +miniature +zagreb +barton +escapes +umbrella +automated +doubted +differs +cooled +georgetown +dresden +cooked +fade +wyatt +rna +jacobs +carlton +abundant +stereo +boost +madras +inning +##hia +spur +ip +malayalam +begged +osaka +groan +escaping +charging +dose +vista +##aj +bud +papa +communists +advocates +edged +tri +##cent +resemble +peaking +necklace +fried +montenegro +saxony +goose +glances +stuttgart +curator +recruit +grocery +sympathetic +##tting +##fort +127 +lotus +randolph +ancestor +##rand +succeeding +jupiter +1798 +macedonian +##heads +hiking +1808 +handing +fischer +##itive +garbage +node +##pies +prone +singular +papua +inclined +attractions +italia +pouring +motioned +grandma +garnered +jacksonville +corp +ego +ringing +aluminum +##hausen +ordering +##foot +drawer +traders +synagogue +##play +##kawa +resistant +wandering +fragile +fiona +teased +var +hardcore +soaked +jubilee +decisive +exposition +mercer +poster +valencia +hale +kuwait +1811 +##ises +##wr +##eed +tavern +gamma +122 +johan +##uer +airways +amino +gil +##ury +vocational +domains +torres +##sp +generator +folklore +outcomes +##keeper +canberra +shooter +fl +beams +confrontation +##lling +##gram +feb +aligned +forestry +pipeline +jax +motorway +conception +decay +##tos +coffin +##cott +stalin +1805 +escorted +minded +##nam +sitcom +purchasing +twilight +veronica +additions +passive +tensions +straw +123 +frequencies +1804 +refugee +cultivation +##iate +christie +clary +bulletin +crept +disposal +##rich +##zong +processor +crescent +##rol +bmw +emphasized +whale +nazis +aurora +##eng +dwelling +hauled +sponsors +toledo +mega +ideology +theatres +tessa +cerambycidae +saves +turtle +cone +suspects +kara +rusty +yelling +greeks +mozart +shades +cocked +participant +##tro +shire +spit +freeze +necessity +##cos +inmates +nielsen +councillors +loaned +uncommon +omar +peasants +botanical +offspring +daniels +formations +jokes +1794 +pioneers +sigma +licensing +##sus +wheelchair +polite +1807 +liquor +pratt +trustee +##uta +forewings +balloon +##zz +kilometre +camping +explicit +casually +shawn +foolish +teammates +nm +hassan +carrie +judged +satisfy +vanessa +knives +selective +cnn +flowed +##lice +eclipse +stressed +eliza +mathematician +cease +cultivated +##roy +commissions +browns +##ania +destroyers +sheridan +meadow +##rius +minerals +##cial +downstream +clash +gram +memoirs +ventures +baha +seymour +archie +midlands +edith +fare +flynn +invite +canceled +tiles +stabbed +boulder +incorporate +amended +camden +facial +mollusk +unreleased +descriptions +yoga +grabs +550 +raises +ramp +shiver +##rose +coined +pioneering +tunes +qing +warwick +tops +119 +melanie +giles +##rous +wandered +##inal +annexed +nov +30th +unnamed +##ished +organizational +airplane +normandy +stoke +whistle +blessing +violations +chased +holders +shotgun +##ctic +outlet +reactor +##vik +tires +tearing +shores +fortified +mascot +constituencies +nc +columnist +productive +tibet +##rta +lineage +hooked +oct +tapes +judging +cody +##gger +hansen +kashmir +triggered +##eva +solved +cliffs +##tree +resisted +anatomy +protesters +transparent +implied +##iga +injection +mattress +excluding +##mbo +defenses +helpless +devotion +##elli +growl +liberals +weber +phenomena +atoms +plug +##iff +mortality +apprentice +howe +convincing +aaa +swimmer +barber +leone +promptly +sodium +def +nowadays +arise +##oning +gloucester +corrected +dignity +norm +erie +##ders +elders +evacuated +sylvia +compression +##yar +hartford +pose +backpack +reasoning +accepts +24th +wipe +millimetres +marcel +##oda +dodgers +albion +1790 +overwhelmed +aerospace +oaks +1795 +showcase +acknowledge +recovering +nolan +ashe +hurts +geology +fashioned +disappearance +farewell +swollen +shrug +marquis +wimbledon +124 +rue +1792 +commemorate +reduces +experiencing +inevitable +calcutta +intel +##court +murderer +sticking +fisheries +imagery +bloom +280 +brake +##inus +gustav +hesitation +memorable +po +viral +beans +accidents +tunisia +antenna +spilled +consort +treatments +aye +perimeter +##gard +donation +hostage +migrated +banker +addiction +apex +lil +trout +##ously +conscience +##nova +rams +sands +genome +passionate +troubles +##lets +##set +amid +##ibility +##ret +higgins +exceed +vikings +##vie +payne +##zan +muscular +##ste +defendant +sucking +##wal +ibrahim +fuselage +claudia +vfl +europeans +snails +interval +##garh +preparatory +statewide +tasked +lacrosse +viktor +##lation +angola +##hra +flint +implications +employs +teens +patrons +stall +weekends +barriers +scrambled +nucleus +tehran +jenna +parsons +lifelong +robots +displacement +5000 +##bles +precipitation +##gt +knuckles +clutched +1802 +marrying +ecology +marx +accusations +declare +scars +kolkata +mat +meadows +bermuda +skeleton +finalists +vintage +crawl +coordinate +affects +subjected +orchestral +mistaken +##tc +mirrors +dipped +relied +260 +arches +candle +##nick +incorporating +wildly +fond +basilica +owl +fringe +rituals +whispering +stirred +feud +tertiary +slick +goat +honorable +whereby +skip +ricardo +stripes +parachute +adjoining +submerged +synthesizer +##gren +intend +positively +ninety +phi +beaver +partition +fellows +alexis +prohibition +carlisle +bizarre +fraternity +##bre +doubts +icy +cbc +aquatic +sneak +sonny +combines +airports +crude +supervised +spatial +merge +alfonso +##bic +corrupt +scan +undergo +##ams +disabilities +colombian +comparing +dolphins +perkins +##lish +reprinted +unanimous +bounced +hairs +underworld +midwest +semester +bucket +paperback +miniseries +coventry +demise +##leigh +demonstrations +sensor +rotating +yan +##hler +arrange +soils +##idge +hyderabad +labs +##dr +brakes +grandchildren +##nde +negotiated +rover +ferrari +continuation +directorate +augusta +stevenson +counterpart +gore +##rda +nursery +rican +ave +collectively +broadly +pastoral +repertoire +asserted +discovering +nordic +styled +fiba +cunningham +harley +middlesex +survives +tumor +tempo +zack +aiming +lok +urgent +##rade +##nto +devils +##ement +contractor +turin +##wl +##ool +bliss +repaired +simmons +moan +astronomical +cr +negotiate +lyric +1890s +lara +bred +clad +angus +pbs +##ience +engineered +posed +##lk +hernandez +possessions +elbows +psychiatric +strokes +confluence +electorate +lifts +campuses +lava +alps +##ep +##ution +##date +physicist +woody +##page +##ographic +##itis +juliet +reformation +sparhawk +320 +complement +suppressed +jewel +##½ +floated +##kas +continuity +sadly +##ische +inability +melting +scanning +paula +flour +judaism +safer +vague +##lm +solving +curb +##stown +financially +gable +bees +expired +miserable +cassidy +dominion +1789 +cupped +145 +robbery +facto +amos +warden +resume +tallest +marvin +ing +pounded +usd +declaring +gasoline +##aux +darkened +270 +650 +sophomore +##mere +erection +gossip +televised +risen +dial +##eu +pillars +##link +passages +profound +##tina +arabian +ashton +silicon +nail +##ead +##lated +##wer +##hardt +fleming +firearms +ducked +circuits +blows +waterloo +titans +##lina +atom +fireplace +cheshire +financed +activation +algorithms +##zzi +constituent +catcher +cherokee +partnerships +sexuality +platoon +tragic +vivian +guarded +whiskey +meditation +poetic +##late +##nga +##ake +porto +listeners +dominance +kendra +mona +chandler +factions +22nd +salisbury +attitudes +derivative +##ido +##haus +intake +paced +javier +illustrator +barrels +bias +cockpit +burnett +dreamed +ensuing +##anda +receptors +someday +hawkins +mattered +##lal +slavic +1799 +jesuit +cameroon +wasted +tai +wax +lowering +victorious +freaking +outright +hancock +librarian +sensing +bald +calcium +myers +tablet +announcing +barack +shipyard +pharmaceutical +##uan +greenwich +flush +medley +patches +wolfgang +pt +speeches +acquiring +exams +nikolai +##gg +hayden +kannada +##type +reilly +##pt +waitress +abdomen +devastated +capped +pseudonym +pharmacy +fulfill +paraguay +1796 +clicked +##trom +archipelago +syndicated +##hman +lumber +orgasm +rejection +clifford +lorraine +advent +mafia +rodney +brock +##ght +##used +##elia +cassette +chamberlain +despair +mongolia +sensors +developmental +upstream +##eg +##alis +spanning +165 +trombone +basque +seeded +interred +renewable +rhys +leapt +revision +molecule +##ages +chord +vicious +nord +shivered +23rd +arlington +debts +corpus +sunrise +bays +blackburn +centimetres +##uded +shuddered +gm +strangely +gripping +cartoons +isabelle +orbital +##ppa +seals +proving +##lton +refusal +strengthened +bust +assisting +baghdad +batsman +portrayal +mara +pushes +spears +og +##cock +reside +nathaniel +brennan +1776 +confirmation +caucus +##worthy +markings +yemen +nobles +ku +lazy +viewer +catalan +encompasses +sawyer +##fall +sparked +substances +patents +braves +arranger +evacuation +sergio +persuade +dover +tolerance +penguin +cum +jockey +insufficient +townships +occupying +declining +plural +processed +projection +puppet +flanders +introduces +liability +##yon +gymnastics +antwerp +taipei +hobart +candles +jeep +wes +observers +126 +chaplain +bundle +glorious +##hine +hazel +flung +sol +excavations +dumped +stares +sh +bangalore +triangular +icelandic +intervals +expressing +turbine +##vers +songwriting +crafts +##igo +jasmine +ditch +rite +##ways +entertaining +comply +sorrow +wrestlers +basel +emirates +marian +rivera +helpful +##some +caution +downward +networking +##atory +##tered +darted +genocide +emergence +replies +specializing +spokesman +convenient +unlocked +fading +augustine +concentrations +resemblance +elijah +investigator +andhra +##uda +promotes +bean +##rrell +fleeing +wan +simone +announcer +##ame +##bby +lydia +weaver +132 +residency +modification +##fest +stretches +##ast +alternatively +nat +lowe +lacks +##ented +pam +tile +concealed +inferior +abdullah +residences +tissues +vengeance +##ided +moisture +peculiar +groove +zip +bologna +jennings +ninja +oversaw +zombies +pumping +batch +livingston +emerald +installations +1797 +peel +nitrogen +rama +##fying +##star +schooling +strands +responding +werner +##ost +lime +casa +accurately +targeting +##rod +underway +##uru +hemisphere +lester +##yard +occupies +2d +griffith +angrily +reorganized +##owing +courtney +deposited +##dd +##30 +estadio +##ifies +dunn +exiled +##ying +checks +##combe +##о +##fly +successes +unexpectedly +blu +assessed +##flower +##ه +observing +sacked +spiders +kn +##tail +mu +nodes +prosperity +audrey +divisional +155 +broncos +tangled +adjust +feeds +erosion +paolo +surf +directory +snatched +humid +admiralty +screwed +gt +reddish +##nese +modules +trench +lamps +bind +leah +bucks +competes +##nz +##form +transcription +##uc +isles +violently +clutching +pga +cyclist +inflation +flats +ragged +unnecessary +##hian +stubborn +coordinated +harriet +baba +disqualified +330 +insect +wolfe +##fies +reinforcements +rocked +duel +winked +embraced +bricks +##raj +hiatus +defeats +pending +brightly +jealousy +##xton +##hm +##uki +lena +gdp +colorful +##dley +stein +kidney +##shu +underwear +wanderers +##haw +##icus +guardians +m³ +roared +habits +##wise +permits +gp +uranium +punished +disguise +bundesliga +elise +dundee +erotic +partisan +pi +collectors +float +individually +rendering +behavioral +bucharest +ser +hare +valerie +corporal +nutrition +proportional +##isa +immense +##kis +pavement +##zie +##eld +sutherland +crouched +1775 +##lp +suzuki +trades +endurance +operas +crosby +prayed +priory +rory +socially +##urn +gujarat +##pu +walton +cube +pasha +privilege +lennon +floods +thorne +waterfall +nipple +scouting +approve +##lov +minorities +voter +dwight +extensions +assure +ballroom +slap +dripping +privileges +rejoined +confessed +demonstrating +patriotic +yell +investor +##uth +pagan +slumped +squares +##cle +##kins +confront +bert +embarrassment +##aid +aston +urging +sweater +starr +yuri +brains +williamson +commuter +mortar +structured +selfish +exports +##jon +cds +##him +unfinished +##rre +mortgage +destinations +##nagar +canoe +solitary +buchanan +delays +magistrate +fk +##pling +motivation +##lier +##vier +recruiting +assess +##mouth +malik +antique +1791 +pius +rahman +reich +tub +zhou +smashed +airs +galway +xii +conditioning +honduras +discharged +dexter +##pf +lionel +129 +debates +lemon +tiffany +volunteered +dom +dioxide +procession +devi +sic +tremendous +advertisements +colts +transferring +verdict +hanover +decommissioned +utter +relate +pac +racism +##top +beacon +limp +similarity +terra +occurrence +ant +##how +becky +capt +updates +armament +richie +pal +##graph +halloween +mayo +##ssen +##bone +cara +serena +fcc +dolls +obligations +##dling +violated +lafayette +jakarta +exploitation +##ime +infamous +iconic +##lah +##park +kitty +moody +reginald +dread +spill +crystals +olivier +modeled +bluff +equilibrium +separating +notices +ordnance +extinction +onset +cosmic +attachment +sammy +expose +privy +anchored +##bil +abbott +admits +bending +baritone +emmanuel +policeman +vaughan +winged +climax +dresses +denny +polytechnic +mohamed +burmese +authentic +nikki +genetics +grandparents +homestead +gaza +postponed +metacritic +una +##sby +##bat +unstable +dissertation +##rial +##cian +curls +obscure +uncovered +bronx +praying +disappearing +##hoe +prehistoric +coke +turret +mutations +nonprofit +pits +monaco +##ي +##usion +prominently +dispatched +podium +##mir +uci +##uation +133 +fortifications +birthplace +kendall +##lby +##oll +preacher +rack +goodman +##rman +persistent +##ott +countless +jaime +recorder +lexington +persecution +jumps +renewal +wagons +##11 +crushing +##holder +decorations +##lake +abundance +wrath +laundry +£1 +garde +##rp +jeanne +beetles +peasant +##sl +splitting +caste +sergei +##rer +##ema +scripts +##ively +rub +satellites +##vor +inscribed +verlag +scrapped +gale +packages +chick +potato +slogan +kathleen +arabs +##culture +counterparts +reminiscent +choral +##tead +rand +retains +bushes +dane +accomplish +courtesy +closes +##oth +slaughter +hague +krakow +lawson +tailed +elias +ginger +##ttes +canopy +betrayal +rebuilding +turf +##hof +frowning +allegiance +brigades +kicks +rebuild +polls +alias +nationalism +td +rowan +audition +bowie +fortunately +recognizes +harp +dillon +horrified +##oro +renault +##tics +ropes +##α +presumed +rewarded +infrared +wiping +accelerated +illustration +##rid +presses +practitioners +badminton +##iard +detained +##tera +recognizing +relates +misery +##sies +##tly +reproduction +piercing +potatoes +thornton +esther +manners +hbo +##aan +ours +bullshit +ernie +perennial +sensitivity +illuminated +rupert +##jin +##iss +##ear +rfc +nassau +##dock +staggered +socialism +##haven +appointments +nonsense +prestige +sharma +haul +##tical +solidarity +gps +##ook +##rata +igor +pedestrian +##uit +baxter +tenants +wires +medication +unlimited +guiding +impacts +diabetes +##rama +sasha +pas +clive +extraction +131 +continually +constraints +##bilities +sonata +hunted +sixteenth +chu +planting +quote +mayer +pretended +abs +spat +##hua +ceramic +##cci +curtains +pigs +pitching +##dad +latvian +sore +dayton +##sted +##qi +patrols +slice +playground +##nted +shone +stool +apparatus +inadequate +mates +treason +##ija +desires +##liga +##croft +somalia +laurent +mir +leonardo +oracle +grape +obliged +chevrolet +thirteenth +stunning +enthusiastic +##ede +accounted +concludes +currents +basil +##kovic +drought +##rica +mai +##aire +shove +posting +##shed +pilgrimage +humorous +packing +fry +pencil +wines +smells +144 +marilyn +aching +newest +clung +bon +neighbours +sanctioned +##pie +mug +##stock +drowning +##mma +hydraulic +##vil +hiring +reminder +lilly +investigators +##ncies +sour +##eous +compulsory +packet +##rion +##graphic +##elle +cannes +##inate +depressed +##rit +heroic +importantly +theresa +##tled +conway +saturn +marginal +rae +##xia +corresponds +royce +pact +jasper +explosives +packaging +aluminium +##ttered +denotes +rhythmic +spans +assignments +hereditary +outlined +originating +sundays +lad +reissued +greeting +beatrice +##dic +pillar +marcos +plots +handbook +alcoholic +judiciary +avant +slides +extract +masculine +blur +##eum +##force +homage +trembled +owens +hymn +trey +omega +signaling +socks +accumulated +reacted +attic +theo +lining +angie +distraction +primera +talbot +##key +1200 +ti +creativity +billed +##hey +deacon +eduardo +identifies +proposition +dizzy +gunner +hogan +##yam +##pping +##hol +ja +##chan +jensen +reconstructed +##berger +clearance +darius +##nier +abe +harlem +plea +dei +circled +emotionally +notation +fascist +neville +exceeded +upwards +viable +ducks +##fo +workforce +racer +limiting +shri +##lson +possesses +1600 +kerr +moths +devastating +laden +disturbing +locking +##cture +gal +fearing +accreditation +flavor +aide +1870s +mountainous +##baum +melt +##ures +motel +texture +servers +soda +##mb +herd +##nium +erect +puzzled +hum +peggy +examinations +gould +testified +geoff +ren +devised +sacks +##law +denial +posters +grunted +cesar +tutor +ec +gerry +offerings +byrne +falcons +combinations +ct +incoming +pardon +rocking +26th +avengers +flared +mankind +seller +uttar +loch +nadia +stroking +exposing +##hd +fertile +ancestral +instituted +##has +noises +prophecy +taxation +eminent +vivid +pol +##bol +dart +indirect +multimedia +notebook +upside +displaying +adrenaline +referenced +geometric +##iving +progression +##ddy +blunt +announce +##far +implementing +##lav +aggression +liaison +cooler +cares +headache +plantations +gorge +dots +impulse +thickness +ashamed +averaging +kathy +obligation +precursor +137 +fowler +symmetry +thee +225 +hears +##rai +undergoing +ads +butcher +bowler +##lip +cigarettes +subscription +goodness +##ically +browne +##hos +##tech +kyoto +donor +##erty +damaging +friction +drifting +expeditions +hardened +prostitution +152 +fauna +blankets +claw +tossing +snarled +butterflies +recruits +investigative +coated +healed +138 +communal +hai +xiii +academics +boone +psychologist +restless +lahore +stephens +mba +brendan +foreigners +printer +##pc +ached +explode +27th +deed +scratched +dared +##pole +cardiac +1780 +okinawa +proto +commando +compelled +oddly +electrons +##base +replica +thanksgiving +##rist +sheila +deliberate +stafford +tidal +representations +hercules +ou +##path +##iated +kidnapping +lenses +##tling +deficit +samoa +mouths +consuming +computational +maze +granting +smirk +razor +fixture +ideals +inviting +aiden +nominal +##vs +issuing +julio +pitt +ramsey +docks +##oss +exhaust +##owed +bavarian +draped +anterior +mating +ethiopian +explores +noticing +##nton +discarded +convenience +hoffman +endowment +beasts +cartridge +mormon +paternal +probe +sleeves +interfere +lump +deadline +##rail +jenks +bulldogs +scrap +alternating +justified +reproductive +nam +seize +descending +secretariat +kirby +coupe +grouped +smash +panther +sedan +tapping +##18 +lola +cheer +germanic +unfortunate +##eter +unrelated +##fan +subordinate +##sdale +suzanne +advertisement +##ility +horsepower +##lda +cautiously +discourse +luigi +##mans +##fields +noun +prevalent +mao +schneider +everett +surround +governorate +kira +##avia +westward +##take +misty +rails +sustainability +134 +unused +##rating +packs +toast +unwilling +regulate +thy +suffrage +nile +awe +assam +definitions +travelers +affordable +##rb +conferred +sells +undefeated +beneficial +torso +basal +repeating +remixes +##pass +bahrain +cables +fang +##itated +excavated +numbering +statutory +##rey +deluxe +##lian +forested +ramirez +derbyshire +zeus +slamming +transfers +astronomer +banana +lottery +berg +histories +bamboo +##uchi +resurrection +posterior +bowls +vaguely +##thi +thou +preserving +tensed +offence +##inas +meyrick +callum +ridden +watt +langdon +tying +lowland +snorted +daring +truman +##hale +##girl +aura +overly +filing +weighing +goa +infections +philanthropist +saunders +eponymous +##owski +latitude +perspectives +reviewing +mets +commandant +radial +##kha +flashlight +reliability +koch +vowels +amazed +ada +elaine +supper +##rth +##encies +predator +debated +soviets +cola +##boards +##nah +compartment +crooked +arbitrary +fourteenth +##ctive +havana +majors +steelers +clips +profitable +ambush +exited +packers +##tile +nude +cracks +fungi +##е +limb +trousers +josie +shelby +tens +frederic +##ος +definite +smoothly +constellation +insult +baton +discs +lingering +##nco +conclusions +lent +staging +becker +grandpa +shaky +##tron +einstein +obstacles +sk +adverse +elle +economically +##moto +mccartney +thor +dismissal +motions +readings +nostrils +treatise +##pace +squeezing +evidently +prolonged +1783 +venezuelan +je +marguerite +beirut +takeover +shareholders +##vent +denise +digit +airplay +norse +##bbling +imaginary +pills +hubert +blaze +vacated +eliminating +##ello +vine +mansfield +##tty +retrospective +barrow +borne +clutch +bail +forensic +weaving +##nett +##witz +desktop +citadel +promotions +worrying +dorset +ieee +subdivided +##iating +manned +expeditionary +pickup +synod +chuckle +185 +barney +##rz +##ffin +functionality +karachi +litigation +meanings +uc +lick +turbo +anders +##ffed +execute +curl +oppose +ankles +typhoon +##د +##ache +##asia +linguistics +compassion +pressures +grazing +perfection +##iting +immunity +monopoly +muddy +backgrounds +136 +namibia +francesca +monitors +attracting +stunt +tuition +##ии +vegetable +##mates +##quent +mgm +jen +complexes +forts +##ond +cellar +bites +seventeenth +royals +flemish +failures +mast +charities +##cular +peruvian +capitals +macmillan +ipswich +outward +frigate +postgraduate +folds +employing +##ouse +concurrently +fiery +##tai +contingent +nightmares +monumental +nicaragua +##kowski +lizard +mal +fielding +gig +reject +##pad +harding +##ipe +coastline +##cin +##nos +beethoven +humphrey +innovations +##tam +##nge +norris +doris +solicitor +huang +obey +141 +##lc +niagara +##tton +shelves +aug +bourbon +curry +nightclub +specifications +hilton +##ndo +centennial +dispersed +worm +neglected +briggs +sm +font +kuala +uneasy +plc +##nstein +##bound +##aking +##burgh +awaiting +pronunciation +##bbed +##quest +eh +optimal +zhu +raped +greens +presided +brenda +worries +##life +venetian +marxist +turnout +##lius +refined +braced +sins +grasped +sunderland +nickel +speculated +lowell +cyrillic +communism +fundraising +resembling +colonists +mutant +freddie +usc +##mos +gratitude +##run +mural +##lous +chemist +wi +reminds +28th +steals +tess +pietro +##ingen +promoter +ri +microphone +honoured +rai +sant +##qui +feather +##nson +burlington +kurdish +terrorists +deborah +sickness +##wed +##eet +hazard +irritated +desperation +veil +clarity +##rik +jewels +xv +##gged +##ows +##cup +berkshire +unfair +mysteries +orchid +winced +exhaustion +renovations +stranded +obe +infinity +##nies +adapt +redevelopment +thanked +registry +olga +domingo +noir +tudor +ole +##atus +commenting +behaviors +##ais +crisp +pauline +probable +stirling +wigan +##bian +paralympics +panting +surpassed +##rew +luca +barred +pony +famed +##sters +cassandra +waiter +carolyn +exported +##orted +andres +destructive +deeds +jonah +castles +vacancy +suv +##glass +1788 +orchard +yep +famine +belarusian +sprang +##forth +skinny +##mis +administrators +rotterdam +zambia +zhao +boiler +discoveries +##ride +##physics +lucius +disappointing +outreach +spoon +##frame +qualifications +unanimously +enjoys +regency +##iidae +stade +realism +veterinary +rodgers +dump +alain +chestnut +castile +censorship +rumble +gibbs +##itor +communion +reggae +inactivated +logs +loads +##houses +homosexual +##iano +ale +informs +##cas +phrases +plaster +linebacker +ambrose +kaiser +fascinated +850 +limerick +recruitment +forge +mastered +##nding +leinster +rooted +threaten +##strom +borneo +##hes +suggestions +scholarships +propeller +documentaries +patronage +coats +constructing +invest +neurons +comet +entirety +shouts +identities +annoying +unchanged +wary +##antly +##ogy +neat +oversight +##kos +phillies +replay +constance +##kka +incarnation +humble +skies +minus +##acy +smithsonian +##chel +guerrilla +jar +cadets +##plate +surplus +audit +##aru +cracking +joanna +louisa +pacing +##lights +intentionally +##iri +diner +nwa +imprint +australians +tong +unprecedented +bunker +naive +specialists +ark +nichols +railing +leaked +pedal +##uka +shrub +longing +roofs +v8 +captains +neural +tuned +##ntal +##jet +emission +medina +frantic +codex +definitive +sid +abolition +intensified +stocks +enrique +sustain +genoa +oxide +##written +clues +cha +##gers +tributaries +fragment +venom +##rity +##ente +##sca +muffled +vain +sire +laos +##ingly +##hana +hastily +snapping +surfaced +sentiment +motive +##oft +contests +approximate +mesa +luckily +dinosaur +exchanges +propelled +accord +bourne +relieve +tow +masks +offended +##ues +cynthia +##mmer +rains +bartender +zinc +reviewers +lois +##sai +legged +arrogant +rafe +rosie +comprise +handicap +blockade +inlet +lagoon +copied +drilling +shelley +petals +##inian +mandarin +obsolete +##inated +onward +arguably +productivity +cindy +praising +seldom +busch +discusses +raleigh +shortage +ranged +stanton +encouragement +firstly +conceded +overs +temporal +##uke +cbe +##bos +woo +certainty +pumps +##pton +stalked +##uli +lizzie +periodic +thieves +weaker +##night +gases +shoving +chooses +wc +##chemical +prompting +weights +##kill +robust +flanked +sticky +hu +tuberculosis +##eb +##eal +christchurch +resembled +wallet +reese +inappropriate +pictured +distract +fixing +fiddle +giggled +burger +heirs +hairy +mechanic +torque +apache +obsessed +chiefly +cheng +logging +##tag +extracted +meaningful +numb +##vsky +gloucestershire +reminding +##bay +unite +##lit +breeds +diminished +clown +glove +1860s +##ن +##ug +archibald +focal +freelance +sliced +depiction +##yk +organism +switches +sights +stray +crawling +##ril +lever +leningrad +interpretations +loops +anytime +reel +alicia +delighted +##ech +inhaled +xiv +suitcase +bernie +vega +licenses +northampton +exclusion +induction +monasteries +racecourse +homosexuality +##right +##sfield +##rky +dimitri +michele +alternatives +ions +commentators +genuinely +objected +pork +hospitality +fencing +stephan +warships +peripheral +wit +drunken +wrinkled +quentin +spends +departing +chung +numerical +spokesperson +##zone +johannesburg +caliber +killers +##udge +assumes +neatly +demographic +abigail +bloc +##vel +mounting +##lain +bentley +slightest +xu +recipients +##jk +merlin +##writer +seniors +prisons +blinking +hindwings +flickered +kappa +##hel +80s +strengthening +appealing +brewing +gypsy +mali +lashes +hulk +unpleasant +harassment +bio +treaties +predict +instrumentation +pulp +troupe +boiling +mantle +##ffe +ins +##vn +dividing +handles +verbs +##onal +coconut +senegal +340 +thorough +gum +momentarily +##sto +cocaine +panicked +destined +##turing +teatro +denying +weary +captained +mans +##hawks +##code +wakefield +bollywood +thankfully +##16 +cyril +##wu +amendments +##bahn +consultation +stud +reflections +kindness +1787 +internally +##ovo +tex +mosaic +distribute +paddy +seeming +143 +##hic +piers +##15 +##mura +##verse +popularly +winger +kang +sentinel +mccoy +##anza +covenant +##bag +verge +fireworks +suppress +thrilled +dominate +##jar +swansea +##60 +142 +reconciliation +##ndi +stiffened +cue +dorian +##uf +damascus +amor +ida +foremost +##aga +porsche +unseen +dir +##had +##azi +stony +lexi +melodies +##nko +angular +integer +podcast +ants +inherent +jaws +justify +persona +##olved +josephine +##nr +##ressed +customary +flashes +gala +cyrus +glaring +backyard +ariel +physiology +greenland +html +stir +avon +atletico +finch +methodology +ked +##lent +mas +catholicism +townsend +branding +quincy +fits +containers +1777 +ashore +aragon +##19 +forearm +poisoning +##sd +adopting +conquer +grinding +amnesty +keller +finances +evaluate +forged +lankan +instincts +##uto +guam +bosnian +photographed +workplace +desirable +protector +##dog +allocation +intently +encourages +willy +##sten +bodyguard +electro +brighter +##ν +bihar +##chev +lasts +opener +amphibious +sal +verde +arte +##cope +captivity +vocabulary +yields +##tted +agreeing +desmond +pioneered +##chus +strap +campaigned +railroads +##ович +emblem +##dre +stormed +501 +##ulous +marijuana +northumberland +##gn +##nath +bowen +landmarks +beaumont +##qua +danube +##bler +attorneys +th +ge +flyers +critique +villains +cass +mutation +acc +##0s +colombo +mckay +motif +sampling +concluding +syndicate +##rell +neon +stables +ds +warnings +clint +mourning +wilkinson +##tated +merrill +leopard +evenings +exhaled +emil +sonia +ezra +discrete +stove +farrell +fifteenth +prescribed +superhero +##rier +worms +helm +wren +##duction +##hc +expo +##rator +hq +unfamiliar +antony +prevents +acceleration +fiercely +mari +painfully +calculations +cheaper +ign +clifton +irvine +davenport +mozambique +##np +pierced +##evich +wonders +##wig +##cate +##iling +crusade +ware +##uel +enzymes +reasonably +mls +##coe +mater +ambition +bunny +eliot +kernel +##fin +asphalt +headmaster +torah +aden +lush +pins +waived +##care +##yas +joao +substrate +enforce +##grad +##ules +alvarez +selections +epidemic +tempted +##bit +bremen +translates +ensured +waterfront +29th +forrest +manny +malone +kramer +reigning +cookies +simpler +absorption +205 +engraved +##ffy +evaluated +1778 +haze +146 +comforting +crossover +##abe +thorn +##rift +##imo +##pop +suppression +fatigue +cutter +##tr +201 +wurttemberg +##orf +enforced +hovering +proprietary +gb +samurai +syllable +ascent +lacey +tick +lars +tractor +merchandise +rep +bouncing +defendants +##yre +huntington +##ground +##oko +standardized +##hor +##hima +assassinated +nu +predecessors +rainy +liar +assurance +lyrical +##uga +secondly +flattened +ios +parameter +undercover +##mity +bordeaux +punish +ridges +markers +exodus +inactive +hesitate +debbie +nyc +pledge +savoy +nagar +offset +organist +##tium +hesse +marin +converting +##iver +diagram +propulsion +pu +validity +reverted +supportive +##dc +ministries +clans +responds +proclamation +##inae +##ø +##rea +ein +pleading +patriot +sf +birch +islanders +strauss +hates +##dh +brandenburg +concession +rd +##ob +1900s +killings +textbook +antiquity +cinematography +wharf +embarrassing +setup +creed +farmland +inequality +centred +signatures +fallon +370 +##ingham +##uts +ceylon +gazing +directive +laurie +##tern +globally +##uated +##dent +allah +excavation +threads +##cross +148 +frantically +icc +utilize +determines +respiratory +thoughtful +receptions +##dicate +merging +chandra +seine +147 +builders +builds +diagnostic +dev +visibility +goddamn +analyses +dhaka +cho +proves +chancel +concurrent +curiously +canadians +pumped +restoring +1850s +turtles +jaguar +sinister +spinal +traction +declan +vows +1784 +glowed +capitalism +swirling +install +universidad +##lder +##oat +soloist +##genic +##oor +coincidence +beginnings +nissan +dip +resorts +caucasus +combustion +infectious +##eno +pigeon +serpent +##itating +conclude +masked +salad +jew +##gr +surreal +toni +##wc +harmonica +151 +##gins +##etic +##coat +fishermen +intending +bravery +##wave +klaus +titan +wembley +taiwanese +ransom +40th +incorrect +hussein +eyelids +jp +cooke +dramas +utilities +##etta +##print +eisenhower +principally +granada +lana +##rak +openings +concord +##bl +bethany +connie +morality +sega +##mons +##nard +earnings +##kara +##cine +wii +communes +##rel +coma +composing +softened +severed +grapes +##17 +nguyen +analyzed +warlord +hubbard +heavenly +behave +slovenian +##hit +##ony +hailed +filmmakers +trance +caldwell +skye +unrest +coward +likelihood +##aging +bern +sci +taliban +honolulu +propose +##wang +1700 +browser +imagining +cobra +contributes +dukes +instinctively +conan +violinist +##ores +accessories +gradual +##amp +quotes +sioux +##dating +undertake +intercepted +sparkling +compressed +139 +fungus +tombs +haley +imposing +rests +degradation +lincolnshire +retailers +wetlands +tulsa +distributor +dungeon +nun +greenhouse +convey +atlantis +aft +exits +oman +dresser +lyons +##sti +joking +eddy +judgement +omitted +digits +##cts +##game +juniors +##rae +cents +stricken +une +##ngo +wizards +weir +breton +nan +technician +fibers +liking +royalty +##cca +154 +persia +terribly +magician +##rable +##unt +vance +cafeteria +booker +camille +warmer +##static +consume +cavern +gaps +compass +contemporaries +foyer +soothing +graveyard +maj +plunged +blush +##wear +cascade +demonstrates +ordinance +##nov +boyle +##lana +rockefeller +shaken +banjo +izzy +##ense +breathless +vines +##32 +##eman +alterations +chromosome +dwellings +feudal +mole +153 +catalonia +relics +tenant +mandated +##fm +fridge +hats +honesty +patented +raul +heap +cruisers +accusing +enlightenment +infants +wherein +chatham +contractors +zen +affinity +hc +osborne +piston +156 +traps +maturity +##rana +lagos +##zal +peering +##nay +attendant +dealers +protocols +subset +prospects +biographical +##cre +artery +##zers +insignia +nuns +endured +##eration +recommend +schwartz +serbs +berger +cromwell +crossroads +##ctor +enduring +clasped +grounded +##bine +marseille +twitched +abel +choke +https +catalyst +moldova +italians +##tist +disastrous +wee +##oured +##nti +wwf +nope +##piration +##asa +expresses +thumbs +167 +##nza +coca +1781 +cheating +##ption +skipped +sensory +heidelberg +spies +satan +dangers +semifinal +202 +bohemia +whitish +confusing +shipbuilding +relies +surgeons +landings +ravi +baku +moor +suffix +alejandro +##yana +litre +upheld +##unk +rajasthan +##rek +coaster +insists +posture +scenarios +etienne +favoured +appoint +transgender +elephants +poked +greenwood +defences +fulfilled +militant +somali +1758 +chalk +potent +##ucci +migrants +wink +assistants +nos +restriction +activism +niger +##ario +colon +shaun +##sat +daphne +##erated +swam +congregations +reprise +considerations +magnet +playable +xvi +##р +overthrow +tobias +knob +chavez +coding +##mers +propped +katrina +orient +newcomer +##suke +temperate +##pool +farmhouse +interrogation +##vd +committing +##vert +forthcoming +strawberry +joaquin +macau +ponds +shocking +siberia +##cellular +chant +contributors +##nant +##ologists +sped +absorb +hail +1782 +spared +##hore +barbados +karate +opus +originates +saul +##xie +evergreen +leaped +##rock +correlation +exaggerated +weekday +unification +bump +tracing +brig +afb +pathways +utilizing +##ners +mod +mb +disturbance +kneeling +##stad +##guchi +100th +pune +##thy +decreasing +168 +manipulation +miriam +academia +ecosystem +occupational +rbi +##lem +rift +##14 +rotary +stacked +incorporation +awakening +generators +guerrero +racist +##omy +cyber +derivatives +culminated +allie +annals +panzer +sainte +wikipedia +pops +zu +austro +##vate +algerian +politely +nicholson +mornings +educate +tastes +thrill +dartmouth +##gating +db +##jee +regan +differing +concentrating +choreography +divinity +##media +pledged +alexandre +routing +gregor +madeline +##idal +apocalypse +##hora +gunfire +culminating +elves +fined +liang +lam +programmed +tar +guessing +transparency +gabrielle +##gna +cancellation +flexibility +##lining +accession +shea +stronghold +nets +specializes +##rgan +abused +hasan +sgt +ling +exceeding +##₄ +admiration +supermarket +##ark +photographers +specialised +tilt +resonance +hmm +perfume +380 +sami +threatens +garland +botany +guarding +boiled +greet +puppy +russo +supplier +wilmington +vibrant +vijay +##bius +paralympic +grumbled +paige +faa +licking +margins +hurricanes +##gong +fest +grenade +ripping +##uz +counseling +weigh +##sian +needles +wiltshire +edison +costly +##not +fulton +tramway +redesigned +staffordshire +cache +gasping +watkins +sleepy +candidacy +##group +monkeys +timeline +throbbing +##bid +##sos +berth +uzbekistan +vanderbilt +bothering +overturned +ballots +gem +##iger +sunglasses +subscribers +hooker +compelling +ang +exceptionally +saloon +stab +##rdi +carla +terrifying +rom +##vision +coil +##oids +satisfying +vendors +31st +mackay +deities +overlooked +ambient +bahamas +felipe +olympia +whirled +botanist +advertised +tugging +##dden +disciples +morales +unionist +rites +foley +morse +motives +creepy +##₀ +soo +##sz +bargain +highness +frightening +turnpike +tory +reorganization +##cer +depict +biographer +##walk +unopposed +manifesto +##gles +institut +emile +accidental +kapoor +##dam +kilkenny +cortex +lively +##13 +romanesque +jain +shan +cannons +##ood +##ske +petrol +echoing +amalgamated +disappears +cautious +proposes +sanctions +trenton +##ر +flotilla +aus +contempt +tor +canary +cote +theirs +##hun +conceptual +deleted +fascinating +paso +blazing +elf +honourable +hutchinson +##eiro +##outh +##zin +surveyor +tee +amidst +wooded +reissue +intro +##ono +cobb +shelters +newsletter +hanson +brace +encoding +confiscated +dem +caravan +marino +scroll +melodic +cows +imam +##adi +##aneous +northward +searches +biodiversity +cora +310 +roaring +##bers +connell +theologian +halo +compose +pathetic +unmarried +dynamo +##oot +az +calculation +toulouse +deserves +humour +nr +forgiveness +tam +undergone +martyr +pamela +myths +whore +counselor +hicks +290 +heavens +battleship +electromagnetic +##bbs +stellar +establishments +presley +hopped +##chin +temptation +90s +wills +nas +##yuan +nhs +##nya +seminars +##yev +adaptations +gong +asher +lex +indicator +sikh +tobago +cites +goin +##yte +satirical +##gies +characterised +correspond +bubbles +lure +participates +##vid +eruption +skate +therapeutic +1785 +canals +wholesale +defaulted +sac +460 +petit +##zzled +virgil +leak +ravens +256 +portraying +##yx +ghetto +creators +dams +portray +vicente +##rington +fae +namesake +bounty +##arium +joachim +##ota +##iser +aforementioned +axle +snout +depended +dismantled +reuben +480 +##ibly +gallagher +##lau +##pd +earnest +##ieu +##iary +inflicted +objections +##llar +asa +gritted +##athy +jericho +##sea +##was +flick +underside +ceramics +undead +substituted +195 +eastward +undoubtedly +wheeled +chimney +##iche +guinness +cb +##ager +siding +##bell +traitor +baptiste +disguised +inauguration +149 +tipperary +choreographer +perched +warmed +stationary +eco +##ike +##ntes +bacterial +##aurus +flores +phosphate +##core +attacker +invaders +alvin +intersects +a1 +indirectly +immigrated +businessmen +cornelius +valves +narrated +pill +sober +ul +nationale +monastic +applicants +scenery +##jack +161 +motifs +constitutes +cpu +##osh +jurisdictions +sd +tuning +irritation +woven +##uddin +fertility +gao +##erie +antagonist +impatient +glacial +hides +boarded +denominations +interception +##jas +cookie +nicola +##tee +algebraic +marquess +bahn +parole +buyers +bait +turbines +paperwork +bestowed +natasha +renee +oceans +purchases +157 +vaccine +215 +##tock +fixtures +playhouse +integrate +jai +oswald +intellectuals +##cky +booked +nests +mortimer +##isi +obsession +sept +##gler +##sum +440 +scrutiny +simultaneous +squinted +##shin +collects +oven +shankar +penned +remarkably +##я +slips +luggage +spectral +1786 +collaborations +louie +consolidation +##ailed +##ivating +420 +hoover +blackpool +harness +ignition +vest +tails +belmont +mongol +skinner +##nae +visually +mage +derry +##tism +##unce +stevie +transitional +##rdy +redskins +drying +prep +prospective +##21 +annoyance +oversee +##loaded +fills +##books +##iki +announces +fda +scowled +respects +prasad +mystic +tucson +##vale +revue +springer +bankrupt +1772 +aristotle +salvatore +habsburg +##geny +dal +natal +nut +pod +chewing +darts +moroccan +walkover +rosario +lenin +punjabi +##ße +grossed +scattering +wired +invasive +hui +polynomial +corridors +wakes +gina +portrays +##cratic +arid +retreating +erich +irwin +sniper +##dha +linen +lindsey +maneuver +butch +shutting +socio +bounce +commemorative +postseason +jeremiah +pines +275 +mystical +beads +bp +abbas +furnace +bidding +consulted +assaulted +empirical +rubble +enclosure +sob +weakly +cancel +polly +yielded +##emann +curly +prediction +battered +70s +vhs +jacqueline +render +sails +barked +detailing +grayson +riga +sloane +raging +##yah +herbs +bravo +##athlon +alloy +giggle +imminent +suffers +assumptions +waltz +##itate +accomplishments +##ited +bathing +remixed +deception +prefix +##emia +deepest +##tier +##eis +balkan +frogs +##rong +slab +##pate +philosophers +peterborough +grains +imports +dickinson +rwanda +##atics +1774 +dirk +lan +tablets +##rove +clone +##rice +caretaker +hostilities +mclean +##gre +regimental +treasures +norms +impose +tsar +tango +diplomacy +variously +complain +192 +recognise +arrests +1779 +celestial +pulitzer +##dus +bing +libretto +##moor +adele +splash +##rite +expectation +lds +confronts +##izer +spontaneous +harmful +wedge +entrepreneurs +buyer +##ope +bilingual +translate +rugged +conner +circulated +uae +eaton +##gra +##zzle +lingered +lockheed +vishnu +reelection +alonso +##oom +joints +yankee +headline +cooperate +heinz +laureate +invading +##sford +echoes +scandinavian +##dham +hugging +vitamin +salute +micah +hind +trader +##sper +radioactive +##ndra +militants +poisoned +ratified +remark +campeonato +deprived +wander +prop +##dong +outlook +##tani +##rix +##eye +chiang +darcy +##oping +mandolin +spice +statesman +babylon +182 +walled +forgetting +afro +##cap +158 +giorgio +buffer +##polis +planetary +##gis +overlap +terminals +kinda +centenary +##bir +arising +manipulate +elm +ke +1770 +ak +##tad +chrysler +mapped +moose +pomeranian +quad +macarthur +assemblies +shoreline +recalls +stratford +##rted +noticeable +##evic +imp +##rita +##sque +accustomed +supplying +tents +disgusted +vogue +sipped +filters +khz +reno +selecting +luftwaffe +mcmahon +tyne +masterpiece +carriages +collided +dunes +exercised +flare +remembers +muzzle +##mobile +heck +##rson +burgess +lunged +middleton +boycott +bilateral +##sity +hazardous +lumpur +multiplayer +spotlight +jackets +goldman +liege +porcelain +rag +waterford +benz +attracts +hopeful +battling +ottomans +kensington +baked +hymns +cheyenne +lattice +levine +borrow +polymer +clashes +michaels +monitored +commitments +denounced +##25 +##von +cavity +##oney +hobby +akin +##holders +futures +intricate +cornish +patty +##oned +illegally +dolphin +##lag +barlow +yellowish +maddie +apologized +luton +plagued +##puram +nana +##rds +sway +fanny +łodz +##rino +psi +suspicions +hanged +##eding +initiate +charlton +##por +nak +competent +235 +analytical +annex +wardrobe +reservations +##rma +sect +162 +fairfax +hedge +piled +buckingham +uneven +bauer +simplicity +snyder +interpret +accountability +donors +moderately +byrd +continents +##cite +##max +disciple +hr +jamaican +ping +nominees +##uss +mongolian +diver +attackers +eagerly +ideological +pillows +miracles +apartheid +revolver +sulfur +clinics +moran +163 +##enko +ile +katy +rhetoric +##icated +chronology +recycling +##hrer +elongated +mughal +pascal +profiles +vibration +databases +domination +##fare +##rant +matthias +digest +rehearsal +polling +weiss +initiation +reeves +clinging +flourished +impress +ngo +##hoff +##ume +buckley +symposium +rhythms +weed +emphasize +transforming +##taking +##gence +##yman +accountant +analyze +flicker +foil +priesthood +voluntarily +decreases +##80 +##hya +slater +sv +charting +mcgill +##lde +moreno +##iu +besieged +zur +robes +##phic +admitting +api +deported +turmoil +peyton +earthquakes +##ares +nationalists +beau +clair +brethren +interrupt +welch +curated +galerie +requesting +164 +##ested +impending +steward +viper +##vina +complaining +beautifully +brandy +foam +nl +1660 +##cake +alessandro +punches +laced +explanations +##lim +attribute +clit +reggie +discomfort +##cards +smoothed +whales +##cene +adler +countered +duffy +disciplinary +widening +recipe +reliance +conducts +goats +gradient +preaching +##shaw +matilda +quasi +striped +meridian +cannabis +cordoba +certificates +##agh +##tering +graffiti +hangs +pilgrims +repeats +##ych +revive +urine +etat +##hawk +fueled +belts +fuzzy +susceptible +##hang +mauritius +salle +sincere +beers +hooks +##cki +arbitration +entrusted +advise +sniffed +seminar +junk +donnell +processors +principality +strapped +celia +mendoza +everton +fortunes +prejudice +starving +reassigned +steamer +##lund +tuck +evenly +foreman +##ffen +dans +375 +envisioned +slit +##xy +baseman +liberia +rosemary +##weed +electrified +periodically +potassium +stride +contexts +sperm +slade +mariners +influx +bianca +subcommittee +##rane +spilling +icao +estuary +##nock +delivers +iphone +##ulata +isa +mira +bohemian +dessert +##sbury +welcoming +proudly +slowing +##chs +musee +ascension +russ +##vian +waits +##psy +africans +exploit +##morphic +gov +eccentric +crab +peck +##ull +entrances +formidable +marketplace +groom +bolted +metabolism +patton +robbins +courier +payload +endure +##ifier +andes +refrigerator +##pr +ornate +##uca +ruthless +illegitimate +masonry +strasbourg +bikes +adobe +##³ +apples +quintet +willingly +niche +bakery +corpses +energetic +##cliffe +##sser +##ards +177 +centimeters +centro +fuscous +cretaceous +rancho +##yde +andrei +telecom +tottenham +oasis +ordination +vulnerability +presiding +corey +cp +penguins +sims +##pis +malawi +piss +##48 +correction +##cked +##ffle +##ryn +countdown +detectives +psychiatrist +psychedelic +dinosaurs +blouse +##get +choi +vowed +##oz +randomly +##pol +49ers +scrub +blanche +bruins +dusseldorf +##using +unwanted +##ums +212 +dominique +elevations +headlights +om +laguna +##oga +1750 +famously +ignorance +shrewsbury +##aine +ajax +breuning +che +confederacy +greco +overhaul +##screen +paz +skirts +disagreement +cruelty +jagged +phoebe +shifter +hovered +viruses +##wes +mandy +##lined +##gc +landlord +squirrel +dashed +##ι +ornamental +gag +wally +grange +literal +spurs +undisclosed +proceeding +yin +##text +billie +orphan +spanned +humidity +indy +weighted +presentations +explosions +lucian +##tary +vaughn +hindus +##anga +##hell +psycho +171 +daytona +protects +efficiently +rematch +sly +tandem +##oya +rebranded +impaired +hee +metropolis +peach +godfrey +diaspora +ethnicity +prosperous +gleaming +dar +grossing +playback +##rden +stripe +pistols +##tain +births +labelled +##cating +172 +rudy +alba +##onne +aquarium +hostility +##gb +##tase +shudder +sumatra +hardest +lakers +consonant +creeping +demos +homicide +capsule +zeke +liberties +expulsion +pueblo +##comb +trait +transporting +##ddin +##neck +##yna +depart +gregg +mold +ledge +hangar +oldham +playboy +termination +analysts +gmbh +romero +##itic +insist +cradle +filthy +brightness +slash +shootout +deposed +bordering +##truct +isis +microwave +tumbled +sheltered +cathy +werewolves +messy +andersen +convex +clapped +clinched +satire +wasting +edo +vc +rufus +##jak +mont +##etti +poznan +##keeping +restructuring +transverse +##rland +azerbaijani +slovene +gestures +roommate +choking +shear +##quist +vanguard +oblivious +##hiro +disagreed +baptism +##lich +coliseum +##aceae +salvage +societe +cory +locke +relocation +relying +versailles +ahl +swelling +##elo +cheerful +##word +##edes +gin +sarajevo +obstacle +diverted +##nac +messed +thoroughbred +fluttered +utrecht +chewed +acquaintance +assassins +dispatch +mirza +##wart +nike +salzburg +swell +yen +##gee +idle +ligue +samson +##nds +##igh +playful +spawned +##cise +tease +##case +burgundy +##bot +stirring +skeptical +interceptions +marathi +##dies +bedrooms +aroused +pinch +##lik +preferences +tattoos +buster +digitally +projecting +rust +##ital +kitten +priorities +addison +pseudo +##guard +dusk +icons +sermon +##psis +##iba +bt +##lift +##xt +ju +truce +rink +##dah +##wy +defects +psychiatry +offences +calculate +glucose +##iful +##rized +##unda +francaise +##hari +richest +warwickshire +carly +1763 +purity +redemption +lending +##cious +muse +bruises +cerebral +aero +carving +##name +preface +terminology +invade +monty +##int +anarchist +blurred +##iled +rossi +treats +guts +shu +foothills +ballads +undertaking +premise +cecilia +affiliates +blasted +conditional +wilder +minors +drone +rudolph +buffy +swallowing +horton +attested +##hop +rutherford +howell +primetime +livery +penal +##bis +minimize +hydro +wrecked +wrought +palazzo +##gling +cans +vernacular +friedman +nobleman +shale +walnut +danielle +##ection +##tley +sears +##kumar +chords +lend +flipping +streamed +por +dracula +gallons +sacrifices +gamble +orphanage +##iman +mckenzie +##gible +boxers +daly +##balls +##ان +208 +##ific +##rative +##iq +exploited +slated +##uity +circling +hillary +pinched +goldberg +provost +campaigning +lim +piles +ironically +jong +mohan +successors +usaf +##tem +##ught +autobiographical +haute +preserves +##ending +acquitted +comparisons +203 +hydroelectric +gangs +cypriot +torpedoes +rushes +chrome +derive +bumps +instability +fiat +pets +##mbe +silas +dye +reckless +settler +##itation +info +heats +##writing +176 +canonical +maltese +fins +mushroom +stacy +aspen +avid +##kur +##loading +vickers +gaston +hillside +statutes +wilde +gail +kung +sabine +comfortably +motorcycles +##rgo +169 +pneumonia +fetch +##sonic +axel +faintly +parallels +##oop +mclaren +spouse +compton +interdisciplinary +miner +##eni +181 +clamped +##chal +##llah +separates +versa +##mler +scarborough +labrador +##lity +##osing +rutgers +hurdles +como +166 +burt +divers +##100 +wichita +cade +coincided +##erson +bruised +mla +##pper +vineyard +##ili +##brush +notch +mentioning +jase +hearted +kits +doe +##acle +pomerania +##ady +ronan +seizure +pavel +problematic +##zaki +domenico +##ulin +catering +penelope +dependence +parental +emilio +ministerial +atkinson +##bolic +clarkson +chargers +colby +grill +peeked +arises +summon +##aged +fools +##grapher +faculties +qaeda +##vial +garner +refurbished +##hwa +geelong +disasters +nudged +bs +shareholder +lori +algae +reinstated +rot +##ades +##nous +invites +stainless +183 +inclusive +##itude +diocesan +til +##icz +denomination +##xa +benton +floral +registers +##ider +##erman +##kell +absurd +brunei +guangzhou +hitter +retaliation +##uled +##eve +blanc +nh +consistency +contamination +##eres +##rner +dire +palermo +broadcasters +diaries +inspire +vols +brewer +tightening +ky +mixtape +hormone +##tok +stokes +##color +##dly +##ssi +pg +##ometer +##lington +sanitation +##tility +intercontinental +apps +##adt +¹⁄₂ +cylinders +economies +favourable +unison +croix +gertrude +odyssey +vanity +dangling +##logists +upgrades +dice +middleweight +practitioner +##ight +206 +henrik +parlor +orion +angered +lac +python +blurted +##rri +sensual +intends +swings +angled +##phs +husky +attain +peerage +precinct +textiles +cheltenham +shuffled +dai +confess +tasting +bhutan +##riation +tyrone +segregation +abrupt +ruiz +##rish +smirked +blackwell +confidential +browning +amounted +##put +vase +scarce +fabulous +raided +staple +guyana +unemployed +glider +shay +##tow +carmine +troll +intervene +squash +superstar +##uce +cylindrical +len +roadway +researched +handy +##rium +##jana +meta +lao +declares +##rring +##tadt +##elin +##kova +willem +shrubs +napoleonic +realms +skater +qi +volkswagen +##ł +tad +hara +archaeologist +awkwardly +eerie +##kind +wiley +##heimer +##24 +titus +organizers +cfl +crusaders +lama +usb +vent +enraged +thankful +occupants +maximilian +##gaard +possessing +textbooks +##oran +collaborator +quaker +##ulo +avalanche +mono +silky +straits +isaiah +mustang +surged +resolutions +potomac +descend +cl +kilograms +plato +strains +saturdays +##olin +bernstein +##ype +holstein +ponytail +##watch +belize +conversely +heroine +perpetual +##ylus +charcoal +piedmont +glee +negotiating +backdrop +prologue +##jah +##mmy +pasadena +climbs +ramos +sunni +##holm +##tner +##tri +anand +deficiency +hertfordshire +stout +##avi +aperture +orioles +##irs +doncaster +intrigued +bombed +coating +otis +##mat +cocktail +##jit +##eto +amir +arousal +sar +##proof +##act +##ories +dixie +pots +##bow +whereabouts +159 +##fted +drains +bullying +cottages +scripture +coherent +fore +poe +appetite +##uration +sampled +##ators +##dp +derrick +rotor +jays +peacock +installment +##rro +advisors +##coming +rodeo +scotch +##mot +##db +##fen +##vant +ensued +rodrigo +dictatorship +martyrs +twenties +##н +towed +incidence +marta +rainforest +sai +scaled +##cles +oceanic +qualifiers +symphonic +mcbride +dislike +generalized +aubrey +colonization +##iation +##lion +##ssing +disliked +lublin +salesman +##ulates +spherical +whatsoever +sweating +avalon +contention +punt +severity +alderman +atari +##dina +##grant +##rop +scarf +seville +vertices +annexation +fairfield +fascination +inspiring +launches +palatinate +regretted +##rca +feral +##iom +elk +nap +olsen +reddy +yong +##leader +##iae +garment +transports +feng +gracie +outrage +viceroy +insides +##esis +breakup +grady +organizer +softer +grimaced +222 +murals +galicia +arranging +vectors +##rsten +bas +##sb +##cens +sloan +##eka +bitten +ara +fender +nausea +bumped +kris +banquet +comrades +detector +persisted +##llan +adjustment +endowed +cinemas +##shot +sellers +##uman +peek +epa +kindly +neglect +simpsons +talon +mausoleum +runaway +hangul +lookout +##cic +rewards +coughed +acquainted +chloride +##ald +quicker +accordion +neolithic +##qa +artemis +coefficient +lenny +pandora +tx +##xed +ecstasy +litter +segunda +chairperson +gemma +hiss +rumor +vow +nasal +antioch +compensate +patiently +transformers +##eded +judo +morrow +penis +posthumous +philips +bandits +husbands +denote +flaming +##any +##phones +langley +yorker +1760 +walters +##uo +##kle +gubernatorial +fatty +samsung +leroy +outlaw +##nine +unpublished +poole +jakob +##ᵢ +##ₙ +crete +distorted +superiority +##dhi +intercept +crust +mig +claus +crashes +positioning +188 +stallion +301 +frontal +armistice +##estinal +elton +aj +encompassing +camel +commemorated +malaria +woodward +calf +cigar +penetrate +##oso +willard +##rno +##uche +illustrate +amusing +convergence +noteworthy +##lma +##rva +journeys +realise +manfred +##sable +410 +##vocation +hearings +fiance +##posed +educators +provoked +adjusting +##cturing +modular +stockton +paterson +vlad +rejects +electors +selena +maureen +##tres +uber +##rce +swirled +##num +proportions +nanny +pawn +naturalist +parma +apostles +awoke +ethel +wen +##bey +monsoon +overview +##inating +mccain +rendition +risky +adorned +##ih +equestrian +germain +nj +conspicuous +confirming +##yoshi +shivering +##imeter +milestone +rumours +flinched +bounds +smacked +token +##bei +lectured +automobiles +##shore +impacted +##iable +nouns +nero +##leaf +ismail +prostitute +trams +##lace +bridget +sud +stimulus +impressions +reins +revolves +##oud +##gned +giro +honeymoon +##swell +criterion +##sms +##uil +libyan +prefers +##osition +211 +preview +sucks +accusation +bursts +metaphor +diffusion +tolerate +faye +betting +cinematographer +liturgical +specials +bitterly +humboldt +##ckle +flux +rattled +##itzer +archaeologists +odor +authorised +marshes +discretion +##ов +alarmed +archaic +inverse +##leton +explorers +##pine +drummond +tsunami +woodlands +##minate +##tland +booklet +insanity +owning +insert +crafted +calculus +##tore +receivers +##bt +stung +##eca +##nched +prevailing +travellers +eyeing +lila +graphs +##borne +178 +julien +##won +morale +adaptive +therapist +erica +cw +libertarian +bowman +pitches +vita +##ional +crook +##ads +##entation +caledonia +mutiny +##sible +1840s +automation +##ß +flock +##pia +ironic +pathology +##imus +remarried +##22 +joker +withstand +energies +##att +shropshire +hostages +madeleine +tentatively +conflicting +mateo +recipes +euros +ol +mercenaries +nico +##ndon +albuquerque +augmented +mythical +bel +freud +##child +cough +##lica +365 +freddy +lillian +genetically +nuremberg +calder +209 +bonn +outdoors +paste +suns +urgency +vin +restraint +tyson +##cera +##selle +barrage +bethlehem +kahn +##par +mounts +nippon +barony +happier +ryu +makeshift +sheldon +blushed +castillo +barking +listener +taped +bethel +fluent +headlines +pornography +rum +disclosure +sighing +mace +doubling +gunther +manly +##plex +rt +interventions +physiological +forwards +emerges +##tooth +##gny +compliment +rib +recession +visibly +barge +faults +connector +exquisite +prefect +##rlin +patio +##cured +elevators +brandt +italics +pena +173 +wasp +satin +ea +botswana +graceful +respectable +##jima +##rter +##oic +franciscan +generates +##dl +alfredo +disgusting +##olate +##iously +sherwood +warns +cod +promo +cheryl +sino +##ة +##escu +twitch +##zhi +brownish +thom +ortiz +##dron +densely +##beat +carmel +reinforce +##bana +187 +anastasia +downhill +vertex +contaminated +remembrance +harmonic +homework +##sol +fiancee +gears +olds +angelica +loft +ramsay +quiz +colliery +sevens +##cape +autism +##hil +walkway +##boats +ruben +abnormal +ounce +khmer +##bbe +zachary +bedside +morphology +punching +##olar +sparrow +convinces +##35 +hewitt +queer +remastered +rods +mabel +solemn +notified +lyricist +symmetric +##xide +174 +encore +passports +wildcats +##uni +baja +##pac +mildly +##ease +bleed +commodity +mounds +glossy +orchestras +##omo +damian +prelude +ambitions +##vet +awhile +remotely +##aud +asserts +imply +##iques +distinctly +modelling +remedy +##dded +windshield +dani +xiao +##endra +audible +powerplant +1300 +invalid +elemental +acquisitions +##hala +immaculate +libby +plata +smuggling +ventilation +denoted +minh +##morphism +430 +differed +dion +kelley +lore +mocking +sabbath +spikes +hygiene +drown +runoff +stylized +tally +liberated +aux +interpreter +righteous +aba +siren +reaper +pearce +millie +##cier +##yra +gaius +##iso +captures +##ttering +dorm +claudio +##sic +benches +knighted +blackness +##ored +discount +fumble +oxidation +routed +##ς +novak +perpendicular +spoiled +fracture +splits +##urt +pads +topology +##cats +axes +fortunate +offenders +protestants +esteem +221 +broadband +convened +frankly +hound +prototypes +isil +facilitated +keel +##sher +sahara +awaited +bubba +orb +prosecutors +186 +hem +520 +##xing +relaxing +remnant +romney +sorted +slalom +stefano +ulrich +##active +exemption +folder +pauses +foliage +hitchcock +epithet +204 +criticisms +##aca +ballistic +brody +hinduism +chaotic +youths +equals +##pala +pts +thicker +analogous +capitalist +improvised +overseeing +sinatra +ascended +beverage +##tl +straightforward +##kon +curran +##west +bois +325 +induce +surveying +emperors +sax +unpopular +##kk +cartoonist +fused +##mble +unto +##yuki +localities +##cko +##ln +darlington +slain +academie +lobbying +sediment +puzzles +##grass +defiance +dickens +manifest +tongues +alumnus +arbor +coincide +184 +appalachian +mustafa +examiner +cabaret +traumatic +yves +bracelet +draining +heroin +magnum +baths +odessa +consonants +mitsubishi +##gua +kellan +vaudeville +##fr +joked +null +straps +probation +##ław +ceded +interfaces +##pas +##zawa +blinding +viet +224 +rothschild +museo +640 +huddersfield +##vr +tactic +##storm +brackets +dazed +incorrectly +##vu +reg +glazed +fearful +manifold +benefited +irony +##sun +stumbling +##rte +willingness +balkans +mei +wraps +##aba +injected +##lea +gu +syed +harmless +##hammer +bray +takeoff +poppy +timor +cardboard +astronaut +purdue +weeping +southbound +cursing +stalls +diagonal +##neer +lamar +bryce +comte +weekdays +harrington +##uba +negatively +##see +lays +grouping +##cken +##henko +affirmed +halle +modernist +##lai +hodges +smelling +aristocratic +baptized +dismiss +justification +oilers +##now +coupling +qin +snack +healer +##qing +gardener +layla +battled +formulated +stephenson +gravitational +##gill +##jun +1768 +granny +coordinating +suites +##cd +##ioned +monarchs +##cote +##hips +sep +blended +apr +barrister +deposition +fia +mina +policemen +paranoid +##pressed +churchyard +covert +crumpled +creep +abandoning +tr +transmit +conceal +barr +understands +readiness +spire +##cology +##enia +##erry +610 +startling +unlock +vida +bowled +slots +##nat +##islav +spaced +trusting +admire +rig +##ink +slack +##70 +mv +207 +casualty +##wei +classmates +##odes +##rar +##rked +amherst +furnished +evolve +foundry +menace +mead +##lein +flu +wesleyan +##kled +monterey +webber +##vos +wil +##mith +##на +bartholomew +justices +restrained +##cke +amenities +191 +mediated +sewage +trenches +ml +mainz +##thus +1800s +##cula +##inski +caine +bonding +213 +converts +spheres +superseded +marianne +crypt +sweaty +ensign +historia +##br +spruce +##post +##ask +forks +thoughtfully +yukon +pamphlet +ames +##uter +karma +##yya +bryn +negotiation +sighs +incapable +##mbre +##ntial +actresses +taft +##mill +luce +prevailed +##amine +1773 +motionless +envoy +testify +investing +sculpted +instructors +provence +kali +cullen +horseback +##while +goodwin +##jos +gaa +norte +##ldon +modify +wavelength +abd +214 +skinned +sprinter +forecast +scheduling +marries +squared +tentative +##chman +boer +##isch +bolts +swap +fisherman +assyrian +impatiently +guthrie +martins +murdoch +194 +tanya +nicely +dolly +lacy +med +##45 +syn +decks +fashionable +millionaire +##ust +surfing +##ml +##ision +heaved +tammy +consulate +attendees +routinely +197 +fuse +saxophonist +backseat +malaya +##lord +scowl +tau +##ishly +193 +sighted +steaming +##rks +303 +911 +##holes +##hong +ching +##wife +bless +conserved +jurassic +stacey +unix +zion +chunk +rigorous +blaine +198 +peabody +slayer +dismay +brewers +nz +##jer +det +##glia +glover +postwar +int +penetration +sylvester +imitation +vertically +airlift +heiress +knoxville +viva +##uin +390 +macon +##rim +##fighter +##gonal +janice +##orescence +##wari +marius +belongings +leicestershire +196 +blanco +inverted +preseason +sanity +sobbing +##due +##elt +##dled +collingwood +regeneration +flickering +shortest +##mount +##osi +feminism +##lat +sherlock +cabinets +fumbled +northbound +precedent +snaps +##mme +researching +##akes +guillaume +insights +manipulated +vapor +neighbour +sap +gangster +frey +f1 +stalking +scarcely +callie +barnett +tendencies +audi +doomed +assessing +slung +panchayat +ambiguous +bartlett +##etto +distributing +violating +wolverhampton +##hetic +swami +histoire +##urus +liable +pounder +groin +hussain +larsen +popping +surprises +##atter +vie +curt +##station +mute +relocate +musicals +authorization +richter +##sef +immortality +tna +bombings +##press +deteriorated +yiddish +##acious +robbed +colchester +cs +pmid +ao +verified +balancing +apostle +swayed +recognizable +oxfordshire +retention +nottinghamshire +contender +judd +invitational +shrimp +uhf +##icient +cleaner +longitudinal +tanker +##mur +acronym +broker +koppen +sundance +suppliers +##gil +4000 +clipped +fuels +petite +##anne +landslide +helene +diversion +populous +landowners +auspices +melville +quantitative +##xes +ferries +nicky +##llus +doo +haunting +roche +carver +downed +unavailable +##pathy +approximation +hiroshima +##hue +garfield +valle +comparatively +keyboardist +traveler +##eit +congestion +calculating +subsidiaries +##bate +serb +modernization +fairies +deepened +ville +averages +##lore +inflammatory +tonga +##itch +co₂ +squads +##hea +gigantic +serum +enjoyment +retailer +verona +35th +cis +##phobic +magna +technicians +##vati +arithmetic +##sport +levin +##dation +amtrak +chow +sienna +##eyer +backstage +entrepreneurship +##otic +learnt +tao +##udy +worcestershire +formulation +baggage +hesitant +bali +sabotage +##kari +barren +enhancing +murmur +pl +freshly +putnam +syntax +aces +medicines +resentment +bandwidth +##sier +grins +chili +guido +##sei +framing +implying +gareth +lissa +genevieve +pertaining +admissions +geo +thorpe +proliferation +sato +bela +analyzing +parting +##gor +awakened +##isman +huddled +secrecy +##kling +hush +gentry +540 +dungeons +##ego +coasts +##utz +sacrificed +##chule +landowner +mutually +prevalence +programmer +adolescent +disrupted +seaside +gee +trusts +vamp +georgie +##nesian +##iol +schedules +sindh +##market +etched +hm +sparse +bey +beaux +scratching +gliding +unidentified +216 +collaborating +gems +jesuits +oro +accumulation +shaping +mbe +anal +##xin +231 +enthusiasts +newscast +##egan +janata +dewey +parkinson +179 +ankara +biennial +towering +dd +inconsistent +950 +##chet +thriving +terminate +cabins +furiously +eats +advocating +donkey +marley +muster +phyllis +leiden +##user +grassland +glittering +iucn +loneliness +217 +memorandum +armenians +##ddle +popularized +rhodesia +60s +lame +##illon +sans +bikini +header +orbits +##xx +##finger +##ulator +sharif +spines +biotechnology +strolled +naughty +yates +##wire +fremantle +milo +##mour +abducted +removes +##atin +humming +wonderland +##chrome +##ester +hume +pivotal +##rates +armand +grams +believers +elector +rte +apron +bis +scraped +##yria +endorsement +initials +##llation +eps +dotted +hints +buzzing +emigration +nearer +##tom +indicators +##ulu +coarse +neutron +protectorate +##uze +directional +exploits +pains +loire +1830s +proponents +guggenheim +rabbits +ritchie +305 +hectare +inputs +hutton +##raz +verify +##ako +boilers +longitude +##lev +skeletal +yer +emilia +citrus +compromised +##gau +pokemon +prescription +paragraph +eduard +cadillac +attire +categorized +kenyan +weddings +charley +##bourg +entertain +monmouth +##lles +nutrients +davey +mesh +incentive +practised +ecosystems +kemp +subdued +overheard +##rya +bodily +maxim +##nius +apprenticeship +ursula +##fight +lodged +rug +silesian +unconstitutional +patel +inspected +coyote +unbeaten +##hak +34th +disruption +convict +parcel +##cl +##nham +collier +implicated +mallory +##iac +##lab +susannah +winkler +##rber +shia +phelps +sediments +graphical +robotic +##sner +adulthood +mart +smoked +##isto +kathryn +clarified +##aran +divides +convictions +oppression +pausing +burying +##mt +federico +mathias +eileen +##tana +kite +hunched +##acies +189 +##atz +disadvantage +liza +kinetic +greedy +paradox +yokohama +dowager +trunks +ventured +##gement +gupta +vilnius +olaf +##thest +crimean +hopper +##ej +progressively +arturo +mouthed +arrondissement +##fusion +rubin +simulcast +oceania +##orum +##stra +##rred +busiest +intensely +navigator +cary +##vine +##hini +##bies +fife +rowe +rowland +posing +insurgents +shafts +lawsuits +activate +conor +inward +culturally +garlic +265 +##eering +eclectic +##hui +##kee +##nl +furrowed +vargas +meteorological +rendezvous +##aus +culinary +commencement +##dition +quota +##notes +mommy +salaries +overlapping +mule +##iology +##mology +sums +wentworth +##isk +##zione +mainline +subgroup +##illy +hack +plaintiff +verdi +bulb +differentiation +engagements +multinational +supplemented +bertrand +caller +regis +##naire +##sler +##arts +##imated +blossom +propagation +kilometer +viaduct +vineyards +##uate +beckett +optimization +golfer +songwriters +seminal +semitic +thud +volatile +evolving +ridley +##wley +trivial +distributions +scandinavia +jiang +##ject +wrestled +insistence +##dio +emphasizes +napkin +##ods +adjunct +rhyme +##ricted +##eti +hopeless +surrounds +tremble +32nd +smoky +##ntly +oils +medicinal +padded +steer +wilkes +219 +255 +concessions +hue +uniquely +blinded +landon +yahoo +##lane +hendrix +commemorating +dex +specify +chicks +##ggio +intercity +1400 +morley +##torm +highlighting +##oting +pang +oblique +stalled +##liner +flirting +newborn +1769 +bishopric +shaved +232 +currie +##ush +dharma +spartan +##ooped +favorites +smug +novella +sirens +abusive +creations +espana +##lage +paradigm +semiconductor +sheen +##rdo +##yen +##zak +nrl +renew +##pose +##tur +adjutant +marches +norma +##enity +ineffective +weimar +grunt +##gat +lordship +plotting +expenditure +infringement +lbs +refrain +av +mimi +mistakenly +postmaster +1771 +##bara +ras +motorsports +tito +199 +subjective +##zza +bully +stew +##kaya +prescott +1a +##raphic +##zam +bids +styling +paranormal +reeve +sneaking +exploding +katz +akbar +migrant +syllables +indefinitely +##ogical +destroys +replaces +applause +##phine +pest +##fide +218 +articulated +bertie +##thing +##cars +##ptic +courtroom +crowley +aesthetics +cummings +tehsil +hormones +titanic +dangerously +##ibe +stadion +jaenelle +auguste +ciudad +##chu +mysore +partisans +##sio +lucan +philipp +##aly +debating +henley +interiors +##rano +##tious +homecoming +beyonce +usher +henrietta +prepares +weeds +##oman +ely +plucked +##pire +##dable +luxurious +##aq +artifact +password +pasture +juno +maddy +minsk +##dder +##ologies +##rone +assessments +martian +royalist +1765 +examines +##mani +##rge +nino +223 +parry +scooped +relativity +##eli +##uting +##cao +congregational +noisy +traverse +##agawa +strikeouts +nickelodeon +obituary +transylvania +binds +depictions +polk +trolley +##yed +##lard +breeders +##under +dryly +hokkaido +1762 +strengths +stacks +bonaparte +connectivity +neared +prostitutes +stamped +anaheim +gutierrez +sinai +##zzling +bram +fresno +madhya +##86 +proton +##lena +##llum +##phon +reelected +wanda +##anus +##lb +ample +distinguishing +##yler +grasping +sermons +tomato +bland +stimulation +avenues +##eux +spreads +scarlett +fern +pentagon +assert +baird +chesapeake +ir +calmed +distortion +fatalities +##olis +correctional +pricing +##astic +##gina +prom +dammit +ying +collaborate +##chia +welterweight +33rd +pointer +substitution +bonded +umpire +communicating +multitude +paddle +##obe +federally +intimacy +##insky +betray +ssr +##lett +##lean +##lves +##therapy +airbus +##tery +functioned +ud +bearer +biomedical +netflix +##hire +##nca +condom +brink +ik +##nical +macy +##bet +flap +gma +experimented +jelly +lavender +##icles +##ulia +munro +##mian +##tial +rye +##rle +60th +gigs +hottest +rotated +predictions +fuji +bu +##erence +##omi +barangay +##fulness +##sas +clocks +##rwood +##liness +cereal +roe +wight +decker +uttered +babu +onion +xml +forcibly +##df +petra +sarcasm +hartley +peeled +storytelling +##42 +##xley +##ysis +##ffa +fibre +kiel +auditor +fig +harald +greenville +##berries +geographically +nell +quartz +##athic +cemeteries +##lr +crossings +nah +holloway +reptiles +chun +sichuan +snowy +660 +corrections +##ivo +zheng +ambassadors +blacksmith +fielded +fluids +hardcover +turnover +medications +melvin +academies +##erton +ro +roach +absorbing +spaniards +colton +##founded +outsider +espionage +kelsey +245 +edible +##ulf +dora +establishes +##sham +##tries +contracting +##tania +cinematic +costello +nesting +##uron +connolly +duff +##nology +mma +##mata +fergus +sexes +gi +optics +spectator +woodstock +banning +##hee +##fle +differentiate +outfielder +refinery +226 +312 +gerhard +horde +lair +drastically +##udi +landfall +##cheng +motorsport +odi +##achi +predominant +quay +skins +##ental +edna +harshly +complementary +murdering +##aves +wreckage +##90 +ono +outstretched +lennox +munitions +galen +reconcile +470 +scalp +bicycles +gillespie +questionable +rosenberg +guillermo +hostel +jarvis +kabul +volvo +opium +yd +##twined +abuses +decca +outpost +##cino +sensible +neutrality +##64 +ponce +anchorage +atkins +turrets +inadvertently +disagree +libre +vodka +reassuring +weighs +##yal +glide +jumper +ceilings +repertory +outs +stain +##bial +envy +##ucible +smashing +heightened +policing +hyun +mixes +lai +prima +##ples +celeste +##bina +lucrative +intervened +kc +manually +##rned +stature +staffed +bun +bastards +nairobi +priced +##auer +thatcher +##kia +tripped +comune +##ogan +##pled +brasil +incentives +emanuel +hereford +musica +##kim +benedictine +biennale +##lani +eureka +gardiner +rb +knocks +sha +##ael +##elled +##onate +efficacy +ventura +masonic +sanford +maize +leverage +##feit +capacities +santana +##aur +novelty +vanilla +##cter +##tour +benin +##oir +##rain +neptune +drafting +tallinn +##cable +humiliation +##boarding +schleswig +fabian +bernardo +liturgy +spectacle +sweeney +pont +routledge +##tment +cosmos +ut +hilt +sleek +universally +##eville +##gawa +typed +##dry +favors +allegheny +glaciers +##rly +recalling +aziz +##log +parasite +requiem +auf +##berto +##llin +illumination +##breaker +##issa +festivities +bows +govern +vibe +vp +333 +sprawled +larson +pilgrim +bwf +leaping +##rts +##ssel +alexei +greyhound +hoarse +##dler +##oration +seneca +##cule +gaping +##ulously +##pura +cinnamon +##gens +##rricular +craven +fantasies +houghton +engined +reigned +dictator +supervising +##oris +bogota +commentaries +unnatural +fingernails +spirituality +tighten +##tm +canadiens +protesting +intentional +cheers +sparta +##ytic +##iere +##zine +widen +belgarath +controllers +dodd +iaaf +navarre +##ication +defect +squire +steiner +whisky +##mins +560 +inevitably +tome +##gold +chew +##uid +##lid +elastic +##aby +streaked +alliances +jailed +regal +##ined +##phy +czechoslovak +narration +absently +##uld +bluegrass +guangdong +quran +criticizing +hose +hari +##liest +##owa +skier +streaks +deploy +##lom +raft +bose +dialed +huff +##eira +haifa +simplest +bursting +endings +ib +sultanate +##titled +franks +whitman +ensures +sven +##ggs +collaborators +forster +organising +ui +banished +napier +injustice +teller +layered +thump +##otti +roc +battleships +evidenced +fugitive +sadie +robotics +##roud +equatorial +geologist +##iza +yielding +##bron +##sr +internationale +mecca +##diment +sbs +skyline +toad +uploaded +reflective +undrafted +lal +leafs +bayern +##dai +lakshmi +shortlisted +##stick +##wicz +camouflage +donate +af +christi +lau +##acio +disclosed +nemesis +1761 +assemble +straining +northamptonshire +tal +##asi +bernardino +premature +heidi +42nd +coefficients +galactic +reproduce +buzzed +sensations +zionist +monsieur +myrtle +##eme +archery +strangled +musically +viewpoint +antiquities +bei +trailers +seahawks +cured +pee +preferring +tasmanian +lange +sul +##mail +##working +colder +overland +lucivar +massey +gatherings +haitian +##smith +disapproval +flaws +##cco +##enbach +1766 +npr +##icular +boroughs +creole +forums +techno +1755 +dent +abdominal +streetcar +##eson +##stream +procurement +gemini +predictable +##tya +acheron +christoph +feeder +fronts +vendor +bernhard +jammu +tumors +slang +##uber +goaltender +twists +curving +manson +vuelta +mer +peanut +confessions +pouch +unpredictable +allowance +theodor +vascular +##factory +bala +authenticity +metabolic +coughing +nanjing +##cea +pembroke +##bard +splendid +36th +ff +hourly +##ahu +elmer +handel +##ivate +awarding +thrusting +dl +experimentation +##hesion +##46 +caressed +entertained +steak +##rangle +biologist +orphans +baroness +oyster +stepfather +##dridge +mirage +reefs +speeding +##31 +barons +1764 +227 +inhabit +preached +repealed +##tral +honoring +boogie +captives +administer +johanna +##imate +gel +suspiciously +1767 +sobs +##dington +backbone +hayward +garry +##folding +##nesia +maxi +##oof +##ppe +ellison +galileo +##stand +crimea +frenzy +amour +bumper +matrices +natalia +baking +garth +palestinians +##grove +smack +conveyed +ensembles +gardening +##manship +##rup +##stituting +1640 +harvesting +topography +jing +shifters +dormitory +##carriage +##lston +ist +skulls +##stadt +dolores +jewellery +sarawak +##wai +##zier +fences +christy +confinement +tumbling +credibility +fir +stench +##bria +##plication +##nged +##sam +virtues +##belt +marjorie +pba +##eem +##made +celebrates +schooner +agitated +barley +fulfilling +anthropologist +##pro +restrict +novi +regulating +##nent +padres +##rani +##hesive +loyola +tabitha +milky +olson +proprietor +crambidae +guarantees +intercollegiate +ljubljana +hilda +##sko +ignorant +hooded +##lts +sardinia +##lidae +##vation +frontman +privileged +witchcraft +##gp +jammed +laude +poking +##than +bracket +amazement +yunnan +##erus +maharaja +linnaeus +264 +commissioning +milano +peacefully +##logies +akira +rani +regulator +##36 +grasses +##rance +luzon +crows +compiler +gretchen +seaman +edouard +tab +buccaneers +ellington +hamlets +whig +socialists +##anto +directorial +easton +mythological +##kr +##vary +rhineland +semantic +taut +dune +inventions +succeeds +##iter +replication +branched +##pired +jul +prosecuted +kangaroo +penetrated +##avian +middlesbrough +doses +bleak +madam +predatory +relentless +##vili +reluctance +##vir +hailey +crore +silvery +1759 +monstrous +swimmers +transmissions +hawthorn +informing +##eral +toilets +caracas +crouch +kb +##sett +295 +cartel +hadley +##aling +alexia +yvonne +##biology +cinderella +eton +superb +blizzard +stabbing +industrialist +maximus +##gm +##orus +groves +maud +clade +oversized +comedic +##bella +rosen +nomadic +fulham +montane +beverages +galaxies +redundant +swarm +##rot +##folia +##llis +buckinghamshire +fen +bearings +bahadur +##rom +gilles +phased +dynamite +faber +benoit +vip +##ount +##wd +booking +fractured +tailored +anya +spices +westwood +cairns +auditions +inflammation +steamed +##rocity +##acion +##urne +skyla +thereof +watford +torment +archdeacon +transforms +lulu +demeanor +fucked +serge +##sor +mckenna +minas +entertainer +##icide +caress +originate +residue +##sty +1740 +##ilised +##org +beech +##wana +subsidies +##ghton +emptied +gladstone +ru +firefighters +voodoo +##rcle +het +nightingale +tamara +edmond +ingredient +weaknesses +silhouette +285 +compatibility +withdrawing +hampson +##mona +anguish +giggling +##mber +bookstore +##jiang +southernmost +tilting +##vance +bai +economical +rf +briefcase +dreadful +hinted +projections +shattering +totaling +##rogate +analogue +indicted +periodical +fullback +##dman +haynes +##tenberg +##ffs +##ishment +1745 +thirst +stumble +penang +vigorous +##ddling +##kor +##lium +octave +##ove +##enstein +##inen +##ones +siberian +##uti +cbn +repeal +swaying +##vington +khalid +tanaka +unicorn +otago +plastered +lobe +riddle +##rella +perch +##ishing +croydon +filtered +graeme +tripoli +##ossa +crocodile +##chers +sufi +mined +##tung +inferno +lsu +##phi +swelled +utilizes +£2 +cale +periodicals +styx +hike +informally +coop +lund +##tidae +ala +hen +qui +transformations +disposed +sheath +chickens +##cade +fitzroy +sas +silesia +unacceptable +odisha +1650 +sabrina +pe +spokane +ratios +athena +massage +shen +dilemma +##drum +##riz +##hul +corona +doubtful +niall +##pha +##bino +fines +cite +acknowledging +bangor +ballard +bathurst +##resh +huron +mustered +alzheimer +garments +kinase +tyre +warship +##cp +flashback +pulmonary +braun +cheat +kamal +cyclists +constructions +grenades +ndp +traveller +excuses +stomped +signalling +trimmed +futsal +mosques +relevance +##wine +wta +##23 +##vah +##lter +hoc +##riding +optimistic +##´s +deco +sim +interacting +rejecting +moniker +waterways +##ieri +##oku +mayors +gdansk +outnumbered +pearls +##ended +##hampton +fairs +totals +dominating +262 +notions +stairway +compiling +pursed +commodities +grease +yeast +##jong +carthage +griffiths +residual +amc +contraction +laird +sapphire +##marine +##ivated +amalgamation +dissolve +inclination +lyle +packaged +altitudes +suez +canons +graded +lurched +narrowing +boasts +guise +wed +enrico +##ovsky +rower +scarred +bree +cub +iberian +protagonists +bargaining +proposing +trainers +voyages +vans +fishes +##aea +##ivist +##verance +encryption +artworks +kazan +sabre +cleopatra +hepburn +rotting +supremacy +mecklenburg +##brate +burrows +hazards +outgoing +flair +organizes +##ctions +scorpion +##usions +boo +234 +chevalier +dunedin +slapping +##34 +ineligible +pensions +##38 +##omic +manufactures +emails +bismarck +238 +weakening +blackish +ding +mcgee +quo +##rling +northernmost +xx +manpower +greed +sampson +clicking +##ange +##horpe +##inations +##roving +torre +##eptive +##moral +symbolism +38th +asshole +meritorious +outfits +splashed +biographies +sprung +astros +##tale +302 +737 +filly +raoul +nw +tokugawa +linden +clubhouse +##apa +tracts +romano +##pio +putin +tags +##note +chained +dickson +gunshot +moe +gunn +rashid +##tails +zipper +##bas +##nea +contrasted +##ply +##udes +plum +pharaoh +##pile +aw +comedies +ingrid +sandwiches +subdivisions +1100 +mariana +nokia +kamen +hz +delaney +veto +herring +##words +possessive +outlines +##roup +siemens +stairwell +rc +gallantry +messiah +palais +yells +233 +zeppelin +##dm +bolivar +##cede +smackdown +mckinley +##mora +##yt +muted +geologic +finely +unitary +avatar +hamas +maynard +rees +bog +contrasting +##rut +liv +chico +disposition +pixel +##erate +becca +dmitry +yeshiva +narratives +##lva +##ulton +mercenary +sharpe +tempered +navigate +stealth +amassed +keynes +##lini +untouched +##rrie +havoc +lithium +##fighting +abyss +graf +southward +wolverine +balloons +implements +ngos +transitions +##icum +ambushed +concacaf +dormant +economists +##dim +costing +csi +rana +universite +boulders +verity +##llon +collin +mellon +misses +cypress +fluorescent +lifeless +spence +##ulla +crewe +shepard +pak +revelations +##م +jolly +gibbons +paw +##dro +##quel +freeing +##test +shack +fries +palatine +##51 +##hiko +accompaniment +cruising +recycled +##aver +erwin +sorting +synthesizers +dyke +realities +sg +strides +enslaved +wetland +##ghan +competence +gunpowder +grassy +maroon +reactors +objection +##oms +carlson +gearbox +macintosh +radios +shelton +##sho +clergyman +prakash +254 +mongols +trophies +oricon +228 +stimuli +twenty20 +cantonese +cortes +mirrored +##saurus +bhp +cristina +melancholy +##lating +enjoyable +nuevo +##wny +downfall +schumacher +##ind +banging +lausanne +rumbled +paramilitary +reflex +ax +amplitude +migratory +##gall +##ups +midi +barnard +lastly +sherry +##hp +##nall +keystone +##kra +carleton +slippery +##53 +coloring +foe +socket +otter +##rgos +mats +##tose +consultants +bafta +bison +topping +##km +490 +primal +abandonment +transplant +atoll +hideous +mort +pained +reproduced +tae +howling +##turn +unlawful +billionaire +hotter +poised +lansing +##chang +dinamo +retro +messing +nfc +domesday +##mina +blitz +timed +##athing +##kley +ascending +gesturing +##izations +signaled +tis +chinatown +mermaid +savanna +jameson +##aint +catalina +##pet +##hers +cochrane +cy +chatting +##kus +alerted +computation +mused +noelle +majestic +mohawk +campo +octagonal +##sant +##hend +241 +aspiring +##mart +comprehend +iona +paralyzed +shimmering +swindon +rhone +##eley +reputed +configurations +pitchfork +agitation +francais +gillian +lipstick +##ilo +outsiders +pontifical +resisting +bitterness +sewer +rockies +##edd +##ucher +misleading +1756 +exiting +galloway +##nging +risked +##heart +246 +commemoration +schultz +##rka +integrating +##rsa +poses +shrieked +##weiler +guineas +gladys +jerking +owls +goldsmith +nightly +penetrating +##unced +lia +##33 +ignited +betsy +##aring +##thorpe +follower +vigorously +##rave +coded +kiran +knit +zoology +tbilisi +##28 +##bered +repository +govt +deciduous +dino +growling +##bba +enhancement +unleashed +chanting +pussy +biochemistry +##eric +kettle +repression +toxicity +nrhp +##arth +##kko +##bush +ernesto +commended +outspoken +242 +mca +parchment +sms +kristen +##aton +bisexual +raked +glamour +navajo +a2 +conditioned +showcased +##hma +spacious +youthful +##esa +usl +appliances +junta +brest +layne +conglomerate +enchanted +chao +loosened +picasso +circulating +inspect +montevideo +##centric +##kti +piazza +spurred +##aith +bari +freedoms +poultry +stamford +lieu +##ect +indigo +sarcastic +bahia +stump +attach +dvds +frankenstein +lille +approx +scriptures +pollen +##script +nmi +overseen +##ivism +tides +proponent +newmarket +inherit +milling +##erland +centralized +##rou +distributors +credentials +drawers +abbreviation +##lco +##xon +downing +uncomfortably +ripe +##oes +erase +franchises +##ever +populace +##bery +##khar +decomposition +pleas +##tet +daryl +sabah +##stle +##wide +fearless +genie +lesions +annette +##ogist +oboe +appendix +nair +dripped +petitioned +maclean +mosquito +parrot +rpg +hampered +1648 +operatic +reservoirs +##tham +irrelevant +jolt +summarized +##fp +medallion +##taff +##− +clawed +harlow +narrower +goddard +marcia +bodied +fremont +suarez +altering +tempest +mussolini +porn +##isms +sweetly +oversees +walkers +solitude +grimly +shrines +hk +ich +supervisors +hostess +dietrich +legitimacy +brushes +expressive +##yp +dissipated +##rse +localized +systemic +##nikov +gettysburg +##js +##uaries +dialogues +muttering +251 +housekeeper +sicilian +discouraged +##frey +beamed +kaladin +halftime +kidnap +##amo +##llet +1754 +synonymous +depleted +instituto +insulin +reprised +##opsis +clashed +##ctric +interrupting +radcliffe +insisting +medici +1715 +ejected +playfully +turbulent +##47 +starvation +##rini +shipment +rebellious +petersen +verification +merits +##rified +cakes +##charged +1757 +milford +shortages +spying +fidelity +##aker +emitted +storylines +harvested +seismic +##iform +cheung +kilda +theoretically +barbie +lynx +##rgy +##tius +goblin +mata +poisonous +##nburg +reactive +residues +obedience +##евич +conjecture +##rac +401 +hating +sixties +kicker +moaning +motown +##bha +emancipation +neoclassical +##hering +consoles +ebert +professorship +##tures +sustaining +assaults +obeyed +affluent +incurred +tornadoes +##eber +##zow +emphasizing +highlanders +cheated +helmets +##ctus +internship +terence +bony +executions +legislators +berries +peninsular +tinged +##aco +1689 +amplifier +corvette +ribbons +lavish +pennant +##lander +worthless +##chfield +##forms +mariano +pyrenees +expenditures +##icides +chesterfield +mandir +tailor +39th +sergey +nestled +willed +aristocracy +devotees +goodnight +raaf +rumored +weaponry +remy +appropriations +harcourt +burr +riaa +##lence +limitation +unnoticed +guo +soaking +swamps +##tica +collapsing +tatiana +descriptive +brigham +psalm +##chment +maddox +##lization +patti +caliph +##aja +akron +injuring +serra +##ganj +basins +##sari +astonished +launcher +##church +hilary +wilkins +sewing +##sf +stinging +##fia +##ncia +underwood +startup +##ition +compilations +vibrations +embankment +jurist +##nity +bard +juventus +groundwater +kern +palaces +helium +boca +cramped +marissa +soto +##worm +jae +princely +##ggy +faso +bazaar +warmly +##voking +229 +pairing +##lite +##grate +##nets +wien +freaked +ulysses +rebirth +##alia +##rent +mummy +guzman +jimenez +stilled +##nitz +trajectory +tha +woken +archival +professions +##pts +##pta +hilly +shadowy +shrink +##bolt +norwood +glued +migrate +stereotypes +devoid +##pheus +625 +evacuate +horrors +infancy +gotham +knowles +optic +downloaded +sachs +kingsley +parramatta +darryl +mor +##onale +shady +commence +confesses +kan +##meter +##placed +marlborough +roundabout +regents +frigates +io +##imating +gothenburg +revoked +carvings +clockwise +convertible +intruder +##sche +banged +##ogo +vicky +bourgeois +##mony +dupont +footing +##gum +pd +##real +buckle +yun +penthouse +sane +720 +serviced +stakeholders +neumann +bb +##eers +comb +##gam +catchment +pinning +rallies +typing +##elles +forefront +freiburg +sweetie +giacomo +widowed +goodwill +worshipped +aspirations +midday +##vat +fishery +##trick +bournemouth +turk +243 +hearth +ethanol +guadalajara +murmurs +sl +##uge +afforded +scripted +##hta +wah +##jn +coroner +translucent +252 +memorials +puck +progresses +clumsy +##race +315 +candace +recounted +##27 +##slin +##uve +filtering +##mac +howl +strata +heron +leveled +##ays +dubious +##oja +##т +##wheel +citations +exhibiting +##laya +##mics +##pods +turkic +##lberg +injunction +##ennial +##mit +antibodies +##44 +organise +##rigues +cardiovascular +cushion +inverness +##zquez +dia +cocoa +sibling +##tman +##roid +expanse +feasible +tunisian +algiers +##relli +rus +bloomberg +dso +westphalia +bro +tacoma +281 +downloads +##ours +konrad +duran +##hdi +continuum +jett +compares +legislator +secession +##nable +##gues +##zuka +translating +reacher +##gley +##ła +aleppo +##agi +tc +orchards +trapping +linguist +versatile +drumming +postage +calhoun +superiors +##mx +barefoot +leary +##cis +ignacio +alfa +kaplan +##rogen +bratislava +mori +##vot +disturb +haas +313 +cartridges +gilmore +radiated +salford +tunic +hades +##ulsive +archeological +delilah +magistrates +auditioned +brewster +charters +empowerment +blogs +cappella +dynasties +iroquois +whipping +##krishna +raceway +truths +myra +weaken +judah +mcgregor +##horse +mic +refueling +37th +burnley +bosses +markus +premio +query +##gga +dunbar +##economic +darkest +lyndon +sealing +commendation +reappeared +##mun +addicted +ezio +slaughtered +satisfactory +shuffle +##eves +##thic +##uj +fortification +warrington +##otto +resurrected +fargo +mane +##utable +##lei +##space +foreword +ox +##aris +##vern +abrams +hua +##mento +sakura +##alo +uv +sentimental +##skaya +midfield +##eses +sturdy +scrolls +macleod +##kyu +entropy +##lance +mitochondrial +cicero +excelled +thinner +convoys +perceive +##oslav +##urable +systematically +grind +burkina +287 +##tagram +ops +##aman +guantanamo +##cloth +##tite +forcefully +wavy +##jou +pointless +##linger +##tze +layton +portico +superficial +clerical +outlaws +##hism +burials +muir +##inn +creditors +hauling +rattle +##leg +calais +monde +archers +reclaimed +dwell +wexford +hellenic +falsely +remorse +##tek +dough +furnishings +##uttered +gabon +neurological +novice +##igraphy +contemplated +pulpit +nightstand +saratoga +##istan +documenting +pulsing +taluk +##firmed +busted +marital +##rien +disagreements +wasps +##yes +hodge +mcdonnell +mimic +fran +pendant +dhabi +musa +##nington +congratulations +argent +darrell +concussion +losers +regrets +thessaloniki +reversal +donaldson +hardwood +thence +achilles +ritter +##eran +demonic +jurgen +prophets +goethe +eki +classmate +buff +##cking +yank +irrational +##inging +perished +seductive +qur +sourced +##crat +##typic +mustard +ravine +barre +horizontally +characterization +phylogenetic +boise +##dit +##runner +##tower +brutally +intercourse +seduce +##bbing +fay +ferris +ogden +amar +nik +unarmed +##inator +evaluating +kyrgyzstan +sweetness +##lford +##oki +mccormick +meiji +notoriety +stimulate +disrupt +figuring +instructional +mcgrath +##zoo +groundbreaking +##lto +flinch +khorasan +agrarian +bengals +mixer +radiating +##sov +ingram +pitchers +nad +tariff +##cript +tata +##codes +##emi +##ungen +appellate +lehigh +##bled +##giri +brawl +duct +texans +##ciation +##ropolis +skipper +speculative +vomit +doctrines +stresses +253 +davy +graders +whitehead +jozef +timely +cumulative +haryana +paints +appropriately +boon +cactus +##ales +##pid +dow +legions +##pit +perceptions +1730 +picturesque +##yse +periphery +rune +wr +##aha +celtics +sentencing +whoa +##erin +confirms +variance +425 +moines +mathews +spade +rave +m1 +fronted +fx +blending +alleging +reared +##gl +237 +##paper +grassroots +eroded +##free +##physical +directs +ordeal +##sław +accelerate +hacker +rooftop +##inia +lev +buys +cebu +devote +##lce +specialising +##ulsion +choreographed +repetition +warehouses +##ryl +paisley +tuscany +analogy +sorcerer +hash +huts +shards +descends +exclude +nix +chaplin +gaga +ito +vane +##drich +causeway +misconduct +limo +orchestrated +glands +jana +##kot +u2 +##mple +##sons +branching +contrasts +scoop +longed +##virus +chattanooga +##75 +syrup +cornerstone +##tized +##mind +##iaceae +careless +precedence +frescoes +##uet +chilled +consult +modelled +snatch +peat +##thermal +caucasian +humane +relaxation +spins +temperance +##lbert +occupations +lambda +hybrids +moons +mp3 +##oese +247 +rolf +societal +yerevan +ness +##ssler +befriended +mechanized +nominate +trough +boasted +cues +seater +##hom +bends +##tangle +conductors +emptiness +##lmer +eurasian +adriatic +tian +##cie +anxiously +lark +propellers +chichester +jock +ev +2a +##holding +credible +recounts +tori +loyalist +abduction +##hoot +##redo +nepali +##mite +ventral +tempting +##ango +##crats +steered +##wice +javelin +dipping +laborers +prentice +looming +titanium +##ː +badges +emir +tensor +##ntation +egyptians +rash +denies +hawthorne +lombard +showers +wehrmacht +dietary +trojan +##reus +welles +executing +horseshoe +lifeboat +##lak +elsa +infirmary +nearing +roberta +boyer +mutter +trillion +joanne +##fine +##oked +sinks +vortex +uruguayan +clasp +sirius +##block +accelerator +prohibit +sunken +byu +chronological +diplomats +ochreous +510 +symmetrical +1644 +maia +##tology +salts +reigns +atrocities +##ия +hess +bared +issn +##vyn +cater +saturated +##cycle +##isse +sable +voyager +dyer +yusuf +##inge +fountains +wolff +##39 +##nni +engraving +rollins +atheist +ominous +##ault +herr +chariot +martina +strung +##fell +##farlane +horrific +sahib +gazes +saetan +erased +ptolemy +##olic +flushing +lauderdale +analytic +##ices +530 +navarro +beak +gorilla +herrera +broom +guadalupe +raiding +sykes +311 +bsc +deliveries +1720 +invasions +carmichael +tajikistan +thematic +ecumenical +sentiments +onstage +##rians +##brand +##sume +catastrophic +flanks +molten +##arns +waller +aimee +terminating +##icing +alternately +##oche +nehru +printers +outraged +##eving +empires +template +banners +repetitive +za +##oise +vegetarian +##tell +guiana +opt +cavendish +lucknow +synthesized +##hani +##mada +finalized +##ctable +fictitious +mayoral +unreliable +##enham +embracing +peppers +rbis +##chio +##neo +inhibition +slashed +togo +orderly +embroidered +safari +salty +236 +barron +benito +totaled +##dak +pubs +simulated +caden +devin +tolkien +momma +welding +sesame +##ept +gottingen +hardness +630 +shaman +temeraire +620 +adequately +pediatric +##kit +ck +assertion +radicals +composure +cadence +seafood +beaufort +lazarus +mani +warily +cunning +kurdistan +249 +cantata +##kir +ares +##41 +##clusive +nape +townland +geared +insulted +flutter +boating +violate +draper +dumping +malmo +##hh +##romatic +firearm +alta +bono +obscured +##clave +exceeds +panorama +unbelievable +##train +preschool +##essed +disconnected +installing +rescuing +secretaries +accessibility +##castle +##drive +##ifice +##film +bouts +slug +waterway +mindanao +##buro +##ratic +halves +##ل +calming +liter +maternity +adorable +bragg +electrification +mcc +##dote +roxy +schizophrenia +##body +munoz +kaye +whaling +239 +mil +tingling +tolerant +##ago +unconventional +volcanoes +##finder +deportivo +##llie +robson +kaufman +neuroscience +wai +deportation +masovian +scraping +converse +##bh +hacking +bulge +##oun +administratively +yao +580 +amp +mammoth +booster +claremont +hooper +nomenclature +pursuits +mclaughlin +melinda +##sul +catfish +barclay +substrates +taxa +zee +originals +kimberly +packets +padma +##ality +borrowing +ostensibly +solvent +##bri +##genesis +##mist +lukas +shreveport +veracruz +##ь +##lou +##wives +cheney +tt +anatolia +hobbs +##zyn +cyclic +radiant +alistair +greenish +siena +dat +independents +##bation +conform +pieter +hyper +applicant +bradshaw +spores +telangana +vinci +inexpensive +nuclei +322 +jang +nme +soho +spd +##ign +cradled +receptionist +pow +##43 +##rika +fascism +##ifer +experimenting +##ading +##iec +##region +345 +jocelyn +maris +stair +nocturnal +toro +constabulary +elgin +##kker +msc +##giving +##schen +##rase +doherty +doping +sarcastically +batter +maneuvers +##cano +##apple +##gai +##git +intrinsic +##nst +##stor +1753 +showtime +cafes +gasps +lviv +ushered +##thed +fours +restart +astonishment +transmitting +flyer +shrugs +##sau +intriguing +cones +dictated +mushrooms +medial +##kovsky +##elman +escorting +gaped +##26 +godfather +##door +##sell +djs +recaptured +timetable +vila +1710 +3a +aerodrome +mortals +scientology +##orne +angelina +mag +convection +unpaid +insertion +intermittent +lego +##nated +endeavor +kota +pereira +##lz +304 +bwv +glamorgan +insults +agatha +fey +##cend +fleetwood +mahogany +protruding +steamship +zeta +##arty +mcguire +suspense +##sphere +advising +urges +##wala +hurriedly +meteor +gilded +inline +arroyo +stalker +##oge +excitedly +revered +##cure +earle +introductory +##break +##ilde +mutants +puff +pulses +reinforcement +##haling +curses +lizards +stalk +correlated +##fixed +fallout +macquarie +##unas +bearded +denton +heaving +802 +##ocation +winery +assign +dortmund +##lkirk +everest +invariant +charismatic +susie +##elling +bled +lesley +telegram +sumner +bk +##ogen +##к +wilcox +needy +colbert +duval +##iferous +##mbled +allotted +attends +imperative +##hita +replacements +hawker +##inda +insurgency +##zee +##eke +casts +##yla +680 +ives +transitioned +##pack +##powering +authoritative +baylor +flex +cringed +plaintiffs +woodrow +##skie +drastic +ape +aroma +unfolded +commotion +nt +preoccupied +theta +routines +lasers +privatization +wand +domino +ek +clenching +nsa +strategically +showered +bile +handkerchief +pere +storing +christophe +insulting +316 +nakamura +romani +asiatic +magdalena +palma +cruises +stripping +405 +konstantin +soaring +##berman +colloquially +forerunner +havilland +incarcerated +parasites +sincerity +##utus +disks +plank +saigon +##ining +corbin +homo +ornaments +powerhouse +##tlement +chong +fastened +feasibility +idf +morphological +usable +##nish +##zuki +aqueduct +jaguars +keepers +##flies +aleksandr +faust +assigns +ewing +bacterium +hurled +tricky +hungarians +integers +wallis +321 +yamaha +##isha +hushed +oblivion +aviator +evangelist +friars +##eller +monograph +ode +##nary +airplanes +labourers +charms +##nee +1661 +hagen +tnt +rudder +fiesta +transcript +dorothea +ska +inhibitor +maccabi +retorted +raining +encompassed +clauses +menacing +1642 +lineman +##gist +vamps +##ape +##dick +gloom +##rera +dealings +easing +seekers +##nut +##pment +helens +unmanned +##anu +##isson +basics +##amy +##ckman +adjustments +1688 +brutality +horne +##zell +sui +##55 +##mable +aggregator +##thal +rhino +##drick +##vira +counters +zoom +##01 +##rting +mn +montenegrin +packard +##unciation +##♭ +##kki +reclaim +scholastic +thugs +pulsed +##icia +syriac +quan +saddam +banda +kobe +blaming +buddies +dissent +##lusion +##usia +corbett +jaya +delle +erratic +lexie +##hesis +435 +amiga +hermes +##pressing +##leen +chapels +gospels +jamal +##uating +compute +revolving +warp +##sso +##thes +armory +##eras +##gol +antrim +loki +##kow +##asian +##good +##zano +braid +handwriting +subdistrict +funky +pantheon +##iculate +concurrency +estimation +improper +juliana +##his +newcomers +johnstone +staten +communicated +##oco +##alle +sausage +stormy +##stered +##tters +superfamily +##grade +acidic +collateral +tabloid +##oped +##rza +bladder +austen +##ellant +mcgraw +##hay +hannibal +mein +aquino +lucifer +wo +badger +boar +cher +christensen +greenberg +interruption +##kken +jem +244 +mocked +bottoms +cambridgeshire +##lide +sprawling +##bbly +eastwood +ghent +synth +##buck +advisers +##bah +nominally +hapoel +qu +daggers +estranged +fabricated +towels +vinnie +wcw +misunderstanding +anglia +nothin +unmistakable +##dust +##lova +chilly +marquette +truss +##edge +##erine +reece +##lty +##chemist +##connected +272 +308 +41st +bash +raion +waterfalls +##ump +##main +labyrinth +queue +theorist +##istle +bharatiya +flexed +soundtracks +rooney +leftist +patrolling +wharton +plainly +alleviate +eastman +schuster +topographic +engages +immensely +unbearable +fairchild +1620 +dona +lurking +parisian +oliveira +ia +indictment +hahn +bangladeshi +##aster +vivo +##uming +##ential +antonia +expects +indoors +kildare +harlan +##logue +##ogenic +##sities +forgiven +##wat +childish +tavi +##mide +##orra +plausible +grimm +successively +scooted +##bola +##dget +##rith +spartans +emery +flatly +azure +epilogue +##wark +flourish +##iny +##tracted +##overs +##oshi +bestseller +distressed +receipt +spitting +hermit +topological +##cot +drilled +subunit +francs +##layer +eel +##fk +##itas +octopus +footprint +petitions +ufo +##say +##foil +interfering +leaking +palo +##metry +thistle +valiant +##pic +narayan +mcpherson +##fast +gonzales +##ym +##enne +dustin +novgorod +solos +##zman +doin +##raph +##patient +##meyer +soluble +ashland +cuffs +carole +pendleton +whistling +vassal +##river +deviation +revisited +constituents +rallied +rotate +loomed +##eil +##nting +amateurs +augsburg +auschwitz +crowns +skeletons +##cona +bonnet +257 +dummy +globalization +simeon +sleeper +mandal +differentiated +##crow +##mare +milne +bundled +exasperated +talmud +owes +segregated +##feng +##uary +dentist +piracy +props +##rang +devlin +##torium +malicious +paws +##laid +dependency +##ergy +##fers +##enna +258 +pistons +rourke +jed +grammatical +tres +maha +wig +512 +ghostly +jayne +##achal +##creen +##ilis +##lins +##rence +designate +##with +arrogance +cambodian +clones +showdown +throttle +twain +##ception +lobes +metz +nagoya +335 +braking +##furt +385 +roaming +##minster +amin +crippled +##37 +##llary +indifferent +hoffmann +idols +intimidating +1751 +261 +influenza +memo +onions +1748 +bandage +consciously +##landa +##rage +clandestine +observes +swiped +tangle +##ener +##jected +##trum +##bill +##lta +hugs +congresses +josiah +spirited +##dek +humanist +managerial +filmmaking +inmate +rhymes +debuting +grimsby +ur +##laze +duplicate +vigor +##tf +republished +bolshevik +refurbishment +antibiotics +martini +methane +newscasts +royale +horizons +levant +iain +visas +##ischen +paler +##around +manifestation +snuck +alf +chop +futile +pedestal +rehab +##kat +bmg +kerman +res +fairbanks +jarrett +abstraction +saharan +##zek +1746 +procedural +clearer +kincaid +sash +luciano +##ffey +crunch +helmut +##vara +revolutionaries +##tute +creamy +leach +##mmon +1747 +permitting +nes +plight +wendell +##lese +contra +ts +clancy +ipa +mach +staples +autopsy +disturbances +nueva +karin +pontiac +##uding +proxy +venerable +haunt +leto +bergman +expands +##helm +wal +##pipe +canning +celine +cords +obesity +##enary +intrusion +planner +##phate +reasoned +sequencing +307 +harrow +##chon +##dora +marred +mcintyre +repay +tarzan +darting +248 +harrisburg +margarita +repulsed +##hur +##lding +belinda +hamburger +novo +compliant +runways +bingham +registrar +skyscraper +ic +cuthbert +improvisation +livelihood +##corp +##elial +admiring +##dened +sporadic +believer +casablanca +popcorn +##29 +asha +shovel +##bek +##dice +coiled +tangible +##dez +casper +elsie +resin +tenderness +rectory +##ivision +avail +sonar +##mori +boutique +##dier +guerre +bathed +upbringing +vaulted +sandals +blessings +##naut +##utnant +1680 +306 +foxes +pia +corrosion +hesitantly +confederates +crystalline +footprints +shapiro +tirana +valentin +drones +45th +microscope +shipments +texted +inquisition +wry +guernsey +unauthorized +resigning +760 +ripple +schubert +stu +reassure +felony +##ardo +brittle +koreans +##havan +##ives +dun +implicit +tyres +##aldi +##lth +magnolia +##ehan +##puri +##poulos +aggressively +fei +gr +familiarity +##poo +indicative +##trust +fundamentally +jimmie +overrun +395 +anchors +moans +##opus +britannia +armagh +##ggle +purposely +seizing +##vao +bewildered +mundane +avoidance +cosmopolitan +geometridae +quartermaster +caf +415 +chatter +engulfed +gleam +purge +##icate +juliette +jurisprudence +guerra +revisions +##bn +casimir +brew +##jm +1749 +clapton +cloudy +conde +hermitage +278 +simulations +torches +vincenzo +matteo +##rill +hidalgo +booming +westbound +accomplishment +tentacles +unaffected +##sius +annabelle +flopped +sloping +##litz +dreamer +interceptor +vu +##loh +consecration +copying +messaging +breaker +climates +hospitalized +1752 +torino +afternoons +winfield +witnessing +##teacher +breakers +choirs +sawmill +coldly +##ege +sipping +haste +uninhabited +conical +bibliography +pamphlets +severn +edict +##oca +deux +illnesses +grips +##pl +rehearsals +sis +thinkers +tame +##keepers +1690 +acacia +reformer +##osed +##rys +shuffling +##iring +##shima +eastbound +ionic +rhea +flees +littered +##oum +rocker +vomiting +groaning +champ +overwhelmingly +civilizations +paces +sloop +adoptive +##tish +skaters +##vres +aiding +mango +##joy +nikola +shriek +##ignon +pharmaceuticals +##mg +tuna +calvert +gustavo +stocked +yearbook +##urai +##mana +computed +subsp +riff +hanoi +kelvin +hamid +moors +pastures +summons +jihad +nectar +##ctors +bayou +untitled +pleasing +vastly +republics +intellect +##η +##ulio +##tou +crumbling +stylistic +sb +##ی +consolation +frequented +h₂o +walden +widows +##iens +404 +##ignment +chunks +improves +288 +grit +recited +##dev +snarl +sociological +##arte +##gul +inquired +##held +bruise +clube +consultancy +homogeneous +hornets +multiplication +pasta +prick +savior +##grin +##kou +##phile +yoon +##gara +grimes +vanishing +cheering +reacting +bn +distillery +##quisite +##vity +coe +dockyard +massif +##jord +escorts +voss +##valent +byte +chopped +hawke +illusions +workings +floats +##koto +##vac +kv +annapolis +madden +##onus +alvaro +noctuidae +##cum +##scopic +avenge +steamboat +forte +illustrates +erika +##trip +570 +dew +nationalities +bran +manifested +thirsty +diversified +muscled +reborn +##standing +arson +##lessness +##dran +##logram +##boys +##kushima +##vious +willoughby +##phobia +286 +alsace +dashboard +yuki +##chai +granville +myspace +publicized +tricked +##gang +adjective +##ater +relic +reorganisation +enthusiastically +indications +saxe +##lassified +consolidate +iec +padua +helplessly +ramps +renaming +regulars +pedestrians +accents +convicts +inaccurate +lowers +mana +##pati +barrie +bjp +outta +someplace +berwick +flanking +invoked +marrow +sparsely +excerpts +clothed +rei +##ginal +wept +##straße +##vish +alexa +excel +##ptive +membranes +aquitaine +creeks +cutler +sheppard +implementations +ns +##dur +fragrance +budge +concordia +magnesium +marcelo +##antes +gladly +vibrating +##rral +##ggles +montrose +##omba +lew +seamus +1630 +cocky +##ament +##uen +bjorn +##rrick +fielder +fluttering +##lase +methyl +kimberley +mcdowell +reductions +barbed +##jic +##tonic +aeronautical +condensed +distracting +##promising +huffed +##cala +##sle +claudius +invincible +missy +pious +balthazar +ci +##lang +butte +combo +orson +##dication +myriad +1707 +silenced +##fed +##rh +coco +netball +yourselves +##oza +clarify +heller +peg +durban +etudes +offender +roast +blackmail +curvature +##woods +vile +309 +illicit +suriname +##linson +overture +1685 +bubbling +gymnast +tucking +##mming +##ouin +maldives +##bala +gurney +##dda +##eased +##oides +backside +pinto +jars +racehorse +tending +##rdial +baronetcy +wiener +duly +##rke +barbarian +cupping +flawed +##thesis +bertha +pleistocene +puddle +swearing +##nob +##tically +fleeting +prostate +amulet +educating +##mined +##iti +##tler +75th +jens +respondents +analytics +cavaliers +papacy +raju +##iente +##ulum +##tip +funnel +271 +disneyland +##lley +sociologist +##iam +2500 +faulkner +louvre +menon +##dson +276 +##ower +afterlife +mannheim +peptide +referees +comedians +meaningless +##anger +##laise +fabrics +hurley +renal +sleeps +##bour +##icle +breakout +kristin +roadside +animator +clover +disdain +unsafe +redesign +##urity +firth +barnsley +portage +reset +narrows +268 +commandos +expansive +speechless +tubular +##lux +essendon +eyelashes +smashwords +##yad +##bang +##claim +craved +sprinted +chet +somme +astor +wrocław +orton +266 +bane +##erving +##uing +mischief +##amps +##sund +scaling +terre +##xious +impairment +offenses +undermine +moi +soy +contiguous +arcadia +inuit +seam +##tops +macbeth +rebelled +##icative +##iot +590 +elaborated +frs +uniformed +##dberg +259 +powerless +priscilla +stimulated +980 +qc +arboretum +frustrating +trieste +bullock +##nified +enriched +glistening +intern +##adia +locus +nouvelle +ollie +ike +lash +starboard +ee +tapestry +headlined +hove +rigged +##vite +pollock +##yme +thrive +clustered +cas +roi +gleamed +olympiad +##lino +pressured +regimes +##hosis +##lick +ripley +##ophone +kickoff +gallon +rockwell +##arable +crusader +glue +revolutions +scrambling +1714 +grover +##jure +englishman +aztec +263 +contemplating +coven +ipad +preach +triumphant +tufts +##esian +rotational +##phus +328 +falkland +##brates +strewn +clarissa +rejoin +environmentally +glint +banded +drenched +moat +albanians +johor +rr +maestro +malley +nouveau +shaded +taxonomy +v6 +adhere +bunk +airfields +##ritan +1741 +encompass +remington +tran +##erative +amelie +mazda +friar +morals +passions +##zai +breadth +vis +##hae +argus +burnham +caressing +insider +rudd +##imov +##mini +##rso +italianate +murderous +textual +wainwright +armada +bam +weave +timer +##taken +##nh +fra +##crest +ardent +salazar +taps +tunis +##ntino +allegro +gland +philanthropic +##chester +implication +##optera +esq +judas +noticeably +wynn +##dara +inched +indexed +crises +villiers +bandit +royalties +patterned +cupboard +interspersed +accessory +isla +kendrick +entourage +stitches +##esthesia +headwaters +##ior +interlude +distraught +draught +1727 +##basket +biased +sy +transient +triad +subgenus +adapting +kidd +shortstop +##umatic +dimly +spiked +mcleod +reprint +nellie +pretoria +windmill +##cek +singled +##mps +273 +reunite +##orous +747 +bankers +outlying +##omp +##ports +##tream +apologies +cosmetics +patsy +##deh +##ocks +##yson +bender +nantes +serene +##nad +lucha +mmm +323 +##cius +##gli +cmll +coinage +nestor +juarez +##rook +smeared +sprayed +twitching +sterile +irina +embodied +juveniles +enveloped +miscellaneous +cancers +dq +gulped +luisa +crested +swat +donegal +ref +##anov +##acker +hearst +mercantile +##lika +doorbell +ua +vicki +##alla +##som +bilbao +psychologists +stryker +sw +horsemen +turkmenistan +wits +##national +anson +mathew +screenings +##umb +rihanna +##agne +##nessy +aisles +##iani +##osphere +hines +kenton +saskatoon +tasha +truncated +##champ +##itan +mildred +advises +fredrik +interpreting +inhibitors +##athi +spectroscopy +##hab +##kong +karim +panda +##oia +##nail +##vc +conqueror +kgb +leukemia +##dity +arrivals +cheered +pisa +phosphorus +shielded +##riated +mammal +unitarian +urgently +chopin +sanitary +##mission +spicy +drugged +hinges +##tort +tipping +trier +impoverished +westchester +##caster +267 +epoch +nonstop +##gman +##khov +aromatic +centrally +cerro +##tively +##vio +billions +modulation +sedimentary +283 +facilitating +outrageous +goldstein +##eak +##kt +ld +maitland +penultimate +pollard +##dance +fleets +spaceship +vertebrae +##nig +alcoholism +als +recital +##bham +##ference +##omics +m2 +##bm +trois +##tropical +##в +commemorates +##meric +marge +##raction +1643 +670 +cosmetic +ravaged +##ige +catastrophe +eng +##shida +albrecht +arterial +bellamy +decor +harmon +##rde +bulbs +synchronized +vito +easiest +shetland +shielding +wnba +##glers +##ssar +##riam +brianna +cumbria +##aceous +##rard +cores +thayer +##nsk +brood +hilltop +luminous +carts +keynote +larkin +logos +##cta +##ا +##mund +##quay +lilith +tinted +277 +wrestle +mobilization +##uses +sequential +siam +bloomfield +takahashi +274 +##ieving +presenters +ringo +blazed +witty +##oven +##ignant +devastation +haydn +harmed +newt +therese +##peed +gershwin +molina +rabbis +sudanese +001 +innate +restarted +##sack +##fus +slices +wb +##shah +enroll +hypothetical +hysterical +1743 +fabio +indefinite +warped +##hg +exchanging +525 +unsuitable +##sboro +gallo +1603 +bret +cobalt +homemade +##hunter +mx +operatives +##dhar +terraces +durable +latch +pens +whorls +##ctuated +##eaux +billing +ligament +succumbed +##gly +regulators +spawn +##brick +##stead +filmfare +rochelle +##nzo +1725 +circumstance +saber +supplements +##nsky +##tson +crowe +wellesley +carrot +##9th +##movable +primate +drury +sincerely +topical +##mad +##rao +callahan +kyiv +smarter +tits +undo +##yeh +announcements +anthologies +barrio +nebula +##islaus +##shaft +##tyn +bodyguards +2021 +assassinate +barns +emmett +scully +##mah +##yd +##eland +##tino +##itarian +demoted +gorman +lashed +prized +adventist +writ +##gui +alla +invertebrates +##ausen +1641 +amman +1742 +align +healy +redistribution +##gf +##rize +insulation +##drop +adherents +hezbollah +vitro +ferns +yanking +269 +php +registering +uppsala +cheerleading +confines +mischievous +tully +##ross +49th +docked +roam +stipulated +pumpkin +##bry +prompt +##ezer +blindly +shuddering +craftsmen +frail +scented +katharine +scramble +shaggy +sponge +helix +zaragoza +279 +##52 +43rd +backlash +fontaine +seizures +posse +cowan +nonfiction +telenovela +wwii +hammered +undone +##gpur +encircled +irs +##ivation +artefacts +oneself +searing +smallpox +##belle +##osaurus +shandong +breached +upland +blushing +rankin +infinitely +psyche +tolerated +docking +evicted +##col +unmarked +##lving +gnome +lettering +litres +musique +##oint +benevolent +##jal +blackened +##anna +mccall +racers +tingle +##ocene +##orestation +introductions +radically +292 +##hiff +##باد +1610 +1739 +munchen +plead +##nka +condo +scissors +##sight +##tens +apprehension +##cey +##yin +hallmark +watering +formulas +sequels +##llas +aggravated +bae +commencing +##building +enfield +prohibits +marne +vedic +civilized +euclidean +jagger +beforehand +blasts +dumont +##arney +##nem +740 +conversions +hierarchical +rios +simulator +##dya +##lellan +hedges +oleg +thrusts +shadowed +darby +maximize +1744 +gregorian +##nded +##routed +sham +unspecified +##hog +emory +factual +##smo +##tp +fooled +##rger +ortega +wellness +marlon +##oton +##urance +casket +keating +ley +enclave +##ayan +char +influencing +jia +##chenko +412 +ammonia +erebidae +incompatible +violins +cornered +##arat +grooves +astronauts +columbian +rampant +fabrication +kyushu +mahmud +vanish +##dern +mesopotamia +##lete +ict +##rgen +caspian +kenji +pitted +##vered +999 +grimace +roanoke +tchaikovsky +twinned +##analysis +##awan +xinjiang +arias +clemson +kazakh +sizable +1662 +##khand +##vard +plunge +tatum +vittorio +##nden +cholera +##dana +##oper +bracing +indifference +projectile +superliga +##chee +realises +upgrading +299 +porte +retribution +##vies +nk +stil +##resses +ama +bureaucracy +blackberry +bosch +testosterone +collapses +greer +##pathic +ioc +fifties +malls +##erved +bao +baskets +adolescents +siegfried +##osity +##tosis +mantra +detecting +existent +fledgling +##cchi +dissatisfied +gan +telecommunication +mingled +sobbed +6000 +controversies +outdated +taxis +##raus +fright +slams +##lham +##fect +##tten +detectors +fetal +tanned +##uw +fray +goth +olympian +skipping +mandates +scratches +sheng +unspoken +hyundai +tracey +hotspur +restrictive +##buch +americana +mundo +##bari +burroughs +diva +vulcan +##6th +distinctions +thumping +##ngen +mikey +sheds +fide +rescues +springsteen +vested +valuation +##ece +##ely +pinnacle +rake +sylvie +##edo +almond +quivering +##irus +alteration +faltered +##wad +51st +hydra +ticked +##kato +recommends +##dicated +antigua +arjun +stagecoach +wilfred +trickle +pronouns +##pon +aryan +nighttime +##anian +gall +pea +stitch +##hei +leung +milos +##dini +eritrea +nexus +starved +snowfall +kant +parasitic +cot +discus +hana +strikers +appleton +kitchens +##erina +##partisan +##itha +##vius +disclose +metis +##channel +1701 +tesla +##vera +fitch +1735 +blooded +##tila +decimal +##tang +##bai +cyclones +eun +bottled +peas +pensacola +basha +bolivian +crabs +boil +lanterns +partridge +roofed +1645 +necks +##phila +opined +patting +##kla +##lland +chuckles +volta +whereupon +##nche +devout +euroleague +suicidal +##dee +inherently +involuntary +knitting +nasser +##hide +puppets +colourful +courageous +southend +stills +miraculous +hodgson +richer +rochdale +ethernet +greta +uniting +prism +umm +##haya +##itical +##utation +deterioration +pointe +prowess +##ropriation +lids +scranton +billings +subcontinent +##koff +##scope +brute +kellogg +psalms +degraded +##vez +stanisław +##ructured +ferreira +pun +astonishing +gunnar +##yat +arya +prc +gottfried +##tight +excursion +##ographer +dina +##quil +##nare +huffington +illustrious +wilbur +gundam +verandah +##zard +naacp +##odle +constructive +fjord +kade +##naud +generosity +thrilling +baseline +cayman +frankish +plastics +accommodations +zoological +##fting +cedric +qb +motorized +##dome +##otted +squealed +tackled +canucks +budgets +situ +asthma +dail +gabled +grasslands +whimpered +writhing +judgments +##65 +minnie +pv +##carbon +bananas +grille +domes +monique +odin +maguire +markham +tierney +##estra +##chua +libel +poke +speedy +atrium +laval +notwithstanding +##edly +fai +kala +##sur +robb +##sma +listings +luz +supplementary +tianjin +##acing +enzo +jd +ric +scanner +croats +transcribed +##49 +arden +cv +##hair +##raphy +##lver +##uy +357 +seventies +staggering +alam +horticultural +hs +regression +timbers +blasting +##ounded +montagu +manipulating +##cit +catalytic +1550 +troopers +##meo +condemnation +fitzpatrick +##oire +##roved +inexperienced +1670 +castes +##lative +outing +314 +dubois +flicking +quarrel +ste +learners +1625 +iq +whistled +##class +282 +classify +tariffs +temperament +355 +folly +liszt +##yles +immersed +jordanian +ceasefire +apparel +extras +maru +fished +##bio +harta +stockport +assortment +craftsman +paralysis +transmitters +##cola +blindness +##wk +fatally +proficiency +solemnly +##orno +repairing +amore +groceries +ultraviolet +##chase +schoolhouse +##tua +resurgence +nailed +##otype +##× +ruse +saliva +diagrams +##tructing +albans +rann +thirties +1b +antennas +hilarious +cougars +paddington +stats +##eger +breakaway +ipod +reza +authorship +prohibiting +scoffed +##etz +##ttle +conscription +defected +trondheim +##fires +ivanov +keenan +##adan +##ciful +##fb +##slow +locating +##ials +##tford +cadiz +basalt +blankly +interned +rags +rattling +##tick +carpathian +reassured +sync +bum +guildford +iss +staunch +##onga +astronomers +sera +sofie +emergencies +susquehanna +##heard +duc +mastery +vh1 +williamsburg +bayer +buckled +craving +##khan +##rdes +bloomington +##write +alton +barbecue +##bians +justine +##hri +##ndt +delightful +smartphone +newtown +photon +retrieval +peugeot +hissing +##monium +##orough +flavors +lighted +relaunched +tainted +##games +##lysis +anarchy +microscopic +hopping +adept +evade +evie +##beau +inhibit +sinn +adjustable +hurst +intuition +wilton +cisco +44th +lawful +lowlands +stockings +thierry +##dalen +##hila +##nai +fates +prank +tb +maison +lobbied +provocative +1724 +4a +utopia +##qual +carbonate +gujarati +purcell +##rford +curtiss +##mei +overgrown +arenas +mediation +swallows +##rnik +respectful +turnbull +##hedron +##hope +alyssa +ozone +##ʻi +ami +gestapo +johansson +snooker +canteen +cuff +declines +empathy +stigma +##ags +##iner +##raine +taxpayers +gui +volga +##wright +##copic +lifespan +overcame +tattooed +enactment +giggles +##ador +##camp +barrington +bribe +obligatory +orbiting +peng +##enas +elusive +sucker +##vating +cong +hardship +empowered +anticipating +estrada +cryptic +greasy +detainees +planck +sudbury +plaid +dod +marriott +kayla +##ears +##vb +##zd +mortally +##hein +cognition +radha +319 +liechtenstein +meade +richly +argyle +harpsichord +liberalism +trumpets +lauded +tyrant +salsa +tiled +lear +promoters +reused +slicing +trident +##chuk +##gami +##lka +cantor +checkpoint +##points +gaul +leger +mammalian +##tov +##aar +##schaft +doha +frenchman +nirvana +##vino +delgado +headlining +##eron +##iography +jug +tko +1649 +naga +intersections +##jia +benfica +nawab +##suka +ashford +gulp +##deck +##vill +##rug +brentford +frazier +pleasures +dunne +potsdam +shenzhen +dentistry +##tec +flanagan +##dorff +##hear +chorale +dinah +prem +quezon +##rogated +relinquished +sutra +terri +##pani +flaps +##rissa +poly +##rnet +homme +aback +##eki +linger +womb +##kson +##lewood +doorstep +orthodoxy +threaded +westfield +##rval +dioceses +fridays +subsided +##gata +loyalists +##biotic +##ettes +letterman +lunatic +prelate +tenderly +invariably +souza +thug +winslow +##otide +furlongs +gogh +jeopardy +##runa +pegasus +##umble +humiliated +standalone +tagged +##roller +freshmen +klan +##bright +attaining +initiating +transatlantic +logged +viz +##uance +1723 +combatants +intervening +stephane +chieftain +despised +grazed +317 +cdc +galveston +godzilla +macro +simulate +##planes +parades +##esses +960 +##ductive +##unes +equator +overdose +##cans +##hosh +##lifting +joshi +epstein +sonora +treacherous +aquatics +manchu +responsive +##sation +supervisory +##christ +##llins +##ibar +##balance +##uso +kimball +karlsruhe +mab +##emy +ignores +phonetic +reuters +spaghetti +820 +almighty +danzig +rumbling +tombstone +designations +lured +outset +##felt +supermarkets +##wt +grupo +kei +kraft +susanna +##blood +comprehension +genealogy +##aghan +##verted +redding +##ythe +1722 +bowing +##pore +##roi +lest +sharpened +fulbright +valkyrie +sikhs +##unds +swans +bouquet +merritt +##tage +##venting +commuted +redhead +clerks +leasing +cesare +dea +hazy +##vances +fledged +greenfield +servicemen +##gical +armando +blackout +dt +sagged +downloadable +intra +potion +pods +##4th +##mism +xp +attendants +gambia +stale +##ntine +plump +asteroids +rediscovered +buds +flea +hive +##neas +1737 +classifications +debuts +##eles +olympus +scala +##eurs +##gno +##mute +hummed +sigismund +visuals +wiggled +await +pilasters +clench +sulfate +##ances +bellevue +enigma +trainee +snort +##sw +clouded +denim +##rank +##rder +churning +hartman +lodges +riches +sima +##missible +accountable +socrates +regulates +mueller +##cr +1702 +avoids +solids +himalayas +nutrient +pup +##jevic +squat +fades +nec +##lates +##pina +##rona +##ου +privateer +tequila +##gative +##mpton +apt +hornet +immortals +##dou +asturias +cleansing +dario +##rries +##anta +etymology +servicing +zhejiang +##venor +##nx +horned +erasmus +rayon +relocating +£10 +##bags +escalated +promenade +stubble +2010s +artisans +axial +liquids +mora +sho +yoo +##tsky +bundles +oldies +##nally +notification +bastion +##ths +sparkle +##lved +1728 +leash +pathogen +highs +##hmi +immature +880 +gonzaga +ignatius +mansions +monterrey +sweets +bryson +##loe +polled +regatta +brightest +pei +rosy +squid +hatfield +payroll +addict +meath +cornerback +heaviest +lodging +##mage +capcom +rippled +##sily +barnet +mayhem +ymca +snuggled +rousseau +##cute +blanchard +284 +fragmented +leighton +chromosomes +risking +##md +##strel +##utter +corinne +coyotes +cynical +hiroshi +yeomanry +##ractive +ebook +grading +mandela +plume +agustin +magdalene +##rkin +bea +femme +trafford +##coll +##lun +##tance +52nd +fourier +upton +##mental +camilla +gust +iihf +islamabad +longevity +##kala +feldman +netting +##rization +endeavour +foraging +mfa +orr +##open +greyish +contradiction +graz +##ruff +handicapped +marlene +tweed +oaxaca +spp +campos +miocene +pri +configured +cooks +pluto +cozy +pornographic +##entes +70th +fairness +glided +jonny +lynne +rounding +sired +##emon +##nist +remade +uncover +##mack +complied +lei +newsweek +##jured +##parts +##enting +##pg +293 +finer +guerrillas +athenian +deng +disused +stepmother +accuse +gingerly +seduction +521 +confronting +##walker +##going +gora +nostalgia +sabres +virginity +wrenched +##minated +syndication +wielding +eyre +##56 +##gnon +##igny +behaved +taxpayer +sweeps +##growth +childless +gallant +##ywood +amplified +geraldine +scrape +##ffi +babylonian +fresco +##rdan +##kney +##position +1718 +restricting +tack +fukuoka +osborn +selector +partnering +##dlow +318 +gnu +kia +tak +whitley +gables +##54 +##mania +mri +softness +immersion +##bots +##evsky +1713 +chilling +insignificant +pcs +##uis +elites +lina +purported +supplemental +teaming +##americana +##dding +##inton +proficient +rouen +##nage +##rret +niccolo +selects +##bread +fluffy +1621 +gruff +knotted +mukherjee +polgara +thrash +nicholls +secluded +smoothing +thru +corsica +loaf +whitaker +inquiries +##rrier +##kam +indochina +289 +marlins +myles +peking +##tea +extracts +pastry +superhuman +connacht +vogel +##ditional +##het +##udged +##lash +gloss +quarries +refit +teaser +##alic +##gaon +20s +materialized +sling +camped +pickering +tung +tracker +pursuant +##cide +cranes +soc +##cini +##typical +##viere +anhalt +overboard +workout +chores +fares +orphaned +stains +##logie +fenton +surpassing +joyah +triggers +##itte +grandmaster +##lass +##lists +clapping +fraudulent +ledger +nagasaki +##cor +##nosis +##tsa +eucalyptus +tun +##icio +##rney +##tara +dax +heroism +ina +wrexham +onboard +unsigned +##dates +moshe +galley +winnie +droplets +exiles +praises +watered +noodles +##aia +fein +adi +leland +multicultural +stink +bingo +comets +erskine +modernized +canned +constraint +domestically +chemotherapy +featherweight +stifled +##mum +darkly +irresistible +refreshing +hasty +isolate +##oys +kitchener +planners +##wehr +cages +yarn +implant +toulon +elects +childbirth +yue +##lind +##lone +cn +rightful +sportsman +junctions +remodeled +specifies +##rgh +291 +##oons +complimented +##urgent +lister +ot +##logic +bequeathed +cheekbones +fontana +gabby +##dial +amadeus +corrugated +maverick +resented +triangles +##hered +##usly +nazareth +tyrol +1675 +assent +poorer +sectional +aegean +##cous +296 +nylon +ghanaian +##egorical +##weig +cushions +forbid +fusiliers +obstruction +somerville +##scia +dime +earrings +elliptical +leyte +oder +polymers +timmy +atm +midtown +piloted +settles +continual +externally +mayfield +##uh +enrichment +henson +keane +persians +1733 +benji +braden +pep +324 +##efe +contenders +pepsi +valet +##isches +298 +##asse +##earing +goofy +stroll +##amen +authoritarian +occurrences +adversary +ahmedabad +tangent +toppled +dorchester +1672 +modernism +marxism +islamist +charlemagne +exponential +racks +unicode +brunette +mbc +pic +skirmish +##bund +##lad +##powered +##yst +hoisted +messina +shatter +##ctum +jedi +vantage +##music +##neil +clemens +mahmoud +corrupted +authentication +lowry +nils +##washed +omnibus +wounding +jillian +##itors +##opped +serialized +narcotics +handheld +##arm +##plicity +intersecting +stimulating +##onis +crate +fellowships +hemingway +casinos +climatic +fordham +copeland +drip +beatty +leaflets +robber +brothel +madeira +##hedral +sphinx +ultrasound +##vana +valor +forbade +leonid +villas +##aldo +duane +marquez +##cytes +disadvantaged +forearms +kawasaki +reacts +consular +lax +uncles +uphold +##hopper +concepcion +dorsey +lass +##izan +arching +passageway +1708 +researches +tia +internationals +##graphs +##opers +distinguishes +javanese +divert +##uven +plotted +##listic +##rwin +##erik +##tify +affirmative +signifies +validation +##bson +kari +felicity +georgina +zulu +##eros +##rained +##rath +overcoming +##dot +argyll +##rbin +1734 +chiba +ratification +windy +earls +parapet +##marks +hunan +pristine +astrid +punta +##gart +brodie +##kota +##oder +malaga +minerva +rouse +##phonic +bellowed +pagoda +portals +reclamation +##gur +##odies +##⁄₄ +parentheses +quoting +allergic +palette +showcases +benefactor +heartland +nonlinear +##tness +bladed +cheerfully +scans +##ety +##hone +1666 +girlfriends +pedersen +hiram +sous +##liche +##nator +1683 +##nery +##orio +##umen +bobo +primaries +smiley +##cb +unearthed +uniformly +fis +metadata +1635 +ind +##oted +recoil +##titles +##tura +##ια +406 +hilbert +jamestown +mcmillan +tulane +seychelles +##frid +antics +coli +fated +stucco +##grants +1654 +bulky +accolades +arrays +caledonian +carnage +optimism +puebla +##tative +##cave +enforcing +rotherham +seo +dunlop +aeronautics +chimed +incline +zoning +archduke +hellenistic +##oses +##sions +candi +thong +##ople +magnate +rustic +##rsk +projective +slant +##offs +danes +hollis +vocalists +##ammed +congenital +contend +gesellschaft +##ocating +##pressive +douglass +quieter +##cm +##kshi +howled +salim +spontaneously +townsville +buena +southport +##bold +kato +1638 +faerie +stiffly +##vus +##rled +297 +flawless +realising +taboo +##7th +bytes +straightening +356 +jena +##hid +##rmin +cartwright +berber +bertram +soloists +411 +noses +417 +coping +fission +hardin +inca +##cen +1717 +mobilized +vhf +##raf +biscuits +curate +##85 +##anial +331 +gaunt +neighbourhoods +1540 +##abas +blanca +bypassed +sockets +behold +coincidentally +##bane +nara +shave +splinter +terrific +##arion +##erian +commonplace +juris +redwood +waistband +boxed +caitlin +fingerprints +jennie +naturalized +##ired +balfour +craters +jody +bungalow +hugely +quilt +glitter +pigeons +undertaker +bulging +constrained +goo +##sil +##akh +assimilation +reworked +##person +persuasion +##pants +felicia +##cliff +##ulent +1732 +explodes +##dun +##inium +##zic +lyman +vulture +hog +overlook +begs +northwards +ow +spoil +##urer +fatima +favorably +accumulate +sargent +sorority +corresponded +dispersal +kochi +toned +##imi +##lita +internacional +newfound +##agger +##lynn +##rigue +booths +peanuts +##eborg +medicare +muriel +nur +##uram +crates +millennia +pajamas +worsened +##breakers +jimi +vanuatu +yawned +##udeau +carousel +##hony +hurdle +##ccus +##mounted +##pod +rv +##eche +airship +ambiguity +compulsion +recapture +##claiming +arthritis +##osomal +1667 +asserting +ngc +sniffing +dade +discontent +glendale +ported +##amina +defamation +rammed +##scent +fling +livingstone +##fleet +875 +##ppy +apocalyptic +comrade +lcd +##lowe +cessna +eine +persecuted +subsistence +demi +hoop +reliefs +710 +coptic +progressing +stemmed +perpetrators +1665 +priestess +##nio +dobson +ebony +rooster +itf +tortricidae +##bbon +##jian +cleanup +##jean +##øy +1721 +eighties +taxonomic +holiness +##hearted +##spar +antilles +showcasing +stabilized +##nb +gia +mascara +michelangelo +dawned +##uria +##vinsky +extinguished +fitz +grotesque +£100 +##fera +##loid +##mous +barges +neue +throbbed +cipher +johnnie +##a1 +##mpt +outburst +##swick +spearheaded +administrations +c1 +heartbreak +pixels +pleasantly +##enay +lombardy +plush +##nsed +bobbie +##hly +reapers +tremor +xiang +minogue +substantive +hitch +barak +##wyl +kwan +##encia +910 +obscene +elegance +indus +surfer +bribery +conserve +##hyllum +##masters +horatio +##fat +apes +rebound +psychotic +##pour +iteration +##mium +##vani +botanic +horribly +antiques +dispose +paxton +##hli +##wg +timeless +1704 +disregard +engraver +hounds +##bau +##version +looted +uno +facilitates +groans +masjid +rutland +antibody +disqualification +decatur +footballers +quake +slacks +48th +rein +scribe +stabilize +commits +exemplary +tho +##hort +##chison +pantry +traversed +##hiti +disrepair +identifiable +vibrated +baccalaureate +##nnis +csa +interviewing +##iensis +##raße +greaves +wealthiest +343 +classed +jogged +£5 +##58 +##atal +illuminating +knicks +respecting +##uno +scrubbed +##iji +##dles +kruger +moods +growls +raider +silvia +chefs +kam +vr +cree +percival +##terol +gunter +counterattack +defiant +henan +ze +##rasia +##riety +equivalence +submissions +##fra +##thor +bautista +mechanically +##heater +cornice +herbal +templar +##mering +outputs +ruining +ligand +renumbered +extravagant +mika +blockbuster +eta +insurrection +##ilia +darkening +ferocious +pianos +strife +kinship +##aer +melee +##anor +##iste +##may +##oue +decidedly +weep +##jad +##missive +##ppel +354 +puget +unease +##gnant +1629 +hammering +kassel +ob +wessex +##lga +bromwich +egan +paranoia +utilization +##atable +##idad +contradictory +provoke +##ols +##ouring +##tangled +knesset +##very +##lette +plumbing +##sden +##¹ +greensboro +occult +sniff +338 +zev +beaming +gamer +haggard +mahal +##olt +##pins +mendes +utmost +briefing +gunnery +##gut +##pher +##zh +##rok +1679 +khalifa +sonya +##boot +principals +urbana +wiring +##liffe +##minating +##rrado +dahl +nyu +skepticism +np +townspeople +ithaca +lobster +somethin +##fur +##arina +##−1 +freighter +zimmerman +biceps +contractual +##herton +amend +hurrying +subconscious +##anal +336 +meng +clermont +spawning +##eia +##lub +dignitaries +impetus +snacks +spotting +twigs +##bilis +##cz +##ouk +libertadores +nic +skylar +##aina +##firm +gustave +asean +##anum +dieter +legislatures +flirt +bromley +trolls +umar +##bbies +##tyle +blah +parc +bridgeport +crank +negligence +##nction +46th +constantin +molded +bandages +seriousness +00pm +siegel +carpets +compartments +upbeat +statehood +##dner +##edging +marko +730 +platt +##hane +paving +##iy +1738 +abbess +impatience +limousine +nbl +##talk +441 +lucille +mojo +nightfall +robbers +##nais +karel +brisk +calves +replicate +ascribed +telescopes +##olf +intimidated +##reen +ballast +specialization +##sit +aerodynamic +caliphate +rainer +visionary +##arded +epsilon +##aday +##onte +aggregation +auditory +boosted +reunification +kathmandu +loco +robyn +402 +acknowledges +appointing +humanoid +newell +redeveloped +restraints +##tained +barbarians +chopper +1609 +italiana +##lez +##lho +investigates +wrestlemania +##anies +##bib +690 +##falls +creaked +dragoons +gravely +minions +stupidity +volley +##harat +##week +musik +##eries +##uously +fungal +massimo +semantics +malvern +##ahl +##pee +discourage +embryo +imperialism +1910s +profoundly +##ddled +jiangsu +sparkled +stat +##holz +sweatshirt +tobin +##iction +sneered +##cheon +##oit +brit +causal +smyth +##neuve +diffuse +perrin +silvio +##ipes +##recht +detonated +iqbal +selma +##nism +##zumi +roasted +##riders +tay +##ados +##mament +##mut +##rud +840 +completes +nipples +cfa +flavour +hirsch +##laus +calderon +sneakers +moravian +##ksha +1622 +rq +294 +##imeters +bodo +##isance +##pre +##ronia +anatomical +excerpt +##lke +dh +kunst +##tablished +##scoe +biomass +panted +unharmed +gael +housemates +montpellier +##59 +coa +rodents +tonic +hickory +singleton +##taro +451 +1719 +aldo +breaststroke +dempsey +och +rocco +##cuit +merton +dissemination +midsummer +serials +##idi +haji +polynomials +##rdon +gs +enoch +prematurely +shutter +taunton +£3 +##grating +##inates +archangel +harassed +##asco +326 +archway +dazzling +##ecin +1736 +sumo +wat +##kovich +1086 +honneur +##ently +##nostic +##ttal +##idon +1605 +403 +1716 +blogger +rents +##gnan +hires +##ikh +##dant +howie +##rons +handler +retracted +shocks +1632 +arun +duluth +kepler +trumpeter +##lary +peeking +seasoned +trooper +##mara +laszlo +##iciencies +##rti +heterosexual +##inatory +##ssion +indira +jogging +##inga +##lism +beit +dissatisfaction +malice +##ately +nedra +peeling +##rgeon +47th +stadiums +475 +vertigo +##ains +iced +restroom +##plify +##tub +illustrating +pear +##chner +##sibility +inorganic +rappers +receipts +watery +##kura +lucinda +##oulos +reintroduced +##8th +##tched +gracefully +saxons +nutritional +wastewater +rained +favourites +bedrock +fisted +hallways +likeness +upscale +##lateral +1580 +blinds +prequel +##pps +##tama +deter +humiliating +restraining +tn +vents +1659 +laundering +recess +rosary +tractors +coulter +federer +##ifiers +##plin +persistence +##quitable +geschichte +pendulum +quakers +##beam +bassett +pictorial +buffet +koln +##sitor +drills +reciprocal +shooters +##57 +##cton +##tees +converge +pip +dmitri +donnelly +yamamoto +aqua +azores +demographics +hypnotic +spitfire +suspend +wryly +roderick +##rran +sebastien +##asurable +mavericks +##fles +##200 +himalayan +prodigy +##iance +transvaal +demonstrators +handcuffs +dodged +mcnamara +sublime +1726 +crazed +##efined +##till +ivo +pondered +reconciled +shrill +sava +##duk +bal +cad +heresy +jaipur +goran +##nished +341 +lux +shelly +whitehall +##hre +israelis +peacekeeping +##wled +1703 +demetrius +ousted +##arians +##zos +beale +anwar +backstroke +raged +shrinking +cremated +##yck +benign +towing +wadi +darmstadt +landfill +parana +soothe +colleen +sidewalks +mayfair +tumble +hepatitis +ferrer +superstructure +##gingly +##urse +##wee +anthropological +translators +##mies +closeness +hooves +##pw +mondays +##roll +##vita +landscaping +##urized +purification +sock +thorns +thwarted +jalan +tiberius +##taka +saline +##rito +confidently +khyber +sculptors +##ij +brahms +hammersmith +inspectors +battista +fivb +fragmentation +hackney +##uls +arresting +exercising +antoinette +bedfordshire +##zily +dyed +##hema +1656 +racetrack +variability +##tique +1655 +austrians +deteriorating +madman +theorists +aix +lehman +weathered +1731 +decreed +eruptions +1729 +flaw +quinlan +sorbonne +flutes +nunez +1711 +adored +downwards +fable +rasped +1712 +moritz +mouthful +renegade +shivers +stunts +dysfunction +restrain +translit +327 +pancakes +##avio +##cision +##tray +351 +vial +##lden +bain +##maid +##oxide +chihuahua +malacca +vimes +##rba +##rnier +1664 +donnie +plaques +##ually +337 +bangs +floppy +huntsville +loretta +nikolay +##otte +eater +handgun +ubiquitous +##hett +eras +zodiac +1634 +##omorphic +1820s +##zog +cochran +##bula +##lithic +warring +##rada +dalai +excused +blazers +mcconnell +reeling +bot +este +##abi +geese +hoax +taxon +##bla +guitarists +##icon +condemning +hunts +inversion +moffat +taekwondo +##lvis +1624 +stammered +##rest +##rzy +sousa +fundraiser +marylebone +navigable +uptown +cabbage +daniela +salman +shitty +whimper +##kian +##utive +programmers +protections +rm +##rmi +##rued +forceful +##enes +fuss +##tao +##wash +brat +oppressive +reykjavik +spartak +ticking +##inkles +##kiewicz +adolph +horst +maui +protege +straighten +cpc +landau +concourse +clements +resultant +##ando +imaginative +joo +reactivated +##rem +##ffled +##uising +consultative +##guide +flop +kaitlyn +mergers +parenting +somber +##vron +supervise +vidhan +##imum +courtship +exemplified +harmonies +medallist +refining +##rrow +##ка +amara +##hum +780 +goalscorer +sited +overshadowed +rohan +displeasure +secretive +multiplied +osman +##orth +engravings +padre +##kali +##veda +miniatures +mis +##yala +clap +pali +rook +##cana +1692 +57th +antennae +astro +oskar +1628 +bulldog +crotch +hackett +yucatan +##sure +amplifiers +brno +ferrara +migrating +##gree +thanking +turing +##eza +mccann +ting +andersson +onslaught +gaines +ganga +incense +standardization +##mation +sentai +scuba +stuffing +turquoise +waivers +alloys +##vitt +regaining +vaults +##clops +##gizing +digger +furry +memorabilia +probing +##iad +payton +rec +deutschland +filippo +opaque +seamen +zenith +afrikaans +##filtration +disciplined +inspirational +##merie +banco +confuse +grafton +tod +##dgets +championed +simi +anomaly +biplane +##ceptive +electrode +##para +1697 +cleavage +crossbow +swirl +informant +##lars +##osta +afi +bonfire +spec +##oux +lakeside +slump +##culus +##lais +##qvist +##rrigan +1016 +facades +borg +inwardly +cervical +xl +pointedly +050 +stabilization +##odon +chests +1699 +hacked +ctv +orthogonal +suzy +##lastic +gaulle +jacobite +rearview +##cam +##erted +ashby +##drik +##igate +##mise +##zbek +affectionately +canine +disperse +latham +##istles +##ivar +spielberg +##orin +##idium +ezekiel +cid +##sg +durga +middletown +##cina +customized +frontiers +harden +##etano +##zzy +1604 +bolsheviks +##66 +coloration +yoko +##bedo +briefs +slabs +debra +liquidation +plumage +##oin +blossoms +dementia +subsidy +1611 +proctor +relational +jerseys +parochial +ter +##ici +esa +peshawar +cavalier +loren +cpi +idiots +shamrock +1646 +dutton +malabar +mustache +##endez +##ocytes +referencing +terminates +marche +yarmouth +##sop +acton +mated +seton +subtly +baptised +beige +extremes +jolted +kristina +telecast +##actic +safeguard +waldo +##baldi +##bular +endeavors +sloppy +subterranean +##ensburg +##itung +delicately +pigment +tq +##scu +1626 +##ound +collisions +coveted +herds +##personal +##meister +##nberger +chopra +##ricting +abnormalities +defective +galician +lucie +##dilly +alligator +likened +##genase +burundi +clears +complexion +derelict +deafening +diablo +fingered +champaign +dogg +enlist +isotope +labeling +mrna +##erre +brilliance +marvelous +##ayo +1652 +crawley +ether +footed +dwellers +deserts +hamish +rubs +warlock +skimmed +##lizer +870 +buick +embark +heraldic +irregularities +##ajan +kiara +##kulam +##ieg +antigen +kowalski +##lge +oakley +visitation +##mbit +vt +##suit +1570 +murderers +##miento +##rites +chimneys +##sling +condemn +custer +exchequer +havre +##ghi +fluctuations +##rations +dfb +hendricks +vaccines +##tarian +nietzsche +biking +juicy +##duced +brooding +scrolling +selangor +##ragan +352 +annum +boomed +seminole +sugarcane +##dna +departmental +dismissing +innsbruck +arteries +ashok +batavia +daze +kun +overtook +##rga +##tlan +beheaded +gaddafi +holm +electronically +faulty +galilee +fractures +kobayashi +##lized +gunmen +magma +aramaic +mala +eastenders +inference +messengers +bf +##qu +407 +bathrooms +##vere +1658 +flashbacks +ideally +misunderstood +##jali +##weather +mendez +##grounds +505 +uncanny +##iii +1709 +friendships +##nbc +sacrament +accommodated +reiterated +logistical +pebbles +thumped +##escence +administering +decrees +drafts +##flight +##cased +##tula +futuristic +picket +intimidation +winthrop +##fahan +interfered +339 +afar +francoise +morally +uta +cochin +croft +dwarfs +##bruck +##dents +##nami +biker +##hner +##meral +nano +##isen +##ometric +##pres +##ан +brightened +meek +parcels +securely +gunners +##jhl +##zko +agile +hysteria +##lten +##rcus +bukit +champs +chevy +cuckoo +leith +sadler +theologians +welded +##section +1663 +jj +plurality +xander +##rooms +##formed +shredded +temps +intimately +pau +tormented +##lok +##stellar +1618 +charred +ems +essen +##mmel +alarms +spraying +ascot +blooms +twinkle +##abia +##apes +internment +obsidian +##chaft +snoop +##dav +##ooping +malibu +##tension +quiver +##itia +hays +mcintosh +travers +walsall +##ffie +1623 +beverley +schwarz +plunging +structurally +m3 +rosenthal +vikram +##tsk +770 +ghz +##onda +##tiv +chalmers +groningen +pew +reckon +unicef +##rvis +55th +##gni +1651 +sulawesi +avila +cai +metaphysical +screwing +turbulence +##mberg +augusto +samba +56th +baffled +momentary +toxin +##urian +##wani +aachen +condoms +dali +steppe +##3d +##app +##oed +##year +adolescence +dauphin +electrically +inaccessible +microscopy +nikita +##ega +atv +##cel +##enter +##oles +##oteric +##ы +accountants +punishments +wrongly +bribes +adventurous +clinch +flinders +southland +##hem +##kata +gough +##ciency +lads +soared +##ה +undergoes +deformation +outlawed +rubbish +##arus +##mussen +##nidae +##rzburg +arcs +##ingdon +##tituted +1695 +wheelbase +wheeling +bombardier +campground +zebra +##lices +##oj +##bain +lullaby +##ecure +donetsk +wylie +grenada +##arding +##ης +squinting +eireann +opposes +##andra +maximal +runes +##broken +##cuting +##iface +##ror +##rosis +additive +britney +adultery +triggering +##drome +detrimental +aarhus +containment +jc +swapped +vichy +##ioms +madly +##oric +##rag +brant +##ckey +##trix +1560 +1612 +broughton +rustling +##stems +##uder +asbestos +mentoring +##nivorous +finley +leaps +##isan +apical +pry +slits +substitutes +##dict +intuitive +fantasia +insistent +unreasonable +##igen +##vna +domed +hannover +margot +ponder +##zziness +impromptu +jian +lc +rampage +stemming +##eft +andrey +gerais +whichever +amnesia +appropriated +anzac +clicks +modifying +ultimatum +cambrian +maids +verve +yellowstone +##mbs +conservatoire +##scribe +adherence +dinners +spectra +imperfect +mysteriously +sidekick +tatar +tuba +##aks +##ifolia +distrust +##athan +##zle +c2 +ronin +zac +##pse +celaena +instrumentalist +scents +skopje +##mbling +comical +compensated +vidal +condor +intersect +jingle +wavelengths +##urrent +mcqueen +##izzly +carp +weasel +422 +kanye +militias +postdoctoral +eugen +gunslinger +##ɛ +faux +hospice +##for +appalled +derivation +dwarves +##elis +dilapidated +##folk +astoria +philology +##lwyn +##otho +##saka +inducing +philanthropy +##bf +##itative +geek +markedly +sql +##yce +bessie +indices +rn +##flict +495 +frowns +resolving +weightlifting +tugs +cleric +contentious +1653 +mania +rms +##miya +##reate +##ruck +##tucket +bien +eels +marek +##ayton +##cence +discreet +unofficially +##ife +leaks +##bber +1705 +332 +dung +compressor +hillsborough +pandit +shillings +distal +##skin +381 +##tat +##you +nosed +##nir +mangrove +undeveloped +##idia +textures +##inho +##500 +##rise +ae +irritating +nay +amazingly +bancroft +apologetic +compassionate +kata +symphonies +##lovic +airspace +##lch +930 +gifford +precautions +fulfillment +sevilla +vulgar +martinique +##urities +looting +piccolo +tidy +##dermott +quadrant +armchair +incomes +mathematicians +stampede +nilsson +##inking +##scan +foo +quarterfinal +##ostal +shang +shouldered +squirrels +##owe +344 +vinegar +##bner +##rchy +##systems +delaying +##trics +ars +dwyer +rhapsody +sponsoring +##gration +bipolar +cinder +starters +##olio +##urst +421 +signage +##nty +aground +figurative +mons +acquaintances +duets +erroneously +soyuz +elliptic +recreated +##cultural +##quette +##ssed +##tma +##zcz +moderator +scares +##itaire +##stones +##udence +juniper +sighting +##just +##nsen +britten +calabria +ry +bop +cramer +forsyth +stillness +##л +airmen +gathers +unfit +##umber +##upt +taunting +##rip +seeker +streamlined +##bution +holster +schumann +tread +vox +##gano +##onzo +strive +dil +reforming +covent +newbury +predicting +##orro +decorate +tre +##puted +andover +ie +asahi +dept +dunkirk +gills +##tori +buren +huskies +##stis +##stov +abstracts +bets +loosen +##opa +1682 +yearning +##glio +##sir +berman +effortlessly +enamel +napoli +persist +##peration +##uez +attache +elisa +b1 +invitations +##kic +accelerating +reindeer +boardwalk +clutches +nelly +polka +starbucks +##kei +adamant +huey +lough +unbroken +adventurer +embroidery +inspecting +stanza +##ducted +naia +taluka +##pone +##roids +chases +deprivation +florian +##jing +##ppet +earthly +##lib +##ssee +colossal +foreigner +vet +freaks +patrice +rosewood +triassic +upstate +##pkins +dominates +ata +chants +ks +vo +##400 +##bley +##raya +##rmed +555 +agra +infiltrate +##ailing +##ilation +##tzer +##uppe +##werk +binoculars +enthusiast +fujian +squeak +##avs +abolitionist +almeida +boredom +hampstead +marsden +rations +##ands +inflated +334 +bonuses +rosalie +patna +##rco +329 +detachments +penitentiary +54th +flourishing +woolf +##dion +##etched +papyrus +##lster +##nsor +##toy +bobbed +dismounted +endelle +inhuman +motorola +tbs +wince +wreath +##ticus +hideout +inspections +sanjay +disgrace +infused +pudding +stalks +##urbed +arsenic +leases +##hyl +##rrard +collarbone +##waite +##wil +dowry +##bant +##edance +genealogical +nitrate +salamanca +scandals +thyroid +necessitated +##! +##" +### +##$ +##% +##& +##' +##( +##) +##* +##+ +##, +##- +##. +##/ +##: +##; +##< +##= +##> +##? +##@ +##[ +##\ +##] +##^ +##_ +##` +##{ +##| +##} +##~ +##¡ +##¢ +##£ +##¤ +##¥ +##¦ +##§ +##¨ +##© +##ª +##« +##¬ +##® +##± +##´ +##µ +##¶ +##· +##º +##» +##¼ +##¾ +##¿ +##æ +##ð +##÷ +##þ +##đ +##ħ +##ŋ +##œ +##ƒ +##ɐ +##ɑ +##ɒ +##ɔ +##ɕ +##ə +##ɡ +##ɣ +##ɨ +##ɪ +##ɫ +##ɬ +##ɯ +##ɲ +##ɴ +##ɹ +##ɾ +##ʀ +##ʁ +##ʂ +##ʃ +##ʉ +##ʊ +##ʋ +##ʌ +##ʎ +##ʐ +##ʑ +##ʒ +##ʔ +##ʰ +##ʲ +##ʳ +##ʷ +##ʸ +##ʻ +##ʼ +##ʾ +##ʿ +##ˈ +##ˡ +##ˢ +##ˣ +##ˤ +##β +##γ +##δ +##ε +##ζ +##θ +##κ +##λ +##μ +##ξ +##ο +##π +##ρ +##σ +##τ +##υ +##φ +##χ +##ψ +##ω +##б +##г +##д +##ж +##з +##м +##п +##с +##у +##ф +##х +##ц +##ч +##ш +##щ +##ъ +##э +##ю +##ђ +##є +##і +##ј +##љ +##њ +##ћ +##ӏ +##ա +##բ +##գ +##դ +##ե +##թ +##ի +##լ +##կ +##հ +##մ +##յ +##ն +##ո +##պ +##ս +##վ +##տ +##ր +##ւ +##ք +##־ +##א +##ב +##ג +##ד +##ו +##ז +##ח +##ט +##י +##ך +##כ +##ל +##ם +##מ +##ן +##נ +##ס +##ע +##ף +##פ +##ץ +##צ +##ק +##ר +##ש +##ת +##، +##ء +##ب +##ت +##ث +##ج +##ح +##خ +##ذ +##ز +##س +##ش +##ص +##ض +##ط +##ظ +##ع +##غ +##ـ +##ف +##ق +##ك +##و +##ى +##ٹ +##پ +##چ +##ک +##گ +##ں +##ھ +##ہ +##ے +##अ +##आ +##उ +##ए +##क +##ख +##ग +##च +##ज +##ट +##ड +##ण +##त +##थ +##द +##ध +##न +##प +##ब +##भ +##म +##य +##र +##ल +##व +##श +##ष +##स +##ह +##ा +##ि +##ी +##ो +##। +##॥ +##ং +##অ +##আ +##ই +##উ +##এ +##ও +##ক +##খ +##গ +##চ +##ছ +##জ +##ট +##ড +##ণ +##ত +##থ +##দ +##ধ +##ন +##প +##ব +##ভ +##ম +##য +##র +##ল +##শ +##ষ +##স +##হ +##া +##ি +##ী +##ে +##க +##ச +##ட +##த +##ந +##ன +##ப +##ம +##ய +##ர +##ல +##ள +##வ +##ா +##ி +##ு +##ே +##ை +##ನ +##ರ +##ಾ +##ක +##ය +##ර +##ල +##ව +##ා +##ก +##ง +##ต +##ท +##น +##พ +##ม +##ย +##ร +##ล +##ว +##ส +##อ +##า +##เ +##་ +##། +##ག +##ང +##ད +##ན +##པ +##བ +##མ +##འ +##ར +##ལ +##ས +##မ +##ა +##ბ +##გ +##დ +##ე +##ვ +##თ +##ი +##კ +##ლ +##მ +##ნ +##ო +##რ +##ს +##ტ +##უ +##ᄀ +##ᄂ +##ᄃ +##ᄅ +##ᄆ +##ᄇ +##ᄉ +##ᄊ +##ᄋ +##ᄌ +##ᄎ +##ᄏ +##ᄐ +##ᄑ +##ᄒ +##ᅡ +##ᅢ +##ᅥ +##ᅦ +##ᅧ +##ᅩ +##ᅪ +##ᅭ +##ᅮ +##ᅯ +##ᅲ +##ᅳ +##ᅴ +##ᅵ +##ᆨ +##ᆫ +##ᆯ +##ᆷ +##ᆸ +##ᆼ +##ᴬ +##ᴮ +##ᴰ +##ᴵ +##ᴺ +##ᵀ +##ᵃ +##ᵇ +##ᵈ +##ᵉ +##ᵍ +##ᵏ +##ᵐ +##ᵒ +##ᵖ +##ᵗ +##ᵘ +##ᵣ +##ᵤ +##ᵥ +##ᶜ +##ᶠ +##‐ +##‑ +##‒ +##– +##— +##― +##‖ +##‘ +##’ +##‚ +##“ +##” +##„ +##† +##‡ +##• +##… +##‰ +##′ +##″ +##› +##‿ +##⁄ +##⁰ +##ⁱ +##⁴ +##⁵ +##⁶ +##⁷ +##⁸ +##⁹ +##⁻ +##ⁿ +##₅ +##₆ +##₇ +##₈ +##₉ +##₊ +##₍ +##₎ +##ₐ +##ₑ +##ₒ +##ₓ +##ₕ +##ₖ +##ₗ +##ₘ +##ₚ +##ₛ +##ₜ +##₤ +##₩ +##€ +##₱ +##₹ +##ℓ +##№ +##ℝ +##™ +##⅓ +##⅔ +##← +##↑ +##→ +##↓ +##↔ +##↦ +##⇄ +##⇌ +##⇒ +##∂ +##∅ +##∆ +##∇ +##∈ +##∗ +##∘ +##√ +##∞ +##∧ +##∨ +##∩ +##∪ +##≈ +##≡ +##≤ +##≥ +##⊂ +##⊆ +##⊕ +##⊗ +##⋅ +##─ +##│ +##■ +##▪ +##● +##★ +##☆ +##☉ +##♠ +##♣ +##♥ +##♦ +##♯ +##⟨ +##⟩ +##ⱼ +##⺩ +##⺼ +##⽥ +##、 +##。 +##〈 +##〉 +##《 +##》 +##「 +##」 +##『 +##』 +##〜 +##あ +##い +##う +##え +##お +##か +##き +##く +##け +##こ +##さ +##し +##す +##せ +##そ +##た +##ち +##っ +##つ +##て +##と +##な +##に +##ぬ +##ね +##の +##は +##ひ +##ふ +##へ +##ほ +##ま +##み +##む +##め +##も +##や +##ゆ +##よ +##ら +##り +##る +##れ +##ろ +##を +##ん +##ァ +##ア +##ィ +##イ +##ウ +##ェ +##エ +##オ +##カ +##キ +##ク +##ケ +##コ +##サ +##シ +##ス +##セ +##タ +##チ +##ッ +##ツ +##テ +##ト +##ナ +##ニ +##ノ +##ハ +##ヒ +##フ +##ヘ +##ホ +##マ +##ミ +##ム +##メ +##モ +##ャ +##ュ +##ョ +##ラ +##リ +##ル +##レ +##ロ +##ワ +##ン +##・ +##ー +##一 +##三 +##上 +##下 +##不 +##世 +##中 +##主 +##久 +##之 +##也 +##事 +##二 +##五 +##井 +##京 +##人 +##亻 +##仁 +##介 +##代 +##仮 +##伊 +##会 +##佐 +##侍 +##保 +##信 +##健 +##元 +##光 +##八 +##公 +##内 +##出 +##分 +##前 +##劉 +##力 +##加 +##勝 +##北 +##区 +##十 +##千 +##南 +##博 +##原 +##口 +##古 +##史 +##司 +##合 +##吉 +##同 +##名 +##和 +##囗 +##四 +##国 +##國 +##土 +##地 +##坂 +##城 +##堂 +##場 +##士 +##夏 +##外 +##大 +##天 +##太 +##夫 +##奈 +##女 +##子 +##学 +##宀 +##宇 +##安 +##宗 +##定 +##宣 +##宮 +##家 +##宿 +##寺 +##將 +##小 +##尚 +##山 +##岡 +##島 +##崎 +##川 +##州 +##巿 +##帝 +##平 +##年 +##幸 +##广 +##弘 +##張 +##彳 +##後 +##御 +##德 +##心 +##忄 +##志 +##忠 +##愛 +##成 +##我 +##戦 +##戸 +##手 +##扌 +##政 +##文 +##新 +##方 +##日 +##明 +##星 +##春 +##昭 +##智 +##曲 +##書 +##月 +##有 +##朝 +##木 +##本 +##李 +##村 +##東 +##松 +##林 +##森 +##楊 +##樹 +##橋 +##歌 +##止 +##正 +##武 +##比 +##氏 +##民 +##水 +##氵 +##氷 +##永 +##江 +##沢 +##河 +##治 +##法 +##海 +##清 +##漢 +##瀬 +##火 +##版 +##犬 +##王 +##生 +##田 +##男 +##疒 +##発 +##白 +##的 +##皇 +##目 +##相 +##省 +##真 +##石 +##示 +##社 +##神 +##福 +##禾 +##秀 +##秋 +##空 +##立 +##章 +##竹 +##糹 +##美 +##義 +##耳 +##良 +##艹 +##花 +##英 +##華 +##葉 +##藤 +##行 +##街 +##西 +##見 +##訁 +##語 +##谷 +##貝 +##貴 +##車 +##軍 +##辶 +##道 +##郎 +##郡 +##部 +##都 +##里 +##野 +##金 +##鈴 +##镇 +##長 +##門 +##間 +##阝 +##阿 +##陳 +##陽 +##雄 +##青 +##面 +##風 +##食 +##香 +##馬 +##高 +##龍 +##龸 +##fi +##fl +##! +##( +##) +##, +##- +##. +##/ +##: +##? +##~ diff --git a/model_cache/roberta/text_toxicity.onnx b/model_cache/roberta/text_toxicity.onnx new file mode 100644 index 0000000000000000000000000000000000000000..d1119952f6c295e2c9bae1fd1cee6870bb9caa6f --- /dev/null +++ b/model_cache/roberta/text_toxicity.onnx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8174995615e7064a4c45d39e7dbc56a6072d714002c54b01bad25c6541f23500 +size 1476910 diff --git a/model_cache/roberta/text_toxicity.onnx.data b/model_cache/roberta/text_toxicity.onnx.data new file mode 100644 index 0000000000000000000000000000000000000000..a2516a35f4871c37a2a4bd06aa438ec36beab9ac --- /dev/null +++ b/model_cache/roberta/text_toxicity.onnx.data @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:685da57ad776065b677fa046595f12697a352e0e320b93882d5d3e522eb9402d +size 437958656 diff --git a/readme copy.md b/readme copy.md new file mode 100644 index 0000000000000000000000000000000000000000..e7b0be07ee8dc4ec260b934472875656e4f973db --- /dev/null +++ b/readme copy.md @@ -0,0 +1,219 @@ +--- +title: Hubble AI Engine +emoji: 🔍 +colorFrom: blue +colorTo: indigo +sdk: docker +app_port: 7860 +pinned: false +--- + +# Hubble AI Engine — Cyberbullying Detection Pipeline + +A production-grade, layered AI content moderation system for detecting cyberbullying across **text**, **image**, and **video** inputs. Designed as a universal safety tool for social media platforms. + +--- + +## 🏗️ Architecture Overview + +``` +User Input (text/image/video) + → Preprocessing (normalization, frame extraction) + → Fast AI Filter (RoBERTa text, EfficientNet image) — ONNX optimized + → Risk Scoring Engine (0-100 composite score) + → LangGraph Router + ├─ LOW (0-30) → Allow ✅ + ├─ MEDIUM (31-65) → Warning ⚠️ + └─ HIGH (66-100) → Deep Analysis 🔴 + ├─ CLIP multimodal alignment + ├─ Gemini reasoning (via LangChain) + └─ Final verdict + → Decision Engine (severity + user history + rules) + → Response + Logging +``` + +### Key Components + +| Layer | Technology | Purpose | +|-------|-----------|---------| +| **Fast Filter** | RoBERTa (ONNX), EfficientNet (ONNX) | Sub-200ms first-pass classification | +| **Risk Scoring** | Custom weighted engine | Composite score with category weights + user history | +| **Routing** | LangGraph state machine | Conditional deep analysis for HIGH-risk content only | +| **Deep Analysis** | CLIP + Gemini (LangChain) | Multimodal alignment + LLM contextual reasoning | +| **Decision Engine** | Rule-based system | ALLOWED / WARNING / BLOCKED with escalation logic | +| **Observability** | LangSmith + structlog | Full pipeline tracing and structured logging | +| **Storage** | MongoDB (motor) + Redis | Moderation logs, user history, result caching | + +--- + +## 📁 Project Structure + +``` +Ai/ +├── app/ +│ ├── main.py # FastAPI app factory + lifespan +│ ├── config.py # Pydantic Settings (.env) +│ ├── dependencies.py # FastAPI dependency injection +│ ├── api/ # API layer +│ │ ├── router.py # Route aggregator +│ │ ├── v1/ +│ │ │ ├── analyze.py # POST /analyze/text, /image, /video +│ │ │ ├── health.py # GET /health +│ │ │ └── history.py # GET /history/{user_id} +│ │ └── schemas/ +│ │ ├── requests.py # Request models +│ │ └── responses.py # Response models +│ ├── pipeline/ # Core moderation pipeline +│ │ ├── preprocessor.py # Input normalization +│ │ ├── fast_filter.py # RoBERTa + EfficientNet inference +│ │ ├── risk_scorer.py # Composite risk scoring +│ │ ├── deep_analyzer.py # CLIP + Gemini deep analysis +│ │ ├── decision_engine.py # Rule-based verdicts +│ │ └── workflow.py # LangGraph state machine +│ ├── models/ # ML model management +│ │ ├── model_registry.py # Singleton model loader +│ │ ├── text_model.py # RoBERTa (ONNX) +│ │ ├── image_model.py # EfficientNet (ONNX) +│ │ ├── clip_model.py # OpenCLIP +│ │ └── onnx_utils.py # ONNX export/inference +│ ├── services/ # External integrations +│ │ ├── gemini_service.py # Gemini via LangChain +│ │ ├── mongo_service.py # MongoDB (async) +│ │ └── redis_service.py # Redis (async) +│ ├── observability/ # Monitoring +│ │ ├── langsmith.py # LangSmith tracing +│ │ └── logging.py # structlog config +│ └── utils/ # Helpers +│ ├── image_utils.py # Image preprocessing +│ └── video_utils.py # Video frame extraction +├── tests/ # Test suite +├── model_cache/ # Downloaded models (gitignored) +├── _legacy/ # Old code (preserved for reference) +├── .env.example # Environment template +├── requirements.txt # Python dependencies +└── README.md # This file +``` + +--- + +## 🚀 Quick Start + +### 1. Setup Python Environment + +```bash +cd Ai +python -m venv venv +venv\Scripts\activate # Windows +# source venv/bin/activate # macOS/Linux +pip install -r requirements.txt +``` + +### 2. Configure Environment + +```bash +cp .env.example .env +# Edit .env with your API keys and database URIs +``` + +### 3. Start Services (MongoDB + Redis) + +```bash +# Using Docker +docker run -d -p 27017:27017 --name hubble-mongo mongo:7 +docker run -d -p 6379:6379 --name hubble-redis redis:7-alpine +``` + +### 4. Run the Server + +```bash +cd Ai +python -m app.main +# Or: uvicorn app.main:app --reload --port 8000 +``` + +### 5. Test the API + +```bash +# Health check +curl http://localhost:8000/health + +# Analyze text +curl -X POST http://localhost:8000/api/v1/analyze/text \ + -H "Content-Type: application/json" \ + -d '{"text": "You are worthless", "user_id": "user123"}' + +# Analyze image +curl -X POST http://localhost:8000/api/v1/analyze/image \ + -F "file=@test.jpg" -F "user_id=user123" +``` + +--- + +## 📡 API Endpoints + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `GET` | `/health` | Health check with model/service status | +| `GET` | `/health/ping` | Lightweight liveness probe | +| `POST` | `/api/v1/analyze/text` | Analyze text for cyberbullying | +| `POST` | `/api/v1/analyze/image` | Analyze image for harmful content | +| `POST` | `/api/v1/analyze/video` | Analyze video (frame extraction) | +| `GET` | `/api/v1/history/{user_id}` | Get moderation history | +| `GET` | `/api/v1/history/{user_id}/summary` | Get aggregated user stats | + +### Response Schema + +All `/analyze/*` endpoints return a unified `AnalysisResponse`: + +```json +{ + "request_id": "req_abc123", + "input_type": "text", + "status": "WARNING", + "risk_level": "MEDIUM", + "risk_score": 45.2, + "categories": ["insult", "toxic"], + "confidence": 0.82, + "decision": { + "action": "WARNING", + "reason": "Content flagged as potentially harmful", + "severity": "medium", + "should_alert_parent": false + }, + "processing_time_ms": 156, + "cached": false +} +``` + +--- + +## 🧪 Running Tests + +```bash +cd Ai +python -m pytest tests/ -v +``` + +--- + +## 📊 Models Used + +| Model | Purpose | Size | Backend | +|-------|---------|------|---------| +| `unitary/toxic-bert` | Text toxicity (6 labels) | ~450 MB | ONNX | +| `google/efficientnet-b0` | Image classification | ~20 MB | ONNX | +| `openai/clip-vit-base-patch32` | Multimodal alignment | ~600 MB | PyTorch | +| `gemini-2.0-flash` | Deep contextual reasoning | Cloud API | LangChain | + +--- + +## 🔒 Security Notes + +- API keys loaded from `.env` only (never hardcoded) +- CORS restricted in production mode +- User data isolated by `user_id` +- All moderation events logged for audit + +--- + +Built for the **National Hackathon — SentinelAI Project** \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..2ec5fe0a25d25daba7fed05d45457e1d5cfd7269 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,48 @@ +# ============================================ +# Hubble Unified API — Python Dependencies +# ============================================ + +# --- Core Framework --- +fastapi>=0.110.0 +uvicorn[standard]>=0.27.0 +python-multipart>=0.0.9 +pydantic>=2.5.0 +pydantic-settings>=2.1.0 + +# --- Auth --- +argon2-cffi>=23.1.0 +python-jose[cryptography]>=3.3.0 +email-validator>=2.1.0 + +# --- Machine Learning --- +# torch and torchvision are installed separately in Dockerfile via CPU-only wheel +# torch>=2.1.0 +# torchvision>=0.16.0 +transformers>=4.38.0 +onnxruntime>=1.17.0 + +# --- CLIP (multimodal alignment) --- +open-clip-torch>=2.24.0 + +# --- LangChain + LangGraph --- +langchain>=0.1.0 +langchain-google-genai>=1.0.0 +langgraph>=0.0.30 + +# --- Observability --- +langsmith>=0.1.0 +structlog>=24.1.0 + +# --- Storage (async) --- +motor>=3.3.0 +beanie>=1.25.0 +redis>=5.0.0 + +# --- Media Processing --- +Pillow>=10.0.0 +opencv-python-headless>=4.9.0 +numpy>=1.26.0 + +# --- Utilities --- +python-dotenv>=1.0.0 +httpx>=0.27.0 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..ab187669e9cd6eed2173bb9b54e49c63f94c089c --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,2 @@ +# tests/__init__.py +"""Hubble AI Engine tests.""" diff --git a/tests/test_pipeline.py b/tests/test_pipeline.py new file mode 100644 index 0000000000000000000000000000000000000000..ee75301436ee5265b427898383ee3d76bbb55fe2 --- /dev/null +++ b/tests/test_pipeline.py @@ -0,0 +1,161 @@ +# tests/test_pipeline.py +# Integration tests for the moderation pipeline + +import pytest +from unittest.mock import MagicMock, AsyncMock, patch + +from app.pipeline.preprocessor import Preprocessor, ProcessedText +from app.pipeline.fast_filter import FastFilter, FilterResult +from app.pipeline.risk_scorer import RiskScorer, RiskScore +from app.pipeline.decision_engine import DecisionEngine, Decision +from app.pipeline.deep_analyzer import DeepAnalysisResult + + +class TestPreprocessor: + """Tests for the Preprocessor module.""" + + def setup_method(self): + self.preprocessor = Preprocessor() + + def test_process_text_basic(self): + result = self.preprocessor.process_text("Hello, this is a test message") + assert isinstance(result, ProcessedText) + assert result.cleaned == "Hello, this is a test message" + assert result.word_count == 6 + + def test_process_text_whitespace_normalization(self): + result = self.preprocessor.process_text("Hello \t world \n test") + assert result.cleaned == "Hello world test" + assert result.word_count == 3 + + def test_process_text_zero_width_removal(self): + result = self.preprocessor.process_text("He\u200bllo\u200cWo\u200drld") + assert "\u200b" not in result.cleaned + assert "\u200c" not in result.cleaned + + def test_process_text_empty_after_clean(self): + result = self.preprocessor.process_text(" ") + assert result.cleaned == "" + assert result.word_count == 1 # split("") still gives [''] + + +class TestRiskScorer: + """Tests for the RiskScorer module.""" + + def setup_method(self): + self.scorer = RiskScorer() + + def test_low_risk_unflagged(self): + result = FilterResult( + input_type="text", + is_flagged=False, + scores={"toxic": 0.1, "insult": 0.05}, + max_score=0.1, + max_label="toxic", + categories=[], + confidence=0.1, + ) + score = self.scorer.score(result) + assert score.level == "LOW" + assert score.score < 30 + + def test_high_risk_flagged(self): + result = FilterResult( + input_type="text", + is_flagged=True, + scores={"severe_toxic": 0.95, "threat": 0.9, "insult": 0.8}, + max_score=0.95, + max_label="severe_toxic", + categories=["severe_toxic", "threat", "insult"], + confidence=0.95, + ) + score = self.scorer.score(result) + assert score.level == "HIGH" + assert score.score > 65 + + def test_repeat_offender_boost(self): + result = FilterResult( + input_type="text", + is_flagged=True, + scores={"toxic": 0.6}, + max_score=0.6, + max_label="toxic", + categories=["toxic"], + confidence=0.6, + ) + history = {"total_violations": 5} + score = self.scorer.score(result, history) + assert score.repeat_offender is True + assert score.components["repeat_offender_boost"] > 0 + + def test_no_user_history(self): + result = FilterResult( + input_type="text", + is_flagged=False, + scores={}, + max_score=0.05, + max_label="safe", + categories=[], + confidence=0.05, + ) + score = self.scorer.score(result, None) + assert score.repeat_offender is False + + +class TestDecisionEngine: + """Tests for the DecisionEngine module.""" + + def setup_method(self): + self.engine = DecisionEngine() + + def test_low_risk_allowed(self): + risk = RiskScore(score=10.0, level="LOW", components={}) + decision = self.engine.decide(risk) + assert decision.action == "ALLOWED" + assert decision.should_alert_parent is False + + def test_medium_risk_warning(self): + risk = RiskScore(score=45.0, level="MEDIUM", components={}) + decision = self.engine.decide(risk) + assert decision.action == "WARNING" + assert decision.should_alert_parent is False + + def test_high_risk_confirmed_blocked(self): + risk = RiskScore(score=80.0, level="HIGH", components={}) + deep = DeepAnalysisResult( + is_confirmed=True, + severity="high", + reasoning="Explicit threat detected", + recommended_action="block", + confidence=0.9, + ) + decision = self.engine.decide(risk, deep) + assert decision.action == "BLOCKED" + assert decision.should_alert_parent is True + + def test_high_risk_not_confirmed_warning(self): + risk = RiskScore(score=70.0, level="HIGH", components={}) + deep = DeepAnalysisResult( + is_confirmed=False, + severity="low", + reasoning="Content is sarcastic, not a real threat", + recommended_action="allow", + confidence=0.85, + ) + decision = self.engine.decide(risk, deep) + assert decision.action == "WARNING" + assert decision.severity == "low" + + def test_repeat_offender_medium_escalated(self): + risk = RiskScore( + score=50.0, level="MEDIUM", components={}, repeat_offender=True + ) + decision = self.engine.decide(risk) + assert decision.action == "BLOCKED" + assert decision.should_alert_parent is True + + def test_high_risk_no_deep_analysis_caution(self): + risk = RiskScore(score=75.0, level="HIGH", components={}) + decision = self.engine.decide(risk, deep_result=None) + assert decision.action == "BLOCKED" + assert "unavailable" in decision.reason.lower() or "Manual" in decision.escalation_notes