| """Pydantic request/response models shared across the pipeline (Stage 0: I/O contracts).""" |
| import asyncio |
| import html |
| import json |
| import logging |
| import os |
| import re |
| import time |
| import uuid |
| from datetime import datetime |
| from typing import Any, Dict, List, Literal, Optional, Tuple |
| from urllib.parse import quote |
|
|
| import httpx |
| from pydantic import BaseModel, ConfigDict, Field |
|
|
| from src.config import get_settings, LIBBEE_VERSION |
|
|
| logger = logging.getLogger(__name__) |
|
|
| class ChatMessage(BaseModel): |
| role: str |
| content: str |
|
|
|
|
| class SearchContextPayload(BaseModel): |
| context_id: str |
| topic: str |
| display_topic: Optional[str] = None |
| intent: str = "search_academic" |
| source: str = "primo" |
| resource_type: str = "articles" |
| peer_reviewed: bool = False |
| open_access: bool = False |
| year_from: Optional[str] = None |
| year_to: Optional[str] = None |
| ai_tool_query: Optional[str] = None |
| primo_boolean_query: Optional[str] = None |
| created_at: float = Field(default_factory=time.time) |
| |
| clarification_needed: bool = False |
| clarification_message: Optional[str] = None |
|
|
|
|
| class ClientStatePayload(BaseModel): |
| session_id: Optional[str] = None |
| active_search_context_id: Optional[str] = None |
| recent_search_contexts: List[SearchContextPayload] = Field(default_factory=list) |
| follow_up_action: Optional[str] = None |
| follow_up_context_id: Optional[str] = None |
|
|
|
|
| class AgentRequest(BaseModel): |
| question: str |
| |
| model: Literal["gpt", "claude"] = "gpt" |
| history: List[ChatMessage] = Field(default_factory=list) |
| client_state: Optional[ClientStatePayload] = None |
|
|
|
|
| class AgentResponse(BaseModel): |
| model_config = ConfigDict(extra="ignore") |
|
|
| answer: str |
| intent: str = "general" |
| tools_used: List[str] = Field(default_factory=list) |
| search_results: List[dict] = Field(default_factory=list) |
| sources: List[dict] = Field(default_factory=list) |
| model_used: str = "gpt" |
| response_time: float = 0 |
| corrected_query: Optional[str] = None |
| natural_query: Optional[str] = None |
| database_query: Optional[str] = None |
| ask_librarian: Optional[bool] = None |
| is_follow_up: bool = False |
| follow_up_question: Optional[str] = None |
| follow_up_suggestions: List[dict] = Field(default_factory=list) |
| search_context: Optional[dict] = None |
| ai_tool_query: Optional[str] = None |
| primo_boolean_query: Optional[str] = None |
| primo_search_url: Optional[str] = None |
| primo_ai_url: Optional[str] = None |
| pubmed_search_url: Optional[str] = None |
|
|
|
|
|
|