Código-fonte para llm4time.core.prompt

"""
Módulo para geração e carregamento de prompts de previsão em séries temporais.
"""

from .prompts import PromptType
from .prompts import ZERO_SHOT, FEW_SHOT, COT, COT_FEW
from .formatting import TSFormat, TSType
from .formatter import format
from .data import Sampling
from .data.sampling import frontend, backend, random, uniform
from .evaluate.statistics import Statistics
import pandas as pd


[documentos] def load_prompt(path: str, **kwargs) -> str: """ Carrega um template de prompt de um arquivo e realiza substituições de variáveis. Lê o conteúdo do arquivo especificado por `path` e formata a string com os argumentos fornecidos em `kwargs`. É útil para reutilizar prompts de previsão de séries temporais com placeholders dinâmicos. Args: path (str): Caminho para o arquivo de texto contendo o template do prompt. **kwargs: Argumentos para substituição de placeholders no template. Returns: str: Conteúdo do arquivo formatado com os argumentos fornecidos. Raises: FileNotFoundError: Se o arquivo não for encontrado. IOError: Se houver erro ao ler o arquivo. KeyError: Se algum placeholder no template não tiver correspondência em `kwargs`. Examples: >>> load_prompt("templates/zero_shot.txt", train_data="...", periods=7) """ try: with open(path, 'r', encoding='utf-8') as file: prompt = file.read() return prompt.format(**kwargs) except FileNotFoundError: raise FileNotFoundError(f"Arquivo não encontrado: {path}") except IOError as e: raise IOError(f"Erro ao ler o arquivo {path}: {e}") except KeyError as e: raise KeyError(f"Chave de formatação não encontrada: {e}")
[documentos] def generate( train: list[tuple], periods: int, prompt_type: PromptType, ts_format: TSFormat, ts_type: TSType, sampling: Sampling = None, num_examples: int = 0, template: str = None, **kwargs ) -> str: """ Gera um prompt de previsão de séries temporais de acordo com o tipo especificado. A função prepara os dados de treino no formato e tipo desejados, constrói exemplos de acordo com a estratégia de amostragem especificada e insere essas informações em diferentes templates. Args: train (list[tuple]): Série temporal de treino no formato [(date, value), ...]. periods (int): Número de períodos a serem previstos. prompt_type (PromptType): Tipo de prompt a ser gerado: - ZERO_SHOT: Sem exemplos. - FEW_SHOT: Com exemplos de previsões passadas. - COT: Com raciocínio passo a passo (Chain of Thought). - COT_FEW: Combinação de exemplos e raciocínio passo a passo. - CUSTOM: Se desejar utilizar um prompt customizado. ts_format (TSFormat): Formato de serialização da série temporal (ex.: CSV, JSON, Markdown). ts_type (TSType): Tipo de codificação dos valores (ex.: NUMERIC, TEXTUAL). sampling (Sampling, opcional): Estratégia de amostragem dos dados de exemplo. Padrão: Sampling.FRONTEND. num_examples (int, opcional): Quantidade de exemplos a serem gerados. Padrão: 0. template (str, opcional): Prompt customizado se `prompt_type` for CUSTOM. Padrão: None. **kwargs: Se desejar inserir chaves adicionais ao prompt ou substituir as chaves padrão. Returns: str: Prompt formatado pronto para ser usado em um modelo de linguagem. Raises: ValueError: - Se `prompt_type` for inválido. - Se `prompt_type` for CUSTOM e `template` for None. - Se `num_examples` for maior que 0 e não houver períodos suficientes para os exemplos solicitados. Examples: >>> generate( ... train=[("2025-01-01", 100), ("2025-01-02", 200)], ... periods=7, ... prompt_type=PromptType.ZERO_SHOT, ... ts_format=TSFormat.CSV, ... ts_type=TSType.NUMERIC ... ) """ if prompt_type == PromptType.CUSTOM and template is None: raise ValueError(f"Para o tipo CUSTOM é obrigatório um template.") n_periods_input = len(train) n_periods_forecast = periods n_periods_example = periods df = pd.DataFrame(train, columns=['date', 'value']) stats = Statistics(df['value']) stl = stats.trend_seasonality(df) base_kwargs = { "input": format(train, ts_format, ts_type), "input_example": format(train[:4], ts_format, ts_type), "output_example": format(train[:n_periods_example], ts_format, ts_type), "n_periods_input": n_periods_input, "n_periods_forecast": n_periods_forecast, "n_periods_example": n_periods_example, "mean": stats.mean, "median": stats.median, "std": stats.std, "min": stats.min, "max": stats.max, "first_quartile": stats.first_quartile, "third_quartile": stats.third_quartile, "trend_strength": stl[3], "seasonality_strength": stl[4], } base_kwargs.update(kwargs) min_required = n_periods_forecast * 2 * num_examples if n_periods_input < min_required: raise ValueError( f"Para o número de exemplos solicitado é necessário pelo menos {min_required} períodos.") if sampling is not None: sampling_map = { Sampling.FRONTEND: frontend, Sampling.BACKEND: backend, Sampling.RANDOM: random, Sampling.UNIFORM: uniform, } if sampling not in sampling_map: raise ValueError(f"Estratégia de amostragem inválida: {sampling}") samples = sampling_map[sampling]( train, window_size=n_periods_example, num_samples=num_examples) examples = [ f"Exemplo {i}:\n" f"Entrada (histórico):\n{format(history, ts_format, ts_type)}\n" f"Saída (previsto):\n<out>\n{format(forecast, ts_format, ts_type)}\n</out>\n" for i, (history, forecast) in enumerate(samples, 1)] base_kwargs.update({"examples": "\n".join(examples)}) prompt_map = { PromptType.ZERO_SHOT: ZERO_SHOT, PromptType.FEW_SHOT: FEW_SHOT, PromptType.COT_FEW: COT_FEW, PromptType.COT: COT, PromptType.CUSTOM: template, } if prompt_type not in prompt_map: raise ValueError(f"Tipo de prompt inválido: {prompt_type}") try: return prompt_map[prompt_type].format(**base_kwargs) except KeyError as e: raise ValueError(f"Chave {e} não definida.")