import httpx from typing import Dict, Any, Optional import logging from urllib.parse import urljoin import json class LatticeClient: """Main SDK client for Lattice""" def __init__( self, api_key: str, base_url: str = "https://api.lattice.ai", timeout: int = 60, verify_ssl: bool = True ): self.api_key = api_key self.base_url = base_url.rstrip('/') self.timeout = timeout self.verify_ssl = verify_ssl self.logger = logging.getLogger("lattice.client") # Initialize components from .interfaces.document import DocumentClient from .interfaces.rag import RAGClient from .interfaces.agent import AgentClient from .interfaces.prompt import PromptClient self.document = DocumentClient(self) self.rag = RAGClient(self) self.agent = AgentClient(self) self.prompt = PromptClient(self) async def _request( self, method: str, endpoint: str, params: Optional[Dict[str, Any]] = None, data: Optional[Dict[str, Any]] = None, files: Optional[Dict[str, Any]] = None, timeout: Optional[int] = None ) -> Dict[str, Any]: """Make HTTP request to API""" url = urljoin(self.base_url, endpoint.lstrip('/')) headers = { "Authorization": f"Bearer {self.api_key}", "Accept": "application/json" } if not files: headers["Content-Type"] = "application/json" timeout = timeout or self.timeout try: async with httpx.AsyncClient(verify=self.verify_ssl) as client: response = await client.request( method=method, url=url, headers=headers, params=params, json=data if not files else None, files=files, timeout=timeout ) response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: self.logger.error(f"HTTP error occurred: {str(e)}") raise LatticeAPIError(f"HTTP error: {str(e)}") except httpx.RequestError as e: self.logger.error(f"Request error occurred: {str(e)}") raise LatticeAPIError(f"Request error: {str(e)}") except Exception as e: self.logger.error(f"Unexpected error occurred: {str(e)}") raise LatticeAPIError(f"Unexpected error: {str(e)}") async def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]: """Make GET request""" return await self._request("GET", endpoint, params=params) async def post( self, endpoint: str, data: Optional[Dict[str, Any]] = None, files: Optional[Dict[str, Any]] = None ) -> Dict[str, Any]: """Make POST request""" return await self._request("POST", endpoint, data=data, files=files) async def put(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]: """Make PUT request""" return await self._request("PUT", endpoint, data=data) async def delete(self, endpoint: str) -> Dict[str, Any]: """Make DELETE request""" return await self._request("DELETE", endpoint) async def health_check(self) -> Dict[str, Any]: """Check API health""" return await self.get("/health") async def list_components(self) -> Dict[str, Any]: """List available components""" return await self.get("/components") class LatticeAPIError(Exception): """API related errors""" pass # Usage example: async def main(): # Initialize client client = LatticeClient( api_key="your-api-key", base_url="https://api.lattice.ai" ) # Use document processing doc_result = await client.document.process( file_path="example.pdf", options={"extract_text": True} ) # Use RAG rag_result = await client.rag.generate( query="What is the main topic?", context=doc_result['content'] ) print(rag_result) if __name__ == "__main__": import asyncio asyncio.run(main())