# Octen Python SDK

[![PyPI version](https://badge.fury.io/py/octen.svg)](https://badge.fury.io/py/octen)
[![Python Support](https://img.shields.io/pypi/pyversions/octen.svg)](https://pypi.org/project/octen/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Official Python SDK for accessing [Octen API](https://octen.ai) - Powerful web search and text embedding capabilities.

## ✨ Features

- 🔍 **Web Search** - Search and retrieve ranked web results with filtering, highlighting, and full content
- 🧮 **Text Embeddings** - Convert text into high-quality vector representations
- ⚡ **High Performance** - HTTP/2 support, connection pooling, and keep-alive
- 🔄 **Auto Retry** - Smart retry mechanism for handling temporary errors
- 🛡️ **Type Safe** - Full type annotations with IDE auto-completion
- 📦 **Easy to Use** - Get started with just a few lines of code

## 📦 Installation

```bash
pip install octen
```

Requires Python 3.8 or higher.

### Development Version

```bash
pip install octen[dev]
```

### Async Support

```bash
pip install octen[async]
```

## 🚀 Quick Start

### Basic Usage

```python
from octen import Octen

# Create client
with Octen(api_key="your-api-key") as client:
    # Web search
    response = client.search.search(query="Python programming", count=5)

    for result in response.results:
        print(f"Title: {result['title']}")
        print(f"URL: {result['url']}")
        print(f"Highlight: {result.get('highlight', '')}")
        print("-" * 80)

    # Create text embedding
    embedding = client.embedding.create(
        input=["Hello, world!"],
        model="octen-embedding-4b"
    )
    vector = embedding.get_first_embedding()
    print(f"Vector dimension: {len(vector)}")
```

### Advanced Search

```python
from octen import Octen, HighlightOptions, FullContentOptions

with Octen(api_key="your-api-key") as client:
    response = client.search.search(
        query="machine learning best practices",
        count=10,
        search_type="auto",
        include_domains=["github.com", "arxiv.org"],  # Search only these domains
        start_time="2024-01-01T00:00:00Z",  # Time filtering
        highlight=HighlightOptions(
            enable=True,
            max_tokens=500
        ),
        full_content=FullContentOptions(
            enable=True,
            max_tokens=2000
        ),
        timeout=60.0  # Custom timeout
    )

    print(f"Found {len(response.results)} results")
    print(f"Actual search type: {response.search_type}")
    print(f"Token usage: {response.usage}")
```

### Batch Embeddings

```python
from octen import Octen

with Octen(api_key="your-api-key") as client:
    # Process multiple texts
    texts = [
        "Artificial intelligence is transforming the world",
        "Applications of deep learning",
        "Natural language processing technology"
    ]

    response = client.embedding.create(
        input=texts,
        model="octen-embedding-8b",
        input_type="document"
    )

    vectors = response.get_embeddings()
    print(f"Generated {len(vectors)} vectors")

    # Or use convenience methods
    query_vector = client.embedding.embed_query("search query")
    doc_vectors = client.embedding.embed_documents(["document 1", "document 2"])
```

### Custom Configuration

```python
from octen import Octen

client = Octen(
    api_key="your-api-key",
    base_url="https://api.octen.ai",  # Custom API endpoint
    timeout=10.0,  # Global default timeout (seconds)
    max_retries=3,  # Maximum retry attempts
    http2=True  # Enable HTTP/2
)

try:
    # This request uses global timeout (10 seconds)
    response1 = client.search.search("query 1")

    # This request overrides timeout to 30 seconds
    response2 = client.search.search("complex query", timeout=30.0)
finally:
    client.close()  # Release connection pool resources
```

## 📚 API Documentation

### Search API

#### `client.search.search()`

Perform a web search query.

**Parameters:**

- `query` (str, required): Search query string, max 500 characters
- `count` (int, optional): Number of results to return, range 1-100, default 5
- `search_type` (str, optional): Search type, options:
  - `"auto"` - Automatically select (default)
  - `"fast"` - Fast search
- `include_domains` (List[str], optional): Include only results from these domains
- `exclude_domains` (List[str], optional): Exclude results from these domains
- `include_text` (List[str], optional): Results must contain these texts
- `exclude_text` (List[str], optional): Results must exclude these texts
- `time_basis` (str, optional): Time basis, options: `"auto"`, `"published"`, `"crawled"`
- `start_time` (str, optional): Start time in ISO 8601 format
- `end_time` (str, optional): End time in ISO 8601 format
- `highlight` (HighlightOptions, optional): Highlight options configuration
- `format` (str, optional): Content format, options: `"text"`, `"markdown"`
- `safesearch` (str, optional): Safe search, options: `"off"`, `"strict"` (default)
- `full_content` (FullContentOptions, optional): Full content options configuration
- `timeout` (float, optional): Request timeout in seconds

**Returns:** `SearchResponse` object

**Response Properties:**

- `results` - List of search results
- `query` - The actual query used
- `search_type` - The actual search type used
- `usage` - Token usage information
- `latency` - Latency information

### Embedding API

#### `client.embedding.create()`

Create text embedding vectors.

**Parameters:**

- `input` (str | List[str], required): Input text or list of texts
- `model` (str, optional): Model name, options:
  - `"octen-embedding-0.6b"` - Lightweight model
  - `"octen-embedding-4b"` - Balanced performance
  - `"octen-embedding-8b"` - Highest quality
- `dimension` (int, optional): Vector dimension
- `input_type` (str, optional): Input type, options: `"query"` or `"document"`
- `truncation` (bool, optional): Whether to truncate long inputs, default True
- `timeout` (float, optional): Request timeout in seconds

**Returns:** `EmbeddingResponse` object

**Response Methods:**

- `get_embeddings()` - Get all vectors
- `get_first_embedding()` - Get first vector (for single input)

**Convenience Methods:**

- `embed_query(text)` - Embed a single query text
- `embed_documents(texts)` - Batch embed document texts

## 🔧 Async Support

```python
import asyncio
from octen import AsyncOcten

async def main():
    async with AsyncOcten(api_key="your-api-key") as client:
        # Execute multiple requests concurrently
        search_task = client.search.search(query="AI")
        embedding_task = client.embedding.create(
            input=["Hello"],
            model="octen-embedding-4b"
        )

        results, embeddings = await asyncio.gather(
            search_task,
            embedding_task
        )

        print(f"Search results: {len(results.results)}")
        print(f"Vector dimension: {len(embeddings.get_first_embedding())}")

asyncio.run(main())
```

## ⚠️ Error Handling

```python
from octen import (
    Octen,
    OctenAPIError,
    OctenTimeoutError,
    OctenConnectionError,
    OctenRateLimitError,
    OctenAuthenticationError,
)

with Octen(api_key="your-api-key") as client:
    try:
        response = client.search.search("query")
    except OctenAuthenticationError as e:
        print(f"Authentication failed: {e}")
    except OctenRateLimitError as e:
        print(f"Rate limit exceeded: {e}")
        print(f"Retry after {e.retry_after} seconds")
    except OctenTimeoutError as e:
        print(f"Request timeout: {e}")
    except OctenConnectionError as e:
        print(f"Connection error: {e}")
    except OctenAPIError as e:
        print(f"API error: {e}")
        print(f"Status code: {e.status_code}")
        print(f"Request ID: {e.request_id}")
```

## 🧪 Development

### Install Development Dependencies

```bash
# Install development version from source
pip install -e ".[dev]"
```

### Run Tests

```bash
pytest tests/
```

### Code Formatting

```bash
black octen/
ruff check octen/ --fix
```

### Type Checking

```bash
mypy octen/
```

## 📝 License

MIT License - See [LICENSE](LICENSE) file for details

## 🔗 Links

- [Official Website](https://octen.ai)
- [API Documentation](https://docs.octen.ai)

## 📧 Support

For questions or help, please:

- Check the [Documentation](https://docs.octen.ai)
- Email us at support@octen.ai
