# Tipos: Extraction Pipeline

Diseño original para fuzzygraph.

## Tipos a implementar

### 1. EntityCandidate (product)

- **Dominio:** datascience
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class EntityCandidate:
      name: str                                   # nombre extraido del texto
      name_normalized: str = ""                   # nombre normalizado (se llena en dedup)
      type_ref: str = ""                          # registry type ID (ej: osint_person_go_cybersecurity)
      type_label: str = ""                        # label humano (ej: "Person")
      attributes: dict = field(default_factory=dict)  # metadata extraida
      confidence: float = 0.0                     # 0.0-1.0
      source_chunk_indices: list[int] = field(default_factory=list)  # chunks donde aparecio
      merged_from: list[str] = field(default_factory=list)  # nombres originales si fue mergeado
  ```
- **Metodos:** `to_dict() -> dict`
- **Descripcion:** Candidato de entidad extraido por el LLM. Puede venir de un solo chunk o ser el resultado de mergear multiples extracciones. `merged_from` rastrea los nombres originales para debugging.

### 2. RelationCandidate (product)

- **Dominio:** datascience
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class RelationCandidate:
      from_name: str                              # nombre de la entidad origen
      to_name: str                                # nombre de la entidad destino
      from_id: str = ""                           # entity ID resuelto (se llena en dedup)
      to_id: str = ""                             # entity ID resuelto
      relation_type: str = ""                     # tipo de relacion (de relationPresets)
      description: str = ""                       # descripcion textual de la relacion
      confidence: float = 0.0                     # 0.0-1.0
      source_chunk_index: int = -1                # chunk donde se extrajo
  ```
- **Metodos:** `to_dict() -> dict`

### 3. ExtractionResult (product)

- **Dominio:** datascience
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class ExtractionResult:
      entities: list[EntityCandidate]              # entidades finales (deduplicadas)
      relations: list[RelationCandidate]           # relaciones finales (deduplicadas)
      stats: ExtractionStats = field(default_factory=lambda: ExtractionStats())
  ```

### 4. ExtractionStats (product)

- **Dominio:** datascience
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class ExtractionStats:
      total_chunks: int = 0
      total_chars: int = 0
      raw_entities_count: int = 0                 # antes de dedup
      final_entities_count: int = 0               # despues de dedup
      entities_merged: int = 0                    # cuantas se mergearon
      raw_relations_count: int = 0
      final_relations_count: int = 0
      relations_merged: int = 0
      relations_discarded: int = 0                # self-loops + sin match
      entity_types_found: dict[str, int] = field(default_factory=dict)  # type_ref → count
      relation_types_found: dict[str, int] = field(default_factory=dict)
      processing_time_seconds: float = 0.0
  ```
- **Descripcion:** Estadisticas del proceso de extraccion. Util para reporting y debugging.

### 5. DeduplicationResult (product)

- **Dominio:** datascience
- **Lang:** Python
- **Algebraic:** product
- **Definicion:**
  ```python
  @dataclass
  class DeduplicationResult:
      entities: list[EntityCandidate]              # entidades finales
      entity_id_map: dict[str, str]               # nombre_normalizado → entity_id (para resolver relations)
      name_to_id: dict[str, str]                  # todos los nombres originales → entity_id (incluyendo aliases)
      merge_log: list[dict] = field(default_factory=list)  # [{"merged": ["John Smith", "Smith, John"], "into": "John Smith", "score": 0.92}]
      total_before: int = 0
      total_after: int = 0
  ```
- **Descripcion:** Resultado de deduplicacion de entidades. El `name_to_id` mapea TODOS los nombres originales (incluyendo los mergeados) a su ID final, permitiendo resolver relaciones que usan cualquier variante del nombre.
