# 🍬 candy-ai v5 — Première version officielle

Client Python pour **cedric-8EF** — moteur IA multi-personnalités.  
Zéro configuration · 50 personnalités · Profils · Conversations · Batch · Streaming

---

## Installation

```bash
pip install candy-ai
```

---

## Démarrage immédiat

```python
from candy import Coding

print(Coding.ask("Write a quicksort in Python"))
```

Au démarrage, le terminal affiche automatiquement :

```
   ██████╗ █████╗ ███╗   ██╗██████╗ ██╗   ██╗
  ██╔════╝██╔══██╗████╗  ██║██╔══██╗╚██╗ ██╔╝
  ██║     ███████║██╔██╗ ██║██║  ██║ ╚████╔╝
  ██║     ██╔══██║██║╚██╗██║██║  ██║  ╚██╔╝
  ╚██████╗██║  ██║██║ ╚████║██████╔╝   ██║
   ╚═════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═════╝    ╚═╝
  ⚡ cedric-8EF Engine  │  v5.0.0  │  50 personalities
```

---

## Profils

```python
from candy import cfg, Coding, Math, Full

# Créer des profils personnalisés
cfg.A.lang         = "FR"
cfg.A.max_tokens   = 2000
cfg.A.style        = "detailed"
cfg.A.tone         = "encouraging"
cfg.A.expertise    = "beginner"

cfg.B.lang         = "EN"
cfg.B.style        = "technical"
cfg.B.expertise    = "expert"

cfg.default.lang   = "FR"     # profil utilisé sans .use()

# Utilisation
print(Coding.ask("Explique les générateurs"))       # → default
print(Math.use("A").ask("Résous ∫x²sin(x)dx"))     # → profil A
print(Coding.use("B").ask("Optimise ce code"))      # → profil B
```

---

## Presets rapides

```python
from candy import cfg, Coding, Tutor

cfg.A = cfg.preset("coder")            # technique, expert, markdown
cfg.B = cfg.preset("french_beginner")  # FR, détaillé, encourageant
cfg.C = cfg.preset("quick")            # ultra court

# Presets disponibles :
# french_beginner  french_expert  english_beginner  english_expert
# quick  academic  creative  teacher  coder  journalist  storyteller
# analyst  coach  debug

print(cfg.list_presets())
```

---

## Conversations multi-tours

```python
from candy import cfg, Coding, Conversation

cfg.A.lang  = "FR"
cfg.A.style = "detailed"

# Méthode 1 — via le module
session = Coding.chat(profile="A")
print(session.say("Explique les décorateurs Python"))
print(session.say("Donne un exemple avec une classe"))
print(session.say("Et avec des arguments ?"))

# Méthode 2 — via Conversation directement
from candy import Conversation
session = Conversation(Coding, profile="A", max_history=10)
session.say("Hello !")
session.show_history()    # affiche tout l'historique
session.save("chat.json") # sauvegarde
session.load("chat.json") # charge
session.clear()           # efface l'historique
print(session.count_turns())  # nb de tours
```

---

## Batch — plusieurs prompts d'un coup

```python
from candy import cfg, Coding

cfg.A = cfg.preset("coder")

questions = [
    "What is a closure ?",
    "What is a decorator ?",
    "What is a generator ?",
]

responses = Coding.use("A").batch(questions)
for q, r in zip(questions, responses):
    print(f"Q: {q}\nA: {r}\n")
```

---

## Streaming

```python
from candy import cfg, Writing

cfg.A.lang  = "FR"
cfg.A.style = "casual"

# Option 1 — itérer
for token in Writing.use("A").stream("Écris une histoire de pirates"):
    print(token, end="", flush=True)

# Option 2 — stream_print() fait tout
Writing.use("A").stream_print("Écris une histoire de pirates")
```

---

## Tous les paramètres par profil

| Paramètre | Défaut | Valeurs |
|-----------|--------|---------|
| `lang` | `"EN"` | `FR EN ES DE IT PT ZH JA AR RU NL PL SV TR KO HI VI ID CS RO` |
| `max_tokens` | `1024` | `100` → `4096` |
| `temperature` | `0.7` | `0.0` (factuel) → `1.5` (créatif) |
| `style` | `"default"` | `default concise detailed bullet academic casual technical eli5` |
| `tone` | `"neutral"` | `neutral encouraging strict humorous empathetic socratic` |
| `output_format` | `"text"` | `text markdown json html` |
| `expertise` | `"intermediate"` | `beginner intermediate expert` |
| `include_examples` | `True` | `True / False` |
| `safe_mode` | `True` | `True / False` |
| `timeout` | `120` | secondes |
| `cache_url` | `True` | `True / False` |
| `retry` | `1` | nb tentatives en cas d'échec |
| `verbose` | `False` | `True` = affiche infos de requête |

---

## Utilitaires

```python
from candy import Coding, cfg, list_profiles

# État de l'API
print(Coding.is_online())   # True / False
print(Coding.ping())        # latence en ms : 142.3

# Quota
print(Coding.quota())       # {'quota_remaining': 488, 'quota_limit': 500, ...}

# Métadonnées complètes
data = Coding.use("A").ask_with_meta("Hello")
print(data["response"])
print("Quota restant :", data["quota_remaining"])

# Profils
print(cfg.A)                # détails du profil A
print(cfg)                  # tous les profils
print(list_profiles())      # ['default', 'A', 'B', ...]
cfg.A.reset()               # remet aux défauts
cfg.A.summary()             # résumé compact

# Mode verbose (affiche les requêtes)
cfg.A.verbose = True

# Retry automatique
cfg.A.retry = 3             # réessaie 3 fois en cas d'échec
```

---

## Combiner plusieurs personnalités

```python
from candy import cfg, Coding, Debugger, Reviewer

cfg.A = cfg.preset("coder")
cfg.A.lang = "FR"

code   = Coding.use("A").ask("Écris un client REST en Python")
bugs   = Debugger.use("A").ask("Trouve les bugs", context=code)
review = Reviewer.use("A").ask("Évalue ce code", context=code)

print(code)
print(bugs)
print(review)
```

---

## Les 50 personnalités

`Math` `Coding` `Reflexion` `Analytic` `Full` `Science` `Writing` `History`
`Law` `Medicine` `Finance` `Marketing` `Security` `Design` `Language`
`Psychology` `Education` `Research` `Business` `Productivity` `Cooking`
`Travel` `Music` `Film` `Sports` `Philosophy` `Environment` `Architecture`
`Automotive` `Astronomy` `Biology` `Chemistry` `Physics` `Engineering`
`Entrepreneur` `Ethics` `Geopolitics` `Crypto` `AI` `DevOps` `Database`
`GameDev` `Comic` `Storyteller` `Translator` `Summarizer` `Debugger`
`Reviewer` `Planner` `Tutor`

---

Propulsé par **cedric-8EF** · Quota 500 req/jour · MIT License
