Reformatting with ruff
This commit is contained in:
parent
f53ff967cb
commit
f1c2e16389
@ -1,5 +1,5 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import BaseModel, Field, model_validator # type: ignore
|
||||
from pydantic import BaseModel, Field # type: ignore
|
||||
from typing import (
|
||||
Literal,
|
||||
get_args,
|
||||
@ -13,10 +13,10 @@ import time
|
||||
import re
|
||||
from abc import ABC
|
||||
from datetime import datetime, UTC
|
||||
from prometheus_client import Counter, Summary, CollectorRegistry # type: ignore
|
||||
from prometheus_client import CollectorRegistry # type: ignore
|
||||
import numpy as np # type: ignore
|
||||
import json_extractor as json_extractor
|
||||
from pydantic import BaseModel, Field, model_validator # type: ignore
|
||||
from pydantic import BaseModel, Field # type: ignore
|
||||
from uuid import uuid4
|
||||
from typing import List, Optional, ClassVar, Any, Literal
|
||||
|
||||
@ -24,7 +24,7 @@ from datetime import datetime, UTC
|
||||
import numpy as np # type: ignore
|
||||
|
||||
from uuid import uuid4
|
||||
from prometheus_client import CollectorRegistry, Counter # type: ignore
|
||||
from prometheus_client import CollectorRegistry # type: ignore
|
||||
import os
|
||||
import re
|
||||
from pathlib import Path
|
||||
@ -509,7 +509,6 @@ Content: {content}
|
||||
return
|
||||
|
||||
results : List[ChromaDBGetResponse] = []
|
||||
entries: int = 0
|
||||
user: CandidateEntity = self.user
|
||||
for rag in user.rags:
|
||||
if not rag.enabled:
|
||||
@ -594,7 +593,7 @@ Content: {content}
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=session_id,
|
||||
activity=ApiActivityType.GENERATING,
|
||||
content=f"Generating response..."
|
||||
content="Generating response..."
|
||||
)
|
||||
yield status_message
|
||||
|
||||
@ -675,7 +674,6 @@ Content: {content}
|
||||
session_id=session_id,
|
||||
content=prompt,
|
||||
)
|
||||
user = self.user
|
||||
|
||||
self.user.metrics.generate_count.labels(agent=self.agent_type).inc()
|
||||
with self.user.metrics.generate_duration.labels(agent=self.agent_type).time():
|
||||
@ -723,7 +721,6 @@ Content: {content}
|
||||
LLMMessage(role="user", content=prompt)
|
||||
)
|
||||
|
||||
llm_history = messages
|
||||
|
||||
# use_tools = message.tunables.enable_tools and len(self.context.tools) > 0
|
||||
# message.metadata.tools = {
|
||||
@ -829,7 +826,7 @@ Content: {content}
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=session_id,
|
||||
activity=ApiActivityType.GENERATING,
|
||||
content=f"Generating response..."
|
||||
content="Generating response..."
|
||||
)
|
||||
yield status_message
|
||||
|
||||
|
@ -8,7 +8,7 @@ from .registry import agent_registry
|
||||
from models import ( ApiMessage, Tunables, ApiStatusType)
|
||||
|
||||
|
||||
system_message = f"""
|
||||
system_message = """
|
||||
When answering queries, follow these steps:
|
||||
|
||||
- When any content from <|context|> is relevant, synthesize information from all sources to provide the most complete answer.
|
||||
|
@ -1,12 +1,9 @@
|
||||
from __future__ import annotations
|
||||
from typing import (
|
||||
Dict,
|
||||
Literal,
|
||||
ClassVar,
|
||||
cast,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
List,
|
||||
Optional
|
||||
# override
|
||||
) # NOTE: You must import Optional for late binding to work
|
||||
|
@ -1,10 +1,9 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import model_validator, Field, BaseModel # type: ignore
|
||||
from pydantic import Field # type: ignore
|
||||
from typing import (
|
||||
Dict,
|
||||
Literal,
|
||||
ClassVar,
|
||||
cast,
|
||||
Any,
|
||||
Tuple,
|
||||
AsyncGenerator,
|
||||
@ -19,7 +18,6 @@ import time
|
||||
import time
|
||||
import os
|
||||
import random
|
||||
from names_dataset import NameDataset, NameWrapper # type: ignore
|
||||
|
||||
from .base import Agent, agent_registry
|
||||
from models import ApiActivityType, ChatMessage, ChatMessageError, ApiMessageType, ChatMessageStatus, ChatMessageStreaming, ApiStatusType, Tunables
|
||||
@ -339,7 +337,7 @@ Incorporate the following into the job description: {original_prompt}
|
||||
#
|
||||
# Generate the persona
|
||||
#
|
||||
logger.info(f"🤖 Generating persona...")
|
||||
logger.info("🤖 Generating persona...")
|
||||
generating_message = None
|
||||
async for generating_message in self.llm_one_shot(
|
||||
llm=llm, model=model,
|
||||
|
@ -1,17 +1,13 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import model_validator, Field # type: ignore
|
||||
from typing import (
|
||||
Dict,
|
||||
Literal,
|
||||
ClassVar,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
List,
|
||||
Optional
|
||||
List
|
||||
# override
|
||||
) # NOTE: You must import Optional for late binding to work
|
||||
import json
|
||||
import numpy as np # type: ignore
|
||||
|
||||
from logger import logger
|
||||
from .base import Agent, agent_registry
|
||||
@ -172,7 +168,7 @@ Format it in clean, ATS-friendly markdown. Provide ONLY the resume with no comme
|
||||
# Stage 1A: Analyze job requirements
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=session_id,
|
||||
content = f"Analyzing job requirements",
|
||||
content = "Analyzing job requirements",
|
||||
activity=ApiActivityType.THINKING
|
||||
)
|
||||
yield status_message
|
||||
@ -215,7 +211,7 @@ Format it in clean, ATS-friendly markdown. Provide ONLY the resume with no comme
|
||||
system_prompt=system_prompt,
|
||||
)
|
||||
yield resume_message
|
||||
logger.info(f"✅ Resume generation completed successfully.")
|
||||
logger.info("✅ Resume generation completed successfully.")
|
||||
return
|
||||
|
||||
# Register the base agent
|
||||
|
@ -1,18 +1,15 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import model_validator, Field # type: ignore
|
||||
from typing import (
|
||||
Dict,
|
||||
Literal,
|
||||
ClassVar,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
List,
|
||||
Optional
|
||||
# override
|
||||
) # NOTE: You must import Optional for late binding to work
|
||||
import inspect
|
||||
import json
|
||||
import numpy as np # type: ignore
|
||||
|
||||
from .base import Agent, agent_registry
|
||||
from models import ApiActivityType, ApiMessage, ChatMessage, ChatMessageError, ChatMessageStatus, ChatMessageStreaming, ApiStatusType, Job, JobRequirements, JobRequirementsMessage, Tunables
|
||||
@ -163,7 +160,7 @@ Avoid vague categorizations and be precise about whether skills are explicitly r
|
||||
# Stage 1A: Analyze job requirements
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=session_id,
|
||||
content = f"Analyzing job requirements",
|
||||
content = "Analyzing job requirements",
|
||||
activity=ApiActivityType.THINKING
|
||||
)
|
||||
yield status_message
|
||||
@ -238,7 +235,7 @@ Avoid vague categorizations and be precise about whether skills are explicitly r
|
||||
job=job,
|
||||
)
|
||||
yield job_requirements_message
|
||||
logger.info(f"✅ Job requirements analysis completed successfully.")
|
||||
logger.info("✅ Job requirements analysis completed successfully.")
|
||||
return
|
||||
|
||||
# Register the base agent
|
||||
|
@ -1,17 +1,13 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import model_validator, Field # type: ignore
|
||||
from typing import (
|
||||
Dict,
|
||||
Literal,
|
||||
ClassVar,
|
||||
Any,
|
||||
AsyncGenerator,
|
||||
List,
|
||||
Optional
|
||||
# override
|
||||
) # NOTE: You must import Optional for late binding to work
|
||||
import json
|
||||
import numpy as np # type: ignore
|
||||
|
||||
from .base import Agent, agent_registry
|
||||
from models import (ApiMessage, ChatMessage, ChatMessageError, ChatMessageRagSearch, ChatMessageSkillAssessment, ApiStatusType, EvidenceDetail,
|
||||
@ -233,7 +229,7 @@ JSON RESPONSE:"""
|
||||
skill_assessment=skill_assessment,
|
||||
)
|
||||
yield skill_assessment_message
|
||||
logger.info(f"✅ Skill assessment completed successfully.")
|
||||
logger.info("✅ Skill assessment completed successfully.")
|
||||
return
|
||||
|
||||
# Register the base agent
|
||||
|
@ -5,10 +5,6 @@ import logging
|
||||
import os
|
||||
from datetime import datetime, UTC
|
||||
import asyncio
|
||||
from models import (
|
||||
# User models
|
||||
Candidate, Employer, BaseUser, EvidenceDetail, Guest, Authentication, AuthResponse, SkillAssessment,
|
||||
)
|
||||
from .core import RedisDatabase
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -374,7 +374,7 @@ class AuthMixin(DatabaseProtocol):
|
||||
token_data["is_revoked"] = True
|
||||
token_data["revoked_at"] = datetime.now(timezone.utc).isoformat()
|
||||
await self.redis.set(key, json.dumps(token_data, default=str))
|
||||
logger.info(f"🔐 Revoked refresh token")
|
||||
logger.info("🔐 Revoked refresh token")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
@ -457,7 +457,7 @@ class AuthMixin(DatabaseProtocol):
|
||||
token_data["used"] = True
|
||||
token_data["used_at"] = datetime.now(timezone.utc).isoformat()
|
||||
await self.redis.set(key, json.dumps(token_data, default=str))
|
||||
logger.info(f"🔐 Marked password reset token as used")
|
||||
logger.info("🔐 Marked password reset token as used")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
|
@ -13,7 +13,6 @@ class DeviceManager:
|
||||
def generate_device_fingerprint(self, request: Request) -> str:
|
||||
"""Generate device fingerprint from request"""
|
||||
user_agent = request.headers.get("user-agent", "")
|
||||
ip_address = request.client.host if request.client else "unknown"
|
||||
accept_language = request.headers.get("accept-language", "")
|
||||
|
||||
# Create fingerprint
|
||||
|
@ -3,7 +3,7 @@ import weakref
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, Optional
|
||||
from contextlib import asynccontextmanager
|
||||
from pydantic import BaseModel, Field # type: ignore
|
||||
from pydantic import BaseModel # type: ignore
|
||||
|
||||
from models import Candidate
|
||||
from agents.base import CandidateEntity
|
||||
|
@ -23,17 +23,18 @@ def test_model_creation():
|
||||
# Create candidate
|
||||
candidate = Candidate(
|
||||
email="test@example.com",
|
||||
user_type=UserType.CANDIDATE,
|
||||
username="test_candidate",
|
||||
createdAt=datetime.now(),
|
||||
updatedAt=datetime.now(),
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now(),
|
||||
status=UserStatus.ACTIVE,
|
||||
firstName="John",
|
||||
lastName="Doe",
|
||||
fullName="John Doe",
|
||||
first_name="John",
|
||||
last_name="Doe",
|
||||
full_name="John Doe",
|
||||
skills=[skill],
|
||||
experience=[],
|
||||
education=[],
|
||||
preferredJobTypes=[EmploymentType.FULL_TIME],
|
||||
preferred_job_types=[EmploymentType.FULL_TIME],
|
||||
location=location,
|
||||
languages=[],
|
||||
certifications=[]
|
||||
@ -41,18 +42,18 @@ def test_model_creation():
|
||||
|
||||
# Create employer
|
||||
employer = Employer(
|
||||
firstName="Mary",
|
||||
lastName="Smith",
|
||||
fullName="Mary Smith",
|
||||
user_type=UserType.EMPLOYER,
|
||||
first_name="Mary",
|
||||
last_name="Smith",
|
||||
full_name="Mary Smith",
|
||||
email="hr@company.com",
|
||||
username="test_employer",
|
||||
createdAt=datetime.now(),
|
||||
updatedAt=datetime.now(),
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now(),
|
||||
status=UserStatus.ACTIVE,
|
||||
companyName="Test Company",
|
||||
company_name="Test Company",
|
||||
industry="Technology",
|
||||
companySize="50-200",
|
||||
companyDescription="A test company",
|
||||
company_size="50-200",
|
||||
company_description="A test company",
|
||||
location=location
|
||||
)
|
||||
|
||||
@ -84,8 +85,8 @@ def test_json_api_format():
|
||||
assert candidate_back.first_name == candidate.first_name
|
||||
assert employer_back.company_name == employer.company_name
|
||||
|
||||
print(f"✅ JSON round-trip successful")
|
||||
print(f"✅ Data integrity verified")
|
||||
print("✅ JSON round-trip successful")
|
||||
print("✅ Data integrity verified")
|
||||
|
||||
return True
|
||||
|
||||
@ -105,8 +106,8 @@ def test_api_dict_format():
|
||||
assert "createdAt" in candidate_dict
|
||||
assert "companyName" in employer_dict
|
||||
|
||||
print(f"✅ API format dictionaries created")
|
||||
print(f"✅ CamelCase aliases verified")
|
||||
print("✅ API format dictionaries created")
|
||||
print("✅ CamelCase aliases verified")
|
||||
|
||||
# Test deserializing from API format
|
||||
candidate_back = Candidate.model_validate(candidate_dict)
|
||||
@ -115,7 +116,7 @@ def test_api_dict_format():
|
||||
assert candidate_back.email == candidate.email
|
||||
assert employer_back.company_name == employer.company_name
|
||||
|
||||
print(f"✅ API format round-trip successful")
|
||||
print("✅ API format round-trip successful")
|
||||
|
||||
return True
|
||||
|
||||
@ -125,15 +126,16 @@ def test_validation_constraints():
|
||||
|
||||
try:
|
||||
# Create a candidate with invalid email
|
||||
invalid_candidate = Candidate(
|
||||
Candidate(
|
||||
user_type=UserType.CANDIDATE,
|
||||
email="invalid-email",
|
||||
username="test_invalid",
|
||||
createdAt=datetime.now(),
|
||||
updatedAt=datetime.now(),
|
||||
created_at=datetime.now(),
|
||||
updated_at=datetime.now(),
|
||||
status=UserStatus.ACTIVE,
|
||||
firstName="Jane",
|
||||
lastName="Doe",
|
||||
fullName="Jane Doe"
|
||||
first_name="Jane",
|
||||
last_name="Doe",
|
||||
full_name="Jane Doe"
|
||||
)
|
||||
print("❌ Validation should have failed but didn't")
|
||||
return False
|
||||
@ -155,7 +157,7 @@ def test_enum_values():
|
||||
assert candidate_dict["userType"] == "candidate"
|
||||
assert employer.user_type == UserType.EMPLOYER
|
||||
|
||||
print(f"✅ Enum values correctly serialized")
|
||||
print("✅ Enum values correctly serialized")
|
||||
print(f"✅ User types: candidate={candidate.user_type}, employer={employer.user_type}")
|
||||
|
||||
return True
|
||||
@ -172,7 +174,7 @@ def main():
|
||||
test_validation_constraints()
|
||||
test_enum_values()
|
||||
|
||||
print(f"\n🎉 All focused tests passed!")
|
||||
print("\n🎉 All focused tests passed!")
|
||||
print("=" * 40)
|
||||
print("✅ Models work correctly")
|
||||
print("✅ JSON API format works")
|
||||
|
@ -48,7 +48,7 @@ def flux_worker(pipe: Any, params: ImageRequest, status_queue: queue.Queue, task
|
||||
# Flux: Run generation in the background and yield progress updates
|
||||
status_queue.put(ChatMessageStatus(
|
||||
session_id=params.session_id,
|
||||
content=f"Initializing image generation.",
|
||||
content="Initializing image generation.",
|
||||
activity=ApiActivityType.GENERATING_IMAGE,
|
||||
))
|
||||
|
||||
@ -224,7 +224,7 @@ async def generate_image(request: ImageRequest) -> AsyncGenerator[ChatMessage, N
|
||||
return
|
||||
|
||||
filedir = os.path.dirname(request.filepath)
|
||||
filename = os.path.basename(request.filepath)
|
||||
os.path.basename(request.filepath)
|
||||
os.makedirs(filedir, exist_ok=True)
|
||||
|
||||
model_type = "flux"
|
||||
@ -233,11 +233,11 @@ async def generate_image(request: ImageRequest) -> AsyncGenerator[ChatMessage, N
|
||||
# Get initial time estimate, scaled by resolution
|
||||
estimates = TIME_ESTIMATES[model_type][device]
|
||||
resolution_scale = (request.height * request.width) / (512 * 512)
|
||||
estimated_total = estimates["load"] + estimates["per_step"] * request.iterations * resolution_scale
|
||||
estimates["load"] + estimates["per_step"] * request.iterations * resolution_scale
|
||||
|
||||
# Initialize or get cached pipeline
|
||||
start_time = time.time()
|
||||
yield status(session_id, f"Loading generative image model...")
|
||||
yield status(session_id, "Loading generative image model...")
|
||||
pipe = await model_cache.get_pipeline(request.model, device)
|
||||
load_time = time.time() - start_time
|
||||
yield status(session_id, f"Model loaded in {load_time:.1f} seconds.",)
|
||||
|
@ -289,7 +289,7 @@ class MFAData(BaseModel):
|
||||
|
||||
class MFARequestResponse(BaseModel):
|
||||
mfa_required: bool = Field(..., alias=str("mfaRequired"))
|
||||
mfa_data: Optional[MFAData] = Field(None, alias=str("mfaData"))
|
||||
mfa_data: Optional[MFAData] = Field(default=None, alias=str("mfaData"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class ResendVerificationRequest(BaseModel):
|
||||
@ -312,11 +312,11 @@ class Location(BaseModel):
|
||||
city: str
|
||||
state: Optional[str] = None
|
||||
country: str
|
||||
postal_code: Optional[str] = Field(None, alias=str("postalCode"))
|
||||
postal_code: Optional[str] = Field(default=None, alias=str("postalCode"))
|
||||
latitude: Optional[float] = None
|
||||
longitude: Optional[float] = None
|
||||
remote: Optional[bool] = None
|
||||
hybrid_options: Optional[List[str]] = Field(None, alias=str("hybridOptions"))
|
||||
hybrid_options: Optional[List[str]] = Field(default=None, alias=str("hybridOptions"))
|
||||
address: Optional[str] = None
|
||||
|
||||
class Skill(BaseModel):
|
||||
@ -324,14 +324,14 @@ class Skill(BaseModel):
|
||||
name: str
|
||||
category: str
|
||||
level: SkillLevel
|
||||
years_of_experience: Optional[int] = Field(None, alias=str("yearsOfExperience"))
|
||||
years_of_experience: Optional[int] = Field(default=None, alias=str("yearsOfExperience"))
|
||||
|
||||
class WorkExperience(BaseModel):
|
||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||
company_name: str = Field(..., alias=str("companyName"))
|
||||
position: str
|
||||
start_date: datetime = Field(..., alias=str("startDate"))
|
||||
end_date: Optional[datetime] = Field(None, alias=str("endDate"))
|
||||
end_date: Optional[datetime] = Field(default=None, alias=str("endDate"))
|
||||
is_current: bool = Field(..., alias=str("isCurrent"))
|
||||
description: str
|
||||
skills: List[str]
|
||||
@ -344,7 +344,7 @@ class Education(BaseModel):
|
||||
degree: str
|
||||
field_of_study: str = Field(..., alias=str("fieldOfStudy"))
|
||||
start_date: datetime = Field(..., alias=str("startDate"))
|
||||
end_date: Optional[datetime] = Field(None, alias=str("endDate"))
|
||||
end_date: Optional[datetime] = Field(default=None, alias=str("endDate"))
|
||||
is_current: bool = Field(..., alias=str("isCurrent"))
|
||||
gpa: Optional[float] = None
|
||||
achievements: Optional[List[str]] = None
|
||||
@ -359,9 +359,9 @@ class Certification(BaseModel):
|
||||
name: str
|
||||
issuing_organization: str = Field(..., alias=str("issuingOrganization"))
|
||||
issue_date: datetime = Field(..., alias=str("issueDate"))
|
||||
expiration_date: Optional[datetime] = Field(None, alias=str("expirationDate"))
|
||||
credential_id: Optional[str] = Field(None, alias=str("credentialId"))
|
||||
credential_url: Optional[HttpUrl] = Field(None, alias=str("credentialUrl"))
|
||||
expiration_date: Optional[datetime] = Field(default=None, alias=str("expirationDate"))
|
||||
credential_id: Optional[str] = Field(default=None, alias=str("credentialId"))
|
||||
credential_url: Optional[HttpUrl] = Field(default=None, alias=str("credentialUrl"))
|
||||
|
||||
class SocialLink(BaseModel):
|
||||
platform: SocialPlatform
|
||||
@ -391,7 +391,7 @@ class RefreshToken(BaseModel):
|
||||
device: str
|
||||
ip_address: str = Field(..., alias=str("ipAddress"))
|
||||
is_revoked: bool = Field(..., alias=str("isRevoked"))
|
||||
revoked_reason: Optional[str] = Field(None, alias=str("revokedReason"))
|
||||
revoked_reason: Optional[str] = Field(default=None, alias=str("revokedReason"))
|
||||
|
||||
class Attachment(BaseModel):
|
||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||
@ -401,8 +401,8 @@ class Attachment(BaseModel):
|
||||
file_url: str = Field(..., alias=str("fileUrl"))
|
||||
uploaded_at: datetime = Field(..., alias=str("uploadedAt"))
|
||||
is_processed: bool = Field(..., alias=str("isProcessed"))
|
||||
processing_result: Optional[Any] = Field(None, alias=str("processingResult"))
|
||||
thumbnail_url: Optional[str] = Field(None, alias=str("thumbnailUrl"))
|
||||
processing_result: Optional[Any] = Field(default=None, alias=str("processingResult"))
|
||||
thumbnail_url: Optional[str] = Field(default=None, alias=str("thumbnailUrl"))
|
||||
|
||||
class MessageReaction(BaseModel):
|
||||
user_id: str = Field(..., alias=str("userId"))
|
||||
@ -438,22 +438,22 @@ class AccessibilitySettings(BaseModel):
|
||||
high_contrast: bool = Field(..., alias=str("highContrast"))
|
||||
reduce_motion: bool = Field(..., alias=str("reduceMotion"))
|
||||
screen_reader: bool = Field(..., alias=str("screenReader"))
|
||||
color_blind_mode: Optional[ColorBlindMode] = Field(None, alias=str("colorBlindMode"))
|
||||
color_blind_mode: Optional[ColorBlindMode] = Field(default=None, alias=str("colorBlindMode"))
|
||||
|
||||
class ProcessingStep(BaseModel):
|
||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||
type: ProcessingStepType
|
||||
parameters: Dict[str, Any]
|
||||
order: int
|
||||
depends_on: Optional[List[str]] = Field(None, alias=str("dependsOn"))
|
||||
depends_on: Optional[List[str]] = Field(default=None, alias=str("dependsOn"))
|
||||
|
||||
class RetrievalParameters(BaseModel):
|
||||
search_type: SearchType = Field(..., alias=str("searchType"))
|
||||
top_k: int = Field(..., alias=str("topK"))
|
||||
similarity_threshold: Optional[float] = Field(None, alias=str("similarityThreshold"))
|
||||
reranker_model: Optional[str] = Field(None, alias=str("rerankerModel"))
|
||||
similarity_threshold: Optional[float] = Field(default=None, alias=str("similarityThreshold"))
|
||||
reranker_model: Optional[str] = Field(default=None, alias=str("rerankerModel"))
|
||||
use_keyword_boost: bool = Field(..., alias=str("useKeywordBoost"))
|
||||
filter_options: Optional[Dict[str, Any]] = Field(None, alias=str("filterOptions"))
|
||||
filter_options: Optional[Dict[str, Any]] = Field(default=None, alias=str("filterOptions"))
|
||||
context_window: int = Field(..., alias=str("contextWindow"))
|
||||
|
||||
class ErrorDetail(BaseModel):
|
||||
@ -482,8 +482,8 @@ class BaseUser(BaseUserWithType):
|
||||
location: Optional[Location] = None
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("createdAt"))
|
||||
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("updatedAt"))
|
||||
last_login: Optional[datetime] = Field(None, alias=str("lastLogin"))
|
||||
profile_image: Optional[str] = Field(None, alias=str("profileImage"))
|
||||
last_login: Optional[datetime] = Field(default=None, alias=str("lastLogin"))
|
||||
profile_image: Optional[str] = Field(default=None, alias=str("profileImage"))
|
||||
status: UserStatus
|
||||
is_admin: bool = Field(default=False, alias=str("isAdmin"))
|
||||
|
||||
@ -500,8 +500,8 @@ class RagContentMetadata(BaseModel):
|
||||
line_begin: int = Field(..., alias=str("lineBegin"))
|
||||
line_end: int = Field(..., alias=str("lineEnd"))
|
||||
lines: int
|
||||
chunk_begin: Optional[int] = Field(None, alias=str("chunkBegin"))
|
||||
chunk_end: Optional[int] = Field(None, alias=str("chunkEnd"))
|
||||
chunk_begin: Optional[int] = Field(default=None, alias=str("chunkBegin"))
|
||||
chunk_end: Optional[int] = Field(default=None, alias=str("chunkEnd"))
|
||||
metadata: Dict[str, Any] = Field(default_factory=dict)
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -566,13 +566,13 @@ class Candidate(BaseUser):
|
||||
experience: Optional[List[WorkExperience]] = None
|
||||
questions: Optional[List[CandidateQuestion]] = None
|
||||
education: Optional[List[Education]] = None
|
||||
preferred_job_types: Optional[List[EmploymentType]] = Field(None, alias=str("preferredJobTypes"))
|
||||
desired_salary: Optional[DesiredSalary] = Field(None, alias=str("desiredSalary"))
|
||||
availability_date: Optional[datetime] = Field(None, alias=str("availabilityDate"))
|
||||
preferred_job_types: Optional[List[EmploymentType]] = Field(default=None, alias=str("preferredJobTypes"))
|
||||
desired_salary: Optional[DesiredSalary] = Field(default=None, alias=str("desiredSalary"))
|
||||
availability_date: Optional[datetime] = Field(default=None, alias=str("availabilityDate"))
|
||||
summary: Optional[str] = None
|
||||
languages: Optional[List[Language]] = None
|
||||
certifications: Optional[List[Certification]] = None
|
||||
job_applications: Optional[List["JobApplication"]] = Field(None, alias=str("jobApplications"))
|
||||
job_applications: Optional[List["JobApplication"]] = Field(default=None, alias=str("jobApplications"))
|
||||
rags: List[RagEntry] = Field(default_factory=list)
|
||||
rag_content_size : int = 0
|
||||
is_public: bool = Field(default=True, alias=str("isPublic"))
|
||||
@ -591,20 +591,20 @@ class Employer(BaseUser):
|
||||
description: Optional[str] = None
|
||||
company_size: str = Field(..., alias=str("companySize"))
|
||||
company_description: str = Field(..., alias=str("companyDescription"))
|
||||
website_url: Optional[HttpUrl] = Field(None, alias=str("websiteUrl"))
|
||||
website_url: Optional[HttpUrl] = Field(default=None, alias=str("websiteUrl"))
|
||||
jobs: Optional[List["Job"]] = None
|
||||
company_logo: Optional[str] = Field(None, alias=str("companyLogo"))
|
||||
social_links: Optional[List[SocialLink]] = Field(None, alias=str("socialLinks"))
|
||||
company_logo: Optional[str] = Field(default=None, alias=str("companyLogo"))
|
||||
social_links: Optional[List[SocialLink]] = Field(default=None, alias=str("socialLinks"))
|
||||
poc: Optional[PointOfContact] = None
|
||||
|
||||
class Guest(BaseUser):
|
||||
user_type: UserType = Field(UserType.GUEST, alias=str("userType"))
|
||||
session_id: str = Field(..., alias=str("sessionId"))
|
||||
username: str # Add username for consistency with other user types
|
||||
converted_to_user_id: Optional[str] = Field(None, alias=str("convertedToUserId"))
|
||||
ip_address: Optional[str] = Field(None, alias=str("ipAddress"))
|
||||
converted_to_user_id: Optional[str] = Field(default=None, alias=str("convertedToUserId"))
|
||||
ip_address: Optional[str] = Field(default=None, alias=str("ipAddress"))
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("createdAt"))
|
||||
user_agent: Optional[str] = Field(None, alias=str("userAgent"))
|
||||
user_agent: Optional[str] = Field(default=None, alias=str("userAgent"))
|
||||
rag_content_size: int = 0
|
||||
is_public: bool = Field(default=False, alias=str("isPublic"))
|
||||
model_config = ConfigDict(populate_by_name=True, use_enum_values=True)
|
||||
@ -614,14 +614,14 @@ class Authentication(BaseModel):
|
||||
password_hash: str = Field(..., alias=str("passwordHash"))
|
||||
salt: str
|
||||
refresh_tokens: List[RefreshToken] = Field(..., alias=str("refreshTokens"))
|
||||
reset_password_token: Optional[str] = Field(None, alias=str("resetPasswordToken"))
|
||||
reset_password_expiry: Optional[datetime] = Field(None, alias=str("resetPasswordExpiry"))
|
||||
reset_password_token: Optional[str] = Field(default=None, alias=str("resetPasswordToken"))
|
||||
reset_password_expiry: Optional[datetime] = Field(default=None, alias=str("resetPasswordExpiry"))
|
||||
last_password_change: datetime = Field(..., alias=str("lastPasswordChange"))
|
||||
mfa_enabled: bool = Field(..., alias=str("mfaEnabled"))
|
||||
mfa_method: Optional[MFAMethod] = Field(None, alias=str("mfaMethod"))
|
||||
mfa_secret: Optional[str] = Field(None, alias=str("mfaSecret"))
|
||||
mfa_method: Optional[MFAMethod] = Field(default=None, alias=str("mfaMethod"))
|
||||
mfa_secret: Optional[str] = Field(default=None, alias=str("mfaSecret"))
|
||||
login_attempts: int = Field(..., alias=str("loginAttempts"))
|
||||
locked_until: Optional[datetime] = Field(None, alias=str("lockedUntil"))
|
||||
locked_until: Optional[datetime] = Field(default=None, alias=str("lockedUntil"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class AuthResponse(BaseModel):
|
||||
@ -655,23 +655,23 @@ class JobRequirements(BaseModel):
|
||||
experience: Optional[List[str]] = []
|
||||
education: Optional[List[str]] = []
|
||||
certifications: Optional[List[str]] = []
|
||||
preferred_attributes: Optional[List[str]] = Field(None, alias=str("preferredAttributes"))
|
||||
company_values: Optional[List[str]] = Field(None, alias=str("companyValues"))
|
||||
preferred_attributes: Optional[List[str]] = Field(default=None, alias=str("preferredAttributes"))
|
||||
company_values: Optional[List[str]] = Field(default=None, alias=str("companyValues"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class JobDetails(BaseModel):
|
||||
location: Location
|
||||
salary_range: Optional[SalaryRange] = Field(None, alias=str("salaryRange"))
|
||||
salary_range: Optional[SalaryRange] = Field(default=None, alias=str("salaryRange"))
|
||||
employment_type: EmploymentType = Field(..., alias=str("employmentType"))
|
||||
date_posted: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("datePosted"))
|
||||
application_deadline: Optional[datetime] = Field(None, alias=str("applicationDeadline"))
|
||||
application_deadline: Optional[datetime] = Field(default=None, alias=str("applicationDeadline"))
|
||||
is_active: bool = Field(..., alias=str("isActive"))
|
||||
applicants: Optional[List["JobApplication"]] = None
|
||||
department: Optional[str] = None
|
||||
reports_to: Optional[str] = Field(None, alias=str("reportsTo"))
|
||||
reports_to: Optional[str] = Field(default=None, alias=str("reportsTo"))
|
||||
benefits: Optional[List[str]] = None
|
||||
visa_sponsorship: Optional[bool] = Field(None, alias=str("visaSponsorship"))
|
||||
featured_until: Optional[datetime] = Field(None, alias=str("featuredUntil"))
|
||||
visa_sponsorship: Optional[bool] = Field(default=None, alias=str("visaSponsorship"))
|
||||
featured_until: Optional[datetime] = Field(default=None, alias=str("featuredUntil"))
|
||||
views: int = 0
|
||||
application_count: int = Field(0, alias=str("applicationCount"))
|
||||
|
||||
@ -704,7 +704,7 @@ class InterviewFeedback(BaseModel):
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("createdAt"))
|
||||
updated_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("updatedAt"))
|
||||
is_visible: bool = Field(..., alias=str("isVisible"))
|
||||
skill_assessments: Optional[List[SkillAssessment]] = Field(None, alias=str("skillAssessments"))
|
||||
skill_assessments: Optional[List[SkillAssessment]] = Field(default=None, alias=str("skillAssessments"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class InterviewSchedule(BaseModel):
|
||||
@ -718,7 +718,7 @@ class InterviewSchedule(BaseModel):
|
||||
notes: Optional[str] = None
|
||||
feedback: Optional[InterviewFeedback] = None
|
||||
status: Literal["scheduled", "completed", "cancelled", "rescheduled"]
|
||||
meeting_link: Optional[HttpUrl] = Field(None, alias=str("meetingLink"))
|
||||
meeting_link: Optional[HttpUrl] = Field(default=None, alias=str("meetingLink"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class JobApplication(BaseModel):
|
||||
@ -729,11 +729,11 @@ class JobApplication(BaseModel):
|
||||
applied_date: datetime = Field(..., alias=str("appliedDate"))
|
||||
updated_date: datetime = Field(..., alias=str("updatedDate"))
|
||||
resume_version: str = Field(..., alias=str("resumeVersion"))
|
||||
cover_letter: Optional[str] = Field(None, alias=str("coverLetter"))
|
||||
cover_letter: Optional[str] = Field(default=None, alias=str("coverLetter"))
|
||||
notes: Optional[str] = None
|
||||
interview_schedules: Optional[List[InterviewSchedule]] = Field(None, alias=str("interviewSchedules"))
|
||||
custom_questions: Optional[List[CustomQuestion]] = Field(None, alias=str("customQuestions"))
|
||||
candidate_contact: Optional[CandidateContact] = Field(None, alias=str("candidateContact"))
|
||||
interview_schedules: Optional[List[InterviewSchedule]] = Field(default=None, alias=str("interviewSchedules"))
|
||||
custom_questions: Optional[List[CustomQuestion]] = Field(default=None, alias=str("customQuestions"))
|
||||
candidate_contact: Optional[CandidateContact] = Field(default=None, alias=str("candidateContact"))
|
||||
decision: Optional[ApplicationDecision] = None
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -749,8 +749,8 @@ class GuestSessionResponse(BaseModel):
|
||||
|
||||
class ChatContext(BaseModel):
|
||||
type: ChatContextType
|
||||
related_entity_id: Optional[str] = Field(None, alias=str("relatedEntityId"))
|
||||
related_entity_type: Optional[Literal["job", "candidate", "employer"]] = Field(None, alias=str("relatedEntityType"))
|
||||
related_entity_id: Optional[str] = Field(default=None, alias=str("relatedEntityId"))
|
||||
related_entity_type: Optional[Literal["job", "candidate", "employer"]] = Field(default=None, alias=str("relatedEntityType"))
|
||||
additional_context: Optional[Dict[str, Any]] = Field({}, alias=str("additionalContext"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -774,7 +774,7 @@ class RateLimitResult(BaseModel):
|
||||
"""Result of rate limit check"""
|
||||
allowed: bool
|
||||
reason: Optional[str] = None
|
||||
retry_after_seconds: Optional[int] = Field(None, alias=str("retryAfterSeconds"))
|
||||
retry_after_seconds: Optional[int] = Field(default=None, alias=str("retryAfterSeconds"))
|
||||
remaining_requests: Dict[str, int] = Field(default_factory=dict, alias=str("remainingRequests"))
|
||||
reset_times: Dict[str, datetime] = Field(default_factory=dict, alias=str("resetTimes"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
@ -804,11 +804,11 @@ class GuestConversionRequest(BaseModel):
|
||||
phone: Optional[str] = None
|
||||
|
||||
# Employer-specific fields (optional)
|
||||
company_name: Optional[str] = Field(None, alias=str("companyName"))
|
||||
company_name: Optional[str] = Field(default=None, alias=str("companyName"))
|
||||
industry: Optional[str] = None
|
||||
company_size: Optional[str] = Field(None, alias=str("companySize"))
|
||||
company_description: Optional[str] = Field(None, alias=str("companyDescription"))
|
||||
website_url: Optional[HttpUrl] = Field(None, alias=str("websiteUrl"))
|
||||
company_size: Optional[str] = Field(default=None, alias=str("companySize"))
|
||||
company_description: Optional[str] = Field(default=None, alias=str("companyDescription"))
|
||||
website_url: Optional[HttpUrl] = Field(default=None, alias=str("websiteUrl"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@field_validator('username')
|
||||
@ -927,7 +927,7 @@ class ChatMessage(ChatMessageUser):
|
||||
#attachments: Optional[List[Attachment]] = None
|
||||
#reactions: Optional[List[MessageReaction]] = None
|
||||
#is_edited: bool = Field(False, alias=str("isEdited"))
|
||||
#edit_history: Optional[List[EditHistory]] = Field(None, alias=str("editHistory"))
|
||||
#edit_history: Optional[List[EditHistory]] = Field(default=None, alias=str("editHistory"))
|
||||
|
||||
class ChatMessageSkillAssessment(ChatMessageUser):
|
||||
role: ChatSenderType = ChatSenderType.ASSISTANT
|
||||
@ -938,8 +938,8 @@ class ChatMessageResume(ChatMessageUser):
|
||||
role: ChatSenderType = ChatSenderType.ASSISTANT
|
||||
metadata: ChatMessageMetaData = Field(default=ChatMessageMetaData())
|
||||
resume: str = Field(..., alias=str("resume"))
|
||||
system_prompt: Optional[str] = Field(None, alias=str("systemPrompt"))
|
||||
prompt: Optional[str] = Field(None, alias=str("prompt"))
|
||||
system_prompt: Optional[str] = Field(default=None, alias=str("systemPrompt"))
|
||||
prompt: Optional[str] = Field(default=None, alias=str("prompt"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class Resume(BaseModel):
|
||||
@ -974,15 +974,15 @@ class SystemInfo(BaseModel):
|
||||
|
||||
class ChatSession(BaseModel):
|
||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||
user_id: Optional[str] = Field(None, alias=str("userId"))
|
||||
guest_id: Optional[str] = Field(None, alias=str("guestId"))
|
||||
user_id: Optional[str] = Field(default=None, alias=str("userId"))
|
||||
guest_id: Optional[str] = Field(default=None, alias=str("guestId"))
|
||||
created_at: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("createdAt"))
|
||||
last_activity: datetime = Field(default_factory=lambda: datetime.now(UTC), alias=str("lastActivity"))
|
||||
title: Optional[str] = None
|
||||
context: ChatContext
|
||||
# messages: Optional[List[ChatMessage]] = None
|
||||
is_archived: bool = Field(False, alias=str("isArchived"))
|
||||
system_prompt: Optional[str] = Field(None, alias=str("systemPrompt"))
|
||||
system_prompt: Optional[str] = Field(default=None, alias=str("systemPrompt"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@model_validator(mode="after")
|
||||
@ -998,10 +998,10 @@ class DataSourceConfiguration(BaseModel):
|
||||
source_type: DataSourceType = Field(..., alias=str("sourceType"))
|
||||
connection_details: Dict[str, Any] = Field(..., alias=str("connectionDetails"))
|
||||
processing_pipeline: List[ProcessingStep] = Field(..., alias=str("processingPipeline"))
|
||||
refresh_schedule: Optional[str] = Field(None, alias=str("refreshSchedule"))
|
||||
last_refreshed: Optional[datetime] = Field(None, alias=str("lastRefreshed"))
|
||||
refresh_schedule: Optional[str] = Field(default=None, alias=str("refreshSchedule"))
|
||||
last_refreshed: Optional[datetime] = Field(default=None, alias=str("lastRefreshed"))
|
||||
status: Literal["active", "pending", "error", "processing"]
|
||||
error_details: Optional[str] = Field(None, alias=str("errorDetails"))
|
||||
error_details: Optional[str] = Field(default=None, alias=str("errorDetails"))
|
||||
metadata: Optional[Dict[str, Any]] = None
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -1022,14 +1022,14 @@ class RAGConfiguration(BaseModel):
|
||||
|
||||
class UserActivity(BaseModel):
|
||||
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
|
||||
user_id: Optional[str] = Field(None, alias=str("userId"))
|
||||
guest_id: Optional[str] = Field(None, alias=str("guestId"))
|
||||
user_id: Optional[str] = Field(default=None, alias=str("userId"))
|
||||
guest_id: Optional[str] = Field(default=None, alias=str("guestId"))
|
||||
activity_type: ActivityType = Field(..., alias=str("activityType"))
|
||||
timestamp: datetime
|
||||
metadata: Dict[str, Any]
|
||||
ip_address: Optional[str] = Field(None, alias=str("ipAddress"))
|
||||
user_agent: Optional[str] = Field(None, alias=str("userAgent"))
|
||||
session_id: Optional[str] = Field(None, alias=str("sessionId"))
|
||||
ip_address: Optional[str] = Field(default=None, alias=str("ipAddress"))
|
||||
user_agent: Optional[str] = Field(default=None, alias=str("userAgent"))
|
||||
session_id: Optional[str] = Field(default=None, alias=str("sessionId"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@model_validator(mode="after")
|
||||
@ -1054,7 +1054,7 @@ class UserPreference(BaseModel):
|
||||
theme: ThemePreference
|
||||
notifications: List[NotificationPreference]
|
||||
accessibility: AccessibilitySettings
|
||||
dashboard_layout: Optional[Dict[str, Any]] = Field(None, alias=str("dashboardLayout"))
|
||||
dashboard_layout: Optional[Dict[str, Any]] = Field(default=None, alias=str("dashboardLayout"))
|
||||
language: str
|
||||
timezone: str
|
||||
email_frequency: Literal["immediate", "daily", "weekly", "never"] = Field(..., alias=str("emailFrequency"))
|
||||
@ -1096,7 +1096,7 @@ class CreateEmployerRequest(BaseModel):
|
||||
company_size: str = Field(..., alias=str("companySize"))
|
||||
company_description: str = Field(..., alias=str("companyDescription"))
|
||||
# Add other required employer fields
|
||||
website_url: Optional[str] = Field(None, alias=str("websiteUrl"))
|
||||
website_url: Optional[str] = Field(default=None, alias=str("websiteUrl"))
|
||||
phone: Optional[str] = None
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -1116,14 +1116,14 @@ class CreateEmployerRequest(BaseModel):
|
||||
class ChatQuery(BaseModel):
|
||||
prompt: str
|
||||
tunables: Optional[Tunables] = None
|
||||
agent_options: Optional[Dict[str, Any]] = Field(None, alias=str("agentOptions"))
|
||||
agent_options: Optional[Dict[str, Any]] = Field(default=None, alias=str("agentOptions"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class PaginatedRequest(BaseModel):
|
||||
page: Annotated[int, Field(ge=1)] = 1
|
||||
limit: Annotated[int, Field(ge=1, le=100)] = 20
|
||||
sort_by: Optional[str] = Field(None, alias=str("sortBy"))
|
||||
sort_order: Optional[SortOrder] = Field(None, alias=str("sortOrder"))
|
||||
sort_by: Optional[str] = Field(default=None, alias=str("sortBy"))
|
||||
sort_order: Optional[SortOrder] = Field(default=None, alias=str("sortOrder"))
|
||||
filters: Optional[Dict[str, Any]] = None
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
@ -1132,8 +1132,8 @@ class SearchQuery(BaseModel):
|
||||
filters: Optional[Dict[str, Any]] = None
|
||||
page: Annotated[int, Field(ge=1)] = 1
|
||||
limit: Annotated[int, Field(ge=1, le=100)] = 20
|
||||
sort_by: Optional[str] = Field(None, alias=str("sortBy"))
|
||||
sort_order: Optional[SortOrder] = Field(None, alias=str("sortOrder"))
|
||||
sort_by: Optional[str] = Field(default=None, alias=str("sortBy"))
|
||||
sort_order: Optional[SortOrder] = Field(default=None, alias=str("sortOrder"))
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
class PaginatedResponse(BaseModel):
|
||||
|
@ -1,5 +1,5 @@
|
||||
from __future__ import annotations
|
||||
from pydantic import BaseModel, field_serializer, field_validator, model_validator, Field # type: ignore
|
||||
from pydantic import BaseModel # type: ignore
|
||||
from typing import List, Optional, Dict, Any
|
||||
import os
|
||||
import glob
|
||||
|
@ -136,7 +136,7 @@ async def get_system_health(
|
||||
|
||||
if database_manager:
|
||||
try:
|
||||
database = database_manager.get_database()
|
||||
database_manager.get_database()
|
||||
from database.manager import redis_manager
|
||||
redis_health = await redis_manager.health_check()
|
||||
db_health = {
|
||||
|
@ -676,7 +676,7 @@ async def request_mfa(
|
||||
|
||||
# Check if device is trusted
|
||||
device_manager = DeviceManager(database)
|
||||
device_info = device_manager.parse_device_info(http_request)
|
||||
device_manager.parse_device_info(http_request)
|
||||
|
||||
is_trusted = await device_manager.is_trusted_device(user_data["id"], request.device_id)
|
||||
|
||||
|
@ -59,7 +59,7 @@ async def create_candidate_ai(
|
||||
prometheus_collector=prometheus_collector)
|
||||
|
||||
if not generate_agent:
|
||||
logger.warning(f"⚠️ Unable to create AI generation agent.")
|
||||
logger.warning("⚠️ Unable to create AI generation agent.")
|
||||
return JSONResponse(
|
||||
status_code=400,
|
||||
content=create_error_response("AGENT_NOT_FOUND", "Unable to create AI generation agent")
|
||||
@ -91,7 +91,7 @@ async def create_candidate_ai(
|
||||
resume_message = generated_message
|
||||
|
||||
if not persona_message:
|
||||
logger.error(f"❌ AI generation failed: No message generated")
|
||||
logger.error("❌ AI generation failed: No message generated")
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content=create_error_response("AI_GENERATION_FAILED", "Failed to generate AI candidate data")
|
||||
@ -124,7 +124,7 @@ async def create_candidate_ai(
|
||||
})
|
||||
candidate = CandidateAI.model_validate(candidate_data)
|
||||
except ValidationError as e:
|
||||
logger.error(f"❌ AI candidate data validation failed")
|
||||
logger.error("❌ AI candidate data validation failed")
|
||||
for lines in backstory_traceback.format_exc().splitlines():
|
||||
logger.error(lines)
|
||||
logger.error(json.dumps(persona_message.content, indent=2))
|
||||
@ -134,7 +134,7 @@ async def create_candidate_ai(
|
||||
status_code=400,
|
||||
content=create_error_response("AI_VALIDATION_FAILED", "AI-generated data validation failed")
|
||||
)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
# Log the error and return a validation error response
|
||||
for lines in backstory_traceback.format_exc().splitlines():
|
||||
logger.error(lines)
|
||||
@ -165,7 +165,7 @@ async def create_candidate_ai(
|
||||
document_id = str(uuid.uuid4())
|
||||
document_type = DocumentType.MARKDOWN
|
||||
document_content = resume_message.content.encode('utf-8')
|
||||
document_filename = f"resume.md"
|
||||
document_filename = "resume.md"
|
||||
|
||||
document_data = Document(
|
||||
id=document_id,
|
||||
@ -313,7 +313,7 @@ async def upload_candidate_document(
|
||||
# Parse the JSON string and create DocumentOptions object
|
||||
options_dict = json.loads(options_data)
|
||||
options : DocumentOptions = DocumentOptions.model_validate(options_dict)
|
||||
except (json.JSONDecodeError, ValidationError) as e:
|
||||
except (json.JSONDecodeError, ValidationError):
|
||||
return StreamingResponse(
|
||||
iter([json.dumps(ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
@ -733,7 +733,7 @@ async def get_document_content(
|
||||
|
||||
file_path = os.path.join(defines.user_dir, candidate.username, "rag-content" if document.options.include_in_rag else "files", document.original_name)
|
||||
file_path = pathlib.Path(file_path)
|
||||
if not document.type in [DocumentType.TXT, DocumentType.MARKDOWN]:
|
||||
if document.type not in [DocumentType.TXT, DocumentType.MARKDOWN]:
|
||||
file_path = file_path.with_suffix('.md')
|
||||
|
||||
if not file_path.exists():
|
||||
@ -754,7 +754,7 @@ async def get_document_content(
|
||||
content=content,
|
||||
size=document.size
|
||||
)
|
||||
return create_success_response(response.model_dump(by_alias=True));
|
||||
return create_success_response(response.model_dump(by_alias=True))
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to read document file: {e}")
|
||||
@ -820,7 +820,7 @@ async def update_document(
|
||||
dst = pathlib.Path(rag_path)
|
||||
# Move to RAG directory
|
||||
src.rename(dst)
|
||||
logger.info(f"📁 Moved file to RAG directory")
|
||||
logger.info("📁 Moved file to RAG directory")
|
||||
if document.type != DocumentType.MARKDOWN and document.type != DocumentType.TXT:
|
||||
src = pathlib.Path(file_path)
|
||||
src_as_md = src.with_suffix(".md")
|
||||
@ -832,7 +832,7 @@ async def update_document(
|
||||
dst = pathlib.Path(file_path)
|
||||
# Move to regular files directory
|
||||
src.rename(dst)
|
||||
logger.info(f"📁 Moved file to regular files directory")
|
||||
logger.info("📁 Moved file to regular files directory")
|
||||
if document.type != DocumentType.MARKDOWN and document.type != DocumentType.TXT:
|
||||
src_as_md = src.with_suffix(".md")
|
||||
if src_as_md.exists():
|
||||
@ -1347,7 +1347,7 @@ async def get_candidate(
|
||||
|
||||
all_candidates_data = await database.get_all_candidates()
|
||||
if not all_candidates_data:
|
||||
logger.warning(f"⚠️ No candidates found in database")
|
||||
logger.warning("⚠️ No candidates found in database")
|
||||
return JSONResponse(
|
||||
status_code=404,
|
||||
content=create_error_response("NOT_FOUND", "No candidates found")
|
||||
@ -1474,7 +1474,7 @@ async def get_candidate_skill_match(
|
||||
if not agent:
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"No skill match agent found for this candidate"
|
||||
content="No skill match agent found for this candidate"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1517,7 +1517,7 @@ async def get_candidate_skill_match(
|
||||
if final_message is None:
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"No match found for the given skill"
|
||||
content="No match found for the given skill"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1525,7 +1525,7 @@ async def get_candidate_skill_match(
|
||||
if not isinstance(final_message, ChatMessageSkillAssessment):
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Skill match response is not valid"
|
||||
content="Skill match response is not valid"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1535,7 +1535,7 @@ async def get_candidate_skill_match(
|
||||
if not assessment:
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Skill assessment could not be generated"
|
||||
content="Skill assessment could not be generated"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1772,7 +1772,7 @@ async def generate_resume(
|
||||
logger.error("❌ Uninitialized skill match data, cannot generate resume")
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Uninitialized skill match data, cannot generate resume"
|
||||
content="Uninitialized skill match data, cannot generate resume"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1784,7 +1784,7 @@ async def generate_resume(
|
||||
if not agent:
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"No skill match agent found for this candidate"
|
||||
content="No skill match agent found for this candidate"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1793,7 +1793,7 @@ async def generate_resume(
|
||||
if not isinstance(agent, GenerateResume):
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Agent is not a GenerateResume instance"
|
||||
content="Agent is not a GenerateResume instance"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1829,7 +1829,7 @@ async def generate_resume(
|
||||
if final_message is None:
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"No skill match found for the given requirement"
|
||||
content="No skill match found for the given requirement"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
@ -1837,7 +1837,7 @@ async def generate_resume(
|
||||
if not isinstance(final_message, ChatMessageResume):
|
||||
error_message = ChatMessageError(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Skill match response is not valid"
|
||||
content="Skill match response is not valid"
|
||||
)
|
||||
yield error_message
|
||||
return
|
||||
|
@ -29,36 +29,7 @@ import backstory_traceback
|
||||
import entities.entity_manager as entities
|
||||
|
||||
from models import (
|
||||
LoginRequest, CreateCandidateRequest, CreateEmployerRequest,
|
||||
Candidate, Employer, Guest, AuthResponse,
|
||||
MFARequest, MFAData, MFARequestResponse, MFAVerifyRequest,
|
||||
EmailVerificationRequest, ResendVerificationRequest,
|
||||
# API
|
||||
MOCK_UUID, ApiActivityType, ChatMessageError, ChatMessageResume,
|
||||
ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming,
|
||||
ChatMessageUser, DocumentMessage, DocumentOptions, Job,
|
||||
JobRequirements, JobRequirementsMessage, LoginRequest,
|
||||
CreateCandidateRequest, CreateEmployerRequest,
|
||||
|
||||
# User models
|
||||
Candidate, Employer, BaseUserWithType, BaseUser, Guest,
|
||||
Authentication, AuthResponse, CandidateAI,
|
||||
|
||||
# Job models
|
||||
JobApplication, ApplicationStatus,
|
||||
|
||||
# Chat models
|
||||
ChatSession, ChatMessage, ChatContext, ChatQuery, ApiStatusType, ChatSenderType, ApiMessageType, ChatContextType,
|
||||
ChatMessageRagSearch,
|
||||
|
||||
# Document models
|
||||
Document, DocumentType, DocumentListResponse, DocumentUpdateRequest, DocumentContentResponse,
|
||||
|
||||
# Supporting models
|
||||
Location, MFARequest, MFAData, MFARequestResponse, MFAVerifyRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, Resume, ResumeMessage, Skill, SkillAssessment, SystemInfo, UserType, WorkExperience, Education,
|
||||
|
||||
# Email
|
||||
EmailVerificationRequest
|
||||
Candidate, ChatMessageUser, Candidate, BaseUserWithType, ChatSession, ChatMessage
|
||||
)
|
||||
|
||||
|
||||
@ -269,9 +240,9 @@ async def post_chat_session_message_stream(
|
||||
chat_session_data=chat_session_data,
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
logger.error(backstory_traceback.format_exc())
|
||||
logger.error(f"❌ Chat message streaming error")
|
||||
logger.error("❌ Chat message streaming error")
|
||||
return JSONResponse(
|
||||
status_code=500,
|
||||
content=create_error_response("STREAMING_ERROR", "")
|
||||
|
@ -37,7 +37,7 @@ async def debug_guest_session(
|
||||
user_lookup = await database.get_user_by_id(guest_id)
|
||||
|
||||
# Get TTL info
|
||||
primary_ttl = await database.redis.ttl(f"guests")
|
||||
primary_ttl = await database.redis.ttl("guests")
|
||||
backup_ttl = await database.redis.ttl(f"guest_backup:{guest_id}")
|
||||
|
||||
debug_info = {
|
||||
|
@ -44,7 +44,7 @@ async def reformat_as_markdown(database: RedisDatabase, candidate_entity: Candid
|
||||
return
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Reformatting job description as markdown...",
|
||||
content="Reformatting job description as markdown...",
|
||||
activity=ApiActivityType.CONVERTING
|
||||
)
|
||||
yield status_message
|
||||
@ -73,9 +73,9 @@ Return only the markdown content, no other text. Make sure all content is includ
|
||||
chat_message : ChatMessage = message
|
||||
try:
|
||||
chat_message.content = chat_agent.extract_markdown_from_text(chat_message.content)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
logger.info(f"✅ Successfully converted content to markdown")
|
||||
logger.info("✅ Successfully converted content to markdown")
|
||||
yield chat_message
|
||||
return
|
||||
|
||||
@ -114,7 +114,7 @@ async def create_job_from_content(database: RedisDatabase, current_user: Candida
|
||||
return
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=MOCK_UUID, # No session ID for document uploads
|
||||
content=f"Analyzing document for company and requirement details...",
|
||||
content="Analyzing document for company and requirement details...",
|
||||
activity=ApiActivityType.SEARCHING
|
||||
)
|
||||
yield status_message
|
||||
@ -178,7 +178,7 @@ async def create_candidate_job(
|
||||
database: RedisDatabase = Depends(get_database)
|
||||
):
|
||||
"""Create a new job"""
|
||||
is_employer = isinstance(current_user, Employer)
|
||||
isinstance(current_user, Employer)
|
||||
|
||||
try:
|
||||
job = Job.model_validate(job_data)
|
||||
|
@ -31,7 +31,7 @@ async def get_user(
|
||||
|
||||
all_candidate_data = await database.get_all_candidates()
|
||||
if not all_candidate_data:
|
||||
logger.warning(f"⚠️ No users found in database")
|
||||
logger.warning("⚠️ No users found in database")
|
||||
return JSONResponse(
|
||||
status_code=404,
|
||||
content=create_error_response("NOT_FOUND", "No users found")
|
||||
@ -48,7 +48,7 @@ async def get_user(
|
||||
if not user_data:
|
||||
all_guest_data = await database.get_all_guests()
|
||||
if not all_guest_data:
|
||||
logger.warning(f"⚠️ No guests found in database")
|
||||
logger.warning("⚠️ No guests found in database")
|
||||
return JSONResponse(
|
||||
status_code=404,
|
||||
content=create_error_response("NOT_FOUND", "No users found")
|
||||
|
@ -181,7 +181,7 @@ def get_forecast(grid_endpoint):
|
||||
def TickerValue(ticker_symbols):
|
||||
api_key = os.getenv("TWELVEDATA_API_KEY", "")
|
||||
if not api_key:
|
||||
return {"error": f"Error fetching data: No API key for TwelveData"}
|
||||
return {"error": "Error fetching data: No API key for TwelveData"}
|
||||
|
||||
results = []
|
||||
for ticker_symbol in ticker_symbols.split(","):
|
||||
@ -512,13 +512,13 @@ class ToolEntry(BaseModel):
|
||||
tool: Tool
|
||||
|
||||
def llm_tools(tools: List[ToolEntry]) -> List[Dict[str, Any]]:
|
||||
return [entry.tool.model_dump(mode='json') for entry in tools if entry.enabled == True]
|
||||
return [entry.tool.model_dump(mode='json') for entry in tools if entry.enabled is True]
|
||||
|
||||
def all_tools() -> List[ToolEntry]:
|
||||
return [ToolEntry(tool=tool) for tool in tools]
|
||||
|
||||
def enabled_tools(tools: List[ToolEntry]) -> List[ToolEntry]:
|
||||
return [ToolEntry(tool=entry.tool) for entry in tools if entry.enabled == True]
|
||||
return [ToolEntry(tool=entry.tool) for entry in tools if entry.enabled is True]
|
||||
|
||||
tool_functions = ["DateTime", "WeatherForecast", "TickerValue", "AnalyzeSite", "GenerateImage"]
|
||||
__all__ = ["ToolEntry", "all_tools", "llm_tools", "enabled_tools", "tool_functions"]
|
||||
|
@ -14,37 +14,8 @@ import defines
|
||||
from logger import logger
|
||||
from models import DocumentType
|
||||
from models import (
|
||||
LoginRequest, CreateCandidateRequest, CreateEmployerRequest,
|
||||
Candidate, Employer, Guest, AuthResponse,
|
||||
MFARequest, MFAData, MFARequestResponse, MFAVerifyRequest,
|
||||
EmailVerificationRequest, ResendVerificationRequest,
|
||||
# API
|
||||
MOCK_UUID, ApiActivityType, ChatMessageError, ChatMessageResume,
|
||||
ChatMessageSkillAssessment, ChatMessageStatus, ChatMessageStreaming,
|
||||
ChatMessageUser, DocumentMessage, DocumentOptions, Job,
|
||||
JobRequirements, JobRequirementsMessage, LoginRequest,
|
||||
CreateCandidateRequest, CreateEmployerRequest,
|
||||
|
||||
# User models
|
||||
Candidate, Employer, BaseUserWithType, BaseUser, Guest,
|
||||
Authentication, AuthResponse, CandidateAI,
|
||||
|
||||
# Job models
|
||||
JobApplication, ApplicationStatus,
|
||||
|
||||
# Chat models
|
||||
ChatSession, ChatMessage, ChatContext, ChatQuery, ChatSenderType, ApiMessageType, ChatContextType,
|
||||
ChatMessageRagSearch,
|
||||
|
||||
# Document models
|
||||
Document, DocumentType, DocumentListResponse, DocumentUpdateRequest, DocumentContentResponse,
|
||||
|
||||
# Supporting models
|
||||
Location, MFARequest, MFAData, MFARequestResponse, MFAVerifyRequest, RagContentMetadata, RagContentResponse, ResendVerificationRequest, Resume, ResumeMessage, Skill, SkillAssessment, SystemInfo, UserType, WorkExperience, Education,
|
||||
|
||||
# Email
|
||||
EmailVerificationRequest,
|
||||
ApiStatusType
|
||||
Job,
|
||||
ChatMessage, DocumentType, ApiStatusType
|
||||
)
|
||||
|
||||
from typing import List, Dict
|
||||
@ -103,7 +74,6 @@ async def stream_agent_response(chat_agent, user_message, chat_session_data=None
|
||||
"""Stream agent response with proper formatting"""
|
||||
async def message_stream_generator():
|
||||
"""Generator to stream messages with persistence"""
|
||||
last_log = None
|
||||
final_message = None
|
||||
|
||||
import utils.llm_proxy as llm_manager
|
||||
@ -215,7 +185,7 @@ async def reformat_as_markdown(database, candidate_entity, content: str):
|
||||
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=MOCK_UUID,
|
||||
content=f"Reformatting job description as markdown...",
|
||||
content="Reformatting job description as markdown...",
|
||||
activity=ApiActivityType.CONVERTING
|
||||
)
|
||||
yield status_message
|
||||
@ -245,10 +215,10 @@ Return only the markdown content, no other text. Make sure all content is includ
|
||||
chat_message: ChatMessage = message
|
||||
try:
|
||||
chat_message.content = chat_agent.extract_markdown_from_text(chat_message.content)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
logger.info(f"✅ Successfully converted content to markdown")
|
||||
logger.info("✅ Successfully converted content to markdown")
|
||||
yield chat_message
|
||||
return
|
||||
|
||||
@ -298,7 +268,7 @@ async def create_job_from_content(database, current_user, content: str):
|
||||
|
||||
status_message = ChatMessageStatus(
|
||||
session_id=MOCK_UUID,
|
||||
content=f"Analyzing document for company and requirement details...",
|
||||
content="Analyzing document for company and requirement details...",
|
||||
activity=ApiActivityType.SEARCHING
|
||||
)
|
||||
yield status_message
|
||||
|
@ -1066,7 +1066,7 @@ async def example_usage():
|
||||
print(f"Model: {response.model}")
|
||||
|
||||
if response.usage:
|
||||
print(f"Usage Statistics:")
|
||||
print("Usage Statistics:")
|
||||
print(f" Prompt tokens: {response.usage.prompt_tokens}")
|
||||
print(f" Completion tokens: {response.usage.completion_tokens}")
|
||||
print(f" Total tokens: {response.usage.total_tokens}")
|
||||
|
@ -325,7 +325,7 @@ def rate_limited(
|
||||
async def wrapper(*args, **kwargs):
|
||||
# Extract dependencies from function signature
|
||||
import inspect
|
||||
sig = inspect.signature(func)
|
||||
inspect.signature(func)
|
||||
|
||||
# Get request, current_user, and rate_limiter from kwargs or args
|
||||
request = None
|
||||
|
Loading…
x
Reference in New Issue
Block a user