Skip to content

Results

What the methods that generate code, run it or call the LLM return:

Returned by Result
forecast_code(), backtest_code() CodeGenerationResult
forecast() ForecastResult
create_cv() CVResult
backtest() BacktestResult
compare() ComparisonResult
ask() AskResult
check_llm() LLMCheckResult

Every result renders itself in a notebook and serializes to JSON, and all of them except AskResult and LLMCheckResult can be the context of ask(). Every result that ask() accepts, plus ForecastingProfile, also describes itself in plain text with describe(), without an LLM: the text is the context ask() sends about it, with the predictions summarized instead of listed row by row, without the instructions addressed to the LLM and with its lists cut when there are many series.

compare() also sends a CompareProgress to its progress_callback when each candidate starts and ends.

skforecast_ai.schemas.results

Classes:

Name Description
RenderedScript

Structured representation of a rendered forecasting script.

LLMContext

Everything ask() needs in order to explain a result object.

CodeGenerationResult

Result of the forecast_code workflow.

SingleRunResult

Shared base for the result of a single forecasting or backtesting run.

ForecastResult

Result of the forecast workflow (executes the pipeline end-to-end).

BacktestResult

Result of the backtest workflow.

CVResult

Result of the create_cv workflow (a cross-validation strategy).

AskResult

Result of the ask workflow (requires LLM).

LLMCheckResult

Outcome of ForecastingAssistant.check_llm().

CandidateFailure

Reason why a single compare() candidate failed to run.

CompareProgress

Progress event that compare() passes to its progress_callback.

ComparisonResult

Result of the compare workflow (ranks several forecasters).

Attributes:

Name Type Description
CVOverrideName
CV_OVERRIDE_NAMES tuple[str, ...]

Attributes

CVOverrideName module-attribute

CVOverrideName = Literal[
    "initial_train_size",
    "fold_stride",
    "refit",
    "fixed_train_size",
    "gap",
    "skip_folds",
    "allow_incomplete_fold",
]

CV_OVERRIDE_NAMES module-attribute

CV_OVERRIDE_NAMES = get_args(CVOverrideName)

Classes

RenderedScript

Bases: BaseModel

Structured representation of a rendered forecasting script.

Splits the rendered script into logical sections so that forecast() can exec the core logic while forecast_code() returns the full standalone script.

Attributes:

Name Type Description
imports str

Import statements required by the script.

data_loading str

Code that loads data from CSV and sets up the index.

core str

Core execution logic (preprocessing, split, fit, predict, metrics). Operates on a pre-existing data DataFrame variable.

Attributes
imports instance-attribute
imports
data_loading instance-attribute
data_loading
core instance-attribute
core
full_script property
full_script

Return the complete standalone script (imports + loading + core).

executable property
executable

Return code suitable for exec() (imports + core, no CSV loading).

LLMContext

Bases: BaseModel

Everything ask() needs in order to explain a result object.

Produced by ExplainableResult._build_llm_context. Keeping the four fields in a single object means ask() never reads a result's own attributes, so a new kind of result can be explained without touching ask().

Attributes:

Name Type Description
text str

Rendered plain-text context block inserted into the user message.

profile ForecastingProfile, default None

Profile echoed back on AskResult and used to select skills.

plan ForecastPlan, default None

Plan echoed back on AskResult.

code str, default None

Generated script echoed back on AskResult. When not None, ask() strips code blocks from the LLM response, since a validated script already exists.

sends_result_values bool, default True

Whether text ships values the result owns (predictions or metrics), which ask() sends regardless of send_data_to_llm. ask() emits DataSentToLLMWarning only when this is True and send_data_to_llm is False, so a result that holds no such values (for example a generated script) does not warn about data it never sends. Defaults to True so a result type that does not declare it keeps the warning.

