---
name: chunk_with_overlap
kind: function
lang: py
domain: core
version: "1.0.0"
purity: pure
signature: "def chunk_with_overlap(text: str, max_chars: int = 1500, overlap_sentences: int = 2) -> list[dict]"
description: "Divide texto en chunks por sentence boundaries con sliding window overlap. Garantiza avance forzado si una frase supera max_chars (evita bucle infinito). Cada chunk retorna dict con 'text' y 'sentences'."
tags: [text, chunking, nlp, split, overlap, sentence, ner, gliner, sliding-window]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: [re]
params:
  - name: text
    desc: "Texto a dividir. Frases se detectan por [.!?] seguido de espacio. Admite saltos de linea si el texto ya fue limpiado con clean_pdf_text."
  - name: max_chars
    desc: "Limite maximo de caracteres por chunk (soft limit). Si una sola frase supera max_chars se incluye igualmente para evitar bucle infinito."
  - name: overlap_sentences
    desc: "Numero de frases finales del chunk previo a prepender al chunk actual. 0 desactiva el overlap."
output: "Lista de dicts [{'text': str, 'sentences': list[str]}, ...]. 'text' es el texto listo para pasar a GLiNER2. Lista vacia si el input es vacio."
tested: true
tests:
  - "texto vacio retorna lista vacia"
  - "una frase menor que max_chars produce 1 chunk"
  - "multiples frases producen N chunks con overlap"
  - "frase mas larga que max_chars se incluye sin bucle infinito"
  - "overlap=0 no duplica frases entre chunks"
  - "overlap=2 el chunk N+1 empieza con las 2 ultimas frases del chunk N"
test_file_path: "python/functions/core/tests/test_chunk_with_overlap.py"
file_path: "python/functions/core/chunk_with_overlap.py"
notes: |
  Algoritmo validado empiricamente en notebook 06 del analisis
  gliner_glirel_tuning. El overlap sentence-level (vs overlap en caracteres)
  asegura que las entidades que aparecen al final de un chunk tambien
  aparecen al principio del siguiente, mejorando el recall de GLiNER2.

  split_text_into_chunks_py_core hace overlap en caracteres (modo RAG).
  chunk_with_overlap hace overlap en frases completas (modo NER/RE) — son
  complementarias, no competidoras.
---

## Ejemplo

```python
from core.chunk_with_overlap import chunk_with_overlap

text = "Pablo Isla preside Inditex. La empresa opera en 93 paises. Zara es su marca principal."
chunks = chunk_with_overlap(text, max_chars=80, overlap_sentences=1)
# chunk 0: text="Pablo Isla preside Inditex. La empresa opera en 93 paises."
# chunk 1: text="La empresa opera en 93 paises. Zara es su marca principal."
#                 ^--- overlap de 1 frase

for c in chunks:
    print(c["text"])
```

## Diferencia con split_text_into_chunks

- `split_text_into_chunks`: overlap en caracteres, orientado a RAG
- `chunk_with_overlap`: overlap en frases completas, orientado a NER/RE (GLiNER2)
