# Convertible Structured Output System

InferecenKit supports generating plain domain models without the need to import backend-specific libraries.

## Backend: FoundationModels
FoundationModels has two key requirements:
- Output types need to adpot its `Generable` protocol.
- Streaming output types' (`Generable.Partial`) all attributes have to be optional to support the progressive generation.   

To satisfy these requirements, the generable bridge handles both code genetaion and type conversion. 

```
Clean Domain ←→ Generable Bridge ←→ Foundation Models
```

```
┌─────────────────────────────────────────────────────────────────┐
│                    YOU DEFINE                                   │
├─────────────────────────────────────────────────────────────────┤
│ struct FictitiousCompanyInfo {                                  │
│     let name: String                                            │
│     let website: String?                                        │
│     let industry: String?                                       │
│     let employeeCount: Int?                                     │
│ }                                                               │
└─────────────────────────────────────────────────────────────────┘
                           ↓
Located in,
- InferenceKit/Sources/Generated/Output/PartialDomainModels.generated.swift
- InferenceKit/Sources/Generated/Output/GenerableModels.generated.swift                           
┌─────────────────────────────────────────────────────────────────┐
│                 SOURCERY GENERATES                              │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│ struct PartialFictitiousCompanyInfo {                           │
│     let name: String?                                           │
│     let website: String?                                        │
│     let industry: String?                                       │
│     let employeeCount: Int?                                     │
│ }                                                               │
│                                                                 │
│ @Generable                                                      │
│ struct GenerableFictitiousCompanyInfo:                          │
│     ConvertibleStructuredOutput {                               │
│                                                                 │
│     typealias DomainModel = FictitiousCompanyInfo               │
│     typealias PartialDomainModel = PartialFictitiousCompanyInfo │
│     typealias Partial = PartiallyGenerated                      │
│                                                                 │
│     @Guide var name: String                                     │
│     @Guide var website: String?                                 │
│     @Guide var industry: String?                                │
│     @Guide var employeeCount: Int?                              │
│                                                                 │
│     func toDomainModel() -> FictitiousCompanyInfo {             │
│         FictitiousCompanyInfo(...)                              │
│     }                                                           │
│ }                                                               │
│                                                                 │
│ extension GenerableFictitiousCompanyInfo.Partial:               │
│     ConvertiblePartial {                                        │
│     func toPartialDomainModel() -> PartialFictitiousCompanyInfo │
│ }                                                               │
└─────────────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────────┐
│              FOUNDATION MODELS WORKS WITH                       │
├─────────────────────────────────────────────────────────────────┤
│ GenerableFictitiousCompanyInfo                                  │
│ (understands @Generable, @Guide)                                │
└─────────────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────────┐
│                 INFERENCE KIT CONVERTS                          │
├─────────────────────────────────────────────────────────────────┤
│ toDomainModel() / toPartialDomainModel()                        │
└─────────────────────────────────────────────────────────────────┘
                           ↓
┌─────────────────────────────────────────────────────────────────┐
│                    YOU RECEIVE                                  │
├─────────────────────────────────────────────────────────────────┤
│ FictitiousCompanyInfo (complete)                                │
│ PartialFictitiousCompanyInfo (streaming)                        │
│                                                                 │
│ No Foundation Models dependencies in your domain!               │
└─────────────────────────────────────────────────────────────────┘
```


### Example: Two Types Side by Side

```
┌────────────────────────────────────┬────────────────────────────────────┐
│ YOUR DOMAIN                        │ GENERATED BRIDGE                   │
├────────────────────────────────────┼────────────────────────────────────┤
│ FictitiousCustomerInfo             │ GenerableFictitiousCustomerInfo    │
│ ├─ name: String                    │ ├─ @Guide name: String             │
│ ├─ email: String                   │ ├─ @Guide email: String            │
│ └─ phone: String?                  │ └─ @Guide phone: String?           │
│                                    │                                    │
│ PartialFictitiousCustomerInfo      │ .PartiallyGenerated                │
│ ├─ name: String?                   │ ├─ name: String?                   │
│ ├─ email: String?                  │ ├─ email: String?                  │
│ └─ phone: String?                  │ └─ phone: String?                  │
└────────────────────────────────────┴────────────────────────────────────┘
                ↑                                    ↓
                │                                    │
                └──────── .toDomainModel() ──────────┘
```


### Type Architecture

```
                    ┌─────────────────────────┐
                    │ StructuredOutput        │
                    │ (protocol)              │
                    └───────────┬─────────────┘
                                │
                    ┌───────────▼─────────────┐
                    │ ConvertibleStructuredOutput
                    │ (protocol)              │
                    └───────────┬─────────────┘
                                │
         ┌──────────────────────┼──────────────────────┐
         │                                             │
         ▼                                             ▼
┌─────────────────────────┐              ┌─────────────────────────┐
│ GenerableCompanyInfo    │              │ GenerableCustomerInfo   │
│ @Generable              │              │ @Generable              │
├─────────────────────────┤              ├─────────────────────────┤
│ toDomainModel() →       │              │ toDomainModel() →       │
│   CompanyInfo           │              │   CustomerInfo          │
│                         │              │                         │
│ Partial →               │              │ Partial →               │
│   PartiallyGenerated    │              │   PartiallyGenerated    │
│     ↓ converts to       │              │     ↓ converts to       │
│   PartialCompanyInfo    │              │   PartialCustomerInfo   │
└─────────────────────────┘              └─────────────────────────┘
```

### Usage

```
let result: FictitiousCompanyInfo = session.generateDomainModel(
    prompt: "Extract: Acme Corp, acme.com, Tech, 150 employees",
    generating: GenerableFictitiousCompanyInfo.self
)
```