Attributes
model_config class-attribute instance-attribute
model_config = ConfigDict(arbitrary_types_allowed=True)
text instance-attribute
text
profile class-attribute instance-attribute
profile = None
plan class-attribute instance-attribute
plan = None
code class-attribute instance-attribute
code = None
sends_result_values class-attribute instance-attribute
sends_result_values = True

CodeGenerationResult

Bases: PickleDefaultsMixin, DisplayMixin, ExplainableResult, BaseModel

Result of the forecast_code workflow.

Attributes:

Name Type Description
profile ForecastingProfile

Profile of the input dataset and high-level modeling decisions.

plan ForecastPlan

Detailed forecasting plan.

code str

Generated Python script.

Attributes
profile instance-attribute
profile
plan instance-attribute
plan
code instance-attribute
code

SingleRunResult

Bases: PickleDefaultsMixin, DisplayMixin, ExplainableResult, BaseModel

Shared base for the result of a single forecasting or backtesting run.

Declares the fields that every single run produces, and renders them into an LLM context block through _build_llm_context. Concrete results (for example ForecastResult and BacktestResult) inherit from this class and add the fields specific to them.

Aggregate results that wrap several runs (for example ComparisonResult) do not inherit from this class; they implement ExplainableResult directly so they can send a compact summary rather than a concatenation of everything they wrap.

Every result serializes to JSON with model_dump(mode="json") or model_dump_json(): DataFrames become lists of row records with the index as a leading column. model_dump() keeps the live DataFrames.

Attributes:

Name Type Description
profile ForecastingProfile

Profile of the input dataset and high-level modeling decisions.

plan ForecastPlan

Detailed forecasting plan that was executed.

code str

Generated Python script equivalent to the execution.

predictions pandas DataFrame

Forecasted values produced by the run.

metrics pandas DataFrame

Evaluation metrics produced by the run.

Attributes
model_config class-attribute instance-attribute
model_config = ConfigDict(arbitrary_types_allowed=True)
profile instance-attribute
profile
plan instance-attribute
plan
code instance-attribute
code
predictions instance-attribute
predictions
metrics instance-attribute
metrics

ForecastResult

Bases: SingleRunResult

Result of the forecast workflow (executes the pipeline end-to-end).

Attributes:

Name Type Description
profile ForecastingProfile

Profile of the input dataset and high-level modeling decisions.

plan ForecastPlan

Detailed forecasting plan that was executed.

code str

Generated Python script equivalent to the execution.

metrics pandas DataFrame, None

Evaluation metrics. DataFrame with a series column and one column per metric of plan.metrics_to_compute (by default MAE, MSE and MASE, plus MAPE when the target has no values near zero). For single-series tasks this contains one row; for multi-series tasks one row per level. None in prediction mode (test_size=None), where there is no ground truth to evaluate against.

predictions pandas DataFrame

Forecasted values for the requested steps. When prediction intervals (or quantiles) are requested, the corresponding bound columns are included alongside the point predictions.

BacktestResult

Bases: SingleRunResult

Result of the backtest workflow.

Attributes:

Name Type Description
profile ForecastingProfile

Profile of the input dataset and high-level modeling decisions.

plan ForecastPlan

Detailed forecasting plan that was executed.

cv_config dict

Resolved TimeSeriesFold parameters plus the resulting n_folds and n_fits (trainings), for traceability. For a ForecasterFoundation plan, also inference_windows, its cost: one forecast per series and fold.

metrics pandas DataFrame

Backtesting metric values returned by skforecast.

predictions pandas DataFrame

Full backtest predictions across all folds.

code str

Generated Python script reproducing the backtesting workflow.

explanation str

Human-readable explanation of the backtesting configuration and results summary.

cv_overridden_fields (list, None)

Names of the strategy parameters the user passed to create_cv() instead of its defaults (CVResult.overridden_fields). None when backtest() received a TimeSeriesFold, whose origin is not known.

cv_fields_without_effect list

Names in cv_overridden_fields that have no effect on the forecaster that ran.

cv_llm_configured bool

Whether the LLM of create_cv(prompt=...) set the parameters the user did not pass.

