> For the complete documentation index, see [llms.txt](https://cleyrop.gitbook.io/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cleyrop.gitbook.io/docs/documentation-fr-en/support-and-resources/references-techniques-api-sdk/sdk-py-ai-cleyrop.md).

# SDK py-ai-cleyrop

The SDK `py-ai-cleyrop` groups together a set of Python modules designed to easily integrate artificial intelligence capabilities into your data pipelines on the Cleyrop platform. It is based on LangChain and is compatible with the OpenAI format.

It covers three main use cases: conversing with language models (Chat), transforming text into vectors (Embeddings), and automatic document language detection (Language Detection).

{% hint style="danger" %}
An upgrade from LangChain to LangChain v1 will be carried out during release 4.5
{% endhint %}

***

## Installation in the DevSpace

Install the SDK from the Cleyrop GitLab registry using the following command in your DevSpace:

```bash
uv pip install "py_ai_cleyrop" --extra-index-url "https:/gitlab.com/api/v4/projects/60268872/packages/pypi/simple"
```

## Default platform models

Three default models can be configured by the Platform Managers from **Administration > Manage models and API keys**. These models are directly accessible in PyAI via conventional names, without having to specify the exact model ID.

| Model               | Use                                  | Name in PyAI          |
| ------------------- | ------------------------------------ | --------------------- |
| **Instruct model**  | Used by Druide for conversations     | `"default-instruct"`  |
| **Embedding model** | Used for corpus vectorization        | `"default-embedding"` |
| **Coder model**     | Used for code features (MCP Dataset) | `"default-coder"`     |

## Chat Module

The Chat module lets you query different language models (LLMs) through a unified interface. It is particularly well suited for building chatbots, conversational agents, or automating text generation tasks.

**Required dependencies:** `langchain >= 0.2.6`, `langchain-openai >= 0.1.23`, `requests 2.31.0`

### Simple call (synchronous and asynchronous)

```python
from py_ai_cleyrop.chat.chat_bot import ChatCleyrop

chat = ChatCleyrop(
    llm_endpoint="http://ai-gen-proxy.cleyrop.svc.cluster.local/llm/cleyrop/v1",
    llm_token="your-api-key",
    model_name="Mistral-Small-3.2-24B-Instruct-2506",
    max_tokens=8192
)

# Synchronous call
response = chat.invoke("What is machine learning?")
print(response.content)

# Asynchronous call
async def chat_async():
    response = await chat.ainvoke("Explain generative AI to me.")
    return response.content
```

> **Good to know:** To list the models available in your environment:
>
> python
>
> ```python
> import requests, json
> print(json.dumps(requests.get("http://ai-gen-proxy.cleyrop.svc.cluster.local/llm/models").json(), indent=2))
> ```

### Integration with LangChain

Combine `ChatCleyrop` with LangChain prompts and parsers to build processing chains.

```python
from py_ai_cleyrop.chat.chat_bot import ChatCleyrop
from langchain.prompts import ChatPromptTemplate
from langchain.schema.output_parser import StrOutputParser

chat = ChatCleyrop(
    llm_endpoint="http://ai-gen-proxy.cleyrop.svc.cluster.local/llm/cleyrop/v1",
    llm_token="your-api-key",
    model_name="Mistral-Small-3.2-24B-Instruct-2506",
)

prompt = ChatPromptTemplate.from_messages([
    ("system", "You are an expert in {domain}"),
    ("user", "{question}")
])

chain = prompt | chat | StrOutputParser()

result = chain.invoke({
    "domain": "cybersecurity",
    "question": "What is SQL injection?"
})
print(result)
```

### Response streaming

Enable streaming to receive the response token by token, ideal for real-time conversational interfaces.

```python
chat = ChatCleyrop(
    llm_endpoint="http://ai-gen-proxy.cleyrop.svc.cluster.local/llm/cleyrop/v1",
    llm_token="your-api-key",
    model_name="Mistral-Small-3.2-24B-Instruct-2506",
    streaming=True
)

# Synchronous streaming
for chunk in chat.stream("Tell me a short story"):
    print(chunk.content, end="", flush=True)

# Asynchronous streaming
async def stream_response():
    async for chunk in chat.astream("Explain quantum computing"):
        print(chunk.content, end="", flush=True)
```

### Structured output

Get a response formatted according to a Pydantic schema, useful for extracting structured data from an LLM response.

```python
from py_ai_cleyrop.chat.chat_bot import ChatCleyrop
from pydantic import BaseModel

class StructuredOutput(BaseModel):
    title: str
    summary: str

chat = ChatCleyrop(
    temperature=0.1,
    llm_endpoint="http://ai-gen-proxy.cleyrop.svc.cluster.local/llm/cleyrop/v1",
    llm_token="your-api-key",
    model_name="Mistral-Small-3.2-24B-Instruct-2506",
    max_tokens=100
).with_structured_output(StructuredOutput)

result = chat.invoke([
    ("system", "You are a summarization assistant."),
    ("human", "Summarize this article in one sentence."),
])
print(result)
```

### Configuration parameters — Chat

| Parameter      | Type    | Description                              | Default  |
| -------------- | ------- | ---------------------------------------- | -------- |
| `llm_endpoint` | `str`   | Model endpoint URL                       | Required |
| `llm_token`    | `str`   | API authentication token                 | Required |
| `model_name`   | `str`   | Name of the model to use                 | Required |
| `max_tokens`   | `int`   | Maximum number of tokens in the response | `None`   |
| `temperature`  | `float` | Generation creativity (0 to 1)           | `None`   |
| `streaming`    | `bool`  | Enable response streaming                | `False`  |

## Embeddings Module

The Embeddings module converts texts into vector representations (numerical vectors). These vectors can then be used to perform semantic searches, calculate similarities between documents, or feed RAG (Retrieval-Augmented Generation) pipelines.

```python
from py_ai_cleyrop.embeddings.embedding import EmbeddingsCleyrop

embeddings = EmbeddingsCleyrop(
    base_url="http://ai-gen-proxy.cleyrop.svc.cluster.local/emb/cleyrop",
    chunk_size=512,
    model_name="BAAI/bge-m3",
    api_key="your-api-key"
)

# Vectorize multiple documents
documents = ["text 1", "text 2", "text 3"]
embeddings_list = embeddings.embed_documents(documents)

# Vectorize a single query
query = "my search query"
query_embedding = embeddings.embed_query(query)
```

**Good to know:** To list the available embedding models:

```python
import requests, json
print(json.dumps(requests.get("http://ai-gen-proxy.cleyrop.svc.cluster.local/emb/models").json(), indent=2))
```

### Configuration parameters — Embeddings

| Parameter           | Type  | Description                                  |
| ------------------- | ----- | -------------------------------------------- |
| `base_url`          | `str` | URL of the embeddings service endpoint       |
| `chunk_size`        | `int` | Maximum size of processed text chunks        |
| `model_name`        | `str` | Name of the embedding model to use           |
| `api_key`           | `str` | Authentication key (optional)                |
| `query_instruction` | `str` | Prefix added to queries before vectorization |

## Language Detection Module

The Language Detection module automatically identifies the dominant language of a set of documents. It is useful for routing different processing steps depending on the language, or filtering documents before an NLP processing stage.

### Usage

```python
from langchain_core.documents import Document
from py_ai_cleyrop.language_detection.language_detection import detect_language

# Use with the default languages (English and French)
documents = [Document(page_content="Text to analyze")]
result = detect_language(documents)

# Custom detection across multiple languages
result = detect_language(
    documents=documents,
    languages_to_detect=["en", "fr", "es", "de"],
    language_threshold=0.1
)

print(f"Main language: {result.major_language}")
print(f"Language distribution: {result.language_details}")
```

### Configuration parameters — Language Detection

| Parameter             | Type        | Description                                | Default        |
| --------------------- | ----------- | ------------------------------------------ | -------------- |
| `languages_to_detect` | `list[str]` | ISO 639-1 codes of the languages to detect | `["en", "fr"]` |
| `language_threshold`  | `float`     | Minimum confidence threshold for detection | `0`            |

**Good to know:** The result returns two pieces of information: `major_language` (the detected main language) and `language_details` (the percentage distribution of each identified language).

***

### Best practices

* **Always handle errors** : wrap your calls in a `try/except` to anticipate endpoint unavailability or authentication issues.
* **Limit** `max_tokens` according to your use case: a value of 512 is often sufficient for short responses, which reduces latency.
* **Check the available models** before configuring your client, as endpoints and model names can evolve.
* **Prefer streaming** for interactive user interfaces to improve perceived responsiveness.
* **Define a** `language_threshold` suited to your corpus to avoid false positives on very short or multilingual texts.
* **Cleyrop metadata** (`PROJECT_ID`, `HOSTNAME`) are automatically added to each Chat call to ensure traceability.