cv_defaults_explanation str

Why the strategy parameters that the user did not pass have their value, and which ones the user passed. Shown after explanation by describe(), ask() and the rich display. Empty when cv_overridden_fields is None.

Attributes
cv_config instance-attribute
cv_config
explanation instance-attribute
explanation
cv_overridden_fields class-attribute instance-attribute
cv_overridden_fields = None
cv_fields_without_effect class-attribute instance-attribute
cv_fields_without_effect = Field(default_factory=list)
cv_llm_configured class-attribute instance-attribute
cv_llm_configured = False
cv_defaults_explanation class-attribute instance-attribute
cv_defaults_explanation = ''

CVResult

Bases: PickleDefaultsMixin, DisplayMixin, ExplainableResult, BaseModel

Result of the create_cv workflow (a cross-validation strategy).

Wraps the TimeSeriesFold splitter together with the resolved parameters, the fold count, the snippet that builds the splitter, and the explanation of the choices. Pass it to backtest(), backtest_code() or compare() as cv, or to ask() as context.

Attributes:

Name Type Description
profile ForecastingProfile

Profile of the input dataset and high-level modeling decisions the strategy was derived from.

plan ForecastPlan

Forecasting plan the strategy was derived from (its steps is the fold horizon).

cv TimeSeriesFold

Configured cross-validation fold splitter.

cv_config dict

Resolved TimeSeriesFold parameters plus the resulting n_folds and n_fits (trainings). For a ForecasterFoundation plan, also inference_windows, its cost: one forecast per series and fold. For a ForecasterStats plan, the strategy skforecast runs: refit=True (it refits ARIMA in every fold) and, when cv does not refit, fixed_train_size=True.

code str

Python snippet that builds the TimeSeriesFold of cv_config, the one the backtesting script embeds.

explanation str

Human-readable explanation of the chosen configuration. When the strategy was derived from a prompt, the LLM reasoning comes first.

overridden_fields list

Names of the parameters the user passed to create_cv() with a value other than None, instead of its defaults: among initial_train_size, fold_stride, refit, fixed_train_size, gap, skip_folds and allow_incomplete_fold. A value equal to the default counts. It holds names only; the values are those of cv. Empty for a result built without create_cv().

fields_without_effect list

Names in overridden_fields that have no effect on the forecaster of plan: fixed_train_size when the forecaster is trained once, and refit or fixed_train_size when skforecast runs another value for a ForecasterStats plan or when the model is not trained (ForecasterFoundation).

llm_configured bool

Whether the LLM of create_cv(prompt=...) set the parameters the user did not pass. False without a prompt and when the LLM call failed and the deterministic defaults were used.

defaults_explanation str

Why the parameters that the user did not pass have their value (the rule that fixed initial_train_size, and why the forecaster is trained once), and which ones the user passed. It is kept apart from explanation, which only states the strategy; describe(), ask() and the rich display show one after the other.

Notes

create_cv() used to return a (TimeSeriesFold, str) tuple. A CVResult is not iterable, so unpacking it raises a TypeError that points to the cv and explanation attributes.

Attributes
model_config class-attribute instance-attribute
model_config = ConfigDict(arbitrary_types_allowed=True)
profile instance-attribute
profile
plan instance-attribute
plan
cv instance-attribute
cv
cv_config instance-attribute
cv_config
code instance-attribute
code
explanation instance-attribute
explanation
overridden_fields class-attribute instance-attribute
overridden_fields = Field(default_factory=list)
fields_without_effect class-attribute instance-attribute
fields_without_effect = Field(default_factory=list)
llm_configured class-attribute instance-attribute
llm_configured = False
defaults_explanation class-attribute instance-attribute
defaults_explanation = ''

AskResult

Bases: DisplayMixin, BaseModel

Result of the ask workflow (requires LLM).

Attributes:

Name Type Description
profile ForecastingProfile, default None

Profile of the input dataset and high-level modeling decisions, if data was provided.

plan ForecastPlan, default None

Detailed forecasting plan, if the agent produced one.

code str, default None

Generated Python script, if the agent produced one.

explanation str

LLM-generated explanation or response.

skills list of str, default []

Names of the skill documents sent to the model, after any trimming to fit the context budget. Recorded because the budget depends on the profile and context size at call time, so the selection cannot be re-derived from the question alone.

Attributes
profile class-attribute instance-attribute
profile = None
plan class-attribute instance-attribute
plan = None
code class-attribute instance-attribute
code = None
explanation instance-attribute
explanation
skills class-attribute instance-attribute
skills = Field(default_factory=list)

LLMCheckResult

Bases: DisplayMixin, BaseModel

Outcome of ForecastingAssistant.check_llm().

Reports how the LLM configuration resolves before any workflow runs: which provider and model the string names, where the credentials come from, what base_url means for that provider, whether the optional dependencies are installed and, for Ollama, whether the server answers. Credential values are never stored, so the result can be printed or serialized safely.

Attributes:

Name Type Description
llm str

Provider string as given, in the format 'provider:model_name'.

provider (str, None)

Provider prefix, None when the string could not be parsed.

model_name (str, None)

Model name, None when the string could not be parsed.

credential_source str

Where credentials come from: 'api_key' (explicit argument), 'env_var' (the provider environment variable read by pydantic-ai), 'aws_credential_chain' (Bedrock), 'none' (Ollama, no credentials needed) or 'unknown' (a prefix that is not built in, resolved by pydantic-ai at call time).

env_var (str, None)

Name of the environment variable that would be read, when the provider has one.

env_var_set (bool, None)

Whether that variable is set. None when it is not consulted (explicit api_key, Ollama, unknown provider) or, for Bedrock, when no AWS variable is set and the credential chain may still succeed through a profile or an instance role.

credential_note (str, None)

Plain-language description of the credential resolution.

base_url (str, None)

Endpoint that will be used, after applying the provider default (Ollama) or dropping a value the provider ignores.

base_url_note (str, None)

What base_url means for this provider, or why it was dropped.

dependencies_ok bool

Whether every module the provider needs is importable.

missing_dependencies list of str

Modules that are not importable, with the extra that installs them.

reachable (bool, None)

For Ollama, whether the server answered. None for other providers.

call_ok (bool, None)

Whether the round-trip call of test_call=True succeeded. None when no call was attempted.

error (str, None)

First failure found, None when every check passed.

ok bool

True when no check failed (computed).

Attributes
llm instance-attribute
llm
provider class-attribute instance-attribute
provider = None
model_name class-attribute instance-attribute
model_name = None
credential_source class-attribute instance-attribute
credential_source = 'unknown'
env_var class-attribute instance-attribute
env_var = None
env_var_set class-attribute instance-attribute
env_var_set = None
credential_note class-attribute instance-attribute
credential_note = None
base_url class-attribute instance-attribute
base_url = None
base_url_note class-attribute instance-attribute
base_url_note = None
dependencies_ok class-attribute instance-attribute
dependencies_ok = True
missing_dependencies class-attribute instance-attribute
missing_dependencies = Field(default_factory=list)
reachable class-attribute instance-attribute
reachable = None
call_ok class-attribute instance-attribute
call_ok = None
error class-attribute instance-attribute
error = None
ok property
ok

Return True when no check failed.

CandidateFailure

Bases: BaseModel

Reason why a single compare() candidate failed to run.

Holds a plain-data snapshot of the failure instead of the live exception. An exception object keeps its traceback frames alive, and those frames reference the execution namespace (which contains a copy of the dataset, the fitted forecaster and the predictions), so retaining one per failed candidate would pin an unbounded amount of memory. The formatted traceback carries the same debugging information at a fixed, small cost, and keeps ComparisonResult serializable.

Attributes:

Name Type Description
error_type str

Class name of the root-cause exception, for example 'ImportError'. An input error of skforecast-ai is named after the built-in class it derives from ('ValueError' for an InvalidInputError), as before these errors had their own classes.

message str

Message of the root-cause exception.

traceback str

Full formatted traceback of the failure.

generated_code str, default None

Generated script that failed, when the failure happened while executing rendered code. None for failures raised before execution, such as an invalid plan.

Methods:

Name Description
from_exception

Build a CandidateFailure from the exception a candidate raised.

summary

Build a concise one-line "ErrorType: message" summary.

Attributes
error_type instance-attribute
error_type
message instance-attribute
message
traceback instance-attribute
traceback
generated_code class-attribute instance-attribute
generated_code = None
Methods:
from_exception classmethod
from_exception(exc)

Build a CandidateFailure from the exception a candidate raised.

A ForecastExecutionError wraps the generated code and the formatted execution traceback; it is unwrapped to its original_error root cause so the failure reports the underlying reason rather than the verbose execution-context message.

Parameters:

Name Type Description Default
exc Exception

Exception raised while evaluating a candidate.

required

Returns:

Name Type Description
failure CandidateFailure

Plain-data snapshot of the failure.

Source code in skforecast_ai/schemas/results.py
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
@classmethod
def from_exception(cls, exc: Exception) -> CandidateFailure:
    """
    Build a `CandidateFailure` from the exception a candidate raised.

    A `ForecastExecutionError` wraps the generated code and the
    formatted execution traceback; it is unwrapped to its
    `original_error` root cause so the failure reports the underlying
    reason rather than the verbose execution-context message.

    Parameters
    ----------
    exc : Exception
        Exception raised while evaluating a candidate.

    Returns
    -------
    failure : CandidateFailure
        Plain-data snapshot of the failure.
    """

    from ..exceptions import ForecastExecutionError, _reported_type_name

    if isinstance(exc, ForecastExecutionError):
        root = exc.original_error
        formatted = exc.execution_traceback
        generated_code = exc.generated_code
    else:
        root = exc
        formatted = "".join(
            traceback.format_exception(type(exc), exc, exc.__traceback__)
        )
        generated_code = None

    return cls(
        error_type     = _reported_type_name(root),
        message        = str(root),
        traceback      = formatted,
        generated_code = generated_code,
    )
summary
summary(max_length=200)

Build a concise one-line "ErrorType: message" summary.

Parameters:

Name Type Description Default
max_length int

Maximum length of the returned summary. Longer summaries are truncated with a trailing ellipsis.

200

Returns:

Name Type Description
summary str

Single-line summary of the failure.

Source code in skforecast_ai/schemas/results.py
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
def summary(self, max_length: int = 200) -> str:
    """
    Build a concise one-line `"ErrorType: message"` summary.

    Parameters
    ----------
    max_length : int, default 200
        Maximum length of the returned summary. Longer summaries are
        truncated with a trailing ellipsis.

    Returns
    -------
    summary : str
        Single-line summary of the failure.
    """

    return _one_line_summary(self.error_type, self.message, max_length)

CompareProgress

Bases: BaseModel

Progress event that compare() passes to its progress_callback.

compare() sends one event when a candidate starts (status 'started') and one when it ends ('succeeded' or 'failed'), so every comparison of total candidates sends 2 * total events.

Attributes:

Name Type Description
candidate str

Name of the candidate the event refers to, as in the name column of ComparisonResult.results.

status {'started', 'succeeded', 'failed'}

Whether the candidate is about to run, ran, or failed.

completed int

Number of candidates that have ended so far, this one included when status is not 'started'.

total int

Number of candidates the comparison runs, the baseline included.

error str, default None

One-line summary of the failure, the same text as the error column of the results table. Only set when status is 'failed'.

Attributes
model_config class-attribute instance-attribute
model_config = ConfigDict(frozen=True, extra='forbid')
candidate instance-attribute
candidate
status instance-attribute
status
completed class-attribute instance-attribute
completed = Field(ge=0)
total class-attribute instance-attribute
total = Field(ge=1)
error class-attribute instance-attribute
error = None

ComparisonResult

Bases: PickleDefaultsMixin, DisplayMixin, ExplainableResult, BaseModel

Result of the compare workflow (ranks several forecasters).

Backtests several forecaster/estimator configurations with the same cross-validation strategy and returns a metric-ranked leaderboard plus the winning configuration as a reusable BacktestResult.

Attributes:

Name Type Description
profile ForecastingProfile

Shared profile used for every candidate.

cv_config dict

Resolved TimeSeriesFold parameters plus the resulting n_folds, applied identically to every candidate.

results pandas DataFrame

Ranked comparison table, one row per candidate sorted best to worst by ranking_metric. Columns are ['rank', 'name', 'forecaster', 'estimator', <metric columns...>], plus an 'error' column when at least one candidate failed.

candidates dict

Mapping of candidate name to the full BacktestResult of every candidate that ran successfully, ordered best to worst. Never empty, so best_name and best_candidate are always resolvable.

failures dict

Mapping of candidate name to a CandidateFailure describing why it failed, in the order the candidates were evaluated. Empty when every candidate succeeded. Each entry carries the root-cause type and message, the full formatted traceback, and the generated code that failed.

ranking_metric str

Name of the metric used to sort results.

explanation str

Human-readable summary of the comparison.

baseline_name str, default None

Name of the ForecasterEquivalentDate candidate that serves as the naive reference, ranked like any other row. None when the comparison has no baseline (baseline=False, multi-series data, or a target with missing values).

cv_overridden_fields (list, None)

Names of the strategy parameters the user passed to create_cv() instead of its defaults (CVResult.overridden_fields). None when compare() received a TimeSeriesFold, whose origin is not known.

cv_fields_without_effect list

Names in cv_overridden_fields that have no effect on the shared strategy.

cv_llm_configured bool

Whether the LLM of create_cv(prompt=...) set the parameters the user did not pass.

cv_defaults_explanation str

Why the strategy parameters that the user did not pass have their value, and which ones the user passed. Shown after explanation by describe(), ask() and the rich display. Empty when cv_overridden_fields is None.

strategy_plan_name str, default None

Name of the row that runs the plan the strategy was created for (CVResult.plan) in a comparison without explicit candidates: 'Strategy plan' when that plan is none of the candidates the profile recommends and runs as one more row, else the name of the candidate that makes the same decisions. None when compare() received a TimeSeriesFold or explicit candidates, or when the plan belongs to a forecaster family that cannot be ranked with the candidates.

best_name str

Name of the top-ranked candidate.

best_candidate BacktestResult

Top-ranked candidate. Always present: a comparison in which every candidate fails raises AllCandidatesFailedError instead of returning a result.

Notes

Every candidate name appears in exactly one of candidates and failures, never in both and never in neither. The two mappings therefore partition the candidates that were evaluated, and their union matches the 'name' column of results.

best_name is a computed field, so it is included by model_dump(); best_candidate is a plain property, so the winning BacktestResult is not serialized a second time.

Every result serializes to JSON with model_dump(mode="json") or model_dump_json(): DataFrames become lists of row records with the index as a leading column. model_dump() keeps the live DataFrames.

Attributes
model_config class-attribute instance-attribute
model_config = ConfigDict(arbitrary_types_allowed=True)
profile instance-attribute
profile
cv_config instance-attribute
cv_config
results instance-attribute
results
candidates class-attribute instance-attribute
candidates = Field(min_length=1)
failures class-attribute instance-attribute
failures = Field(default_factory=dict)
ranking_metric instance-attribute
ranking_metric
explanation instance-attribute
explanation
baseline_name class-attribute instance-attribute
baseline_name = None
cv_overridden_fields class-attribute instance-attribute
cv_overridden_fields = None
cv_fields_without_effect class-attribute instance-attribute
cv_fields_without_effect = Field(default_factory=list)
cv_llm_configured class-attribute instance-attribute
cv_llm_configured = False
cv_defaults_explanation class-attribute instance-attribute
cv_defaults_explanation = ''
strategy_plan_name class-attribute instance-attribute
strategy_plan_name = None
best_name property
best_name

Return the name of the top-ranked candidate.

best_candidate property
best_candidate

Return the BacktestResult of the top-ranked candidate.

Functions:

skforecast_ai.schemas.explainable.ExplainableResult.describe

describe()

Describe the result in plain text.

The text is the context ask() sends to the LLM about this result, with the predictions summarized instead of listed row by row, without the sentences that only tell the LLM how to answer, and with its lists cut as described in the Notes when there are many series. It is deterministic and needs no LLM, so it can be shown to a user or passed to an agent as it is. A plan is described through the script rendered from it: assistant.forecast_code(profile=profile, plan=plan).describe().

Returns:

Name Type Description
description str

Sections wrapped in XML-style tags (<dataset>, <forecast_plan>, ...), the same ones ask() sends.

Notes

It never includes values row by row: predictions are summarized by their shape, columns, minimum, maximum, mean and standard deviation, and metrics are included as computed.

Its length does not grow with the number of series: it keeps the first 15 items of each list (target and exogenous columns, series or columns with missing values, data warnings, lags, window features, failed candidates) and the statistics, significant lags and metrics of the first 5 series, plus the aggregated metric rows (average, weighted_average, pooling), and says how many there are. With 500 series it is about 4,000 to 5,500 characters. The explanation texts (of the profile, the plan, the cross-validation or the comparison) are kept whole, so the lags that the plan explanation names are all listed there. The context of ask() keeps every list whole.

The summary of the predictions is computed over all their rows, and with several series the point forecast is also summarized for each of the first 5 series, while ask() sends their rows. The fold column of a backtest is an identifier: only the number of folds is given. The script of backtest_code() is described as a backtest, with its cross-validation strategy, number of folds and trainings.

Source code in skforecast_ai/schemas/explainable.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def describe(self) -> str:
    """
    Describe the result in plain text.

    The text is the context `ask()` sends to the LLM about this result,
    with the predictions summarized instead of listed row by row,
    without the sentences that only tell the LLM how to answer, and
    with its lists cut as described in the Notes when there are many
    series. It is deterministic and needs no LLM, so it can be shown to
    a user or passed to an agent as it is. A plan is
    described through the script rendered from it:
    `assistant.forecast_code(profile=profile, plan=plan).describe()`.

    Returns
    -------
    description : str
        Sections wrapped in XML-style tags (`<dataset>`,
        `<forecast_plan>`, ...), the same ones `ask()` sends.

    Notes
    -----
    It never includes values row by row: predictions are summarized
    by their shape, columns, minimum, maximum, mean and standard
    deviation, and metrics are included as computed.

    Its length does not grow with the number of series: it keeps the
    first 15 items of each list (target and exogenous columns, series
    or columns with missing values, data warnings, lags, window
    features, failed candidates) and the statistics, significant lags
    and metrics of the first 5 series, plus the aggregated metric rows
    (`average`, `weighted_average`, `pooling`), and says how many
    there are. With 500 series it is about 4,000 to 5,500 characters. The
    explanation texts (of the profile, the plan, the cross-validation
    or the comparison) are kept whole, so the lags that the plan
    explanation names are all listed there. The context of `ask()`
    keeps every list whole.

    The summary of the predictions is computed over all their rows,
    and with several series the point forecast is also summarized for
    each of the first 5 series, while `ask()` sends their rows. The
    `fold` column of a backtest is an
    identifier: only the number of folds is given. The script of
    `backtest_code()` is described as a backtest, with its
    cross-validation strategy, number of folds and trainings.
    """

    return self._build_llm_context(send_data=False, for_describe=True).text