From d04195dc9e9369d235c5f8ee77811e6da8893b3b Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Fri, 30 Jan 2026 08:59:42 -0800 Subject: [PATCH 1/8] add first pass at python eval docs --- docs.json | 12 +- .../tutorials/configure-your-llm.mdx | 102 +++++ .../evaluation/tutorials/run-your-evals.mdx | 101 +++++ .../tutorials/use-custom-eval-template.mdx | 131 ++++++ .../tutorials/use-pre-build-eval-template.mdx | 85 ++++ .../quickstarts/agno_agent_for_evals.ipynb | 429 ++++++++++++++++++ 6 files changed, 858 insertions(+), 2 deletions(-) create mode 100644 docs/phoenix/evaluation/tutorials/configure-your-llm.mdx create mode 100644 docs/phoenix/evaluation/tutorials/run-your-evals.mdx create mode 100644 docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx create mode 100644 docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx create mode 100644 tutorials/quickstarts/agno_agent_for_evals.ipynb diff --git a/docs.json b/docs.json index 8ef6d8f7a5a..8a8c43291a8 100644 --- a/docs.json +++ b/docs.json @@ -144,6 +144,15 @@ "group": "Evaluation", "icon": "clipboard-check", "pages": [ + { + "group": "Tutorial", + "pages": [ + "docs/phoenix/evaluation/tutorials/configure-your-llm", + "docs/phoenix/evaluation/tutorials/use-pre-build-eval-template", + "docs/phoenix/evaluation/tutorials/use-custom-eval-template", + "docs/phoenix/evaluation/tutorials/run-your-evals" + ] + }, "docs/phoenix/evaluation/typescript-quickstart", "docs/phoenix/evaluation/python-quickstart", { @@ -1218,8 +1227,7 @@ } ] } - ] - , + ], "global": { "anchors": [] } diff --git a/docs/phoenix/evaluation/tutorials/configure-your-llm.mdx b/docs/phoenix/evaluation/tutorials/configure-your-llm.mdx new file mode 100644 index 00000000000..454865266f7 --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/configure-your-llm.mdx @@ -0,0 +1,102 @@ +--- +title: "Configure Your LLM" +--- + +## Why do Evals Matter? + +Evaluations let you measure how well an LLM application performs according to defined criteria, rather than relying on subjective judgment. Traces and raw outputs show what an LLM application produced during a run, but they don’t tell you whether the result meets your expectations. Without a way to score quality, such as relevance, correctness, or other task-specific criteria, it’s difficult to compare runs, detect regressions, or verify that changes actually improved behavior. + +Human labeling is the traditional approach, but it does not scale well across frequent iterations or large datasets. Phoenix Evals supports using an LLM as a judge to automate semantic quality assessments, making it possible to evaluate many outputs consistently. Evals in Phoenix are built from lightweight, composable Python components and are designed to work across multiple model providers via adapter layers. + +At its core, an LLM as a Judge eval combines three things: + +1. **The judge model**: the LLM that makes the judgment +2. **A prompt template or rubric**: the criteria you want judged +3. **Your data**: the examples you want to score + +Once you have defined what you want to evaluate and which data you want to run on, the next step is choosing and configuring the judge model. The model and its invocation settings directly affect how criteria are interpreted and how consistent your eval results are. + +We’ll now walk through how to pick and configure that model using the Phoenix evals library! + +--- + +## Option 1: Core LLM Setup + +Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. + +In the Python evals library, judge models are represented by the LLM class. An LLM describes a specific provider and model configuration and can be reused across multiple evaluators. Phoenix uses adapter layers to wrap provider SDKs so that different models can be used through the same interface. + +When you create an LLM, you specify how Phoenix connects to the model provider. This includes details such as the provider name, model identifier, credentials, and any SDK-specific client configuration. These settings are concerned only with connectivity and authentication. + +How the model behaves during evaluation is configured separately. Evaluators specify invocation parameters, such as sampling temperature or maximum token limits, that control how the judge model generates outputs for a particular eval. Keeping these concerns separate makes it easier to reuse the same judge model across different evals while tuning behavior per task. + +The example below illustrates this separation between model configuration and evaluator behavior: + +```python +from phoenix.evals.llm import LLM +from phoenix.evals import ClassificationEvaluator + +# Configure the judge model (connectivity) +judge_llm = LLM( + provider="openai", + model="gpt-4o", + api_key="YOUR_API_KEY", + timeout=30.0, +) + +# Configure the evaluator (invocation behavior) +eval_for_relevance = ClassificationEvaluator( + name="relevance_eval", + prompt_template=( + "Is this answer relevant to the question?\n" + "Question: {input}\n" + "Answer: {output}" + ), + llm=judge_llm, + temperature=0.0, + max_tokens=150, + choices={"irrelevant": 0, "relevant": 1}, +) +``` + +In practice, this means you can change how a model is called for one eval without affecting others, while keeping provider configuration centralized. + +## Option 2: Custom Endpoint (Self-Hosted or OpenAI-Compatible) + +In addition to standard hosted providers, Phoenix also supports evaluating against **custom or self-**hosted endpoints that are compatible with an existing provider SDK. + +Any keyword arguments passed when creating an `LLM` are forwarded to the underlying client SDK. For OpenAI-compatible endpoints, this includes parameters such as `base_url`, `api_key`, and `api_version`. This allows Phoenix to connect to internal or private inference services that expose the same API surface. + +The same separation of concerns applies when using custom endpoints. Connectivity details live on the `LLM`, while generation behavior continues to be controlled by the evaluator. This makes it possible to reuse the same eval definitions regardless of where the judge model is hosted. + +A minimal example of configuring a custom OpenAI-compatible endpoint looks like this: + +```python +from phoenix.evals.llm import LLM + +custom_llm = LLM( + provider="openai", + model="my-self-hosted", + api_key="MY_INTERNAL_KEY", + base_url="https://internal-inference.local/v1", + api_version="2025-01-01", +) +``` + +With this setup, any evaluator that uses `custom_llm` will route judge requests to your custom endpoint while still respecting evaluator-level settings such as temperature and token limits. + +## **Best Practices for Judge Models** + +Judge models are not user-facing. Their role is to apply a rubric consistently, not to generate creative or varied responses. When configuring a judge model, prioritize stability and repeatability over expressiveness. + +### **Favor consistency over creativity** + +Judge models should produce the same judgment when given the same input. Variability makes it harder to compare results across runs or to detect regressions. In most cases, configure the judge with a sampling temperature of 0.0 (or as low as the provider allows) to minimize randomness and improve consistency. + +### **Prefer categorical judgments** + +For most evaluation tasks, categorical outputs are more reliable than numeric ratings. Asking a model to reason about scales or relative magnitudes introduces additional variability and tends to correlate less well with human judgment. Phoenix Evals recommends using categorical labels for judging outputs and mapping them to numeric values only if needed downstream. + +## **Next Steps** + +With the judge model configured, the next step is defining how that model should make judgments. In the following section, we’ll cover how to write a judge prompt or template, including how to express evaluation criteria clearly and structure outputs so they can be scored consistently. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/run-your-evals.mdx b/docs/phoenix/evaluation/tutorials/run-your-evals.mdx new file mode 100644 index 00000000000..8ef349f1aed --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/run-your-evals.mdx @@ -0,0 +1,101 @@ +--- +title: "How to Run Evals" +--- + +## Running Evals + +Now that you have defined what you want to evaluate and how the judge should make decisions, the final piece is the data. With a judge model and an eval template in place, you are ready to actually run your evaluator and produce quality signals. + +Phoenix evaluators can be executed in a few different ways depending on your workflow: + +- Single examples – During development or testing, you can call an evaluator’s `.evaluate()` method on a single record to see how it behaves with one input. This lets you quickly iterate on templates and check edge cases without preparing a full dataset. +- Batch mode – For real evaluation workloads, you run evaluators over many examples at once using tabular data structures such as pandas DataFrames. This is the standard execution path for scoring large collections of examples and for logging results back to Phoenix. + +Whether your examples come from a dataset, an experiment, or exported trace spans, the core execution model in Phoenix is the same: prepare structured data, run evaluators against it, and examine the scores and execution details. + +The sections below walk through the most common ways to run evals and connect results back to Phoenix. + +--- + +## Running Evals in Batch on a DataFrame + +For scoring many examples at once, Phoenix provides dedicated batch execution APIs that operate on pandas DataFrames. This is the standard path for real evaluation workloads. + +Phoenix exposes: + +- `evaluate_dataframe` — Synchronous batch execution +- `async_evaluate_dataframe` — Asynchronous execution with concurrency controls + +Both accept a DataFrame and a list of evaluators, and return a new DataFrame with evaluation results added. For each evaluator, the output includes: + +- A `{score_name}_score` column with the serialized score or `None` if the evaluation failed +- An `{evaluator_name}_execution_details` column with execution metadata (status, duration, exceptions) + +Before running batch evals, make sure evaluator inputs are mapped to your dataframe columns (see Input Mappings below). If an evaluation fails for a row, the execution details make it clear why, and the corresponding score will be `None`. + +Here’s a minimal illustration of synchronous batch evals: + +```python +from phoenix.evals import evaluate_dataframe + +# `df` is a pandas DataFrame with columns matching your evaluator inputs +results_df = evaluate_dataframe(df, [my_evaluator]) +print(results_df.head()) +``` + +Batch evaluation makes it straightforward to score large datasets, filter by quality results, and prepare for logging or experiment comparisons. + +## DataFrames, Datasets, and Experiments + +Although Phoenix supports higher-level abstractions like Datasets and Experiments, all evaluator executions run over tabular data. Behind the scenes, these abstractions resolve to DataFrames, so the same batch APIs apply regardless of source. + +If your examples originate from: + +- A Phoenix Dataset +- A Phoenix Experiment +- Logs or traces exported from Phoenix + +… you can transform them into a DataFrame and run evals in the same way. This unified model keeps eval execution consistent and predictable across different contexts. + +## Running Evals on Phoenix Traces + +We'll now walk through how to run evals on real trace data. Follow along with the following notebook to have traces ingested into Phoenix. + +TODO: \ + +Evaluations are especially useful on traced executions because they let you attach quality signals directly to spans. + +Once we have some trace data, we can start follow the typical workflow for trace evaluations: + +1. Export trace spans into a dataframe. + + ```python + from phoenix.client import Client + + spans_df = Client().spans.get_spans_dataframe(project_name="agno_travel_agent") + ``` +2. Select or transform fields from the spans so they match evaluator inputs (e.g., mapping nested attributes like `attributes.input.value`). + + ```python + TODO + ``` +3. Run batch evals on the prepared dataframe using the same APIs shown earlier. First I will define our evaluator. + + ```python + TODO + ``` +4. Log evaluation results back to Phoenix as span annotations. Phoenix uses the span identifier to attach annotations correctly. + +```python +from phoenix.client import Client + +Client().spans.log_span_annotations_dataframe( + dataframe=eval_df, + annotation_name="relevance", + annotator_kind="LLM", +) +``` + +Once logged, evaluations appear alongside traces in the Phoenix UI, letting you analyze execution behavior and quality side-by-side. + +That's it! You've successfully logged evaluations using trace data. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx b/docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx new file mode 100644 index 00000000000..7a19c11826e --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx @@ -0,0 +1,131 @@ +--- +title: "Create a Custom Eval Template" +--- + +## Why Define Your Own Eval Template? + +Built-in eval templates are designed to cover common evaluation patterns, but they cannot account for all application-specific requirements. When built-ins are insufficient, defining a custom eval template allows you to make evaluation criteria explicit and aligned with how success is defined in your system. + +Custom templates encode task constraints, domain knowledge, and product expectations directly into the evaluation logic. When evaluation criteria reflect real-world requirements, the resulting eval signal is more meaningful and easier to act on. + +This page focuses on defining a custom eval template: how to structure it, what information to include, and how to make judgments consistent. + +--- + +## Structuring a Custom Eval Template + +Eval templates are most effective when they follow the same order in which a judge model processes information. In practice, this means establishing context first, defining the evaluation criteria, presenting the data to be evaluated, and specifying the allowed outcomes. + +The sections below walk through this structure. + +## Defining the Judge’s Role and Evaluation Criteria + +Eval templates typically begin by establishing who the judge is and what task it is performing. This sets the frame for how the rest of the prompt should be interpreted. + +For example, many templates start by positioning the judge as an expert reviewer or evaluator for a specific task. This is followed by a clear description of what should be evaluated and what criteria should be applied. + +A good eval prompt acts as a rubric, not a question. It should narrowly define what counts as correct, relevant, or acceptable for your use case. Vague or open-ended instructions make judgments harder to reproduce across runs. + +In practice, this means: + +- Stating the evaluation task clearly +- Describing the criteria the judge should apply +- Avoiding subjective or underspecified language + +The goal is to remove ambiguity so the same output is judged the same way every time. + +## Defining the Data the Judge Sees + +After defining the evaluation criteria, the template presents the data to be evaluated. This section determines what information the judge receives and how it is structured. + +In most cases, the judge needs: + +- The **input** that produced the output (for example, a user query) +- The **output** being evaluated + +Some evaluations also require additional context, such as retrieved documents, reference material, or system instructions. This information should be included only when it is necessary for making a correct judgment. + +Inputs should be clearly labeled and consistently formatted. Many templates use a delimited block (for example, a `BEGIN DATA / END DATA` section) to make boundaries explicit and reduce ambiguity. + +## Choosing Evaluation Outputs + +Once the judge’s role, criteria, and inputs are defined, the final step is specifying what the evaluation should return. + +In Phoenix, most LLM-as-a-judge evals use **classification-style outputs**. These return a discrete label for each example, making results easy to compare, aggregate, and analyze across runs. + +Classification outputs work well when: + +- Outcomes can be expressed as a small set of categories +- Judgments must remain consistent across many examples +- Results will be used for filtering, comparisons, or experiments + +Common examples include: + +- `correct` / `incorrect` +- `relevant` / `irrelevant` +- `pass` / `fail` + +Other output formats are possible, but categorical labels tend to be the most stable and interpretable starting point. They also integrate cleanly with Phoenix’s tooling for logging, visualization, and comparison. + +## Best Practices for Eval Templates + +Eval templates are sensitive to wording. Small changes can significantly affect evaluation behavior, so templates should be written deliberately and kept focused. + +### Be explicit about criteria + +Avoid vague instructions such as “judge whether this is good” or “rate the quality.” Instead, specify exactly what the judge should evaluate and what should be ignored. If correctness depends on particular facts, constraints, or assumptions, include them directly in the template. + +Explicit criteria reduce ambiguity and improve consistency across runs. + +### Prefer categorical judgments + +For most evaluation tasks, categorical outcomes are more reliable than numeric scores. Labels such as `correct` / `incorrect` or `relevant` / `irrelevant` are easier for a judge to apply consistently and easier to interpret downstream. + +Numeric scoring introduces additional complexity by requiring the judge to reason about scale and relative magnitude. Numeric scores can be useful in limited cases, but only when each value has a clear, unambiguous definition. If numeric outputs are used, the template must explicitly describe what each score represents and how to choose between them. Without strict definitions, numeric scores tend to drift and become difficult to compare. + +## Example: A Complete Custom Eval Template + +The example below defines a classification-style eval template that determines whether an answer correctly addresses a user’s question. It follows the same structure described above. + +```python +from phoenix.evals import ClassificationEvaluator + +correctness_template = """ +You are an expert evaluator assessing whether an answer correctly addresses a user's question. + +Apply the following criteria: +- The answer must directly address the question. +- The answer must be factually consistent with the information provided. +- Irrelevant or partially correct answers should be marked as incorrect. + +[BEGIN DATA] +************ +[Question]: +{input} + +************ +[Answer]: +{output} +************ +[END DATA] + +Return only one of the following labels: +- correct +- incorrect +""" + +correctness_eval = ClassificationEvaluator( + name="correctness", + prompt_template=correctness_template, + choices={"incorrect": 0, "correct": 1}, +) +``` + +This template makes the evaluation logic explicit: + +- The judge’s role and task are clearly defined +- Evaluation criteria are stated upfront +- Inputs are structured and labeled +- Outputs are constrained to a fixed set of labels + +Because the template is explicit and focused, the same output is likely to be judged consistently across runs. This makes eval results easier to trust, compare, and iterate on. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx b/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx new file mode 100644 index 00000000000..27c4612cd28 --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx @@ -0,0 +1,85 @@ +--- +title: "Use Built-In Eval Templates" +--- + +## Why Do Eval Templates Matter? + +Eval templates define what you are evaluating and how that evaluation should be applied. They capture the criteria a judge model uses, the form of the result (such as a label or score), and the assumptions behind the judgment. Even with a well-configured judge model, an evaluation is only as good as its template. + +Templates also provide consistency. Without clearly defined criteria, the same output can be judged differently across runs, making results difficult to compare. The template ensures that every example is evaluated using the same rules. + +A helpful way to think about this is by analogy. If you ask an LLM to “write a story,” the result could be any genre. If you ask for a “short fairy tale with a clear moral,” the output becomes much more predictable. Eval templates work the same way: the more specific the criteria, the more reliable the evaluation. + +Phoenix includes built-in eval templates that encode common evaluation patterns and best practices, allowing you to get reliable signals without designing a rubric from scratch. + +--- + +## Built-In Eval Templates in Phoenix + +Phoenix includes a set of built-in eval templates that cover many common evaluation tasks, such as relevance, faithfulness, summarization quality, and toxicity. These templates are designed to be used as building blocks: they encode a clear evaluation rubric, a structured output format, and defaults that work well with LLM-as-a-judge workflows. + +The table below highlights some of the most commonly used built-in templates. Each template is designed for a specific evaluation goal and returns a well-defined output that can be logged, analyzed, and compared across runs. + +> **Note:**\ +> Built-in templates focus on providing a strong default. They are intentionally opinionated in how criteria are defined and how outputs are structured, which helps produce more consistent results out of the box. + +| | | | +| :----------------: | :-------------: | :-------------: | +| Faithfulness | Q&A Correctness | Frustration | +| Tool Selection | Tool Invocation | Code Generation | +| Document Relevance | SQL Generation | Summarization | + +## When to Use a Built-In Template + +Built-in eval templates are a good choice when: + +- You are evaluating a common task (for example, relevance or correctness) +- You want fast, reliable signal without designing a rubric from scratch +- You are early in iteration and want to establish a baseline + +These templates are especially useful for exploratory analysis, regression detection, and experiment comparisons, where consistency across many runs is more important than fine-grained customization. + +## How to Use a Built-In Template + +Using a built-in eval template follows the same workflow as any other Phoenix eval. You select the template that matches your evaluation goal, configure the judge model you want to use, and then run the evaluator on your data. + +Built-in templates are designed to work with standard Phoenix evaluator interfaces, so they can be run on datasets, dataframes, or trace-derived data in the same way as custom evaluators. This means you can introduce them into an existing evaluation workflow without changing how data is loaded or how results are logged. + +In practice, using a built-in template typically involves: + +- Choosing a template that matches the quality dimension you want to evaluate +- Providing or reusing a configured judge model +- Mapping your data fields to the inputs expected by the template +- Running the evaluation in batch and inspecting the resulting scores or labels + +The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: + +```python +from phoenix.evals import ClassificationEvaluator +from phoenix.evals.metrics import CorrectnessEvaluator + +# Create the evaluator +correctness_eval = CorrectnessEvaluator(llm=llm) + +# Inspect the evaluator's requirements +print(correctness_eval.describe()) +``` + +Once defined, this evaluator can be run on a dataframe or trace-derived dataset and logged to Phoenix like any other eval. Because the template returns structured outputs, its results can be compared across runs and combined with other evaluations. + +## When to Customize + +Built-in eval templates are designed to cover common evaluation patterns, but they are not intended to fit every use case. As your application evolves, you may need more control over how quality is defined and measured. + +Some common reasons to customize an eval include: + +- You need to evaluate application-specific behavior that is not captured by a generic rubric +- You want to enforce strict formatting, structural, or policy constraints +- You need to distinguish between multiple types of failure rather than a single pass/fail outcome +- You want to align eval behavior more closely with how humans review outputs in practice + +Built-in templates are still a good starting point in these cases. Many teams begin with a built-in template to establish a baseline, inspect failures in Phoenix, and then adapt the template into a custom evaluator. + +## What’s Next + +In the next section, we’ll walk through how to create a custom LLM as a Judge template and the best practices surround how to craft it, and how to create a resuable evaluator in Phoenix. \ No newline at end of file diff --git a/tutorials/quickstarts/agno_agent_for_evals.ipynb b/tutorials/quickstarts/agno_agent_for_evals.ipynb new file mode 100644 index 00000000000..dd46d91612b --- /dev/null +++ b/tutorials/quickstarts/agno_agent_for_evals.ipynb @@ -0,0 +1,429 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "zw-BimTKswh4" + }, + "source": [ + "
\n", + "

\n", + " \"phoenix\n", + "
\n", + " Docs\n", + " |\n", + " GitHub\n", + " |\n", + " Community\n", + "

\n", + "
\n", + "

Agno Travel Agent Tracing Project

" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l8EbE_41szw0" + }, + "source": [ + "We will create a simple travel agent powered by the Agno framework and OpenAI models. We’ll begin by installing the necessary OpenInference packages and setting up tracing with Arize.\n", + "\n", + "Next, we’ll define a set of basic tools that provide destination information, estimate trip budgets, and suggest local activities.\n", + "\n", + "Finally, we’ll build and run our agent, viewing the resulting trace outputs in Phoenix to understand how the agent uses its tools and reasoning." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Gxe7vsT9hKHX" + }, + "source": [ + "You will need to install Arize Phoenix in your terminal (`pip install arize-phoenix`) an OpenAI API key, and a free [Tavily](https://auth.tavily.com/) API Key.\n", + "\n", + "Ensure you have `phoenix serve` running in your terminal prior to running the following cells. " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HzvQoYIksr30" + }, + "source": [ + "# Set up keys and dependenies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "1XtfV7qF6HKg", + "outputId": "70de22d9-591e-4b47-ca33-209070dac3a1" + }, + "outputs": [], + "source": [ + "%pip install -qqqqqq arize-phoenix-otel agno openai openinference-instrumentation-agno openinference-instrumentation-openai httpx" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "hAapTFAi-35H", + "outputId": "1df61df2-4291-4c4e-b4f2-59fb78970eda" + }, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "\n", + "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\"🔑 Enter your OpenAI API Key: \")\n", + "\n", + "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\"🔑 Enter your Tavily API Key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AFdPHLMFuEsl" + }, + "source": [ + "# Setup tracing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "id": "Y8dSorscJDPT", + "outputId": "957bb02a-3faa-4002-ce19-2ab2cf9fa077" + }, + "outputs": [], + "source": [ + "from phoenix.otel import register\n", + "\n", + "tracer_provider = register(project_name=\"agno_travel_agent\", auto_instrument=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Gjd7wU9OuIAQ" + }, + "source": [ + "# Define tools" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mnRbOa8tg_B7" + }, + "source": [ + "First, we’ll define a few helper functions to support our tools. In particular, we’ll use Tavily Search to help the tools gather general information about each destination." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 211 + }, + "id": "H3gLnYV2_KhS", + "outputId": "d24cc345-4cf7-43c3-da38-3f6fc3876ac9" + }, + "outputs": [], + "source": [ + "# --- Helper functions for tools ---\n", + "import httpx\n", + "\n", + "def _search_api(query: str) -> str | None:\n", + " \"\"\"Try Tavily search first, fall back to None.\"\"\"\n", + " tavily_key = os.getenv(\"TAVILY_API_KEY\")\n", + " if not tavily_key:\n", + " return None\n", + " try:\n", + " resp = httpx.post(\n", + " \"https://api.tavily.com/search\",\n", + " json={\n", + " \"api_key\": tavily_key,\n", + " \"query\": query,\n", + " \"max_results\": 3,\n", + " \"search_depth\": \"basic\",\n", + " \"include_answer\": True,\n", + " },\n", + " timeout=8,\n", + " )\n", + " data = resp.json()\n", + " answer = data.get(\"answer\") or \"\"\n", + " snippets = [r.get(\"content\", \"\") for r in data.get(\"results\", [])]\n", + " combined = \" \".join([answer] + snippets).strip()\n", + " return combined[:400] if combined else None\n", + " except Exception:\n", + " return None\n", + "\n", + "\n", + "def _compact(text: str, limit: int = 200) -> str:\n", + " \"\"\"Compact text for cleaner outputs.\"\"\"\n", + " cleaned = \" \".join(text.split())\n", + " return cleaned if len(cleaned) <= limit else cleaned[:limit].rsplit(\" \", 1)[0]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "B4fxzijBgLG5" + }, + "source": [ + "Our agent will have access to three tools, which we’ll continue to enhance in upcoming labs:\n", + "\n", + "1. Essential Info – Provides key travel details about the destination, such as weather and general conditions.\n", + "\n", + "2. Budget Basics – Offers insights into travel costs and helps plan budgets based on selected activities.\n", + "\n", + "3. Local Flavor – Recommends unique local experiences and cultural highlights." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "tNgVS4Fk_QRR" + }, + "outputs": [], + "source": [ + "from agno.tools import tool\n", + "\n", + "@tool\n", + "def essential_info(destination: str) -> str:\n", + " \"\"\"Get basic travel info (weather, best time, attractions, etiquette).\"\"\"\n", + " q = f\"{destination} travel essentials weather best time top attractions etiquette\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} essentials: {_compact(s)}\"\n", + "\n", + " return f\"{destination} is a popular travel destination. Expect local culture, cuisine, and landmarks worth exploring.\"\n", + "\n", + "@tool\n", + "def budget_basics(destination: str, duration: str) -> str:\n", + " \"\"\"Summarize travel cost categories.\"\"\"\n", + " q = f\"{destination} travel budget average daily costs {duration}\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} budget ({duration}): {_compact(s)}\"\n", + " return f\"Budget for {duration} in {destination} depends on lodging, meals, transport, and attractions.\"\n", + "\n", + "@tool\n", + "def local_flavor(destination: str, interests: str = \"local culture\") -> str:\n", + " \"\"\"Suggest authentic local experiences.\"\"\"\n", + " q = f\"{destination} authentic local experiences {interests}\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} {interests}: {_compact(s)}\"\n", + " return f\"Explore {destination}'s unique {interests} through markets, neighborhoods, and local eateries.\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "o48IXEMJuJuI" + }, + "source": [ + "# Define agent" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0hCYAqOShX-c" + }, + "source": [ + "Next, we’ll construct our agent. The Agno framework makes this process straightforward by allowing us to easily define key parameters such as the model, instructions, and tools." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "id": "Sb1jqHcU_R3r" + }, + "outputs": [], + "source": [ + "from agno.agent import Agent\n", + "from agno.models.openai import OpenAIChat\n", + "\n", + "trip_agent = Agent(\n", + " name=\"TripPlanner\",\n", + " role=\"AI Travel Assistant\",\n", + " model=OpenAIChat(id=\"gpt-4.1\"),\n", + " instructions=(\n", + " \"You are a friendly and knowledgeable travel planner. \"\n", + " \"Combine multiple tools to create a trip plan including essentials, budget, and local flavor. \"\n", + " \"Keep the tone natural, clear, and under 1000 words.\"\n", + " ),\n", + " markdown=True,\n", + " tools=[essential_info, budget_basics, local_flavor],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HAKB1WBwuLh2" + }, + "source": [ + "# Run agent" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "I6ZbhUKghmtG" + }, + "source": [ + "Finally, we are ready to run our agent! Run this cell to see an example in action." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 1000, + "referenced_widgets": [ + "9b9ebc48bdad4ef78068eff7a43c6b9e", + "0c6e8d6fc75d43b9ae44f1c066b49d77" + ] + }, + "id": "FVDKZT9x_U-5", + "outputId": "5aad5802-b2d3-4d89-b692-d937839350c4" + }, + "outputs": [], + "source": [ + "# --- Example usage ---\n", + "destination = \"Tokyo\"\n", + "duration = \"5 days\"\n", + "interests = \"food, culture\"\n", + "\n", + "query = f\"\"\"\n", + "Plan a {duration} trip to {destination}.\n", + "Focus on {interests}.\n", + "Include essential info, budget breakdown, and local experiences.\n", + "\"\"\"\n", + "trip_agent.print_response(\n", + " query,\n", + " stream = True\n", + ")" + ] + } + ], + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "display_name": "Python 3", + "name": "python3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "0c6e8d6fc75d43b9ae44f1c066b49d77": { + "model_module": "@jupyter-widgets/base", + "model_module_version": "1.2.0", + "model_name": "LayoutModel", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "9b9ebc48bdad4ef78068eff7a43c6b9e": { + "model_module": "@jupyter-widgets/output", + "model_module_version": "1.0.0", + "model_name": "OutputModel", + "state": { + "_dom_classes": [], + "_model_module": "@jupyter-widgets/output", + "_model_module_version": "1.0.0", + "_model_name": "OutputModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/output", + "_view_module_version": "1.0.0", + "_view_name": "OutputView", + "layout": "IPY_MODEL_0c6e8d6fc75d43b9ae44f1c066b49d77", + "msg_id": "", + "outputs": [ + { + "data": { + "text/html": "
▰▱▱▱▱▱▱ Thinking...\n┏━ Message ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n                                                                                                                 \n                                                                                                                 \n Plan a 5 days trip to Tokyo.                                                                                    \n Focus on food, culture.                                                                                         \n Include essential info, budget breakdown, and local experiences.                                                \n                                                                                                                 \n                                                                                                                 \n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n┏━ Response (17.6s) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n                                                                                                                 \n ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \n5-Day Tokyo Trip: Food & Culture Focus\n ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ \n                                                                                                                 \n                                                                                                                 \n                                                 Essential Info                                                  \n                                                                                                                 \n Best Time to Visit: November is ideal—mild weather and autumn foliage.                                       \n Key Attractions: Meiji Shrine, Senso-ji Temple, Ueno Park, teamLab Borderless, Tsukiji Market, Shibuya &     \n    Harajuku.                                                                                                    \n Etiquette Tips: Bow as a greeting, speak quietly on public transport, remove shoes in homes and some         \n    restaurants, and avoid eating while walking.                                                                 \n Getting Around: Efficient subways & trains; get a prepaid Suica/Pasmo card for convenience.                  \n                                                                                                                 \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n                                                                                                                 \n                                      Budget Breakdown (5 Days, Per Person)                                      \n                                                                                                                 \n                                                                                                                 \n   Category         Estimated Range                                                                              \n  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                                                             \n   Accommodation   $60 – $300/night                                                                              \n   Food              $30 – $100/day                                                                              \n   Local Transit       $7 – $15/day                                                                              \n   Activities        $20 – $100/day                                                                              \n   Total               $650 – $1800                                                                              \n                                                                                                                 \n                                                                                                                 \n Budget stays (hostels/capsules) vs. mid-range (business hotels) account for cost spread. Splurges (Michelin  \n    meals, private tours) will increase this.                                                                    \n Cash is widely used, but credit cards are accepted in many places.                                           \n                                                                                                                 \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n                                                                                                                 \n                                           Authentic Local Experiences                                           \n                                                                                                                 \n Food                                                                                                            \n                                                                                                                 \n Try an omakase sushi dinner in Tsukiji or Ginza.                                                             \n Join a Japanese cooking class—learn to make ramen or wagashi (sweets).                                       \n Hop izakayas in Shinjuku’s Omoide Yokocho and Golden Gai.                                                    \n Savor street food at Ameya-Yokocho (Ueno) or Takeshita Street (Harajuku).                                    \n                                                                                                                 \n Culture                                                                                                         \n                                                                                                                 \n Experience a traditional tea ceremony in Asakusa.                                                            \n Visit the Edo-Tokyo Museum or Nezu Museum for art and history.                                               \n Explore Yanaka for old Tokyo vibes and crafts.                                                               \n See Meiji Shrine (walk through Yoyogi Park), and Senso-ji (Asakusa's iconic temple).                         \n                                                                                                                 \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n                                                                                                                 \n                                             Sample 5-Day Itinerary                                              \n                                                                                                                 \n                                         Day 1: Historic Asakusa & Ueno                                          \n                                                                                                                 \n Senso-ji Temple, Nakamise Street snacks, Ameya-Yokocho Market                                                \n Ueno Park (museums if interested)                                                                            \n                                                                                                                 \n                                     Day 2: Shibuya & Harajuku Youth Culture                                     \n                                                                                                                 \n Scramble crossing, Hachiko Statue                                                                            \n Takeshita Street crepes, quirky shops                                                                        \n Meiji Shrine, Yoyogi Park                                                                                    \n                                                                                                                 \n                                     Day 3: Foodie Focus in Tsukiji & Ginza                                      \n                                                                                                                 \n Fresh sushi breakfast/lunch at Tsukiji Market                                                                \n Cooking class nearby                                                                                         \n Stroll luxury flagship stores and Kabuki-za Theatre in Ginza                                                 \n                                                                                                                 \n                                           Day 4: Day Trip or Museums                                            \n                                                                                                                 \n Edo-Tokyo Museum, teamLab Planets/Borderless, or Ghibli Museum (advance booking)                             \n Explore old neighborhoods in Yanaka                                                                          \n                                                                                                                 \n                                           Day 5: Nightlife & Izakayas                                           \n                                                                                                                 \n Shinjuku: Omoide Yokocho (tiny bars, yakitori)                                                               \n Golden Gai for drinks and late-night bites                                                                   \n Late walk in illuminated Shinjuku/Kabukicho                                                                  \n                                                                                                                 \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n                                                                                                                 \n                                                   Quick Tips                                                    \n                                                                                                                 \n Reserve popular restaurants/tours early: They fill up fast!                                                  \n Cash is king for small eats & market stalls.                                                                 \n Transportation: Use Google Maps or a transit app for trains.                                                 \n                                                                                                                 \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n Enjoy the rhythm of Tokyo—blend tradition and trend, and bring an appetite! If you’d like more specifics        \n (restaurant recs, booking links), let me know!                                                                  \n                                                                                                                 \n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n
\n", + "text/plain": "\u001b[32m▰▱▱▱▱▱▱\u001b[0m Thinking...\n\u001b[36m┏━\u001b[0m\u001b[36m Message \u001b[0m\u001b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[36m━┓\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mPlan a 5 days trip to Tokyo.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mFocus on food, culture.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mInclude essential info, budget breakdown, and local experiences.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n\u001b[34m┏━\u001b[0m\u001b[34m Response (17.6s) \u001b[0m\u001b[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[34m━┓\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┃ \u001b[1m5-Day Tokyo Trip: Food & Culture Focus\u001b[0m ┃ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mEssential Info\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mBest Time to Visit\u001b[0m: November is ideal—mild weather and autumn foliage. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mKey Attractions\u001b[0m: Meiji Shrine, Senso-ji Temple, Ueno Park, teamLab Borderless, Tsukiji Market, Shibuya & \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mHarajuku. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mEtiquette Tips\u001b[0m: Bow as a greeting, speak quietly on public transport, remove shoes in homes and some \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mrestaurants, and avoid eating while walking. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mGetting Around\u001b[0m: Efficient subways & trains; get a prepaid Suica/Pasmo card for convenience. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mBudget Breakdown (5 Days, Per Person)\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1m \u001b[0m\u001b[1mCategory\u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Estimated Range\u001b[0m\u001b[1m \u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Accommodation $60 – $300/night \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Food $30 – $100/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Local Transit $7 – $15/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Activities $20 – $100/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mTotal\u001b[0m \u001b[1m$650 – $1800\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mBudget stays\u001b[0m (hostels/capsules) vs. mid-range (business hotels) account for cost spread. Splurges (Michelin \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mmeals, private tours) will increase this. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mCash is widely used, but credit cards are accepted in many places. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mAuthentic Local Experiences\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mFood\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mTry an omakase sushi dinner in Tsukiji or Ginza. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mJoin a Japanese cooking class—learn to make ramen or wagashi (sweets). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mHop izakayas in Shinjuku’s Omoide Yokocho and Golden Gai. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSavor street food at Ameya-Yokocho (Ueno) or Takeshita Street (Harajuku). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mCulture\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExperience a traditional tea ceremony in Asakusa. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mVisit the Edo-Tokyo Museum or Nezu Museum for art and history. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExplore Yanaka for old Tokyo vibes and crafts. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSee Meiji Shrine (walk through Yoyogi Park), and Senso-ji (Asakusa's iconic temple). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mSample 5-Day Itinerary\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 1: Historic Asakusa & Ueno\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSenso-ji Temple, Nakamise Street snacks, Ameya-Yokocho Market \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mUeno Park (museums if interested) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 2: Shibuya & Harajuku Youth Culture\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mScramble crossing, Hachiko Statue \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mTakeshita Street crepes, quirky shops \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mMeiji Shrine, Yoyogi Park \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 3: Foodie Focus in Tsukiji & Ginza\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mFresh sushi breakfast/lunch at Tsukiji Market \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mCooking class nearby \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mStroll luxury flagship stores and Kabuki-za Theatre in Ginza \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 4: Day Trip or Museums\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mEdo-Tokyo Museum, teamLab Planets/Borderless, or Ghibli Museum (advance booking) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExplore old neighborhoods in Yanaka \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 5: Nightlife & Izakayas\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mShinjuku: Omoide Yokocho (tiny bars, yakitori) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mGolden Gai for drinks and late-night bites \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mLate walk in illuminated Shinjuku/Kabukicho \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mQuick Tips\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mReserve popular restaurants/tours early:\u001b[0m They fill up fast! \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mCash is king\u001b[0m for small eats & market stalls. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mTransportation:\u001b[0m Use Google Maps or a transit app for trains. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Enjoy the rhythm of Tokyo—blend tradition and trend, and bring an appetite! If you’d like more specifics \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m (restaurant recs, booking links), let me know! \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n" + }, + "metadata": {}, + "output_type": "display_data" + } + ] + } + } + } + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} From 9c82535a0f42c99bfc8f4f624a02d4f4e6dc85dd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 30 Jan 2026 17:01:41 +0000 Subject: [PATCH 2/8] chore: update sitemap.xml --- docs/phoenix/sitemap.xml | 16 ++++++++++++++++ sitemap.xml | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/docs/phoenix/sitemap.xml b/docs/phoenix/sitemap.xml index a7fc10bd77e..c018ea9a807 100644 --- a/docs/phoenix/sitemap.xml +++ b/docs/phoenix/sitemap.xml @@ -172,6 +172,22 @@ https://arize.com/docs/phoenix/tracing/how-to-tracing/advanced/multimodal-tracing 2026-01-27T22:36:31+00:00 + + https://arize.com/docs/phoenix/evaluation/tutorials/configure-your-llm + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/use-custom-eval-template + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/run-your-evals + 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/typescript-quickstart 2026-01-27T22:36:31+00:00 diff --git a/sitemap.xml b/sitemap.xml index a7fc10bd77e..c018ea9a807 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -172,6 +172,22 @@ https://arize.com/docs/phoenix/tracing/how-to-tracing/advanced/multimodal-tracing 2026-01-27T22:36:31+00:00 + + https://arize.com/docs/phoenix/evaluation/tutorials/configure-your-llm + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/use-custom-eval-template + 2026-01-30T17:01:41+00:00 + + + https://arize.com/docs/phoenix/evaluation/tutorials/run-your-evals + 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/typescript-quickstart 2026-01-27T22:36:31+00:00 From 2519a8584b2dfdd6571dc6d05a7550993c320fde Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Mon, 2 Feb 2026 09:33:40 -0800 Subject: [PATCH 3/8] adding langchain base agent --- docs/phoenix/evaluation/tutorials/page-1.mdx | 156 ++ .../langchain-ts-quickstart/.gitignore | 6 + .../langchain-ts-quickstart/README.md | 114 + .../langchain-ts-quickstart/SETUP.md | 92 + .../langchain-ts-quickstart/package-lock.json | 2287 +++++++++++++++++ .../langchain-ts-quickstart/package.json | 22 + .../langchain-ts-quickstart/pnpm-lock.yaml | 1200 +++++++++ .../langchain-ts-quickstart/src/index.ts | 101 + .../src/instrumentation.ts | 26 + .../langchain-ts-quickstart/tsconfig.json | 21 + 10 files changed, 4025 insertions(+) create mode 100644 docs/phoenix/evaluation/tutorials/page-1.mdx create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/.gitignore create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/README.md create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/SETUP.md create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/package-lock.json create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/package.json create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/src/index.ts create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/src/instrumentation.ts create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json diff --git a/docs/phoenix/evaluation/tutorials/page-1.mdx b/docs/phoenix/evaluation/tutorials/page-1.mdx new file mode 100644 index 00000000000..9244949ce29 --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/page-1.mdx @@ -0,0 +1,156 @@ +--- +title: "Run evals with built-in eval templates" +--- + +[TODO]: need to add some sort of short intro here. + + +At its core, an LLM as a Judge eval combines three things: + +1. **The judge model**: the LLM that makes the judgment +2. **A prompt template or rubric**: the criteria you want judged +3. **Your data**: the examples you want to score + +Once you have defined what you want to evaluate and which data you want to run on, the next step is choosing and configuring the judge model. The model and its invocation settings directly affect how criteria are interpreted and how consistent your eval results are. + +We’ll now walk through how to pick and configure that model using the Phoenix evals. + +Follow along with the following code assets: + + + + Companion TypeScript project with runnable examples + + + Companion Python project with runnable examples + + + +TODO: \ + +## Configure Core LLM Setup + +[TODO] do not talk specifically only abt the Python evals library, i want this is to content that someone using either python or ts evals library can use. + +Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. + +In the Python evals library, judge models are represented by the LLM class. An LLM describes a specific provider and model configuration and can be reused across multiple evaluators. Phoenix uses adapter layers to wrap provider SDKs so that different models can be used through the same interface. + +When you create an LLM, you specify how Phoenix connects to the model provider. This includes details such as the provider name, model identifier, credentials, and any SDK-specific client configuration. These settings are concerned only with connectivity and authentication. + +How the model behaves during evaluation is configured separately. Evaluators specify invocation parameters, such as sampling temperature or maximum token limits, that control how the judge model generates outputs for a particular eval. Keeping these concerns separate makes it easier to reuse the same judge model across different evals while tuning behavior per task. + +The example below illustrates this separation between model configuration and evaluator behavior: + + + ```python + from phoenix.evals.llm import LLM + + judge_llm = LLM( + provider="openai", + model="gpt-4o", + api_key="YOUR_API_KEY", + timeout=30.0, + ) + ``` + + + + + + +In practice, this means you can change how a model is called for one eval without affecting others, while keeping provider configuration centralized. + +## Built-In Eval Templates in Phoenix + +Phoenix includes a set of built-in eval templates that cover many common evaluation tasks, such as relevance, faithfulness, summarization quality, and toxicity. These templates are designed to be used as building blocks: they encode a clear evaluation rubric, a structured output format, and defaults that work well with LLM-as-a-judge workflows. + +[TODO] add in link to pre-build eval page + +[TODO] make this more concise (a couple sentences:) + +Built-in eval templates are a good choice when: + +- You are evaluating a common task (for example, relevance or correctness) +- You want fast, reliable signal without designing a rubric from scratch +- You are early in iteration and want to establish a baseline + +These templates are especially useful for exploratory analysis, regression detection, and experiment comparisons, where consistency across many runs is more important than fine-grained customization. + +The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: + + + ```python + from phoenix.evals import ClassificationEvaluator + from phoenix.evals.metrics import CorrectnessEvaluator + + # Create the evaluator + correctness_eval = CorrectnessEvaluator(llm=llm) + + # Inspect the evaluator's requirements + print(correctness_eval.describe()) + ``` + + + + + + +Once defined, this evaluator can be run on a dataframe or trace-derived dataset and logged to Phoenix like any other eval. Because the template returns structured outputs, its results can be compared across runs and combined with other evaluations. + +## Running Evals on Phoenix Traces + +We'll now walk through how to run evals on real trace data. + +1. Export trace spans into a dataframe. + + + ```python + from phoenix.client import Client + + spans_df = Client().spans.get_spans_dataframe(project_name="agno_travel_agent") + ``` + + + + + +2. Select or transform fields from the spans so they match evaluator inputs (e.g., mapping nested attributes like `attributes.input.value`). + + + + + + + + + +3. Run batch evals on the prepared dataframe using the same APIs shown earlier. First I will define our evaluator. + + + + + + + + + + +4. Log evaluation results back to Phoenix as span annotations. Phoenix uses the span identifier to attach annotations correctly. + + + + ```python + from phoenix.client import Client + + Client().spans.log_span_annotations_dataframe( + dataframe=eval_df, + annotation_name="relevance", + annotator_kind="LLM", + ) + ``` + + + + + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/.gitignore b/tutorials/quickstarts/langchain-ts-quickstart/.gitignore new file mode 100644 index 00000000000..be340aa48dd --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/.gitignore @@ -0,0 +1,6 @@ +node_modules/ +dist/ +.env +.DS_Store +*.log + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/README.md b/tutorials/quickstarts/langchain-ts-quickstart/README.md new file mode 100644 index 00000000000..e1b7ac2688a --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/README.md @@ -0,0 +1,114 @@ +# LangChain TypeScript Quickstart + +A simple LangChain TypeScript application with Phoenix tracing integration. + +## Prerequisites + +- **Node.js 18+** installed +- **Phoenix** running locally (`pip install arize-phoenix && phoenix serve`) or access to Phoenix Cloud +- **API key** for either: + - OpenAI (`OPENAI_API_KEY`) - for GPT models + - Anthropic (`ANTHROPIC_API_KEY`) - for Claude models + +## Setup + +1. **Install dependencies:** + +```bash +cd langchain-ts-quickstart +npm install +``` + +2. **Set environment variables:** + +```bash +# Choose one: +export OPENAI_API_KEY=your-openai-api-key +# OR +export ANTHROPIC_API_KEY=your-anthropic-api-key + +# Optional: Custom Phoenix project name +export PHOENIX_PROJECT_NAME=langchain-ts-quickstart +``` + +3. **Start Phoenix** (if running locally): + +```bash +pip install arize-phoenix +phoenix serve +``` + +## Running the Application + +```bash +npm start +``` + +This will: +- Create a simple LangChain chain with a prompt template and LLM +- Process multiple questions through the chain +- Send all traces to Phoenix for visualization + +## What to Look For in Phoenix + +Open Phoenix at `http://localhost:6006` after running the application. + +### Traces + +Each chain invocation creates a trace that shows: +- **Prompt Template** - The formatted prompt sent to the LLM +- **LLM Call** - The actual API call to OpenAI +- **Output Parser** - The parsed response + +You can see: +- Token usage (input/output tokens) +- Latency metrics +- The full prompt and response +- Model information + +### Project Structure + +``` +langchain-ts-quickstart/ +├── package.json # Dependencies and scripts +├── tsconfig.json # TypeScript configuration +├── .gitignore # Git ignore file +├── src/ +│ ├── instrumentation.ts # Phoenix/OpenTelemetry setup (import this first!) +│ └── index.ts # Main application with LangChain agent +└── README.md # This file +``` + +**Key Files:** +- `src/instrumentation.ts` - Sets up Phoenix tracing (must be imported first) +- `src/index.ts` - Main application code with LangChain chain +- `package.json` - Dependencies: `langchain`, `@langchain/openai`, `@langchain/anthropic`, `@arizeai/phoenix-otel` + +## Next Steps + +- Add more complex chains with multiple steps +- Integrate tools and agents +- Add RAG (Retrieval Augmented Generation) capabilities +- Set up evaluations to measure response quality + +## Troubleshooting + +**Error: No API key found** +- Make sure you've exported either `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` +- Example: `export OPENAI_API_KEY=your-key` + +**No traces appearing in Phoenix** +- Ensure Phoenix is running: `phoenix serve` +- Check that the Phoenix endpoint is accessible (default: http://localhost:6006) +- Verify the project name matches in Phoenix UI +- Make sure `instrumentation.ts` is imported at the very top of your main file + +**TypeScript errors** +- Run `npm install` to ensure all dependencies are installed +- Check that you're using Node.js 18+ +- Make sure you're using the correct import paths (ES modules) + +**Module not found errors** +- Ensure you've run `npm install` +- Check that `langchain` and `zod` are in your `package.json` dependencies + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/SETUP.md b/tutorials/quickstarts/langchain-ts-quickstart/SETUP.md new file mode 100644 index 00000000000..6300fa5e237 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/SETUP.md @@ -0,0 +1,92 @@ +# Quick Setup Guide + +Follow these steps to get your LangChain TypeScript application running: + +## 1. Navigate to the directory + +```bash +cd quickstarts/langchain-ts-quickstart +``` + +## 2. Install dependencies + +```bash +npm install +``` + +This installs: +- `langchain` - The main LangChain library +- `zod` - Schema validation (used by LangChain tools) +- `@arizeai/phoenix-otel` - Phoenix tracing integration +- `tsx` - TypeScript execution (dev dependency) + +## 3. Set your API key + +Choose one: + +```bash +# For OpenAI (GPT models) +export OPENAI_API_KEY=your-key-here + +# OR for Anthropic (Claude models) +export ANTHROPIC_API_KEY=your-key-here +``` + +## 4. Start Phoenix (if running locally) + +In a separate terminal: + +```bash +pip install arize-phoenix +phoenix serve +``` + +Phoenix will be available at `http://localhost:6006` + +## 5. Run the application + +```bash +npm start +``` + +You should see: +- Questions being processed +- Agent responses +- Instructions to view traces in Phoenix + +## File Structure Explained + +``` +langchain-ts-quickstart/ +│ +├── src/ +│ ├── instrumentation.ts ← Phoenix setup (imported first!) +│ └── index.ts ← Your main application code +│ +├── package.json ← Dependencies and scripts +├── tsconfig.json ← TypeScript configuration +├── README.md ← Full documentation +└── SETUP.md ← This file +``` + +**Important:** The `instrumentation.ts` file must be imported at the very top of `index.ts` before any other imports. This ensures Phoenix tracing is set up correctly. + +## What the code does + +1. **instrumentation.ts** - Configures OpenTelemetry to send traces to Phoenix +2. **index.ts** - Creates a LangChain agent with a weather tool and runs it + +The agent will: +- Receive user questions +- Decide when to use tools +- Call the weather tool when needed +- Generate responses +- Send all traces to Phoenix for visualization + +## Next Steps + +- Modify `src/index.ts` to add more tools +- Change the system prompt to customize agent behavior +- Add memory/checkpointing for conversation history +- See the [LangChain quickstart](https://docs.langchain.com/oss/javascript/langchain/quickstart) for more examples + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/package-lock.json b/tutorials/quickstarts/langchain-ts-quickstart/package-lock.json new file mode 100644 index 00000000000..eef345a6eb4 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/package-lock.json @@ -0,0 +1,2287 @@ +{ + "name": "langchain-ts-quickstart", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "langchain-ts-quickstart", + "version": "1.0.0", + "dependencies": { + "@arizeai/phoenix-otel": "^0.3.0", + "@langchain/anthropic": "^0.3.0", + "@langchain/core": "^0.3.0", + "@langchain/openai": "^0.3.0", + "langchain": "^0.3.0" + }, + "devDependencies": { + "@types/node": "^20.19.30", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.65.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.65.0.tgz", + "integrity": "sha512-zIdPOcrCVEI8t3Di40nH4z9EoeyGZfXbYSvWdDLsB/KkaSYMnEgC7gmcgWu83g2NTn1ZTpbMvpdttWDGGIk6zw==", + "license": "MIT", + "dependencies": { + "json-schema-to-ts": "^3.1.1" + }, + "bin": { + "anthropic-ai-sdk": "bin/cli" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + }, + "peerDependenciesMeta": { + "zod": { + "optional": true + } + } + }, + "node_modules/@arizeai/openinference-core": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-core/-/openinference-core-2.0.5.tgz", + "integrity": "sha512-BnufYaFqmG9twkz/9DHX9WTcOs7YvVAYaufau5tdjOT1c0Y8niJwmNWzV36phNPg3c7SmdD5OYLuzeAUN0T3pQ==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-semantic-conventions": "2.1.7", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^1.25.1" + } + }, + "node_modules/@arizeai/openinference-core/node_modules/@arizeai/openinference-semantic-conventions": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-semantic-conventions/-/openinference-semantic-conventions-2.1.7.tgz", + "integrity": "sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==", + "license": "Apache-2.0" + }, + "node_modules/@arizeai/openinference-semantic-conventions": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-semantic-conventions/-/openinference-semantic-conventions-1.1.0.tgz", + "integrity": "sha512-rxRYnUWjt28DlVXnWukcQAyGhPYQ3ckmKrjEdUjmUNnvvv4k8Dabbp5h6AEjNy7YzN9jL2smNRJnbLIVtkrLEg==", + "license": "Apache-2.0" + }, + "node_modules/@arizeai/openinference-vercel": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-vercel/-/openinference-vercel-2.5.5.tgz", + "integrity": "sha512-1Ot/biSA9RiRj1qy/oE4t4uxS0zmknlGj1yWpSefuREGTNUakWYTk8QwmPgql3D2nYaOSQaQO43tz0hNPNXInQ==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-core": "2.0.5", + "@arizeai/openinference-semantic-conventions": "2.1.7", + "@opentelemetry/core": "^1.30.1" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.7.0 <2.0.0" + } + }, + "node_modules/@arizeai/openinference-vercel/node_modules/@arizeai/openinference-semantic-conventions": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-semantic-conventions/-/openinference-semantic-conventions-2.1.7.tgz", + "integrity": "sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==", + "license": "Apache-2.0" + }, + "node_modules/@arizeai/phoenix-otel": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@arizeai/phoenix-otel/-/phoenix-otel-0.3.4.tgz", + "integrity": "sha512-ocN9gnv7Owp6/mvCpmyOlf6vLv5yE8DV0v/JF3/LjXeIEv+ueuwMvfPycPFrAujvOBv0iGm+CWoA+PGA+tnsYA==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-semantic-conventions": "^1.1.0", + "@arizeai/openinference-vercel": "^2.5.0", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^1.25.1", + "@opentelemetry/exporter-trace-otlp-proto": "^0.57.2", + "@opentelemetry/instrumentation": "^0.57.2", + "@opentelemetry/resources": "^2.0.0", + "@opentelemetry/sdk-trace-base": "^1.30.1", + "@opentelemetry/sdk-trace-node": "^1.30.1" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", + "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@cfworker/json-schema": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", + "integrity": "sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@langchain/anthropic": { + "version": "0.3.34", + "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.34.tgz", + "integrity": "sha512-8bOW1A2VHRCjbzdYElrjxutKNs9NSIxYRGtR+OJWVzluMqoKKh2NmmFrpPizEyqCUEG2tTq5xt6XA1lwfqMJRA==", + "license": "MIT", + "dependencies": { + "@anthropic-ai/sdk": "^0.65.0", + "fast-xml-parser": "^4.4.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.58 <0.4.0" + } + }, + "node_modules/@langchain/core": { + "version": "0.3.80", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.80.tgz", + "integrity": "sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==", + "license": "MIT", + "dependencies": { + "@cfworker/json-schema": "^4.0.2", + "ansi-styles": "^5.0.0", + "camelcase": "6", + "decamelize": "1.2.0", + "js-tiktoken": "^1.0.12", + "langsmith": "^0.3.67", + "mustache": "^4.2.0", + "p-queue": "^6.6.2", + "p-retry": "4", + "uuid": "^10.0.0", + "zod": "^3.25.32", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@langchain/openai": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.17.tgz", + "integrity": "sha512-uw4po32OKptVjq+CYHrumgbfh4NuD7LqyE+ZgqY9I/LrLc6bHLMc+sisHmI17vgek0K/yqtarI0alPJbzrwyag==", + "license": "MIT", + "dependencies": { + "js-tiktoken": "^1.0.12", + "openai": "^4.77.0", + "zod": "^3.22.4", + "zod-to-json-schema": "^3.22.3" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.3.29 <0.4.0" + } + }, + "node_modules/@langchain/textsplitters": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@langchain/textsplitters/-/textsplitters-0.1.0.tgz", + "integrity": "sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==", + "license": "MIT", + "dependencies": { + "js-tiktoken": "^1.0.12" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/core": ">=0.2.21 <0.4.0" + } + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@opentelemetry/api-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/api-logs/-/api-logs-0.57.2.tgz", + "integrity": "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "^1.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/context-async-hooks": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/context-async-hooks/-/context-async-hooks-1.30.1.tgz", + "integrity": "sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/core": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-1.30.1.tgz", + "integrity": "sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/exporter-trace-otlp-proto/-/exporter-trace-otlp-proto-0.57.2.tgz", + "integrity": "sha512-awDdNRMIwDvUtoRYxRhja5QYH6+McBLtoz1q9BeEsskhZcrGmH/V1fWpGx8n+Rc+542e8pJA6y+aullbIzQmlw==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/otlp-exporter-base": "0.57.2", + "@opentelemetry/otlp-transformer": "0.57.2", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/sdk-trace-base": "1.30.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/exporter-trace-otlp-proto/node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/instrumentation": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.57.2.tgz", + "integrity": "sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@types/shimmer": "^1.2.0", + "import-in-the-middle": "^1.8.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-exporter-base": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.57.2.tgz", + "integrity": "sha512-XdxEzL23Urhidyebg5E6jZoaiW5ygP/mRjxLHixogbqwDy2Faduzb5N0o/Oi+XTIJu+iyxXdVORjXax+Qgfxag==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/otlp-transformer": "0.57.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/otlp-transformer/-/otlp-transformer-0.57.2.tgz", + "integrity": "sha512-48IIRj49gbQVK52jYsw70+Jv+JbahT8BqT2Th7C4H7RCM9d0gZ5sgNPoMpWldmfjvIsSgiGJtjfk9MeZvjhoig==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/sdk-logs": "0.57.2", + "@opentelemetry/sdk-metrics": "1.30.1", + "@opentelemetry/sdk-trace-base": "1.30.1", + "protobufjs": "^7.3.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@opentelemetry/otlp-transformer/node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-b3": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-b3/-/propagator-b3-1.30.1.tgz", + "integrity": "sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/propagator-jaeger": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/propagator-jaeger/-/propagator-jaeger-1.30.1.tgz", + "integrity": "sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-2.5.0.tgz", + "integrity": "sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "2.5.0", + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/core": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/core/-/core-2.5.0.tgz", + "integrity": "sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/semantic-conventions": "^1.29.0" + }, + "engines": { + "node": "^18.19.0 || >=20.6.0" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/resources/node_modules/@opentelemetry/semantic-conventions": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.39.0.tgz", + "integrity": "sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@opentelemetry/sdk-logs": { + "version": "0.57.2", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-logs/-/sdk-logs-0.57.2.tgz", + "integrity": "sha512-TXFHJ5c+BKggWbdEQ/inpgIzEmS2BGQowLE9UhsMd7YYlUfBQJ4uax0VF/B5NYigdM/75OoJGhAV3upEhK+3gg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api-logs": "0.57.2", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.4.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-logs/node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.1.tgz", + "integrity": "sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.3.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-metrics/node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.1.tgz", + "integrity": "sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/resources": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-base/node_modules/@opentelemetry/resources": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.30.1.tgz", + "integrity": "sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/core": "1.30.1", + "@opentelemetry/semantic-conventions": "1.28.0" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/sdk-trace-node": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/@opentelemetry/sdk-trace-node/-/sdk-trace-node-1.30.1.tgz", + "integrity": "sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/context-async-hooks": "1.30.1", + "@opentelemetry/core": "1.30.1", + "@opentelemetry/propagator-b3": "1.30.1", + "@opentelemetry/propagator-jaeger": "1.30.1", + "@opentelemetry/sdk-trace-base": "1.30.1", + "semver": "^7.5.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": ">=1.0.0 <1.10.0" + } + }, + "node_modules/@opentelemetry/semantic-conventions": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.28.0.tgz", + "integrity": "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==", + "license": "Apache-2.0", + "engines": { + "node": ">=14" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/node": { + "version": "20.19.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", + "integrity": "sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "form-data": "^4.0.4" + } + }, + "node_modules/@types/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", + "license": "MIT" + }, + "node_modules/@types/shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", + "license": "MIT" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-attributes": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", + "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/console-table-printer": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/console-table-printer/-/console-table-printer-2.15.0.tgz", + "integrity": "sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==", + "license": "MIT", + "dependencies": { + "simple-wcswidth": "^1.1.2" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", + "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.1.1" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/form-data-encoder": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", + "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", + "license": "MIT" + }, + "node_modules/formdata-node": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", + "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", + "license": "MIT", + "dependencies": { + "node-domexception": "1.0.0", + "web-streams-polyfill": "4.0.0-beta.3" + }, + "engines": { + "node": ">= 12.20" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.1.tgz", + "integrity": "sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/import-in-the-middle": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.15.0.tgz", + "integrity": "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.14.0", + "acorn-import-attributes": "^1.9.5", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/js-tiktoken": { + "version": "1.0.21", + "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz", + "integrity": "sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==", + "license": "MIT", + "dependencies": { + "base64-js": "^1.5.1" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-schema-to-ts": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", + "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "ts-algebra": "^2.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/langchain": { + "version": "0.3.37", + "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.37.tgz", + "integrity": "sha512-1jPsZ6xsxkcQPUvqRjvfuOLwZLLyt49hzcOK7OYAJovIkkOxd5gzK4Yw6giPUQ8g4XHyvULNlWBz+subdkcokw==", + "license": "MIT", + "dependencies": { + "@langchain/openai": ">=0.1.0 <0.7.0", + "@langchain/textsplitters": ">=0.0.0 <0.2.0", + "js-tiktoken": "^1.0.12", + "js-yaml": "^4.1.0", + "jsonpointer": "^5.0.1", + "langsmith": "^0.3.67", + "openapi-types": "^12.1.3", + "p-retry": "4", + "uuid": "^10.0.0", + "yaml": "^2.2.1", + "zod": "^3.25.32" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@langchain/anthropic": "*", + "@langchain/aws": "*", + "@langchain/cerebras": "*", + "@langchain/cohere": "*", + "@langchain/core": ">=0.3.58 <0.4.0", + "@langchain/deepseek": "*", + "@langchain/google-genai": "*", + "@langchain/google-vertexai": "*", + "@langchain/google-vertexai-web": "*", + "@langchain/groq": "*", + "@langchain/mistralai": "*", + "@langchain/ollama": "*", + "@langchain/xai": "*", + "axios": "*", + "cheerio": "*", + "handlebars": "^4.7.8", + "peggy": "^3.0.2", + "typeorm": "*" + }, + "peerDependenciesMeta": { + "@langchain/anthropic": { + "optional": true + }, + "@langchain/aws": { + "optional": true + }, + "@langchain/cerebras": { + "optional": true + }, + "@langchain/cohere": { + "optional": true + }, + "@langchain/deepseek": { + "optional": true + }, + "@langchain/google-genai": { + "optional": true + }, + "@langchain/google-vertexai": { + "optional": true + }, + "@langchain/google-vertexai-web": { + "optional": true + }, + "@langchain/groq": { + "optional": true + }, + "@langchain/mistralai": { + "optional": true + }, + "@langchain/ollama": { + "optional": true + }, + "@langchain/xai": { + "optional": true + }, + "axios": { + "optional": true + }, + "cheerio": { + "optional": true + }, + "handlebars": { + "optional": true + }, + "peggy": { + "optional": true + }, + "typeorm": { + "optional": true + } + } + }, + "node_modules/langsmith": { + "version": "0.3.87", + "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.87.tgz", + "integrity": "sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==", + "license": "MIT", + "dependencies": { + "@types/uuid": "^10.0.0", + "chalk": "^4.1.2", + "console-table-printer": "^2.12.1", + "p-queue": "^6.6.2", + "semver": "^7.6.3", + "uuid": "^10.0.0" + }, + "peerDependencies": { + "@opentelemetry/api": "*", + "@opentelemetry/exporter-trace-otlp-proto": "*", + "@opentelemetry/sdk-trace-base": "*", + "openai": "*" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@opentelemetry/exporter-trace-otlp-proto": { + "optional": true + }, + "@opentelemetry/sdk-trace-base": { + "optional": true + }, + "openai": { + "optional": true + } + } + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mustache": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/mustache/-/mustache-4.2.0.tgz", + "integrity": "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==", + "license": "MIT", + "bin": { + "mustache": "bin/mustache" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "deprecated": "Use your platform's native DOMException instead", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "license": "MIT", + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/openai": { + "version": "4.104.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", + "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + }, + "bin": { + "openai": "bin/cli" + }, + "peerDependencies": { + "ws": "^8.18.0", + "zod": "^3.23.8" + }, + "peerDependenciesMeta": { + "ws": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/openai/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/openai/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT" + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-retry": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", + "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "license": "MIT", + "dependencies": { + "@types/retry": "0.12.0", + "retry": "^0.13.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "license": "MIT", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/protobufjs": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz", + "integrity": "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/node": ">=13.7.0", + "long": "^5.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-7.5.2.tgz", + "integrity": "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==", + "license": "BSD-2-Clause" + }, + "node_modules/simple-wcswidth": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/simple-wcswidth/-/simple-wcswidth-1.1.2.tgz", + "integrity": "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==", + "license": "MIT" + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/ts-algebra": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", + "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", + "license": "MIT" + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz", + "integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web-streams-polyfill": { + "version": "4.0.0-beta.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", + "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/yaml": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", + "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.25.1", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.1.tgz", + "integrity": "sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.25 || ^4" + } + } + } +} diff --git a/tutorials/quickstarts/langchain-ts-quickstart/package.json b/tutorials/quickstarts/langchain-ts-quickstart/package.json new file mode 100644 index 00000000000..beffdab8e50 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/package.json @@ -0,0 +1,22 @@ +{ + "name": "langchain-ts-quickstart", + "version": "1.0.0", + "description": "Simple LangChain TypeScript application with Phoenix tracing", + "type": "module", + "scripts": { + "start": "npx tsx src/index.ts", + "build": "tsc" + }, + "dependencies": { + "@arizeai/phoenix-otel": "^0.3.0", + "@langchain/anthropic": "^0.3.0", + "@langchain/core": "^0.3.0", + "@langchain/openai": "^0.3.0", + "langchain": "^0.3.0" + }, + "devDependencies": { + "@types/node": "^20.19.30", + "tsx": "^4.0.0", + "typescript": "^5.0.0" + } +} diff --git a/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml b/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml new file mode 100644 index 00000000000..e20541755fb --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml @@ -0,0 +1,1200 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@arizeai/phoenix-otel': + specifier: ^0.3.0 + version: 0.3.4 + langchain: + specifier: ^0.3.0 + version: 0.3.37(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + zod: + specifier: ^3.25.76 + version: 3.25.76 + devDependencies: + '@types/node': + specifier: ^20.0.0 + version: 20.19.30 + tsx: + specifier: ^4.0.0 + version: 4.21.0 + typescript: + specifier: ^5.0.0 + version: 5.9.3 + +packages: + + '@arizeai/openinference-core@2.0.5': + resolution: {integrity: sha512-BnufYaFqmG9twkz/9DHX9WTcOs7YvVAYaufau5tdjOT1c0Y8niJwmNWzV36phNPg3c7SmdD5OYLuzeAUN0T3pQ==} + + '@arizeai/openinference-semantic-conventions@1.1.0': + resolution: {integrity: sha512-rxRYnUWjt28DlVXnWukcQAyGhPYQ3ckmKrjEdUjmUNnvvv4k8Dabbp5h6AEjNy7YzN9jL2smNRJnbLIVtkrLEg==} + + '@arizeai/openinference-semantic-conventions@2.1.7': + resolution: {integrity: sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==} + + '@arizeai/openinference-vercel@2.5.5': + resolution: {integrity: sha512-1Ot/biSA9RiRj1qy/oE4t4uxS0zmknlGj1yWpSefuREGTNUakWYTk8QwmPgql3D2nYaOSQaQO43tz0hNPNXInQ==} + peerDependencies: + '@opentelemetry/api': '>=1.7.0 <2.0.0' + + '@arizeai/phoenix-otel@0.3.4': + resolution: {integrity: sha512-ocN9gnv7Owp6/mvCpmyOlf6vLv5yE8DV0v/JF3/LjXeIEv+ueuwMvfPycPFrAujvOBv0iGm+CWoA+PGA+tnsYA==} + + '@cfworker/json-schema@4.1.1': + resolution: {integrity: sha512-gAmrUZSGtKc3AiBL71iNWxDsyUC5uMaKKGdvzYsBoTW/xi42JQHl7eKV2OYzCUqvc+D2RCcf7EXY2iCyFIk6og==} + + '@esbuild/aix-ppc64@0.27.2': + resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.27.2': + resolution: {integrity: sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.27.2': + resolution: {integrity: sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.27.2': + resolution: {integrity: sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.27.2': + resolution: {integrity: sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.2': + resolution: {integrity: sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.27.2': + resolution: {integrity: sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.2': + resolution: {integrity: sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.27.2': + resolution: {integrity: sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.27.2': + resolution: {integrity: sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.27.2': + resolution: {integrity: sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.27.2': + resolution: {integrity: sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.27.2': + resolution: {integrity: sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.27.2': + resolution: {integrity: sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.2': + resolution: {integrity: sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.27.2': + resolution: {integrity: sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.27.2': + resolution: {integrity: sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.27.2': + resolution: {integrity: sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.2': + resolution: {integrity: sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.27.2': + resolution: {integrity: sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.2': + resolution: {integrity: sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.27.2': + resolution: {integrity: sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.27.2': + resolution: {integrity: sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.27.2': + resolution: {integrity: sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.27.2': + resolution: {integrity: sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.27.2': + resolution: {integrity: sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@langchain/core@0.3.80': + resolution: {integrity: sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==} + engines: {node: '>=18'} + + '@langchain/openai@0.6.17': + resolution: {integrity: sha512-JVSzD+FL5v/2UQxKd+ikB1h4PQOtn0VlK8nqW2kPp0fshItCv4utrjBKXC/rubBnSXoRTyonBINe8QRZ6OojVQ==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': '>=0.3.68 <0.4.0' + + '@langchain/textsplitters@0.1.0': + resolution: {integrity: sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/core': '>=0.2.21 <0.4.0' + + '@opentelemetry/api-logs@0.57.2': + resolution: {integrity: sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==} + engines: {node: '>=14'} + + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} + engines: {node: '>=8.0.0'} + + '@opentelemetry/context-async-hooks@1.30.1': + resolution: {integrity: sha512-s5vvxXPVdjqS3kTLKMeBMvop9hbWkwzBpu+mUO2M7sZtlkyDJGwFe33wRKnbaYDo8ExRVBIIdwIGrqpxHuKttA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@1.30.1': + resolution: {integrity: sha512-OOCM2C/QIURhJMuKaekP3TRBxBKxG/TWWA0TL2J6nXUtDnuCtccy49LUJF8xPFXMX+0LMcxFpCo8M9cGY1W6rQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/core@2.5.0': + resolution: {integrity: sha512-ka4H8OM6+DlUhSAZpONu0cPBtPPTQKxbxVzC4CzVx5+K4JnroJVBtDzLAMx4/3CDTJXRvVFhpFjtl4SaiTNoyQ==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/exporter-trace-otlp-proto@0.57.2': + resolution: {integrity: sha512-awDdNRMIwDvUtoRYxRhja5QYH6+McBLtoz1q9BeEsskhZcrGmH/V1fWpGx8n+Rc+542e8pJA6y+aullbIzQmlw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation@0.57.2': + resolution: {integrity: sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-exporter-base@0.57.2': + resolution: {integrity: sha512-XdxEzL23Urhidyebg5E6jZoaiW5ygP/mRjxLHixogbqwDy2Faduzb5N0o/Oi+XTIJu+iyxXdVORjXax+Qgfxag==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/otlp-transformer@0.57.2': + resolution: {integrity: sha512-48IIRj49gbQVK52jYsw70+Jv+JbahT8BqT2Th7C4H7RCM9d0gZ5sgNPoMpWldmfjvIsSgiGJtjfk9MeZvjhoig==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/propagator-b3@1.30.1': + resolution: {integrity: sha512-oATwWWDIJzybAZ4pO76ATN5N6FFbOA1otibAVlS8v90B4S1wClnhRUk7K+2CHAwN1JKYuj4jh/lpCEG5BAqFuQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/propagator-jaeger@1.30.1': + resolution: {integrity: sha512-Pj/BfnYEKIOImirH76M4hDaBSx6HyZ2CXUqk+Kj02m6BB80c/yo4BdWkn/1gDFfU+YPY+bPR2U0DKBfdxCKwmg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/resources@1.30.1': + resolution: {integrity: sha512-5UxZqiAgLYGFjS4s9qm5mBVo433u+dSPUFWVWXmLAD4wB65oMCoXaJP1KJa9DIYYMeHu3z4BZcStG3LC593cWA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/resources@2.5.0': + resolution: {integrity: sha512-F8W52ApePshpoSrfsSk1H2yJn9aKjCrbpQF1M9Qii0GHzbfVeFUB+rc3X4aggyZD8x9Gu3Slua+s6krmq6Dt8g==} + engines: {node: ^18.19.0 || >=20.6.0} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-logs@0.57.2': + resolution: {integrity: sha512-TXFHJ5c+BKggWbdEQ/inpgIzEmS2BGQowLE9UhsMd7YYlUfBQJ4uax0VF/B5NYigdM/75OoJGhAV3upEhK+3gg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.4.0 <1.10.0' + + '@opentelemetry/sdk-metrics@1.30.1': + resolution: {integrity: sha512-q9zcZ0Okl8jRgmy7eNW3Ku1XSgg3sDLa5evHZpCwjspw7E8Is4K/haRPDJrBcX3YSn/Y7gUvFnByNYEKQNbNog==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.3.0 <1.10.0' + + '@opentelemetry/sdk-trace-base@1.30.1': + resolution: {integrity: sha512-jVPgBbH1gCy2Lb7X0AVQ8XAfgg0pJ4nvl8/IiQA6nxOsPvS+0zMJaFSs2ltXe0J6C8dqjcnpyqINDJmU30+uOg==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/sdk-trace-node@1.30.1': + resolution: {integrity: sha512-cBjYOINt1JxXdpw1e5MlHmFRc5fgj4GW/86vsKFxJCJ8AL4PdVtYH41gWwl4qd4uQjqEL1oJVrXkSy5cnduAnQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/semantic-conventions@1.28.0': + resolution: {integrity: sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA==} + engines: {node: '>=14'} + + '@opentelemetry/semantic-conventions@1.39.0': + resolution: {integrity: sha512-R5R9tb2AXs2IRLNKLBJDynhkfmx7mX0vi8NkhZb3gUkPWHn6HXk5J8iQ/dql0U3ApfWym4kXXmBDRGO+oeOfjg==} + engines: {node: '>=14'} + + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + + '@types/node@20.19.30': + resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/shimmer@1.2.0': + resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} + + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + + acorn-import-attributes@1.9.5: + resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} + peerDependencies: + acorn: ^8 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + console-table-printer@2.15.0: + resolution: {integrity: sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + + esbuild@0.27.2: + resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} + engines: {node: '>=18'} + hasBin: true + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + get-tsconfig@4.13.1: + resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + import-in-the-middle@1.15.0: + resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + js-tiktoken@1.0.21: + resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + langchain@0.3.37: + resolution: {integrity: sha512-1jPsZ6xsxkcQPUvqRjvfuOLwZLLyt49hzcOK7OYAJovIkkOxd5gzK4Yw6giPUQ8g4XHyvULNlWBz+subdkcokw==} + engines: {node: '>=18'} + peerDependencies: + '@langchain/anthropic': '*' + '@langchain/aws': '*' + '@langchain/cerebras': '*' + '@langchain/cohere': '*' + '@langchain/core': '>=0.3.58 <0.4.0' + '@langchain/deepseek': '*' + '@langchain/google-genai': '*' + '@langchain/google-vertexai': '*' + '@langchain/google-vertexai-web': '*' + '@langchain/groq': '*' + '@langchain/mistralai': '*' + '@langchain/ollama': '*' + '@langchain/xai': '*' + axios: '*' + cheerio: '*' + handlebars: ^4.7.8 + peggy: ^3.0.2 + typeorm: '*' + peerDependenciesMeta: + '@langchain/anthropic': + optional: true + '@langchain/aws': + optional: true + '@langchain/cerebras': + optional: true + '@langchain/cohere': + optional: true + '@langchain/deepseek': + optional: true + '@langchain/google-genai': + optional: true + '@langchain/google-vertexai': + optional: true + '@langchain/google-vertexai-web': + optional: true + '@langchain/groq': + optional: true + '@langchain/mistralai': + optional: true + '@langchain/ollama': + optional: true + '@langchain/xai': + optional: true + axios: + optional: true + cheerio: + optional: true + handlebars: + optional: true + peggy: + optional: true + typeorm: + optional: true + + langsmith@0.3.87: + resolution: {integrity: sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==} + peerDependencies: + '@opentelemetry/api': '*' + '@opentelemetry/exporter-trace-otlp-proto': '*' + '@opentelemetry/sdk-trace-base': '*' + openai: '*' + peerDependenciesMeta: + '@opentelemetry/api': + optional: true + '@opentelemetry/exporter-trace-otlp-proto': + optional: true + '@opentelemetry/sdk-trace-base': + optional: true + openai: + optional: true + + long@5.3.2: + resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + + module-details-from-path@1.0.4: + resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mustache@4.2.0: + resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} + hasBin: true + + openai@5.12.2: + resolution: {integrity: sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + + openapi-types@12.1.3: + resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + + p-finally@1.0.0: + resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} + engines: {node: '>=4'} + + p-queue@6.6.2: + resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} + engines: {node: '>=8'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-timeout@3.2.0: + resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + protobufjs@7.5.4: + resolution: {integrity: sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==} + engines: {node: '>=12.0.0'} + + require-in-the-middle@7.5.2: + resolution: {integrity: sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ==} + engines: {node: '>=8.6.0'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + semver@7.7.3: + resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} + engines: {node: '>=10'} + hasBin: true + + shimmer@1.2.1: + resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} + + simple-wcswidth@1.1.2: + resolution: {integrity: sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + yaml@2.8.2: + resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} + engines: {node: '>= 14.6'} + hasBin: true + + zod-to-json-schema@3.25.1: + resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} + peerDependencies: + zod: ^3.25 || ^4 + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + +snapshots: + + '@arizeai/openinference-core@2.0.5': + dependencies: + '@arizeai/openinference-semantic-conventions': 2.1.7 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + + '@arizeai/openinference-semantic-conventions@1.1.0': {} + + '@arizeai/openinference-semantic-conventions@2.1.7': {} + + '@arizeai/openinference-vercel@2.5.5(@opentelemetry/api@1.9.0)': + dependencies: + '@arizeai/openinference-core': 2.0.5 + '@arizeai/openinference-semantic-conventions': 2.1.7 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + + '@arizeai/phoenix-otel@0.3.4': + dependencies: + '@arizeai/openinference-semantic-conventions': 1.1.0 + '@arizeai/openinference-vercel': 2.5.5(@opentelemetry/api@1.9.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/exporter-trace-otlp-proto': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-node': 1.30.1(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + + '@cfworker/json-schema@4.1.1': {} + + '@esbuild/aix-ppc64@0.27.2': + optional: true + + '@esbuild/android-arm64@0.27.2': + optional: true + + '@esbuild/android-arm@0.27.2': + optional: true + + '@esbuild/android-x64@0.27.2': + optional: true + + '@esbuild/darwin-arm64@0.27.2': + optional: true + + '@esbuild/darwin-x64@0.27.2': + optional: true + + '@esbuild/freebsd-arm64@0.27.2': + optional: true + + '@esbuild/freebsd-x64@0.27.2': + optional: true + + '@esbuild/linux-arm64@0.27.2': + optional: true + + '@esbuild/linux-arm@0.27.2': + optional: true + + '@esbuild/linux-ia32@0.27.2': + optional: true + + '@esbuild/linux-loong64@0.27.2': + optional: true + + '@esbuild/linux-mips64el@0.27.2': + optional: true + + '@esbuild/linux-ppc64@0.27.2': + optional: true + + '@esbuild/linux-riscv64@0.27.2': + optional: true + + '@esbuild/linux-s390x@0.27.2': + optional: true + + '@esbuild/linux-x64@0.27.2': + optional: true + + '@esbuild/netbsd-arm64@0.27.2': + optional: true + + '@esbuild/netbsd-x64@0.27.2': + optional: true + + '@esbuild/openbsd-arm64@0.27.2': + optional: true + + '@esbuild/openbsd-x64@0.27.2': + optional: true + + '@esbuild/openharmony-arm64@0.27.2': + optional: true + + '@esbuild/sunos-x64@0.27.2': + optional: true + + '@esbuild/win32-arm64@0.27.2': + optional: true + + '@esbuild/win32-ia32@0.27.2': + optional: true + + '@esbuild/win32-x64@0.27.2': + optional: true + + '@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))': + dependencies: + '@cfworker/json-schema': 4.1.1 + ansi-styles: 5.2.0 + camelcase: 6.3.0 + decamelize: 1.2.0 + js-tiktoken: 1.0.21 + langsmith: 0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + mustache: 4.2.0 + p-queue: 6.6.2 + p-retry: 4.6.2 + uuid: 10.0.0 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + + '@langchain/openai@0.6.17(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))': + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + js-tiktoken: 1.0.21 + openai: 5.12.2(zod@3.25.76) + zod: 3.25.76 + transitivePeerDependencies: + - ws + + '@langchain/textsplitters@0.1.0(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))': + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + js-tiktoken: 1.0.21 + + '@opentelemetry/api-logs@0.57.2': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/api@1.9.0': {} + + '@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + + '@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.28.0 + + '@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.39.0 + + '@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-exporter-base': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.57.2 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.15.0 + require-in-the-middle: 7.5.2 + semver: 7.7.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/otlp-exporter-base@0.57.2(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/otlp-transformer': 0.57.2(@opentelemetry/api@1.9.0) + + '@opentelemetry/otlp-transformer@0.57.2(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.57.2 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-logs': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + protobufjs: 7.5.4 + + '@opentelemetry/propagator-b3@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/propagator-jaeger@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/resources@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.28.0 + + '@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 2.5.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.39.0 + + '@opentelemetry/sdk-logs@0.57.2(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.57.2 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-metrics@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) + + '@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.28.0 + + '@opentelemetry/sdk-trace-node@1.30.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-b3': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/propagator-jaeger': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + semver: 7.7.3 + + '@opentelemetry/semantic-conventions@1.28.0': {} + + '@opentelemetry/semantic-conventions@1.39.0': {} + + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + + '@types/node@20.19.30': + dependencies: + undici-types: 6.21.0 + + '@types/retry@0.12.0': {} + + '@types/shimmer@1.2.0': {} + + '@types/uuid@10.0.0': {} + + acorn-import-attributes@1.9.5(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + argparse@2.0.1: {} + + base64-js@1.5.1: {} + + camelcase@6.3.0: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + cjs-module-lexer@1.4.3: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + console-table-printer@2.15.0: + dependencies: + simple-wcswidth: 1.1.2 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decamelize@1.2.0: {} + + esbuild@0.27.2: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.2 + '@esbuild/android-arm': 0.27.2 + '@esbuild/android-arm64': 0.27.2 + '@esbuild/android-x64': 0.27.2 + '@esbuild/darwin-arm64': 0.27.2 + '@esbuild/darwin-x64': 0.27.2 + '@esbuild/freebsd-arm64': 0.27.2 + '@esbuild/freebsd-x64': 0.27.2 + '@esbuild/linux-arm': 0.27.2 + '@esbuild/linux-arm64': 0.27.2 + '@esbuild/linux-ia32': 0.27.2 + '@esbuild/linux-loong64': 0.27.2 + '@esbuild/linux-mips64el': 0.27.2 + '@esbuild/linux-ppc64': 0.27.2 + '@esbuild/linux-riscv64': 0.27.2 + '@esbuild/linux-s390x': 0.27.2 + '@esbuild/linux-x64': 0.27.2 + '@esbuild/netbsd-arm64': 0.27.2 + '@esbuild/netbsd-x64': 0.27.2 + '@esbuild/openbsd-arm64': 0.27.2 + '@esbuild/openbsd-x64': 0.27.2 + '@esbuild/openharmony-arm64': 0.27.2 + '@esbuild/sunos-x64': 0.27.2 + '@esbuild/win32-arm64': 0.27.2 + '@esbuild/win32-ia32': 0.27.2 + '@esbuild/win32-x64': 0.27.2 + + eventemitter3@4.0.7: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + get-tsconfig@4.13.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + import-in-the-middle@1.15.0: + dependencies: + acorn: 8.15.0 + acorn-import-attributes: 1.9.5(acorn@8.15.0) + cjs-module-lexer: 1.4.3 + module-details-from-path: 1.0.4 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + js-tiktoken@1.0.21: + dependencies: + base64-js: 1.5.1 + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsonpointer@5.0.1: {} + + langchain@0.3.37(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)): + dependencies: + '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + '@langchain/openai': 0.6.17(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))) + '@langchain/textsplitters': 0.1.0(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))) + js-tiktoken: 1.0.21 + js-yaml: 4.1.1 + jsonpointer: 5.0.1 + langsmith: 0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + openapi-types: 12.1.3 + p-retry: 4.6.2 + uuid: 10.0.0 + yaml: 2.8.2 + zod: 3.25.76 + transitivePeerDependencies: + - '@opentelemetry/api' + - '@opentelemetry/exporter-trace-otlp-proto' + - '@opentelemetry/sdk-trace-base' + - openai + - ws + + langsmith@0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)): + dependencies: + '@types/uuid': 10.0.0 + chalk: 4.1.2 + console-table-printer: 2.15.0 + p-queue: 6.6.2 + semver: 7.7.3 + uuid: 10.0.0 + optionalDependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/exporter-trace-otlp-proto': 0.57.2(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + openai: 5.12.2(zod@3.25.76) + + long@5.3.2: {} + + module-details-from-path@1.0.4: {} + + ms@2.1.3: {} + + mustache@4.2.0: {} + + openai@5.12.2(zod@3.25.76): + optionalDependencies: + zod: 3.25.76 + + openapi-types@12.1.3: {} + + p-finally@1.0.0: {} + + p-queue@6.6.2: + dependencies: + eventemitter3: 4.0.7 + p-timeout: 3.2.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-timeout@3.2.0: + dependencies: + p-finally: 1.0.0 + + path-parse@1.0.7: {} + + protobufjs@7.5.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/node': 20.19.30 + long: 5.3.2 + + require-in-the-middle@7.5.2: + dependencies: + debug: 4.4.3 + module-details-from-path: 1.0.4 + resolve: 1.22.11 + transitivePeerDependencies: + - supports-color + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + semver@7.7.3: {} + + shimmer@1.2.1: {} + + simple-wcswidth@1.1.2: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.2 + get-tsconfig: 4.13.1 + optionalDependencies: + fsevents: 2.3.3 + + typescript@5.9.3: {} + + undici-types@6.21.0: {} + + uuid@10.0.0: {} + + yaml@2.8.2: {} + + zod-to-json-schema@3.25.1(zod@3.25.76): + dependencies: + zod: 3.25.76 + + zod@3.25.76: {} diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts new file mode 100644 index 00000000000..f17c1ea6d17 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts @@ -0,0 +1,101 @@ +/** + * Simple LangChain TypeScript Application + * + * This demonstrates a basic LangChain chain with: + * - Prompt templates + * - LLM integration + * - Phoenix tracing + * + * Run with: npm start + */ + +// Import instrumentation first - this must be at the top! +import "./instrumentation.js"; + +import { ChatOpenAI } from "@langchain/openai"; +import { ChatAnthropic } from "@langchain/anthropic"; +import { PromptTemplate } from "@langchain/core/prompts"; +import { StringOutputParser } from "@langchain/core/output_parsers"; +import { RunnableSequence } from "@langchain/core/runnables"; + +async function main() { + // Check for API key (supports both OpenAI and Anthropic) + if (!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) { + console.error("❌ Error: No API key found"); + console.error(" Please set one of:"); + console.error(" - export OPENAI_API_KEY=your-key-here"); + console.error(" - export ANTHROPIC_API_KEY=your-key-here"); + process.exit(1); + } + + console.log("=".repeat(60)); + console.log("LangChain TypeScript Quickstart"); + console.log("=".repeat(60)); + console.log(""); + + // Initialize the LLM based on available API key + const llm = process.env.ANTHROPIC_API_KEY + ? new ChatAnthropic({ + modelName: "claude-3-5-sonnet-20241022", + temperature: 0.7, + }) + : new ChatOpenAI({ + modelName: "gpt-3.5-turbo", + temperature: 0.7, + }); + + // Create a prompt template + const prompt = PromptTemplate.fromTemplate( + "You are a helpful assistant. Answer the following question in a friendly and concise way.\n\nQuestion: {question}\n\nAnswer:" + ); + + // Create a simple chain: prompt -> llm -> parser + const chain = RunnableSequence.from([ + prompt, + llm, + new StringOutputParser(), + ]); + + console.log("Running LangChain chain with Phoenix tracing...\n"); + + // Example questions + const questions = [ + "What is the capital of France?", + "Explain quantum computing in simple terms.", + "What are the benefits of TypeScript?", + ]; + + // Process multiple questions through the chain + for (let i = 0; i < questions.length; i++) { + const question = questions[i]; + console.log(`📝 Question ${i + 1}: ${question}`); + console.log(" Processing..."); + + try { + const response = await chain.invoke({ question }); + console.log(` ✅ Answer: ${response}\n`); + } catch (error) { + console.error(` ❌ Error: ${error}\n`); + } + + // Small delay between requests + await new Promise((resolve) => setTimeout(resolve, 500)); + } + + console.log("=".repeat(60)); + console.log("✅ All questions processed!"); + console.log(""); + console.log("👀 Open Phoenix UI at http://localhost:6006"); + console.log(""); + console.log("What to look for:"); + console.log(" - Each chain invocation creates a trace"); + console.log(" - The trace includes the prompt, LLM call, and response"); + console.log(" - You can see token usage, latency, and other metrics"); + console.log("=".repeat(60)); +} + +main().catch((error) => { + console.error("Fatal error:", error); + process.exit(1); +}); + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/instrumentation.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/instrumentation.ts new file mode 100644 index 00000000000..a3b42af1c38 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/instrumentation.ts @@ -0,0 +1,26 @@ +/** + * Phoenix Tracing Instrumentation Setup + * + * This file configures OpenTelemetry to send traces to Phoenix. + * Import this file at the top of your application to enable tracing. + */ + +import { register } from "@arizeai/phoenix-otel"; + +// Set OpenTelemetry attribute value length limit BEFORE any imports +// This must be set before OpenTelemetry initializes to prevent truncation +if (!process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT) { + process.env.OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT = "25000"; +} + +// Register with Phoenix - this handles all the OpenTelemetry boilerplate +export const provider = register({ + projectName: process.env.PHOENIX_PROJECT_NAME || "langchain-ts-quickstart", + // Optional: set batch to false for immediate span delivery during development + batch: false, +}); + +console.log("✅ Phoenix tracing enabled"); +console.log(` Project: ${process.env.PHOENIX_PROJECT_NAME || "langchain-ts-quickstart"}`); +console.log(""); + diff --git a/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json b/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json new file mode 100644 index 00000000000..4a9ef80449d --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "moduleResolution": "node", + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +} + From 4bf4fa7322ce6407d05d01e3f1edded9c02fc32f Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Wed, 4 Feb 2026 11:33:31 -0800 Subject: [PATCH 4/8] add in code & docs pages before review --- docs.json | 1965 ++++++++--------- .../tutorials/{ => a}/configure-your-llm.mdx | 0 .../tutorials/{ => a}/run-your-evals.mdx | 0 .../{ => a}/use-custom-eval-template.mdx | 0 .../{ => a}/use-pre-build-eval-template.mdx | 0 .../tutorials/customize-eval-template.mdx | 315 +++ .../tutorials/customize-your-llm-endpoint.mdx | 267 +++ docs/phoenix/evaluation/tutorials/page-1.mdx | 156 -- .../run-evals-with-built-in-evals.mdx | 252 +++ .../quickstarts/agno_agent_for_evals.ipynb | 627 +++++- .../langchain-ts-quickstart/.env.example | 18 + .../langchain-ts-quickstart/README.md | 129 +- .../langchain-ts-quickstart/SETUP.md | 105 +- .../langchain-ts-quickstart/package-lock.json | 807 ++++--- .../langchain-ts-quickstart/package.json | 19 +- .../langchain-ts-quickstart/pnpm-lock.yaml | 870 ++++++-- .../src/custom_evals.ts | 126 ++ .../langchain-ts-quickstart/src/index.ts | 131 +- .../src/pre_built_evals.ts | 71 + .../langchain-ts-quickstart/src/tools.ts | 152 ++ .../langchain-ts-quickstart/tsconfig.json | 5 +- 21 files changed, 4261 insertions(+), 1754 deletions(-) rename docs/phoenix/evaluation/tutorials/{ => a}/configure-your-llm.mdx (100%) rename docs/phoenix/evaluation/tutorials/{ => a}/run-your-evals.mdx (100%) rename docs/phoenix/evaluation/tutorials/{ => a}/use-custom-eval-template.mdx (100%) rename docs/phoenix/evaluation/tutorials/{ => a}/use-pre-build-eval-template.mdx (100%) create mode 100644 docs/phoenix/evaluation/tutorials/customize-eval-template.mdx create mode 100644 docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx delete mode 100644 docs/phoenix/evaluation/tutorials/page-1.mdx create mode 100644 docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/.env.example create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/src/pre_built_evals.ts create mode 100644 tutorials/quickstarts/langchain-ts-quickstart/src/tools.ts diff --git a/docs.json b/docs.json index 8a8c43291a8..f9bc6a01535 100644 --- a/docs.json +++ b/docs.json @@ -34,1200 +34,1197 @@ }, "navigation": { "tabs": [ + { + "tab": "Documentation", + "icon": "book-open", + "groups": [ + { + "group": " ", + "pages": ["docs/phoenix"] + }, { - "tab": "Documentation", - "icon": "book-open", - "groups": [ + "group": "Quick Start", + "pages": [ { - "group": " ", - "pages": ["docs/phoenix"] + "group": "Get Started with Phoenix", + "pages": [ + "docs/phoenix/get-started", + "docs/phoenix/get-started/get-started-tracing", + "docs/phoenix/get-started/get-started-evaluations", + "docs/phoenix/get-started/get-started-prompt-playground", + "docs/phoenix/get-started/get-started-datasets-and-experiments" + ] }, + "docs/phoenix/end-to-end-features-notebook", + "docs/phoenix/phoenix-demo" + ] + }, + { + "group": "Tracing", + "icon": "telescope", + "pages": [ { - "group": "Quick Start", + "group": "Tutorial", "pages": [ - { - "group": "Get Started with Phoenix", - "pages": [ - "docs/phoenix/get-started", - "docs/phoenix/get-started/get-started-tracing", - "docs/phoenix/get-started/get-started-evaluations", - "docs/phoenix/get-started/get-started-prompt-playground", - "docs/phoenix/get-started/get-started-datasets-and-experiments" - ] - }, - "docs/phoenix/end-to-end-features-notebook", - "docs/phoenix/phoenix-demo" + "docs/phoenix/tracing/tutorial", + "docs/phoenix/tracing/tutorial/your-first-traces", + "docs/phoenix/tracing/tutorial/annotations-and-evaluations", + "docs/phoenix/tracing/tutorial/sessions" ] }, { - "group": "Tracing", - "icon": "telescope", + "group": "Overview: Tracing", "pages": [ - { - "group": "Tutorial", - "pages": [ - "docs/phoenix/tracing/tutorial", - "docs/phoenix/tracing/tutorial/your-first-traces", - "docs/phoenix/tracing/tutorial/annotations-and-evaluations", - "docs/phoenix/tracing/tutorial/sessions" - ] - }, - { - "group": "Overview: Tracing", - "pages": [ - "docs/phoenix/tracing/llm-traces", - "docs/phoenix/tracing/llm-traces/projects", - "docs/phoenix/tracing/llm-traces/sessions", - "docs/phoenix/tracing/llm-traces/how-to-annotate-traces", - "docs/phoenix/tracing/llm-traces/metrics" - ] - }, - { - "group": "How-to: Tracing", - "pages": [ - "docs/phoenix/tracing/how-to-tracing", - { - "group": "Setup Tracing", - "pages": [ - "docs/phoenix/tracing/how-to-tracing/setup-tracing", - "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-using-phoenix-otel", - "docs/phoenix/tracing/how-to-tracing/setup-tracing/instrument", - "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-projects", - "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-sessions" - ] - }, - { - "group": "Add Metadata", - "pages": [ - "docs/phoenix/tracing/how-to-tracing/add-metadata", - "docs/phoenix/tracing/how-to-tracing/add-metadata/customize-spans", - "docs/phoenix/tracing/how-to-tracing/add-metadata/instrumenting-prompt-templates-and-prompt-variables" - ] - }, - { - "group": "Annotate Traces", - "pages": [ - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations", - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/annotating-in-the-ui", - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/capture-feedback", - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/annotating-auto-instrumented-spans", - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/evaluating-phoenix-traces", - "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/llm-evaluations" - ] - }, - { - "group": "Importing & Exporting Traces", - "pages": [ - "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces", - "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/importing-existing-traces", - "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans", - "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/exporting-annotated-spans", - "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/retrieve-traces-via-cli" - ] - }, - "docs/phoenix/tracing/how-to-tracing/cost-tracking", - { - "group": "Advanced", - "pages": [ - "docs/phoenix/tracing/how-to-tracing/advanced", - "docs/phoenix/tracing/how-to-tracing/advanced/masking-span-attributes", - "docs/phoenix/tracing/how-to-tracing/advanced/suppress-tracing", - "docs/phoenix/tracing/how-to-tracing/advanced/modifying-spans", - "docs/phoenix/tracing/how-to-tracing/advanced/multimodal-tracing" - ] - } - ] - } + "docs/phoenix/tracing/llm-traces", + "docs/phoenix/tracing/llm-traces/projects", + "docs/phoenix/tracing/llm-traces/sessions", + "docs/phoenix/tracing/llm-traces/how-to-annotate-traces", + "docs/phoenix/tracing/llm-traces/metrics" ] }, { - "group": "Evaluation", - "icon": "clipboard-check", + "group": "How-to: Tracing", "pages": [ + "docs/phoenix/tracing/how-to-tracing", { - "group": "Tutorial", + "group": "Setup Tracing", "pages": [ - "docs/phoenix/evaluation/tutorials/configure-your-llm", - "docs/phoenix/evaluation/tutorials/use-pre-build-eval-template", - "docs/phoenix/evaluation/tutorials/use-custom-eval-template", - "docs/phoenix/evaluation/tutorials/run-your-evals" + "docs/phoenix/tracing/how-to-tracing/setup-tracing", + "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-using-phoenix-otel", + "docs/phoenix/tracing/how-to-tracing/setup-tracing/instrument", + "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-projects", + "docs/phoenix/tracing/how-to-tracing/setup-tracing/setup-sessions" ] }, - "docs/phoenix/evaluation/typescript-quickstart", - "docs/phoenix/evaluation/python-quickstart", { - "group": "Overview: Evals", + "group": "Add Metadata", "pages": [ - "docs/phoenix/evaluation/llm-evals", - "docs/phoenix/evaluation/llm-evals/executors", - "docs/phoenix/evaluation/llm-evals/evaluator-traces" + "docs/phoenix/tracing/how-to-tracing/add-metadata", + "docs/phoenix/tracing/how-to-tracing/add-metadata/customize-spans", + "docs/phoenix/tracing/how-to-tracing/add-metadata/instrumenting-prompt-templates-and-prompt-variables" ] }, { - "group": "How to: Evals", + "group": "Annotate Traces", "pages": [ - "docs/phoenix/evaluation/how-to-evals", - "docs/phoenix/evaluation/how-to-evals/custom-llm-evaluators", - { - "group": "Configuring the LLM", - "pages": [ - "docs/phoenix/evaluation/how-to-evals/configuring-the-llm", - "docs/phoenix/evaluation/how-to-evals/configuring-the-llm/prompt-formats" - ] - }, - "docs/phoenix/evaluation/how-to-evals/code-evaluators", - "docs/phoenix/evaluation/how-to-evals/batch-evaluations", - "docs/phoenix/evaluation/how-to-evals/using-evals-with-phoenix" + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations", + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/annotating-in-the-ui", + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/capture-feedback", + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/annotating-auto-instrumented-spans", + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/evaluating-phoenix-traces", + "docs/phoenix/tracing/how-to-tracing/feedback-and-annotations/llm-evaluations" ] }, { - "group": "Pre-Built Evals", + "group": "Importing & Exporting Traces", "pages": [ - "docs/phoenix/evaluation/running-pre-tested-evals", - "docs/phoenix/evaluation/running-pre-tested-evals/code-metrics", - "docs/phoenix/evaluation/running-pre-tested-evals/faithfulness", - "docs/phoenix/evaluation/running-pre-tested-evals/q-and-a-on-retrieved-data", - "docs/phoenix/evaluation/running-pre-tested-evals/retrieval-rag-relevance", - "docs/phoenix/evaluation/running-pre-tested-evals/summarization-eval", - "docs/phoenix/evaluation/running-pre-tested-evals/code-generation-eval", - "docs/phoenix/evaluation/running-pre-tested-evals/toxicity", - "docs/phoenix/evaluation/running-pre-tested-evals/ai-vs-human-groundtruth", - "docs/phoenix/evaluation/running-pre-tested-evals/reference-link-evals", - "docs/phoenix/evaluation/running-pre-tested-evals/user-frustration", - "docs/phoenix/evaluation/running-pre-tested-evals/sql-generation-eval", - "docs/phoenix/evaluation/running-pre-tested-evals/tool-calling-eval", - "docs/phoenix/evaluation/running-pre-tested-evals/agent-path-convergence", - "docs/phoenix/evaluation/running-pre-tested-evals/agent-planning", - "docs/phoenix/evaluation/running-pre-tested-evals/agent-reflection", - "docs/phoenix/evaluation/running-pre-tested-evals/audio-emotion-detection" - ] - } - ] - }, - { - "group": "Datasets & Experiments", - "icon": "flask", - "pages": [ - { - "group": "Tutorial", - "pages": [ - "docs/phoenix/datasets-and-experiments/tutorial/defining-the-dataset", - "docs/phoenix/datasets-and-experiments/tutorial/run-experiments-with-code-evals", - "docs/phoenix/datasets-and-experiments/tutorial/run-experiments-with-llm-judge", - "docs/phoenix/datasets-and-experiments/tutorial/iteration-workflow-experiments" + "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces", + "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/importing-existing-traces", + "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/extract-data-from-spans", + "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/exporting-annotated-spans", + "docs/phoenix/tracing/how-to-tracing/importing-and-exporting-traces/retrieve-traces-via-cli" ] }, - "docs/phoenix/datasets-and-experiments/overview-datasets", + "docs/phoenix/tracing/how-to-tracing/cost-tracking", { - "group": "How-to: Datasets", + "group": "Advanced", "pages": [ - "docs/phoenix/datasets-and-experiments/how-to-datasets", - "docs/phoenix/datasets-and-experiments/how-to-datasets/creating-datasets", - "docs/phoenix/datasets-and-experiments/how-to-datasets/exporting-datasets" - ] - }, - { - "group": "How-to: Experiments", - "pages": [ - "docs/phoenix/datasets-and-experiments/how-to-experiments", - "docs/phoenix/datasets-and-experiments/how-to-experiments/run-experiments", - "docs/phoenix/datasets-and-experiments/how-to-experiments/using-evaluators", - "docs/phoenix/datasets-and-experiments/how-to-experiments/repetitions", - "docs/phoenix/datasets-and-experiments/how-to-experiments/splits" + "docs/phoenix/tracing/how-to-tracing/advanced", + "docs/phoenix/tracing/how-to-tracing/advanced/masking-span-attributes", + "docs/phoenix/tracing/how-to-tracing/advanced/suppress-tracing", + "docs/phoenix/tracing/how-to-tracing/advanced/modifying-spans", + "docs/phoenix/tracing/how-to-tracing/advanced/multimodal-tracing" ] } ] + } + ] + }, + { + "group": "Evaluation", + "icon": "clipboard-check", + "pages": [ + { + "group": "Tutorial", + "pages": [ + "docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals", + "docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint", + "docs/phoenix/evaluation/tutorials/customize-eval-template" + ] }, + "docs/phoenix/evaluation/typescript-quickstart", + "docs/phoenix/evaluation/python-quickstart", { - "group": "Prompt Engineering", - "icon": "wand-magic-sparkles", + "group": "Overview: Evals", "pages": [ + "docs/phoenix/evaluation/llm-evals", + "docs/phoenix/evaluation/llm-evals/executors", + "docs/phoenix/evaluation/llm-evals/evaluator-traces" + ] + }, + { + "group": "How to: Evals", + "pages": [ + "docs/phoenix/evaluation/how-to-evals", + "docs/phoenix/evaluation/how-to-evals/custom-llm-evaluators", { - "group": "Tutorial", - "pages": [ - "docs/phoenix/prompt-engineering/tutorial", - "docs/phoenix/prompt-engineering/tutorial/identify-and-edit-prompts", - "docs/phoenix/prompt-engineering/tutorial/test-prompts-at-scale", - "docs/phoenix/prompt-engineering/tutorial/compare-prompt-versions", - "docs/phoenix/prompt-engineering/tutorial/optimize-prompts-automatically" - ] - }, - { - "group": "Overview: Prompts", + "group": "Configuring the LLM", "pages": [ - "docs/phoenix/prompt-engineering/overview-prompts", - "docs/phoenix/prompt-engineering/overview-prompts/prompt-management", - "docs/phoenix/prompt-engineering/overview-prompts/prompt-playground", - "docs/phoenix/prompt-engineering/overview-prompts/span-replay", - "docs/phoenix/prompt-engineering/overview-prompts/prompts-in-code" + "docs/phoenix/evaluation/how-to-evals/configuring-the-llm", + "docs/phoenix/evaluation/how-to-evals/configuring-the-llm/prompt-formats" ] }, - { - "group": "How to: Prompts", - "pages": [ - "docs/phoenix/prompt-engineering/how-to-prompts", - "docs/phoenix/prompt-engineering/how-to-prompts/configure-ai-providers", - "docs/phoenix/prompt-engineering/how-to-prompts/using-the-playground", - "docs/phoenix/prompt-engineering/how-to-prompts/create-a-prompt", - "docs/phoenix/prompt-engineering/how-to-prompts/test-a-prompt", - "docs/phoenix/prompt-engineering/how-to-prompts/tag-a-prompt", - "docs/phoenix/prompt-engineering/how-to-prompts/using-a-prompt" - ] - } + "docs/phoenix/evaluation/how-to-evals/code-evaluators", + "docs/phoenix/evaluation/how-to-evals/batch-evaluations", + "docs/phoenix/evaluation/how-to-evals/using-evals-with-phoenix" + ] + }, + { + "group": "Pre-Built Evals", + "pages": [ + "docs/phoenix/evaluation/running-pre-tested-evals", + "docs/phoenix/evaluation/running-pre-tested-evals/code-metrics", + "docs/phoenix/evaluation/running-pre-tested-evals/faithfulness", + "docs/phoenix/evaluation/running-pre-tested-evals/q-and-a-on-retrieved-data", + "docs/phoenix/evaluation/running-pre-tested-evals/retrieval-rag-relevance", + "docs/phoenix/evaluation/running-pre-tested-evals/summarization-eval", + "docs/phoenix/evaluation/running-pre-tested-evals/code-generation-eval", + "docs/phoenix/evaluation/running-pre-tested-evals/toxicity", + "docs/phoenix/evaluation/running-pre-tested-evals/ai-vs-human-groundtruth", + "docs/phoenix/evaluation/running-pre-tested-evals/reference-link-evals", + "docs/phoenix/evaluation/running-pre-tested-evals/user-frustration", + "docs/phoenix/evaluation/running-pre-tested-evals/sql-generation-eval", + "docs/phoenix/evaluation/running-pre-tested-evals/tool-calling-eval", + "docs/phoenix/evaluation/running-pre-tested-evals/agent-path-convergence", + "docs/phoenix/evaluation/running-pre-tested-evals/agent-planning", + "docs/phoenix/evaluation/running-pre-tested-evals/agent-reflection", + "docs/phoenix/evaluation/running-pre-tested-evals/audio-emotion-detection" + ] + } + ] + }, + { + "group": "Datasets & Experiments", + "icon": "flask", + "pages": [ + { + "group": "Tutorial", + "pages": [ + "docs/phoenix/datasets-and-experiments/tutorial/defining-the-dataset", + "docs/phoenix/datasets-and-experiments/tutorial/run-experiments-with-code-evals", + "docs/phoenix/datasets-and-experiments/tutorial/run-experiments-with-llm-judge", + "docs/phoenix/datasets-and-experiments/tutorial/iteration-workflow-experiments" + ] + }, + "docs/phoenix/datasets-and-experiments/overview-datasets", + { + "group": "How-to: Datasets", + "pages": [ + "docs/phoenix/datasets-and-experiments/how-to-datasets", + "docs/phoenix/datasets-and-experiments/how-to-datasets/creating-datasets", + "docs/phoenix/datasets-and-experiments/how-to-datasets/exporting-datasets" + ] + }, + { + "group": "How-to: Experiments", + "pages": [ + "docs/phoenix/datasets-and-experiments/how-to-experiments", + "docs/phoenix/datasets-and-experiments/how-to-experiments/run-experiments", + "docs/phoenix/datasets-and-experiments/how-to-experiments/using-evaluators", + "docs/phoenix/datasets-and-experiments/how-to-experiments/repetitions", + "docs/phoenix/datasets-and-experiments/how-to-experiments/splits" + ] + } + ] + }, + { + "group": "Prompt Engineering", + "icon": "wand-magic-sparkles", + "pages": [ + { + "group": "Tutorial", + "pages": [ + "docs/phoenix/prompt-engineering/tutorial", + "docs/phoenix/prompt-engineering/tutorial/identify-and-edit-prompts", + "docs/phoenix/prompt-engineering/tutorial/test-prompts-at-scale", + "docs/phoenix/prompt-engineering/tutorial/compare-prompt-versions", + "docs/phoenix/prompt-engineering/tutorial/optimize-prompts-automatically" + ] + }, + { + "group": "Overview: Prompts", + "pages": [ + "docs/phoenix/prompt-engineering/overview-prompts", + "docs/phoenix/prompt-engineering/overview-prompts/prompt-management", + "docs/phoenix/prompt-engineering/overview-prompts/prompt-playground", + "docs/phoenix/prompt-engineering/overview-prompts/span-replay", + "docs/phoenix/prompt-engineering/overview-prompts/prompts-in-code" ] }, + { + "group": "How to: Prompts", + "pages": [ + "docs/phoenix/prompt-engineering/how-to-prompts", + "docs/phoenix/prompt-engineering/how-to-prompts/configure-ai-providers", + "docs/phoenix/prompt-engineering/how-to-prompts/using-the-playground", + "docs/phoenix/prompt-engineering/how-to-prompts/create-a-prompt", + "docs/phoenix/prompt-engineering/how-to-prompts/test-a-prompt", + "docs/phoenix/prompt-engineering/how-to-prompts/tag-a-prompt", + "docs/phoenix/prompt-engineering/how-to-prompts/using-a-prompt" + ] + } + ] + }, + { + "group": "Settings", + "icon": "gear-complex", + "pages": [ + "docs/phoenix/settings/access-control-rbac", + "docs/phoenix/settings/api-keys", + "docs/phoenix/settings/data-retention" + ] + }, + { + "group": "Concepts", + "icon": "lightbulb", + "pages": [ + "docs/phoenix/user-guide", + "docs/phoenix/production-guide", + "docs/phoenix/environments", { - "group": "Settings", - "icon": "gear-complex", + "group": "Tracing", "pages": [ - "docs/phoenix/settings/access-control-rbac", - "docs/phoenix/settings/api-keys", - "docs/phoenix/settings/data-retention" + "docs/phoenix/tracing/concepts-tracing/what-are-traces", + "docs/phoenix/tracing/concepts-tracing/how-tracing-works", + "docs/phoenix/tracing/concepts-tracing/annotations-concepts", + "docs/phoenix/tracing/concepts-tracing/translating-conventions", + "docs/phoenix/tracing/concepts-tracing/faqs-tracing" ] }, { - "group": "Concepts", - "icon": "lightbulb", + "group": "Prompts", "pages": [ - "docs/phoenix/user-guide", - "docs/phoenix/production-guide", - "docs/phoenix/environments", - { - "group": "Tracing", - "pages": [ - "docs/phoenix/tracing/concepts-tracing/what-are-traces", - "docs/phoenix/tracing/concepts-tracing/how-tracing-works", - "docs/phoenix/tracing/concepts-tracing/annotations-concepts", - "docs/phoenix/tracing/concepts-tracing/translating-conventions", - "docs/phoenix/tracing/concepts-tracing/faqs-tracing" - ] - }, - { - "group": "Prompts", - "pages": [ - "docs/phoenix/prompt-engineering/concepts-prompts/prompts-concepts", - "docs/phoenix/prompt-engineering/concepts-prompts/context-engineering-basics" - ] - }, - { - "group": "Datasets & Experiments", - "pages": [ - "docs/phoenix/datasets-and-experiments/concepts-datasets" - ] - }, - { - "group": "Evals", - "pages": [ - "docs/phoenix/evaluation/concepts-evals/llm-as-a-judge", - "docs/phoenix/evaluation/concepts-evals/evaluators", - "docs/phoenix/evaluation/concepts-evals/input-mapping" - ] - } + "docs/phoenix/prompt-engineering/concepts-prompts/prompts-concepts", + "docs/phoenix/prompt-engineering/concepts-prompts/context-engineering-basics" ] }, { - "group": "Resources", - "icon": "books", + "group": "Datasets & Experiments", "pages": [ - { - "group": "Frequently Asked Questions", - "pages": [ - "docs/phoenix/resources/frequently-asked-questions", - "docs/phoenix/resources/frequently-asked-questions/what-is-the-difference-between-phoenix-and-arize", - "docs/phoenix/resources/frequently-asked-questions/what-is-my-phoenix-endpoint", - "docs/phoenix/resources/frequently-asked-questions/what-is-llamatrace-vs-phoenix-cloud", - "docs/phoenix/resources/frequently-asked-questions/phoenix-cloud-migration-guide-legacy-to-new-version", - "docs/phoenix/resources/frequently-asked-questions/will-phoenix-cloud-be-on-the-latest-version-of-phoenix", - "docs/phoenix/resources/frequently-asked-questions/can-i-add-other-users-to-my-phoenix-instance", - "docs/phoenix/resources/frequently-asked-questions/can-i-use-azure-openai", - "docs/phoenix/resources/frequently-asked-questions/can-i-use-phoenix-locally-from-a-remote-jupyter-instance", - "docs/phoenix/resources/frequently-asked-questions/how-can-i-configure-the-backend-to-send-the-data-to-the-phoenix-ui-in-another-container", - "docs/phoenix/resources/frequently-asked-questions/can-i-run-phoenix-on-sagemaker", - "docs/phoenix/resources/frequently-asked-questions/can-i-persist-data-in-a-notebook", - "docs/phoenix/resources/frequently-asked-questions/what-is-the-difference-between-grpc-and-http", - "docs/phoenix/resources/frequently-asked-questions/can-i-use-grpc-for-trace-collection", - "docs/phoenix/resources/frequently-asked-questions/how-do-i-resolve-phoenix-evals-showing-not_parsable", - "docs/phoenix/resources/frequently-asked-questions/braintrust-open-source-alternative-llm-evaluation-platform-comparison", - "docs/phoenix/resources/frequently-asked-questions/langfuse-alternative-arize-phoenix-vs-langfuse-key-differences", - "docs/phoenix/resources/frequently-asked-questions/open-source-langsmith-alternative-arize-phoenix-vs.-langsmith" - ] - }, - "docs/phoenix/resources/contribute-to-phoenix", - "docs/phoenix/resources/phoenix-to-arize-ax-migration", - "docs/phoenix/resources/typescript-api", - "docs/phoenix/resources/python-api", - "docs/phoenix/resources/github", - "docs/phoenix/resources/openinference" + "docs/phoenix/datasets-and-experiments/concepts-datasets" + ] + }, + { + "group": "Evals", + "pages": [ + "docs/phoenix/evaluation/concepts-evals/llm-as-a-judge", + "docs/phoenix/evaluation/concepts-evals/evaluators", + "docs/phoenix/evaluation/concepts-evals/input-mapping" ] } ] }, { - "tab": "Integrations", - "icon": "puzzle-piece", - "groups": [ + "group": "Resources", + "icon": "books", + "pages": [ { - "group": " ", + "group": "Frequently Asked Questions", "pages": [ - "docs/phoenix/integrations" + "docs/phoenix/resources/frequently-asked-questions", + "docs/phoenix/resources/frequently-asked-questions/what-is-the-difference-between-phoenix-and-arize", + "docs/phoenix/resources/frequently-asked-questions/what-is-my-phoenix-endpoint", + "docs/phoenix/resources/frequently-asked-questions/what-is-llamatrace-vs-phoenix-cloud", + "docs/phoenix/resources/frequently-asked-questions/phoenix-cloud-migration-guide-legacy-to-new-version", + "docs/phoenix/resources/frequently-asked-questions/will-phoenix-cloud-be-on-the-latest-version-of-phoenix", + "docs/phoenix/resources/frequently-asked-questions/can-i-add-other-users-to-my-phoenix-instance", + "docs/phoenix/resources/frequently-asked-questions/can-i-use-azure-openai", + "docs/phoenix/resources/frequently-asked-questions/can-i-use-phoenix-locally-from-a-remote-jupyter-instance", + "docs/phoenix/resources/frequently-asked-questions/how-can-i-configure-the-backend-to-send-the-data-to-the-phoenix-ui-in-another-container", + "docs/phoenix/resources/frequently-asked-questions/can-i-run-phoenix-on-sagemaker", + "docs/phoenix/resources/frequently-asked-questions/can-i-persist-data-in-a-notebook", + "docs/phoenix/resources/frequently-asked-questions/what-is-the-difference-between-grpc-and-http", + "docs/phoenix/resources/frequently-asked-questions/can-i-use-grpc-for-trace-collection", + "docs/phoenix/resources/frequently-asked-questions/how-do-i-resolve-phoenix-evals-showing-not_parsable", + "docs/phoenix/resources/frequently-asked-questions/braintrust-open-source-alternative-llm-evaluation-platform-comparison", + "docs/phoenix/resources/frequently-asked-questions/langfuse-alternative-arize-phoenix-vs-langfuse-key-differences", + "docs/phoenix/resources/frequently-asked-questions/open-source-langsmith-alternative-arize-phoenix-vs.-langsmith" ] }, + "docs/phoenix/resources/contribute-to-phoenix", + "docs/phoenix/resources/phoenix-to-arize-ax-migration", + "docs/phoenix/resources/typescript-api", + "docs/phoenix/resources/python-api", + "docs/phoenix/resources/github", + "docs/phoenix/resources/openinference" + ] + } + ] + }, + { + "tab": "Integrations", + "icon": "puzzle-piece", + "groups": [ + { + "group": " ", + "pages": ["docs/phoenix/integrations"] + }, + { + "group": "Developer Tools", + "icon": "code", + "pages": [ + "docs/phoenix/integrations/developer-tools/coding-agents", + "docs/phoenix/integrations/phoenix-mcp-server" + ] + }, + { + "group": "LLM Providers", + "icon": "user-robot", + "pages": [ { - "group": "Developer Tools", - "icon": "code", + "group": "Amazon Bedrock", "pages": [ - "docs/phoenix/integrations/developer-tools/coding-agents", - "docs/phoenix/integrations/phoenix-mcp-server" + "docs/phoenix/integrations/llm-providers/amazon-bedrock", + "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-tracing", + "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-sdk-js", + "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-agents-tracing", + "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-agent-runtime-js" ] }, { - "group": "LLM Providers", - "icon": "user-robot", + "group": "Anthropic", "pages": [ - { - "group": "Amazon Bedrock", - "pages": [ - "docs/phoenix/integrations/llm-providers/amazon-bedrock", - "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-tracing", - "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-sdk-js", - "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-agents-tracing", - "docs/phoenix/integrations/llm-providers/amazon-bedrock/amazon-bedrock-agent-runtime-js" - ] - }, - { - "group": "Anthropic", - "pages": [ - "docs/phoenix/integrations/llm-providers/anthropic", - "docs/phoenix/integrations/llm-providers/anthropic/anthropic-tracing", - "docs/phoenix/integrations/llm-providers/anthropic/anthropic-sdk-typescript" - ] - }, - { - "group": "Google", - "pages": [ - "docs/phoenix/integrations/llm-providers/google-gen-ai", - "docs/phoenix/integrations/llm-providers/google-gen-ai/google-genai-tracing" - ] - }, - { - "group": "Groq", - "pages": [ - "docs/phoenix/integrations/llm-providers/groq", - "docs/phoenix/integrations/llm-providers/groq/groq-tracing" - ] - }, - { - "group": "LiteLLM", - "pages": [ - "docs/phoenix/integrations/llm-providers/litellm", - "docs/phoenix/integrations/llm-providers/litellm/litellm-tracing" - ] - }, - { - "group": "MistralAI", - "pages": [ - "docs/phoenix/integrations/llm-providers/mistralai", - "docs/phoenix/integrations/llm-providers/mistralai/mistralai-tracing" - ] - }, - { - "group": "OpenAI", - "pages": [ - "docs/phoenix/integrations/llm-providers/openai", - "docs/phoenix/integrations/llm-providers/openai/openai-tracing", - "docs/phoenix/integrations/llm-providers/openai/openai-agents-sdk-tracing", - "docs/phoenix/integrations/llm-providers/openai/openai-node-js-sdk" - ] - }, - { - "group": "OpenRouter", - "pages": [ - "docs/phoenix/integrations/llm-providers/openrouter", - "docs/phoenix/integrations/llm-providers/openrouter/openai-tracing" - ] - }, - { - "group": "VertexAI", - "pages": [ - "docs/phoenix/integrations/llm-providers/vertexai", - "docs/phoenix/integrations/llm-providers/vertexai/vertexai-tracing" - ] - } + "docs/phoenix/integrations/llm-providers/anthropic", + "docs/phoenix/integrations/llm-providers/anthropic/anthropic-tracing", + "docs/phoenix/integrations/llm-providers/anthropic/anthropic-sdk-typescript" ] }, { - "group": "TypeScript", - "icon": "js", + "group": "Google", "pages": [ - { - "group": "BeeAI", - "pages": [ - "docs/phoenix/integrations/typescript/beeai", - "docs/phoenix/integrations/typescript/beeai/beeai-tracing-js" - ] - }, - { - "group": "LangChain", - "pages": [ - "docs/phoenix/integrations/typescript/langchain", - "docs/phoenix/integrations/typescript/langchain/langchain-js" - ] - }, - { - "group": "Mastra", - "pages": [ - "docs/phoenix/integrations/typescript/mastra", - "docs/phoenix/integrations/typescript/mastra/mastra-tracing" - ] - }, - { - "group": "MCP", - "pages": [ - "docs/phoenix/integrations/typescript/mcp", - "docs/phoenix/integrations/typescript/mcp/mcp-tracing-typescript" - ] - }, - { - "group": "Vercel", - "pages": [ - "docs/phoenix/integrations/typescript/vercel", - "docs/phoenix/integrations/typescript/vercel/vercel-ai-sdk-tracing-js" - ] - } + "docs/phoenix/integrations/llm-providers/google-gen-ai", + "docs/phoenix/integrations/llm-providers/google-gen-ai/google-genai-tracing" ] }, { - "group": "Python", - "icon": "python", + "group": "Groq", "pages": [ - { - "group": "Agno", - "pages": [ - "docs/phoenix/integrations/python/agno", - "docs/phoenix/integrations/python/agno/agno-tracing" - ] - }, - { - "group": "AutoGen", - "pages": [ - "docs/phoenix/integrations/python/autogen", - "docs/phoenix/integrations/python/autogen/autogen-tracing", - "docs/phoenix/integrations/python/autogen/autogen-agentchat-tracing" - ] - }, - { - "group": "BeeAI", - "pages": [ - "docs/phoenix/integrations/python/beeai", - "docs/phoenix/integrations/python/beeai/beeai-tracing-python" - ] - }, - { - "group": "CrewAI", - "pages": [ - "docs/phoenix/integrations/python/crewai", - "docs/phoenix/integrations/python/crewai/crewai-tracing" - ] - }, - { - "group": "DSPy", - "pages": [ - "docs/phoenix/integrations/python/dspy", - "docs/phoenix/integrations/python/dspy/dspy-tracing" - ] - }, - { - "group": "Google ADK", - "pages": [ - "docs/phoenix/integrations/python/google-adk", - "docs/phoenix/integrations/python/google-adk/google-adk-tracing" - ] - }, - { - "group": "Graphite", - "pages": [ - "docs/phoenix/integrations/python/graphite", - "docs/phoenix/integrations/python/graphite/graphite-integration-guide" - ] - }, - { - "group": "Guardrails AI", - "pages": [ - "docs/phoenix/integrations/python/guardrails-ai", - "docs/phoenix/integrations/python/guardrails-ai/guardrails-ai-tracing" - ] - }, - { - "group": "Haystack", - "pages": [ - "docs/phoenix/integrations/python/haystack", - "docs/phoenix/integrations/python/haystack/haystack-tracing" - ] - }, - { - "group": "Hugging Face smolagents", - "pages": [ - "docs/phoenix/integrations/python/hugging-face-smolagents", - "docs/phoenix/integrations/python/hugging-face-smolagents/smolagents-tracing" - ] - }, - { - "group": "Instructor", - "pages": [ - "docs/phoenix/integrations/python/instructor", - "docs/phoenix/integrations/python/instructor/instructor-tracing" - ] - }, - { - "group": "LlamaIndex", - "pages": [ - "docs/phoenix/integrations/python/llamaindex", - "docs/phoenix/integrations/python/llamaindex/llamaindex-tracing", - "docs/phoenix/integrations/python/llamaindex/llamaindex-workflows-tracing" - ] - }, - { - "group": "LangChain", - "pages": [ - "docs/phoenix/integrations/python/langchain", - "docs/phoenix/integrations/python/langchain/langchain-tracing" - ] - }, - { - "group": "LangGraph", - "pages": [ - "docs/phoenix/integrations/python/langgraph", - "docs/phoenix/integrations/python/langgraph/langgraph-tracing" - ] - }, - "docs/phoenix/integrations/python/mcp-tracing", - { - "group": "NVIDIA", - "pages": [ - "docs/phoenix/integrations/python/nvidia", - "docs/phoenix/integrations/python/nvidia/nemo-agent-tracing" - ] - }, - { - "group": "Portkey", - "pages": [ - "docs/phoenix/integrations/python/portkey", - "docs/phoenix/integrations/python/portkey/portkey-tracing" - ] - }, - { - "group": "Pydantic AI", - "pages": [ - "docs/phoenix/integrations/python/pydantic", - "docs/phoenix/integrations/python/pydantic/pydantic-tracing", - "docs/phoenix/integrations/python/pydantic/pydantic-evals" - ] - } + "docs/phoenix/integrations/llm-providers/groq", + "docs/phoenix/integrations/llm-providers/groq/groq-tracing" ] }, { - "group": "Java", - "icon": "java", + "group": "LiteLLM", "pages": [ - { - "group": "LangChain4j", - "pages": [ - "docs/phoenix/integrations/java/langchain4j", - "docs/phoenix/integrations/java/langchain4j/langchain4j-tracing" - ] - }, - { - "group": "Spring AI", - "pages": [ - "docs/phoenix/integrations/java/springai", - "docs/phoenix/integrations/java/springai/springai-tracing" - ] - }, - { - "group": "Arconia", - "pages": [ - "docs/phoenix/integrations/java/arconia", - "docs/phoenix/integrations/java/arconia/arconia-tracing" - ] - } + "docs/phoenix/integrations/llm-providers/litellm", + "docs/phoenix/integrations/llm-providers/litellm/litellm-tracing" + ] + }, + { + "group": "MistralAI", + "pages": [ + "docs/phoenix/integrations/llm-providers/mistralai", + "docs/phoenix/integrations/llm-providers/mistralai/mistralai-tracing" ] }, { - "group": "Platform", - "icon": "computer", + "group": "OpenAI", "pages": [ - { - "group": "Dify", - "pages": [ - "docs/phoenix/integrations/platforms/dify", - "docs/phoenix/integrations/platforms/dify/dify-tracing" - ] - }, - { - "group": "Flowise", - "pages": [ - "docs/phoenix/integrations/platforms/flowise", - "docs/phoenix/integrations/platforms/flowise/flowise-tracing" - ] - }, - { - "group": "LangFlow", - "pages": [ - "docs/phoenix/integrations/platforms/langflow", - "docs/phoenix/integrations/platforms/langflow/langflow-tracing" - ] - }, - { - "group": "Prompt Flow", - "pages": [ - "docs/phoenix/integrations/platforms/prompt-flow", - "docs/phoenix/integrations/platforms/prompt-flow/prompt-flow-tracing" - ] - } + "docs/phoenix/integrations/llm-providers/openai", + "docs/phoenix/integrations/llm-providers/openai/openai-tracing", + "docs/phoenix/integrations/llm-providers/openai/openai-agents-sdk-tracing", + "docs/phoenix/integrations/llm-providers/openai/openai-node-js-sdk" ] }, { - "group": "Evaluation Integrations", - "icon": "clipboard-check", + "group": "OpenRouter", "pages": [ - "docs/phoenix/integrations/evaluation-integrations/cleanlab", - "docs/phoenix/integrations/evaluation-integrations/ragas", - "docs/phoenix/integrations/evaluation-integrations/uqlm" + "docs/phoenix/integrations/llm-providers/openrouter", + "docs/phoenix/integrations/llm-providers/openrouter/openai-tracing" ] }, { - "group": "Vector Databases", - "icon": "database", + "group": "VertexAI", "pages": [ - "docs/phoenix/integrations/vector-databases/mongodb", - "docs/phoenix/integrations/vector-databases/opensearch", - "docs/phoenix/integrations/vector-databases/pinecone", - "docs/phoenix/integrations/vector-databases/qdrant", - "docs/phoenix/integrations/vector-databases/weaviate", - "docs/phoenix/integrations/vector-databases/zilliz-milvus", - "docs/phoenix/integrations/vector-databases/couchbase" + "docs/phoenix/integrations/llm-providers/vertexai", + "docs/phoenix/integrations/llm-providers/vertexai/vertexai-tracing" ] } ] }, { - "tab": "SDK & API Reference", - "icon": "rectangle-terminal", - "groups": [ + "group": "TypeScript", + "icon": "js", + "pages": [ { - "group": "Python", - "icon": "python", + "group": "BeeAI", "pages": [ - "docs/phoenix/sdk-api-reference", - "docs/phoenix/sdk-api-reference/python/reference", - "docs/phoenix/sdk-api-reference/python/arize-phoenix-client", - "docs/phoenix/sdk-api-reference/python/arize-phoenix-evals", - "docs/phoenix/sdk-api-reference/python/arize-phoenix-otel" + "docs/phoenix/integrations/typescript/beeai", + "docs/phoenix/integrations/typescript/beeai/beeai-tracing-js" ] }, { - "group": "TypeScript", - "icon": "js", + "group": "LangChain", "pages": [ - "docs/phoenix/sdk-api-reference/typescript/overview", - "docs/phoenix/sdk-api-reference/typescript/reference", - "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-client", - "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-evals", - "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-otel", - "docs/phoenix/sdk-api-reference/typescript/arizeai-openinference-core", - "docs/phoenix/sdk-api-reference/typescript/mcp-server", - "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-cli" + "docs/phoenix/integrations/typescript/langchain", + "docs/phoenix/integrations/typescript/langchain/langchain-js" ] }, { - "group": "Rest API", - "icon": "network-wired", + "group": "Mastra", "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/overview", - { - "group": "API Reference", - "pages": [ - { - "group": "Annotation Configs", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/list-annotation-configurations", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/create-an-annotation-configuration", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/get-an-annotation-configuration-by-id-or-name", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/update-an-annotation-configuration", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/delete-an-annotation-configuration" - ] - }, - { - "group": "Annotations", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotations/get-span-annotations-for-a-list-of-span_ids" - ] - }, - { - "group": "Datasets", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/list-datasets", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/get-dataset-by-id", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/delete-dataset-by-id", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/list-dataset-versions", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/upload-dataset-from-json-csv-or-pyarrow", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/get-examples-from-a-dataset", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-csv-file", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-openai-fine-tuning-jsonl-file", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-openai-evals-jsonl-file" - ] - }, - { - "group": "Experiments", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/list-experiments-by-dataset", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-experiment-on-a-dataset", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/get-experiment-by-id", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/download-experiment-runs-as-a-json-file", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/download-experiment-runs-as-a-csv-file", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/list-runs-for-an-experiment", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-run-for-an-experiment", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-or-update-evaluation-for-an-experiment-run" - ] - }, - { - "group": "Traces", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/delete-a-trace-by-identifier", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/get-span-trace-or-document-evaluations-from-a-project", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/add-span-trace-or-document-evaluations" - ] - }, - { - "group": "Spans", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/search-spans-with-simple-filters-no-dsl", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/list-spans-with-simple-filters-no-dsl", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/create-spans", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/create-span-annotations", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/delete-a-span-by-span_identifier" - ] - }, - { - "group": "Prompts", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-all-prompts", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/create-a-new-prompt", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-prompt-versions", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-prompt-version-by-id", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-prompt-version-by-tag", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-latest-prompt-version", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-prompt-version-tags", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/add-tag-to-prompt-version" - ] - }, - { - "group": "Projects", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/list-all-projects", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/create-a-new-project", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/get-project-by-id-or-name", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/update-a-project-by-id-or-name", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/delete-a-project-by-id-or-name" - ] - }, - { - "group": "Users", - "pages": [ - "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/list-all-users", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/create-a-new-user", - "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/delete-a-user-by-id" - ] - } - ] - } + "docs/phoenix/integrations/typescript/mastra", + "docs/phoenix/integrations/typescript/mastra/mastra-tracing" + ] + }, + { + "group": "MCP", + "pages": [ + "docs/phoenix/integrations/typescript/mcp", + "docs/phoenix/integrations/typescript/mcp/mcp-tracing-typescript" ] }, { - "group": "OpenInference SDK", - "icon": "puzzle", + "group": "Vercel", "pages": [ - "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-python", - "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-java", - "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-javascript" + "docs/phoenix/integrations/typescript/vercel", + "docs/phoenix/integrations/typescript/vercel/vercel-ai-sdk-tracing-js" ] } ] }, { - "tab": "Self-Hosting", - "icon": "server", - "groups": [ + "group": "Python", + "icon": "python", + "pages": [ { - "group": " ", + "group": "Agno", "pages": [ - "docs/phoenix/self-hosting", - "docs/phoenix/self-hosting/architecture", - "docs/phoenix/self-hosting/license", - { - "group": "Configuration", - "pages": [ - "docs/phoenix/self-hosting/configuration", - "docs/phoenix/self-hosting/configuration/using-amazon-aurora" - ] - } + "docs/phoenix/integrations/python/agno", + "docs/phoenix/integrations/python/agno/agno-tracing" ] }, { - "group": "Deployment Options", - "icon": "rocket-launch", + "group": "AutoGen", "pages": [ - "docs/phoenix/self-hosting/deployment-options/terminal", - "docs/phoenix/self-hosting/deployment-options/docker", - "docs/phoenix/self-hosting/deployment-options/kubernetes", - "docs/phoenix/self-hosting/deployment-options/kubernetes-helm", - "docs/phoenix/self-hosting/deployment-options/aws-with-cloudformation", - "docs/phoenix/self-hosting/deployment-options/railway" + "docs/phoenix/integrations/python/autogen", + "docs/phoenix/integrations/python/autogen/autogen-tracing", + "docs/phoenix/integrations/python/autogen/autogen-agentchat-tracing" ] }, { - "group": "Features", - "icon": "layer-group", + "group": "BeeAI", "pages": [ - "docs/phoenix/self-hosting/features/provisioning", - "docs/phoenix/self-hosting/features/authentication", - "docs/phoenix/self-hosting/features/email", - "docs/phoenix/self-hosting/features/management", - "docs/phoenix/settings/data-retention" + "docs/phoenix/integrations/python/beeai", + "docs/phoenix/integrations/python/beeai/beeai-tracing-python" ] }, { - "group": "Upgrade", - "icon": "angles-up", - "pages": ["docs/phoenix/self-hosting/upgrade/migrations"] + "group": "CrewAI", + "pages": [ + "docs/phoenix/integrations/python/crewai", + "docs/phoenix/integrations/python/crewai/crewai-tracing" + ] }, { - "group": "Security", - "icon": "user-shield", + "group": "DSPy", "pages": [ - "docs/phoenix/settings/access-control-rbac", - "docs/phoenix/self-hosting/security/privacy" + "docs/phoenix/integrations/python/dspy", + "docs/phoenix/integrations/python/dspy/dspy-tracing" ] }, { - "group": "Misc", - "icon": "boxes-stacked", + "group": "Google ADK", "pages": [ - "docs/phoenix/self-hosting/misc/frequently-asked-questions" + "docs/phoenix/integrations/python/google-adk", + "docs/phoenix/integrations/python/google-adk/google-adk-tracing" ] - } - ] - }, - { - "tab": "Phoenix Cloud", - "icon": "cloud", - "groups": [ + }, { - "group": "Phoenix Cloud", - "pages": ["docs/phoenix/phoenix-cloud"] - } - ] - }, - { - "tab": "Cookbooks", - "icon": "user-chef", - "groups": [ + "group": "Graphite", + "pages": [ + "docs/phoenix/integrations/python/graphite", + "docs/phoenix/integrations/python/graphite/graphite-integration-guide" + ] + }, { - "group": " ", + "group": "Guardrails AI", "pages": [ - "docs/phoenix/cookbook", - { - "group": "Agent Workflow Patterns", - "pages": [ - "docs/phoenix/cookbook/agent-workflow-patterns", - "docs/phoenix/cookbook/agent-workflow-patterns/autogen", - "docs/phoenix/cookbook/agent-workflow-patterns/crewai", - "docs/phoenix/cookbook/agent-workflow-patterns/google-genai-sdk-manual-orchestration", - "docs/phoenix/cookbook/agent-workflow-patterns/openai-agents", - "docs/phoenix/cookbook/agent-workflow-patterns/langgraph", - "docs/phoenix/cookbook/agent-workflow-patterns/smolagents" - ] - } + "docs/phoenix/integrations/python/guardrails-ai", + "docs/phoenix/integrations/python/guardrails-ai/guardrails-ai-tracing" ] }, { - "group": "AI Engineering Workflows", - "icon": "gear", + "group": "Haystack", "pages": [ - "docs/phoenix/cookbook/ai-engineering-workflows/iterative-evaluation-and-experimentation-workflow-python", - "docs/phoenix/cookbook/ai-engineering-workflows/iterative-evaluation-and-experimentation-workflow-typescript", - "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/creating-a-custom-llm-evaluator-with-a-benchmark-dataset", - "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/aligning-llm-evals-with-human-annotations-typescript", - "docs/phoenix/cookbook/prompt-engineering/prompt-optimization", - "docs/phoenix/cookbook/ai-engineering-workflows/analyzing-customer-review-evals-with-repetition-experiments" + "docs/phoenix/integrations/python/haystack", + "docs/phoenix/integrations/python/haystack/haystack-tracing" ] }, { - "group": "Tracing", - "icon": "telescope", + "group": "Hugging Face smolagents", "pages": [ - "docs/phoenix/cookbook/tracing/agentic-rag-tracing", - "docs/phoenix/cookbook/tracing/generating-synthetic-datasets-for-llm-evaluators-and-agents", - "docs/phoenix/cookbook/tracing/structured-data-extraction", - "docs/phoenix/cookbook/tracing/product-recommendation-agent-google-agent-engine-and-langgraph", - "docs/phoenix/cookbook/tracing/cookbooks" + "docs/phoenix/integrations/python/hugging-face-smolagents", + "docs/phoenix/integrations/python/hugging-face-smolagents/smolagents-tracing" ] }, { - "group": "Human-in-the-Loop Workflows (Annotations)", - "icon": "user-plus", + "group": "Instructor", "pages": [ - "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/using-human-annotations-for-eval-driven-development", - "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/aligning-llm-evals-with-human-annotations-typescript", - "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/creating-a-custom-llm-evaluator-with-a-benchmark-dataset" + "docs/phoenix/integrations/python/instructor", + "docs/phoenix/integrations/python/instructor/instructor-tracing" ] }, { - "group": "Prompt Engineering", - "icon": "wand-magic-sparkles", + "group": "LlamaIndex", "pages": [ - "docs/phoenix/cookbook/prompt-engineering/optimizing-coding-agent-prompts-prompt-learning", - "docs/phoenix/cookbook/prompt-engineering/prompt-learning-optimizing-prompts-for-classification", - "docs/phoenix/cookbook/prompt-engineering/few-shot-prompting", - "docs/phoenix/cookbook/prompt-engineering/react-prompting", - "docs/phoenix/cookbook/prompt-engineering/chain-of-thought-prompting", - "docs/phoenix/cookbook/prompt-engineering/prompt-optimization", - "docs/phoenix/cookbook/prompt-engineering/llm-as-a-judge-prompt-optimization" + "docs/phoenix/integrations/python/llamaindex", + "docs/phoenix/integrations/python/llamaindex/llamaindex-tracing", + "docs/phoenix/integrations/python/llamaindex/llamaindex-workflows-tracing" ] }, { - "group": "Evaluation", - "icon": "clipboard-check", + "group": "LangChain", "pages": [ - "docs/phoenix/cookbook/evaluation/openai-agents-sdk-cookbook", - "docs/phoenix/cookbook/evaluation/evaluate-an-agent", - "docs/phoenix/cookbook/evaluation/evaluate-rag", - "docs/phoenix/cookbook/evaluation/code-readability-evaluation", - "docs/phoenix/cookbook/evaluation/relevance-classification-evaluation", - "docs/phoenix/cookbook/evaluation/using-ragas-to-evaluate-a-math-problem-solving-agent", - "docs/phoenix/cookbook/evaluation/cookbooks" + "docs/phoenix/integrations/python/langchain", + "docs/phoenix/integrations/python/langchain/langchain-tracing" ] }, { - "group": "Datasets & Experiments", - "icon": "flask", + "group": "LangGraph", "pages": [ - "docs/phoenix/cookbook/datasets-and-experiments/analyzing-customer-review-evals-with-repetition-experiments", - "docs/phoenix/cookbook/datasets-and-experiments/experiment-with-a-customer-support-agent", - "docs/phoenix/cookbook/datasets-and-experiments/model-comparison-for-an-email-text-extraction-service", - "docs/phoenix/cookbook/datasets-and-experiments/comparing-llamaindex-query-engines-with-a-pairwise-evaluator", - "docs/phoenix/cookbook/datasets-and-experiments/summarization", - "docs/phoenix/cookbook/datasets-and-experiments/text2sql", - "docs/phoenix/cookbook/datasets-and-experiments/cookbooks" + "docs/phoenix/integrations/python/langgraph", + "docs/phoenix/integrations/python/langgraph/langgraph-tracing" ] }, + "docs/phoenix/integrations/python/mcp-tracing", { - "group": "Retrieval & Inferences", - "icon": "magnifying-glass", + "group": "NVIDIA", "pages": [ - "docs/phoenix/cookbook/retrieval-and-inferences/embeddings-analysis", - "docs/phoenix/cookbook/retrieval-and-inferences/cookbooks" + "docs/phoenix/integrations/python/nvidia", + "docs/phoenix/integrations/python/nvidia/nemo-agent-tracing" + ] + }, + { + "group": "Portkey", + "pages": [ + "docs/phoenix/integrations/python/portkey", + "docs/phoenix/integrations/python/portkey/portkey-tracing" + ] + }, + { + "group": "Pydantic AI", + "pages": [ + "docs/phoenix/integrations/python/pydantic", + "docs/phoenix/integrations/python/pydantic/pydantic-tracing", + "docs/phoenix/integrations/python/pydantic/pydantic-evals" ] } ] }, { - "tab": "Release Notes", - "icon": "gift", - "groups": [ + "group": "Java", + "icon": "java", + "pages": [ { - "group": " ", + "group": "LangChain4j", + "pages": [ + "docs/phoenix/integrations/java/langchain4j", + "docs/phoenix/integrations/java/langchain4j/langchain4j-tracing" + ] + }, + { + "group": "Spring AI", + "pages": [ + "docs/phoenix/integrations/java/springai", + "docs/phoenix/integrations/java/springai/springai-tracing" + ] + }, + { + "group": "Arconia", + "pages": [ + "docs/phoenix/integrations/java/arconia", + "docs/phoenix/integrations/java/arconia/arconia-tracing" + ] + } + ] + }, + { + "group": "Platform", + "icon": "computer", + "pages": [ + { + "group": "Dify", + "pages": [ + "docs/phoenix/integrations/platforms/dify", + "docs/phoenix/integrations/platforms/dify/dify-tracing" + ] + }, + { + "group": "Flowise", + "pages": [ + "docs/phoenix/integrations/platforms/flowise", + "docs/phoenix/integrations/platforms/flowise/flowise-tracing" + ] + }, + { + "group": "LangFlow", + "pages": [ + "docs/phoenix/integrations/platforms/langflow", + "docs/phoenix/integrations/platforms/langflow/langflow-tracing" + ] + }, + { + "group": "Prompt Flow", + "pages": [ + "docs/phoenix/integrations/platforms/prompt-flow", + "docs/phoenix/integrations/platforms/prompt-flow/prompt-flow-tracing" + ] + } + ] + }, + { + "group": "Evaluation Integrations", + "icon": "clipboard-check", + "pages": [ + "docs/phoenix/integrations/evaluation-integrations/cleanlab", + "docs/phoenix/integrations/evaluation-integrations/ragas", + "docs/phoenix/integrations/evaluation-integrations/uqlm" + ] + }, + { + "group": "Vector Databases", + "icon": "database", + "pages": [ + "docs/phoenix/integrations/vector-databases/mongodb", + "docs/phoenix/integrations/vector-databases/opensearch", + "docs/phoenix/integrations/vector-databases/pinecone", + "docs/phoenix/integrations/vector-databases/qdrant", + "docs/phoenix/integrations/vector-databases/weaviate", + "docs/phoenix/integrations/vector-databases/zilliz-milvus", + "docs/phoenix/integrations/vector-databases/couchbase" + ] + } + ] + }, + { + "tab": "SDK & API Reference", + "icon": "rectangle-terminal", + "groups": [ + { + "group": "Python", + "icon": "python", + "pages": [ + "docs/phoenix/sdk-api-reference", + "docs/phoenix/sdk-api-reference/python/reference", + "docs/phoenix/sdk-api-reference/python/arize-phoenix-client", + "docs/phoenix/sdk-api-reference/python/arize-phoenix-evals", + "docs/phoenix/sdk-api-reference/python/arize-phoenix-otel" + ] + }, + { + "group": "TypeScript", + "icon": "js", + "pages": [ + "docs/phoenix/sdk-api-reference/typescript/overview", + "docs/phoenix/sdk-api-reference/typescript/reference", + "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-client", + "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-evals", + "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-otel", + "docs/phoenix/sdk-api-reference/typescript/arizeai-openinference-core", + "docs/phoenix/sdk-api-reference/typescript/mcp-server", + "docs/phoenix/sdk-api-reference/typescript/arizeai-phoenix-cli" + ] + }, + { + "group": "Rest API", + "icon": "network-wired", + "pages": [ + "docs/phoenix/sdk-api-reference/rest-api/overview", + { + "group": "API Reference", "pages": [ - "docs/phoenix/release-notes", - { - "group": "01.2026", - "pages": [ - "docs/phoenix/release-notes/01-2026/01-17-2026-phoenix-cli-ai-agent-debugging" - ] - }, - { - "group": "12.2025", - "pages": [ - "docs/phoenix/release-notes/12-2025/12-20-2025-improved-user-preferences", - "docs/phoenix/release-notes/12-2025/12-12-2025-support-for-gemini-tool-calls", - "docs/phoenix/release-notes/12-2025/12-09-2025-span-notes-api", - "docs/phoenix/release-notes/12-2025/12-06-2025-ldap-authentication-support", - "docs/phoenix/release-notes/12-2025/12-04-2025-evaluator-message-formats", - "docs/phoenix/release-notes/12-2025/12-03-2025-typescript-create-evaluator", - "docs/phoenix/release-notes/12-2025/12-01-2025-splits-on-experiments-table" - ] - }, - { - "group": "11.2025", - "pages": [ - "docs/phoenix/release-notes/11-2025/11-29-2025-add-support-for-claude-opus-4-5", - "docs/phoenix/release-notes/11-2025/11-27-2025-show-server-credential-setup-in-playground-api-keys", - "docs/phoenix/release-notes/11-2025/11-25-2025-split-assignments-when-uploading-a-dataset", - "docs/phoenix/release-notes/11-2025/11-23-2025-repetitions-for-manual-playground-invocations", - "docs/phoenix/release-notes/11-2025/11-19-2025-expanded-provider-support-with-openai-5-1-+-gemini-3", - "docs/phoenix/release-notes/11-2025/11-12-2025-updated-anthropic-model-list", - "docs/phoenix/release-notes/11-2025/11-09-2025-openinference-typescript-2-0", - "docs/phoenix/release-notes/11-2025/11-07-2025-timezone-preference", - "docs/phoenix/release-notes/11-2025/11-05-2025-metadata-for-prompts", - "docs/phoenix/release-notes/11-2025/11-03-2025-playground-dataset-label-display", - "docs/phoenix/release-notes/11-2025/11-01-2025-resume-experiments-and-evaluations" - ] - }, - { - "group": "10.2025", - "pages": [ - "docs/phoenix/release-notes/10-2025/10-30-2025-metadata-support-for-experiment-run-annotations", - "docs/phoenix/release-notes/10-2025/10-28-2025-enable-aws-iam-auth-for-db-configuration", - "docs/phoenix/release-notes/10-2025/10-26-2025-add-split-edit-menu-to-examples", - "docs/phoenix/release-notes/10-2025/10-24-2025-filter-prompts-page-by-label", - "docs/phoenix/release-notes/10-2025/10-20-2025-splits", - "docs/phoenix/release-notes/10-2025/10-18-2025-filter-annotations-in-compare-experiments-slideover", - "docs/phoenix/release-notes/10-2025/10-15-2025-enhanced-filtering-for-examples-table", - "docs/phoenix/release-notes/10-2025/10-13-2025-view-traces-in-compare-experiments", - "docs/phoenix/release-notes/10-2025/10-10-2025-viewer-role", - "docs/phoenix/release-notes/10-2025/10-08-2025-dataset-labels", - "docs/phoenix/release-notes/10-2025/10-06-2025-paginate-compare-experiments", - "docs/phoenix/release-notes/10-2025/10-05-2025-load-prompt-by-tag-into-playground", - "docs/phoenix/release-notes/10-2025/10-03-2025-prompt-version-editing-in-playground" - ] - }, - { - "group": "09.2025", - "pages": [ - "docs/phoenix/release-notes/09-2025/09-29-2025-day-0-support-for-claude-sonnet-4.5", - "docs/phoenix/release-notes/09-2025/09-27-2025-dataset-splits", - "docs/phoenix/release-notes/09-2025/09-26-2025-session-annotations", - "docs/phoenix/release-notes/09-2025/09-25-2025-repetitions", - "docs/phoenix/release-notes/09-2025/09-24-2025-custom-http-headers-for-requests-in-playground", - "docs/phoenix/release-notes/09-2025/09-23-2025-repetitions-in-experiment-compare-slideover", - "docs/phoenix/release-notes/09-2025/09-22-2025-helm-configurable-image-registry-and-ipv6-support", - "docs/phoenix/release-notes/09-2025/09-17-2025-experiment-compare-details-slideover-in-list-view", - "docs/phoenix/release-notes/09-2025/09-15-2025-prompt-labels", - "docs/phoenix/release-notes/09-2025/09-12-2025-enable-paging-in-experiment-compare-details", - "docs/phoenix/release-notes/09-2025/09-08-2025-experiment-annotation-popover-in-detail-view", - "docs/phoenix/release-notes/09-2025/09-04-2025-experiment-lists-page-frontend-enhancements", - "docs/phoenix/release-notes/09-2025/09-03-2025-add-methods-to-log-document-annotations" - ] - }, { - "group": "08.2025", + "group": "Annotation Configs", "pages": [ - "docs/phoenix/release-notes/08-2025/08-28-2025-new-arize-phoenix-client-package", - "docs/phoenix/release-notes/08-2025/08-22-2025-new-trace-timeline-view", - "docs/phoenix/release-notes/08-2025/08-20-2025-new-experiment-and-annotation-quick-filters", - "docs/phoenix/release-notes/08-2025/08-15-2025-enhance-experiment-comparison-views", - "docs/phoenix/release-notes/08-2025/08-14-2025-trace-transfer-for-long-term-storage", - "docs/phoenix/release-notes/08-2025/08-12-2025-ui-design-overhauls", - "docs/phoenix/release-notes/08-2025/08-09-2025-playground-support-for-gpt-5", - "docs/phoenix/release-notes/08-2025/08-07-2025-improved-error-handling-in-prompt-playground", - "docs/phoenix/release-notes/08-2025/08-06-2025-expanded-search-capabilities", - "docs/phoenix/release-notes/08-2025/08-05-2025-claude-opus-4-1-support", - "docs/phoenix/release-notes/08-2025/08-04-2025-manual-project-creation-and-trace-duplication", - "docs/phoenix/release-notes/08-2025/08-03-2025-delete-spans-via-rest-api" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/list-annotation-configurations", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/create-an-annotation-configuration", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/get-an-annotation-configuration-by-id-or-name", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/update-an-annotation-configuration", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotation-configs/delete-an-annotation-configuration" ] }, { - "group": "07.2025", + "group": "Annotations", "pages": [ - "docs/phoenix/release-notes/07-2025/07-29-2025-google-genai-evals", - "docs/phoenix/release-notes/07-2025/07-25-2025-project-dashboards", - "docs/phoenix/release-notes/07-2025/07-25-2025-average-metrics-in-experiment-comparison-table", - "docs/phoenix/release-notes/07-2025/07-21-2025-project-and-trace-management-via-graphql", - "docs/phoenix/release-notes/07-2025/07-18-2025-openinference-java", - "docs/phoenix/release-notes/07-2025/07-13-2025-experiments-module-in-phoenix-client", - "docs/phoenix/release-notes/07-2025/07-09-2025-baseline-for-experiment-comparisons", - "docs/phoenix/release-notes/07-2025/07-07-2025-databse-disk-usage-monitor", - "docs/phoenix/release-notes/07-2025/07-03-2025-cost-summaries-in-trace-headers", - "docs/phoenix/release-notes/07-2025/07-02-2025-cursor-mcp-button" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/annotations/get-span-annotations-for-a-list-of-span_ids" ] }, { - "group": "06.2025", + "group": "Datasets", "pages": [ - "docs/phoenix/release-notes/06-2025/06-25-2025-cost-tracking", - "docs/phoenix/release-notes/06-2025/06-25-2025-new-phoenix-cloud", - "docs/phoenix/release-notes/06-2025/06-25-2025-amazon-bedrock-support-in-playground", - "docs/phoenix/release-notes/06-2025/06-13-2025-session-filtering", - "docs/phoenix/release-notes/06-2025/06-13-2025-enhanced-span-creation-and-logging", - "docs/phoenix/release-notes/06-2025/06-12-2025-dataset-filtering", - "docs/phoenix/release-notes/06-2025/06-06-2025-experiment-progress-graph", - "docs/phoenix/release-notes/06-2025/06-04-2025-ollama-support-in-playground", - "docs/phoenix/release-notes/06-2025/06-03-2025-deploy-via-helm" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/list-datasets", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/get-dataset-by-id", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/delete-dataset-by-id", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/list-dataset-versions", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/upload-dataset-from-json-csv-or-pyarrow", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/get-examples-from-a-dataset", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-csv-file", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-openai-fine-tuning-jsonl-file", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/datasets/download-dataset-examples-as-openai-evals-jsonl-file" ] }, { - "group": "05.2025", + "group": "Experiments", "pages": [ - "docs/phoenix/release-notes/05-2025/05-30-2025-xai-and-deepseek-support-in-playground", - "docs/phoenix/release-notes/05-2025/05-20-2025-datasets-and-experiment-evaluations-in-the-js-client", - "docs/phoenix/release-notes/05-2025/05-14-2025-experiments-in-the-js-client", - "docs/phoenix/release-notes/05-2025/05-09-2025-annotations-data-retention-policies-hotkeys", - "docs/phoenix/release-notes/05-2025/05-05-2025-openinference-google-genai-instrumentation" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/list-experiments-by-dataset", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-experiment-on-a-dataset", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/get-experiment-by-id", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/download-experiment-runs-as-a-json-file", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/download-experiment-runs-as-a-csv-file", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/list-runs-for-an-experiment", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-run-for-an-experiment", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/experiments/create-or-update-evaluation-for-an-experiment-run" ] }, { - "group": "04.2025", + "group": "Traces", "pages": [ - "docs/phoenix/release-notes/04-2025/04-30-2025-span-querying-and-data-extraction-for-phoenix-client", - "docs/phoenix/release-notes/04-2025/04-28-2025-tls-support-for-phoenix-server", - "docs/phoenix/release-notes/04-2025/04-28-2025-improved-shutdown-handling", - "docs/phoenix/release-notes/04-2025/04-25-2025-scroll-selected-span-into-view", - "docs/phoenix/release-notes/04-2025/04-18-2025-tracing-for-mcp-client-server-applications", - "docs/phoenix/release-notes/04-2025/04-16-2025-api-key-generation-via-api", - "docs/phoenix/release-notes/04-2025/04-15-2025-display-tool-call-and-result-ids-in-span-details", - "docs/phoenix/release-notes/04-2025/04-09-2025-project-management-api-enhancements", - "docs/phoenix/release-notes/04-2025/04-09-2025-new-rest-api-for-projects-with-rbac", - "docs/phoenix/release-notes/04-2025/04-03-2025-phoenix-client-prompt-tagging", - "docs/phoenix/release-notes/04-2025/04-02-2025-improved-span-annotation-editor", - "docs/phoenix/release-notes/04-2025/04-01-2025-support-for-mcp-span-tool-info-in-openai-agents-sdk" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/delete-a-trace-by-identifier", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/get-span-trace-or-document-evaluations-from-a-project", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/traces/add-span-trace-or-document-evaluations" ] }, { - "group": "03.2025", + "group": "Spans", "pages": [ - "docs/phoenix/release-notes/03-2025/03-27-2025-span-view-improvements", - "docs/phoenix/release-notes/03-2025/03-24-2025-tracing-configuration-tab", - "docs/phoenix/release-notes/03-2025/03-21-2025-environment-variable-based-admin-user-configuration", - "docs/phoenix/release-notes/03-2025/03-20-2025-delete-experiment-from-action-menu", - "docs/phoenix/release-notes/03-2025/03-19-2025-access-to-new-integrations-in-projects", - "docs/phoenix/release-notes/03-2025/03-18-2025-resize-span-trace-and-session-tables", - "docs/phoenix/release-notes/03-2025/03-14-2025-openai-agents-instrumentation", - "docs/phoenix/release-notes/03-2025/03-07-2025-model-config-enhancements-for-prompts", - "docs/phoenix/release-notes/03-2025/03-07-2025-new-prompt-playground-evals-and-integration-support", - "docs/phoenix/release-notes/03-2025/03-06-2025-project-improvements" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/search-spans-with-simple-filters-no-dsl", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/list-spans-with-simple-filters-no-dsl", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/create-spans", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/create-span-annotations", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/spans/delete-a-span-by-span_identifier" ] }, { - "group": "02.2025", + "group": "Prompts", "pages": [ - "docs/phoenix/release-notes/02-2025/02-19-2025-prompts", - "docs/phoenix/release-notes/02-2025/02-18-2025-one-line-instrumentation" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-all-prompts", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/create-a-new-prompt", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-prompt-versions", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-prompt-version-by-id", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-prompt-version-by-tag", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/get-latest-prompt-version", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/list-prompt-version-tags", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/prompts/add-tag-to-prompt-version" ] }, { - "group": "01.2025", + "group": "Projects", "pages": [ - "docs/phoenix/release-notes/01-2025/01-18-2025-automatic-and-manual-span-tracing" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/list-all-projects", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/create-a-new-project", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/get-project-by-id-or-name", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/update-a-project-by-id-or-name", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/projects/delete-a-project-by-id-or-name" ] }, { - "group": "2024", + "group": "Users", "pages": [ - "docs/phoenix/release-notes/2024/12-09-2024-sessions", - "docs/phoenix/release-notes/2024/11-18-2024-prompt-playground", - "docs/phoenix/release-notes/2024/09-26-2024-authentication-and-rbac", - "docs/phoenix/release-notes/2024/07-18-2024-guardrails-ai-integrations", - "docs/phoenix/release-notes/2024/07-11-2024-hosted-phoenix-and-llamatrace", - "docs/phoenix/release-notes/2024/07-03-2024-datasets-and-experiments", - "docs/phoenix/release-notes/2024/07-02-2024-function-call-evaluations" + "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/list-all-users", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/create-a-new-user", + "docs/phoenix/sdk-api-reference/rest-api/api-reference/users/delete-a-user-by-id" ] } ] } ] + }, + { + "group": "OpenInference SDK", + "icon": "puzzle", + "pages": [ + "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-python", + "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-java", + "docs/phoenix/sdk-api-reference/openinference-sdk/openinference-javascript" + ] + } + ] + }, + { + "tab": "Self-Hosting", + "icon": "server", + "groups": [ + { + "group": " ", + "pages": [ + "docs/phoenix/self-hosting", + "docs/phoenix/self-hosting/architecture", + "docs/phoenix/self-hosting/license", + { + "group": "Configuration", + "pages": [ + "docs/phoenix/self-hosting/configuration", + "docs/phoenix/self-hosting/configuration/using-amazon-aurora" + ] + } + ] + }, + { + "group": "Deployment Options", + "icon": "rocket-launch", + "pages": [ + "docs/phoenix/self-hosting/deployment-options/terminal", + "docs/phoenix/self-hosting/deployment-options/docker", + "docs/phoenix/self-hosting/deployment-options/kubernetes", + "docs/phoenix/self-hosting/deployment-options/kubernetes-helm", + "docs/phoenix/self-hosting/deployment-options/aws-with-cloudformation", + "docs/phoenix/self-hosting/deployment-options/railway" + ] + }, + { + "group": "Features", + "icon": "layer-group", + "pages": [ + "docs/phoenix/self-hosting/features/provisioning", + "docs/phoenix/self-hosting/features/authentication", + "docs/phoenix/self-hosting/features/email", + "docs/phoenix/self-hosting/features/management", + "docs/phoenix/settings/data-retention" + ] + }, + { + "group": "Upgrade", + "icon": "angles-up", + "pages": ["docs/phoenix/self-hosting/upgrade/migrations"] + }, + { + "group": "Security", + "icon": "user-shield", + "pages": [ + "docs/phoenix/settings/access-control-rbac", + "docs/phoenix/self-hosting/security/privacy" + ] + }, + { + "group": "Misc", + "icon": "boxes-stacked", + "pages": [ + "docs/phoenix/self-hosting/misc/frequently-asked-questions" + ] + } + ] + }, + { + "tab": "Phoenix Cloud", + "icon": "cloud", + "groups": [ + { + "group": "Phoenix Cloud", + "pages": ["docs/phoenix/phoenix-cloud"] + } + ] + }, + { + "tab": "Cookbooks", + "icon": "user-chef", + "groups": [ + { + "group": " ", + "pages": [ + "docs/phoenix/cookbook", + { + "group": "Agent Workflow Patterns", + "pages": [ + "docs/phoenix/cookbook/agent-workflow-patterns", + "docs/phoenix/cookbook/agent-workflow-patterns/autogen", + "docs/phoenix/cookbook/agent-workflow-patterns/crewai", + "docs/phoenix/cookbook/agent-workflow-patterns/google-genai-sdk-manual-orchestration", + "docs/phoenix/cookbook/agent-workflow-patterns/openai-agents", + "docs/phoenix/cookbook/agent-workflow-patterns/langgraph", + "docs/phoenix/cookbook/agent-workflow-patterns/smolagents" + ] + } + ] + }, + { + "group": "AI Engineering Workflows", + "icon": "gear", + "pages": [ + "docs/phoenix/cookbook/ai-engineering-workflows/iterative-evaluation-and-experimentation-workflow-python", + "docs/phoenix/cookbook/ai-engineering-workflows/iterative-evaluation-and-experimentation-workflow-typescript", + "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/creating-a-custom-llm-evaluator-with-a-benchmark-dataset", + "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/aligning-llm-evals-with-human-annotations-typescript", + "docs/phoenix/cookbook/prompt-engineering/prompt-optimization", + "docs/phoenix/cookbook/ai-engineering-workflows/analyzing-customer-review-evals-with-repetition-experiments" + ] + }, + { + "group": "Tracing", + "icon": "telescope", + "pages": [ + "docs/phoenix/cookbook/tracing/agentic-rag-tracing", + "docs/phoenix/cookbook/tracing/generating-synthetic-datasets-for-llm-evaluators-and-agents", + "docs/phoenix/cookbook/tracing/structured-data-extraction", + "docs/phoenix/cookbook/tracing/product-recommendation-agent-google-agent-engine-and-langgraph", + "docs/phoenix/cookbook/tracing/cookbooks" + ] + }, + { + "group": "Human-in-the-Loop Workflows (Annotations)", + "icon": "user-plus", + "pages": [ + "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/using-human-annotations-for-eval-driven-development", + "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/aligning-llm-evals-with-human-annotations-typescript", + "docs/phoenix/cookbook/human-in-the-loop-workflows-annotations/creating-a-custom-llm-evaluator-with-a-benchmark-dataset" + ] + }, + { + "group": "Prompt Engineering", + "icon": "wand-magic-sparkles", + "pages": [ + "docs/phoenix/cookbook/prompt-engineering/optimizing-coding-agent-prompts-prompt-learning", + "docs/phoenix/cookbook/prompt-engineering/prompt-learning-optimizing-prompts-for-classification", + "docs/phoenix/cookbook/prompt-engineering/few-shot-prompting", + "docs/phoenix/cookbook/prompt-engineering/react-prompting", + "docs/phoenix/cookbook/prompt-engineering/chain-of-thought-prompting", + "docs/phoenix/cookbook/prompt-engineering/prompt-optimization", + "docs/phoenix/cookbook/prompt-engineering/llm-as-a-judge-prompt-optimization" + ] + }, + { + "group": "Evaluation", + "icon": "clipboard-check", + "pages": [ + "docs/phoenix/cookbook/evaluation/openai-agents-sdk-cookbook", + "docs/phoenix/cookbook/evaluation/evaluate-an-agent", + "docs/phoenix/cookbook/evaluation/evaluate-rag", + "docs/phoenix/cookbook/evaluation/code-readability-evaluation", + "docs/phoenix/cookbook/evaluation/relevance-classification-evaluation", + "docs/phoenix/cookbook/evaluation/using-ragas-to-evaluate-a-math-problem-solving-agent", + "docs/phoenix/cookbook/evaluation/cookbooks" + ] + }, + { + "group": "Datasets & Experiments", + "icon": "flask", + "pages": [ + "docs/phoenix/cookbook/datasets-and-experiments/analyzing-customer-review-evals-with-repetition-experiments", + "docs/phoenix/cookbook/datasets-and-experiments/experiment-with-a-customer-support-agent", + "docs/phoenix/cookbook/datasets-and-experiments/model-comparison-for-an-email-text-extraction-service", + "docs/phoenix/cookbook/datasets-and-experiments/comparing-llamaindex-query-engines-with-a-pairwise-evaluator", + "docs/phoenix/cookbook/datasets-and-experiments/summarization", + "docs/phoenix/cookbook/datasets-and-experiments/text2sql", + "docs/phoenix/cookbook/datasets-and-experiments/cookbooks" + ] + }, + { + "group": "Retrieval & Inferences", + "icon": "magnifying-glass", + "pages": [ + "docs/phoenix/cookbook/retrieval-and-inferences/embeddings-analysis", + "docs/phoenix/cookbook/retrieval-and-inferences/cookbooks" + ] + } + ] + }, + { + "tab": "Release Notes", + "icon": "gift", + "groups": [ + { + "group": " ", + "pages": [ + "docs/phoenix/release-notes", + { + "group": "01.2026", + "pages": [ + "docs/phoenix/release-notes/01-2026/01-17-2026-phoenix-cli-ai-agent-debugging" + ] + }, + { + "group": "12.2025", + "pages": [ + "docs/phoenix/release-notes/12-2025/12-20-2025-improved-user-preferences", + "docs/phoenix/release-notes/12-2025/12-12-2025-support-for-gemini-tool-calls", + "docs/phoenix/release-notes/12-2025/12-09-2025-span-notes-api", + "docs/phoenix/release-notes/12-2025/12-06-2025-ldap-authentication-support", + "docs/phoenix/release-notes/12-2025/12-04-2025-evaluator-message-formats", + "docs/phoenix/release-notes/12-2025/12-03-2025-typescript-create-evaluator", + "docs/phoenix/release-notes/12-2025/12-01-2025-splits-on-experiments-table" + ] + }, + { + "group": "11.2025", + "pages": [ + "docs/phoenix/release-notes/11-2025/11-29-2025-add-support-for-claude-opus-4-5", + "docs/phoenix/release-notes/11-2025/11-27-2025-show-server-credential-setup-in-playground-api-keys", + "docs/phoenix/release-notes/11-2025/11-25-2025-split-assignments-when-uploading-a-dataset", + "docs/phoenix/release-notes/11-2025/11-23-2025-repetitions-for-manual-playground-invocations", + "docs/phoenix/release-notes/11-2025/11-19-2025-expanded-provider-support-with-openai-5-1-+-gemini-3", + "docs/phoenix/release-notes/11-2025/11-12-2025-updated-anthropic-model-list", + "docs/phoenix/release-notes/11-2025/11-09-2025-openinference-typescript-2-0", + "docs/phoenix/release-notes/11-2025/11-07-2025-timezone-preference", + "docs/phoenix/release-notes/11-2025/11-05-2025-metadata-for-prompts", + "docs/phoenix/release-notes/11-2025/11-03-2025-playground-dataset-label-display", + "docs/phoenix/release-notes/11-2025/11-01-2025-resume-experiments-and-evaluations" + ] + }, + { + "group": "10.2025", + "pages": [ + "docs/phoenix/release-notes/10-2025/10-30-2025-metadata-support-for-experiment-run-annotations", + "docs/phoenix/release-notes/10-2025/10-28-2025-enable-aws-iam-auth-for-db-configuration", + "docs/phoenix/release-notes/10-2025/10-26-2025-add-split-edit-menu-to-examples", + "docs/phoenix/release-notes/10-2025/10-24-2025-filter-prompts-page-by-label", + "docs/phoenix/release-notes/10-2025/10-20-2025-splits", + "docs/phoenix/release-notes/10-2025/10-18-2025-filter-annotations-in-compare-experiments-slideover", + "docs/phoenix/release-notes/10-2025/10-15-2025-enhanced-filtering-for-examples-table", + "docs/phoenix/release-notes/10-2025/10-13-2025-view-traces-in-compare-experiments", + "docs/phoenix/release-notes/10-2025/10-10-2025-viewer-role", + "docs/phoenix/release-notes/10-2025/10-08-2025-dataset-labels", + "docs/phoenix/release-notes/10-2025/10-06-2025-paginate-compare-experiments", + "docs/phoenix/release-notes/10-2025/10-05-2025-load-prompt-by-tag-into-playground", + "docs/phoenix/release-notes/10-2025/10-03-2025-prompt-version-editing-in-playground" + ] + }, + { + "group": "09.2025", + "pages": [ + "docs/phoenix/release-notes/09-2025/09-29-2025-day-0-support-for-claude-sonnet-4.5", + "docs/phoenix/release-notes/09-2025/09-27-2025-dataset-splits", + "docs/phoenix/release-notes/09-2025/09-26-2025-session-annotations", + "docs/phoenix/release-notes/09-2025/09-25-2025-repetitions", + "docs/phoenix/release-notes/09-2025/09-24-2025-custom-http-headers-for-requests-in-playground", + "docs/phoenix/release-notes/09-2025/09-23-2025-repetitions-in-experiment-compare-slideover", + "docs/phoenix/release-notes/09-2025/09-22-2025-helm-configurable-image-registry-and-ipv6-support", + "docs/phoenix/release-notes/09-2025/09-17-2025-experiment-compare-details-slideover-in-list-view", + "docs/phoenix/release-notes/09-2025/09-15-2025-prompt-labels", + "docs/phoenix/release-notes/09-2025/09-12-2025-enable-paging-in-experiment-compare-details", + "docs/phoenix/release-notes/09-2025/09-08-2025-experiment-annotation-popover-in-detail-view", + "docs/phoenix/release-notes/09-2025/09-04-2025-experiment-lists-page-frontend-enhancements", + "docs/phoenix/release-notes/09-2025/09-03-2025-add-methods-to-log-document-annotations" + ] + }, + { + "group": "08.2025", + "pages": [ + "docs/phoenix/release-notes/08-2025/08-28-2025-new-arize-phoenix-client-package", + "docs/phoenix/release-notes/08-2025/08-22-2025-new-trace-timeline-view", + "docs/phoenix/release-notes/08-2025/08-20-2025-new-experiment-and-annotation-quick-filters", + "docs/phoenix/release-notes/08-2025/08-15-2025-enhance-experiment-comparison-views", + "docs/phoenix/release-notes/08-2025/08-14-2025-trace-transfer-for-long-term-storage", + "docs/phoenix/release-notes/08-2025/08-12-2025-ui-design-overhauls", + "docs/phoenix/release-notes/08-2025/08-09-2025-playground-support-for-gpt-5", + "docs/phoenix/release-notes/08-2025/08-07-2025-improved-error-handling-in-prompt-playground", + "docs/phoenix/release-notes/08-2025/08-06-2025-expanded-search-capabilities", + "docs/phoenix/release-notes/08-2025/08-05-2025-claude-opus-4-1-support", + "docs/phoenix/release-notes/08-2025/08-04-2025-manual-project-creation-and-trace-duplication", + "docs/phoenix/release-notes/08-2025/08-03-2025-delete-spans-via-rest-api" + ] + }, + { + "group": "07.2025", + "pages": [ + "docs/phoenix/release-notes/07-2025/07-29-2025-google-genai-evals", + "docs/phoenix/release-notes/07-2025/07-25-2025-project-dashboards", + "docs/phoenix/release-notes/07-2025/07-25-2025-average-metrics-in-experiment-comparison-table", + "docs/phoenix/release-notes/07-2025/07-21-2025-project-and-trace-management-via-graphql", + "docs/phoenix/release-notes/07-2025/07-18-2025-openinference-java", + "docs/phoenix/release-notes/07-2025/07-13-2025-experiments-module-in-phoenix-client", + "docs/phoenix/release-notes/07-2025/07-09-2025-baseline-for-experiment-comparisons", + "docs/phoenix/release-notes/07-2025/07-07-2025-databse-disk-usage-monitor", + "docs/phoenix/release-notes/07-2025/07-03-2025-cost-summaries-in-trace-headers", + "docs/phoenix/release-notes/07-2025/07-02-2025-cursor-mcp-button" + ] + }, + { + "group": "06.2025", + "pages": [ + "docs/phoenix/release-notes/06-2025/06-25-2025-cost-tracking", + "docs/phoenix/release-notes/06-2025/06-25-2025-new-phoenix-cloud", + "docs/phoenix/release-notes/06-2025/06-25-2025-amazon-bedrock-support-in-playground", + "docs/phoenix/release-notes/06-2025/06-13-2025-session-filtering", + "docs/phoenix/release-notes/06-2025/06-13-2025-enhanced-span-creation-and-logging", + "docs/phoenix/release-notes/06-2025/06-12-2025-dataset-filtering", + "docs/phoenix/release-notes/06-2025/06-06-2025-experiment-progress-graph", + "docs/phoenix/release-notes/06-2025/06-04-2025-ollama-support-in-playground", + "docs/phoenix/release-notes/06-2025/06-03-2025-deploy-via-helm" + ] + }, + { + "group": "05.2025", + "pages": [ + "docs/phoenix/release-notes/05-2025/05-30-2025-xai-and-deepseek-support-in-playground", + "docs/phoenix/release-notes/05-2025/05-20-2025-datasets-and-experiment-evaluations-in-the-js-client", + "docs/phoenix/release-notes/05-2025/05-14-2025-experiments-in-the-js-client", + "docs/phoenix/release-notes/05-2025/05-09-2025-annotations-data-retention-policies-hotkeys", + "docs/phoenix/release-notes/05-2025/05-05-2025-openinference-google-genai-instrumentation" + ] + }, + { + "group": "04.2025", + "pages": [ + "docs/phoenix/release-notes/04-2025/04-30-2025-span-querying-and-data-extraction-for-phoenix-client", + "docs/phoenix/release-notes/04-2025/04-28-2025-tls-support-for-phoenix-server", + "docs/phoenix/release-notes/04-2025/04-28-2025-improved-shutdown-handling", + "docs/phoenix/release-notes/04-2025/04-25-2025-scroll-selected-span-into-view", + "docs/phoenix/release-notes/04-2025/04-18-2025-tracing-for-mcp-client-server-applications", + "docs/phoenix/release-notes/04-2025/04-16-2025-api-key-generation-via-api", + "docs/phoenix/release-notes/04-2025/04-15-2025-display-tool-call-and-result-ids-in-span-details", + "docs/phoenix/release-notes/04-2025/04-09-2025-project-management-api-enhancements", + "docs/phoenix/release-notes/04-2025/04-09-2025-new-rest-api-for-projects-with-rbac", + "docs/phoenix/release-notes/04-2025/04-03-2025-phoenix-client-prompt-tagging", + "docs/phoenix/release-notes/04-2025/04-02-2025-improved-span-annotation-editor", + "docs/phoenix/release-notes/04-2025/04-01-2025-support-for-mcp-span-tool-info-in-openai-agents-sdk" + ] + }, + { + "group": "03.2025", + "pages": [ + "docs/phoenix/release-notes/03-2025/03-27-2025-span-view-improvements", + "docs/phoenix/release-notes/03-2025/03-24-2025-tracing-configuration-tab", + "docs/phoenix/release-notes/03-2025/03-21-2025-environment-variable-based-admin-user-configuration", + "docs/phoenix/release-notes/03-2025/03-20-2025-delete-experiment-from-action-menu", + "docs/phoenix/release-notes/03-2025/03-19-2025-access-to-new-integrations-in-projects", + "docs/phoenix/release-notes/03-2025/03-18-2025-resize-span-trace-and-session-tables", + "docs/phoenix/release-notes/03-2025/03-14-2025-openai-agents-instrumentation", + "docs/phoenix/release-notes/03-2025/03-07-2025-model-config-enhancements-for-prompts", + "docs/phoenix/release-notes/03-2025/03-07-2025-new-prompt-playground-evals-and-integration-support", + "docs/phoenix/release-notes/03-2025/03-06-2025-project-improvements" + ] + }, + { + "group": "02.2025", + "pages": [ + "docs/phoenix/release-notes/02-2025/02-19-2025-prompts", + "docs/phoenix/release-notes/02-2025/02-18-2025-one-line-instrumentation" + ] + }, + { + "group": "01.2025", + "pages": [ + "docs/phoenix/release-notes/01-2025/01-18-2025-automatic-and-manual-span-tracing" + ] + }, + { + "group": "2024", + "pages": [ + "docs/phoenix/release-notes/2024/12-09-2024-sessions", + "docs/phoenix/release-notes/2024/11-18-2024-prompt-playground", + "docs/phoenix/release-notes/2024/09-26-2024-authentication-and-rbac", + "docs/phoenix/release-notes/2024/07-18-2024-guardrails-ai-integrations", + "docs/phoenix/release-notes/2024/07-11-2024-hosted-phoenix-and-llamatrace", + "docs/phoenix/release-notes/2024/07-03-2024-datasets-and-experiments", + "docs/phoenix/release-notes/2024/07-02-2024-function-call-evaluations" + ] + } + ] } - ], + ] + } + ], "global": { "anchors": [] } @@ -1252,25 +1249,25 @@ }, { "label": "", - "href": "https://x.com/ArizePhoenix", + "href": "https://x.com/ArizePhoenix", "title": "X", "icon": "x-twitter" }, { "label": "", - "href": "https://bsky.app/profile/arize-phoenix.bsky.social", + "href": "https://bsky.app/profile/arize-phoenix.bsky.social", "title": "Bluesky", "icon": "bluesky" - }, + }, { "label": "", - "href": "https://www.linkedin.com/company/arizeai/", + "href": "https://www.linkedin.com/company/arizeai/", "title": "LinkedIn", "icon": "linkedin" - }, + }, { "label": "", - "href": "https://github.com/Arize-ai/phoenix", + "href": "https://github.com/Arize-ai/phoenix", "title": "GitHub", "icon": "github" } diff --git a/docs/phoenix/evaluation/tutorials/configure-your-llm.mdx b/docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx similarity index 100% rename from docs/phoenix/evaluation/tutorials/configure-your-llm.mdx rename to docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx diff --git a/docs/phoenix/evaluation/tutorials/run-your-evals.mdx b/docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx similarity index 100% rename from docs/phoenix/evaluation/tutorials/run-your-evals.mdx rename to docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx diff --git a/docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx b/docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx similarity index 100% rename from docs/phoenix/evaluation/tutorials/use-custom-eval-template.mdx rename to docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx diff --git a/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx b/docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx similarity index 100% rename from docs/phoenix/evaluation/tutorials/use-pre-build-eval-template.mdx rename to docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx diff --git a/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx new file mode 100644 index 00000000000..cae36db6443 --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx @@ -0,0 +1,315 @@ +--- +title: "Customize Your Evaluation Template" +--- +Built-in eval templates cover many common evaluation patterns, but they can’t capture every application-specific requirement. When evaluation depends on domain knowledge, task constraints, or product expectations, defining a custom evaluator lets you make those criteria explicit. + +This guide shows how to customize an evaluation template in Phoenix by refining the judge prompt, controlling what the judge sees, and defining outputs that remain consistent and actionable across runs. + +Follow along with the following code assets: + + + + Companion TypeScript project with runnable examples + + + Companion Python project with runnable examples + + + +TODO: \ + +--- + +## How Custom Evaluators Work + +A custom evaluator is defined by a prompt template that guides the judge model through a specific decision. The most effective templates follow the same order the judge reads and reasons about information. + +**Start by defining the judge’s role and task.** + +Rather than asking an open-ended question, the prompt should act like a rubric. It should clearly state what is being evaluated and which criteria the judge should apply. Explicit instructions make judgments easier to reproduce, while vague language leads to inconsistent results. + +**Next, present the data to be evaluated.** + +In most cases, this includes the input that produced the output and the output itself. Some evaluations require additional context, such as retrieved documents or reference material, but this should be included only when necessary. Clearly labeling each part of the data and using consistent formatting helps reduce ambiguity. Many templates use a delimited section (such as BEGIN DATA / END DATA) to make boundaries explicit. + +**Finally, constrain the allowed outputs.** + +Most custom evaluators use classification-style outputs that return a single label per example. Labels like correct / incorrect or relevant / irrelevant are easy to compare across runs and integrate cleanly with Phoenix’s logging and analysis tools. While other output formats are possible, categorical labels are generally the most stable and interpretable starting point. + +## Define a Custom Evaluator + +The example below shows a customized version of the built-in correctness evaluation, adapted for a travel planning agent. Compared to the generic template, this version encodes application-specific expectations around essential information, budget clarity, and local context. + +By making these criteria explicit, the resulting evaluation signal is more informative and more useful for identifying concrete areas for improvement. + + + + ```python + CUSTOM_CORRECTNESS_TEMPLATE = """You are an expert evaluator judging whether a travel planner agent's response is correct. The agent is a friendly travel planner that must combine multiple tools to create a trip plan with: (1) essential info, (2) budget breakdown, and (3) local flavor/experiences. + + CORRECT - The response: + - Accurately addresses the user's destination, duration, and stated interests + - Includes essential travel info (e.g., weather, best time to visit, key attractions, etiquette) for the destination + - Includes a budget or cost breakdown appropriate to the destination and trip duration + - Includes local experiences, cultural highlights, or authentic recommendations matching the user's interests + - Is factually accurate, logically consistent, and helpful for planning the trip + - Uses precise, travel-appropriate terminology + + INCORRECT - The response contains any of: + - Factual errors about the destination, costs, or local info + - Missing essential info when the user asked for a full trip plan + - Missing or irrelevant budget information for the given destination/duration + - Missing or generic local experiences that do not match the user's interests + - Wrong destination, duration, or interests addressed + - Contradictions, misleading statements, or unhelpful/off-topic content + + [BEGIN DATA] + ************ + [User Input]: + {{input}} + + ************ + [Travel Plan]: + {{output}} + ************ + [END DATA] + + Focus on factual accuracy and completeness of the trip plan (essentials, budget, local flavor). Is the output correct or incorrect?""" + ``` + + + ```typescript + const correctnessTemplate = ` + You are an expert evaluator judging whether a travel planner agent's response is correct. The agent is a friendly travel planner that must combine multiple tools to create a trip plan with: (1) essential info, (2) budget breakdown, and (3) local flavor/experiences. + + CORRECT - The response: + - Accurately addresses the user's destination, duration, and stated interests + - Includes essential travel info (e.g., weather, best time to visit, key attractions, etiquette) for the destination + - Includes a budget or cost breakdown appropriate to the destination and trip duration + - Includes local experiences, cultural highlights, or authentic recommendations matching the user's interests + - Is factually accurate, logically consistent, and helpful for planning the trip + - Uses precise, travel-appropriate terminology + + INCORRECT - The response contains any of: + - Factual errors about the destination, costs, or local info + - Missing essential info when the user asked for a full trip plan + - Missing or irrelevant budget information for the given destination/duration + - Missing or generic local experiences that do not match the user's interests + - Wrong destination, duration, or interests addressed + - Contradictions, misleading statements, or unhelpful/off-topic content + + [BEGIN DATA] + ************ + [User Input]: + {{input}} + + ************ + [Travel Plan]: + {{output}} + ************ + [END DATA] + + Focus on factual accuracy and completeness of the trip plan (essentials, budget, local flavor). Is the output correct or incorrect? + `; + ``` + + + +## Create the Custom Evaluator + +Once the template is defined, you can create a custom evaluator using any supported judge model. This example uses a custom OpenAI-compatible endpoint, but the same pattern applies regardless of where the model is hosted. + + + + ```python + from phoenix.evals import ClassificationEvaluator + from phoenix.evals.llm import LLM + + custom_llm = LLM( + provider="openai", + model="accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", + base_url="https://api.fireworks.ai/inference/v1", + api_key=os.environ.get("FIREWORKS_API_KEY"), + ) + + custom_correctness_evaluator = ClassificationEvaluator( + name = "custom_correctness", + llm = custom_llm, + prompt_template=CUSTOM_CORRECTNESS_TEMPLATE, + choices={"correct": 1, "incorrect": 0} + ) + ``` + + + ```typescript + import { createClassificationEvaluator } from "@arizeai/phoenix-evals"; + import { createOpenAI } from "@ai-sdk/openai"; + + const llm = createOpenAI({ + baseURL: "https://api.fireworks.ai/inference/v1", + apiKey: process.env.FIREWORKS_API_KEY, + }).chat(FIREWORKS_MODEL); + + const EVAL_NAME = "custom_correctness"; + const evaluator = createClassificationEvaluator({ + model: llm as Parameters[0]["model"], + promptTemplate: correctnessTemplate, + choices: { correct: 1, incorrect: 0 }, + name: EVAL_NAME, + }); + ``` + + + +## Run the Evaluator on Traced Data + +Once defined, custom evaluators can be run the same way as built-in templates, either on individual examples or in batch over trace-derived data. + +**1. Export trace spans** + +Start by exporting spans from a Phoenix project: + + + + ```python + from phoenix.client import Client + + client = Client() + spans_df = client.spans.get_spans_dataframe(project_identifier="agno_travel_agent") + agent_spans = spans_df[spans_df['span_kind'] == 'AGENT'] + agent_spans + ``` + + + ```typescript + import { getSpans } from "@arizeai/phoenix-client/spans"; + + const projectName = + process.env.PHOENIX_PROJECT_NAME || "langchain-travel-agent"; + const { spans } = await getSpans({ project: { projectName }, limit: 500 }); + ``` + + +Each row represents a span and includes identifiers and attributes captured during execution. + +**2. Prepare Evaluator Inputs** +Next, select or transform fields from the exported spans so they match the evaluator’s expected inputs. This often involves extracting nested attributes such as: + +Ex. `attributes.input.value` & `attributes.output.value` + +Input mappings help bridge differences between how data is stored in traces and what evaluators expect. + + + + ```python + from phoenix.evals import bind_evaluator + + bound_evaluator = bind_evaluator( + evaluator=custom_correctness_eval, + input_mapping={ + "input": "attributes.input.value", + "output": "attributes.output.value", + } + ) + ``` + + + We may need to manipulate the data a little bit here to make it easier to pass into the evaluator. We can first define some helper functions. + ```typescript + const toStr = (v: unknown) => + typeof v === "string" ? v : v != null ? JSON.stringify(v) : null; + + function getInputOutput(span: any) { + const attrs = span.attributes ?? {}; + const input = toStr(attrs["input.value"] ?? attrs["input"]); + const output = toStr(attrs["output.value"] ?? attrs["output"]); + return { input, output }; + } + + const parentSpans: { spanId: string; input: string; output: string }[] = []; + for (const s of spans) { + const name = (s as any).name ?? (s as any).span_name; + if (name !== "LangGraph") continue; + const { input, output } = getInputOutput(s); + const spanId = + (s as any).context?.span_id ?? (s as any).span_id ?? (s as any).id; + if (input && output && spanId) { + parentSpans.push({ spanId: String(spanId), input, output }); + } + } + ``` + + + +**3. Run evals on the prepared data** + +Once the evaluation dataframe is prepared, you can run evals in batch using the same APIs used for any tabular data. + + + + ```python + from phoenix.evals import evaluate_dataframe + from phoenix.trace import suppress_tracing + + with suppress_tracing(): + results_df = evaluate_dataframe(agent_spans, [bound_evaluator]) + ``` + + + ```typescript + const spanAnnotations = await Promise.all( + parentSpans.map(async ({ spanId, input, output }) => { + const r = await evaluator.evaluate({ input, output }); + console.log(r.explanation); + return { + spanId, + name: "custom_correctness" as const, + label: r.label, + score: r.score, + explanation: r.explanation ?? undefined, + annotatorKind: "LLM" as const, + metadata: { evaluator: "custom_correctness", input, output }, + }; + }), + ); + ``` + + + +**4. Log results back to Phoenix** + +Finally, log evaluation results back to Phoenix as span annotations. Phoenix uses span identifiers to associate eval outputs with the correct execution. + + + ```python + from phoenix.evals.utils import to_annotation_dataframe + + evaluations = to_annotation_dataframe(dataframe=results_df) + Client().spans.log_span_annotations_dataframe(dataframe=evaluations) + ``` + + + ```typescript + import { logSpanAnnotations } from "@arizeai/phoenix-client/spans"; + + await logSpanAnnotations({ spanAnnotations, sync: true }); + ``` + + +Once logged, eval results appear alongside traces in the Phoenix UI, making it possible to analyze execution behavior and quality together. + +--- + +## Best Practices + +Custom evaluators are sensitive to wording. Small changes can significantly affect evaluation behavior, so prompts should be written deliberately and kept focused. + +Be explicit about what the judge should evaluate and what it should ignore. If correctness depends on specific facts, constraints, or assumptions, include them directly in the template. + +For most tasks, categorical judgments are more reliable than numeric scores. Numeric ratings require reasoning about scale and relative magnitude, which often introduces additional variability. If numeric outputs are used, each value must have a clear, unambiguous definition. + +## Next Steps + +Congratulations! You’ve now seen how to move beyond built-in evals by defining a custom evaluation template that reflects how your application actually defines success. + +If you want to keep going and explore more evaluation patterns or APIs, you can dive deeper in the [full evaluation feature documentation](https://arize.com/docs/phoenix/evaluation/how-to-evals). \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx b/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx new file mode 100644 index 00000000000..88997bf8aaa --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx @@ -0,0 +1,267 @@ +--- +title: "Customize Your LLM Endpoint" +--- +Phoenix Evals gives you flexibility in how you configure the model that acts as a judge. You can use hosted models from common providers, connect to self-hosted or internal inference endpoints, and tune model behavior to match your evaluation needs. + +This guide builds on the previous page by showing how to run built-in eval templates using a custom-configured judge model. The evaluation logic stays the same, but the underlying model can be swapped or customized to fit your environment, cost constraints, or deployment requirements. + +The goal is to demonstrate that judge models are modular: once configured, the same built-in eval templates can be reused regardless of where the model is hosted. + +At its core, an LLM-as-a-judge evaluation combines three things: + +1. The judge model: the LLM that produces the judgment + +2. A prompt template or rubric: the criteria used to make that judgment + +3. Your data: the examples being evaluated + +In this guide, we focus on configuring the judge model, then reusing the same built-in eval templates you’ve already seen. + +Follow along with the following code assets: + + + + Companion TypeScript project with runnable examples + + + Companion Python project with runnable examples + + + +TODO: \ + +--- + +## Using Custom or OpenAI-Compatible Judge Models + +In addition to standard hosted providers, Phoenix supports using custom or self-hosted judge models that are compatible with an existing provider SDK, such as OpenAI-compatible APIs. + +This allows you to run LLM-as-a-judge evaluations against internal inference services, private deployments, or alternative model hosts, while continuing to use the same evaluation templates and execution workflows. + +When configuring a judge model, you can pass any SDK-specific parameters required to reach your endpoint: `base_url`, `api_key`, or `api_version`. These settings control how Phoenix connects and authenticates with the model provider. + +The same separation of responsibilities applies regardless of where the model is hosted: + +* Connectivity and authentication are defined on the judge model + +* Evaluation behavior (for example, temperature or token limits) is controlled by the evaluator + +A minimal example of configuring a custom OpenAI-compatible endpoint looks like this: + + + + ```python + from phoenix.evals.llm import LLM + + custom_llm = LLM( + provider="openai", + model="accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", + base_url="https://api.fireworks.ai/inference/v1", + api_key=os.environ.get("FIREWORKS_API_KEY"), + ) + ``` + + + ```typescript + import { createOpenAI } from "@ai-sdk/openai"; + + const fireworks = createOpenAI({ + baseURL: "https://api.fireworks.ai/inference/v1", + apiKey: process.env.FIREWORKS_API_KEY, + }); + const custom_llm = fireworks.chat( + "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", + ); + ``` + + +Once configured, this judge model can be used with built-in eval templates in exactly the same way as a hosted model, without changing evaluation logic or execution code. + + +## Built-In Eval Templates in Phoenix + +Phoenix includes a set of built-in eval templates that cover common evaluation tasks such as relevance, correctness, faithfulness, summarization quality, and toxicity. These templates encode a predefined rubric, structured outputs, and defaults that work well for LLM-as-a-judge workflows. + +You can find all [built in templates](https://arize.com/docs/phoenix/evaluation/pre-built-metrics) here. + +Built-in templates are a good choice when you want reliable signal quickly without designing a rubric from scratch, especially early in iteration or when establishing a baseline. + +The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: + + + ```python + from phoenix.evals.metrics import CorrectnessEvaluator + + correctness_eval = CorrectnessEvaluator(llm=custom_llm) + ``` + + + ```typescript + import { createCorrectnessEvaluator } from "@arizeai/phoenix-evals"; + + const evaluator = createCorrectnessEvaluator({ + model: custom_llm as any, + }); + ``` + + +Once defined, built-in evaluators can be run on tabular data or trace-derived examples and logged back to Phoenix like any other eval. Because they return structured outputs, results can be compared across runs and combined with other evaluations. + +## Running Evals on Phoenix Traces + +With a judge model and evaluator defined, the workflow for running evals on real application data is unchanged. + +A common pattern is evaluating traced executions and attaching results back to spans in Phoenix. + +**1. Export trace spans** + +Start by exporting spans from a Phoenix project into a tabular structure: + + + + ```python + from phoenix.client import Client + + client = Client() + spans_df = client.spans.get_spans_dataframe(project_identifier="agno_travel_agent") + agent_spans = spans_df[spans_df['span_kind'] == 'AGENT'] + agent_spans + ``` + + + ```typescript + import { getSpans } from "@arizeai/phoenix-client/spans"; + + const projectName = + process.env.PHOENIX_PROJECT_NAME || "langchain-travel-agent"; + const { spans } = await getSpans({ project: { projectName }, limit: 500 }); + ``` + + +Each row represents a span and includes identifiers and attributes captured during execution. + +**2. Prepare Evaluator Inputs** +Next, select or transform fields from the exported spans so they match the evaluator’s expected inputs. This often involves extracting nested attributes such as: + +Ex. `attributes.input.value` & `attributes.output.value` + +Input mappings help bridge differences between how data is stored in traces and what evaluators expect. + + + + ```python + from phoenix.evals import bind_evaluator + + bound_evaluator = bind_evaluator( + evaluator=correctness_eval, + input_mapping={ + "input": "attributes.input.value", + "output": "attributes.output.value", + } + ) + ``` + + + We may need to manipulate the data a little bit here to make it easier to pass into the evaluator. We can first define some helper functions. + ```typescript + const toStr = (v: unknown) => + typeof v === "string" ? v : v != null ? JSON.stringify(v) : null; + + function getInputOutput(span: any) { + const attrs = span.attributes ?? {}; + const input = toStr(attrs["input.value"] ?? attrs["input"]); + const output = toStr(attrs["output.value"] ?? attrs["output"]); + return { input, output }; + } + + const parentSpans: { spanId: string; input: string; output: string }[] = []; + for (const s of spans) { + const name = (s as any).name ?? (s as any).span_name; + if (name !== "LangGraph") continue; + const { input, output } = getInputOutput(s); + const spanId = + (s as any).context?.span_id ?? (s as any).span_id ?? (s as any).id; + if (input && output && spanId) { + parentSpans.push({ spanId: String(spanId), input, output }); + } + } + ``` + + + +**3. Run evals on the prepared data** + +Once the evaluation dataframe is prepared, you can run evals in batch using the same APIs used for any tabular data. + + + + ```python + from phoenix.evals import evaluate_dataframe + from phoenix.trace import suppress_tracing + with suppress_tracing(): + results_df = evaluate_dataframe(agent_spans, [bound_evaluator]) + ``` + + + ```typescript + const spanAnnotations = await Promise.all( + parentSpans.map(async ({ spanId, input, output }) => { + const r = await evaluator.evaluate({ input, output }); + console.log(r.explanation); + return { + spanId, + name: "correctness" as const, + label: r.label, + score: r.score, + explanation: r.explanation ?? undefined, + annotatorKind: "LLM" as const, + metadata: { evaluator: "correctness", input, output }, + }; + }), + ); + ``` + + + +**4. Log results back to Phoenix** + +Finally, log evaluation results back to Phoenix as span annotations. Phoenix uses span identifiers to associate eval outputs with the correct execution. + + + ```python + from phoenix.evals.utils import to_annotation_dataframe + + evaluations = to_annotation_dataframe(dataframe=results_df) + Client().spans.log_span_annotations_dataframe(dataframe=evaluations) + ``` + + + ```typescript + import { logSpanAnnotations } from "@arizeai/phoenix-client/spans"; + + await logSpanAnnotations({ spanAnnotations, sync: true }); + ``` + + +Once logged, eval results appear alongside traces in the Phoenix UI, making it possible to analyze execution behavior and quality together. + +--- +## **Best Practices for Judge Models** + +Judge models are not user-facing. Their role is to apply a rubric consistently, not to generate creative or varied responses. When configuring a judge model, prioritize stability and repeatability over expressiveness. + +### **Favor consistency over creativity** + +Judge models should produce the same judgment when given the same input. Variability makes it harder to compare results across runs or to detect regressions. In most cases, configure the judge with a sampling temperature of 0.0 (or as low as the provider allows) to minimize randomness and improve consistency. + +### **Prefer categorical judgments** + +For most evaluation tasks, categorical outputs are more reliable than numeric ratings. Asking a model to reason about scales or relative magnitudes introduces additional variability and tends to correlate less well with human judgment. Phoenix Evals recommends using categorical labels for judging outputs and mapping them to numeric values only if needed downstream. + +## What’s Next + +You’ve now seen how to run built-in eval templates using both hosted and custom judge models. This allows you to adapt evaluation workflows to different providers and deployment environments while keeping evaluation logic consistent. + +In the next guide, we’ll move beyond built-in templates and show how to define a custom evaluator. This includes writing your own evaluation prompt, defining application-specific criteria, and tailoring outputs to your use case. + +Together, these guides show how to move from out-of-the-box evaluations to fully customized evals tailored to your application. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/page-1.mdx b/docs/phoenix/evaluation/tutorials/page-1.mdx deleted file mode 100644 index 9244949ce29..00000000000 --- a/docs/phoenix/evaluation/tutorials/page-1.mdx +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: "Run evals with built-in eval templates" ---- - -[TODO]: need to add some sort of short intro here. - - -At its core, an LLM as a Judge eval combines three things: - -1. **The judge model**: the LLM that makes the judgment -2. **A prompt template or rubric**: the criteria you want judged -3. **Your data**: the examples you want to score - -Once you have defined what you want to evaluate and which data you want to run on, the next step is choosing and configuring the judge model. The model and its invocation settings directly affect how criteria are interpreted and how consistent your eval results are. - -We’ll now walk through how to pick and configure that model using the Phoenix evals. - -Follow along with the following code assets: - - - - Companion TypeScript project with runnable examples - - - Companion Python project with runnable examples - - - -TODO: \ - -## Configure Core LLM Setup - -[TODO] do not talk specifically only abt the Python evals library, i want this is to content that someone using either python or ts evals library can use. - -Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. - -In the Python evals library, judge models are represented by the LLM class. An LLM describes a specific provider and model configuration and can be reused across multiple evaluators. Phoenix uses adapter layers to wrap provider SDKs so that different models can be used through the same interface. - -When you create an LLM, you specify how Phoenix connects to the model provider. This includes details such as the provider name, model identifier, credentials, and any SDK-specific client configuration. These settings are concerned only with connectivity and authentication. - -How the model behaves during evaluation is configured separately. Evaluators specify invocation parameters, such as sampling temperature or maximum token limits, that control how the judge model generates outputs for a particular eval. Keeping these concerns separate makes it easier to reuse the same judge model across different evals while tuning behavior per task. - -The example below illustrates this separation between model configuration and evaluator behavior: - - - ```python - from phoenix.evals.llm import LLM - - judge_llm = LLM( - provider="openai", - model="gpt-4o", - api_key="YOUR_API_KEY", - timeout=30.0, - ) - ``` - - - - - - -In practice, this means you can change how a model is called for one eval without affecting others, while keeping provider configuration centralized. - -## Built-In Eval Templates in Phoenix - -Phoenix includes a set of built-in eval templates that cover many common evaluation tasks, such as relevance, faithfulness, summarization quality, and toxicity. These templates are designed to be used as building blocks: they encode a clear evaluation rubric, a structured output format, and defaults that work well with LLM-as-a-judge workflows. - -[TODO] add in link to pre-build eval page - -[TODO] make this more concise (a couple sentences:) - -Built-in eval templates are a good choice when: - -- You are evaluating a common task (for example, relevance or correctness) -- You want fast, reliable signal without designing a rubric from scratch -- You are early in iteration and want to establish a baseline - -These templates are especially useful for exploratory analysis, regression detection, and experiment comparisons, where consistency across many runs is more important than fine-grained customization. - -The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: - - - ```python - from phoenix.evals import ClassificationEvaluator - from phoenix.evals.metrics import CorrectnessEvaluator - - # Create the evaluator - correctness_eval = CorrectnessEvaluator(llm=llm) - - # Inspect the evaluator's requirements - print(correctness_eval.describe()) - ``` - - - - - - -Once defined, this evaluator can be run on a dataframe or trace-derived dataset and logged to Phoenix like any other eval. Because the template returns structured outputs, its results can be compared across runs and combined with other evaluations. - -## Running Evals on Phoenix Traces - -We'll now walk through how to run evals on real trace data. - -1. Export trace spans into a dataframe. - - - ```python - from phoenix.client import Client - - spans_df = Client().spans.get_spans_dataframe(project_name="agno_travel_agent") - ``` - - - - - -2. Select or transform fields from the spans so they match evaluator inputs (e.g., mapping nested attributes like `attributes.input.value`). - - - - - - - - - -3. Run batch evals on the prepared dataframe using the same APIs shown earlier. First I will define our evaluator. - - - - - - - - - - -4. Log evaluation results back to Phoenix as span annotations. Phoenix uses the span identifier to attach annotations correctly. - - - - ```python - from phoenix.client import Client - - Client().spans.log_span_annotations_dataframe( - dataframe=eval_df, - annotation_name="relevance", - annotator_kind="LLM", - ) - ``` - - - - - diff --git a/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx b/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx new file mode 100644 index 00000000000..473c420b4f3 --- /dev/null +++ b/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx @@ -0,0 +1,252 @@ +--- +title: "Run Evals With Built-In Eval Templates" +--- + +This guide walks through how to run evaluations using Phoenix’s built-in eval templates. You’ll configure a judge model, select a pre-built evaluation, and run it on real data—specifically, data derived from Phoenix traces. + +The goal is to go from traced application executions to structured quality signals that can be inspected, compared, and logged back to Phoenix. This guide assumes you already have tracing in place and focuses on using evals to measure correctness and behavior. + +At its core, an LLM-as-a-judge evaluation combines three things: + +1. The judge model: the LLM that produces the judgment + +2. A prompt template or rubric: the criteria used to make that judgment + +3. Your data: the examples being evaluated + +Once you’ve defined what you want to evaluate and selected the data to run on, the next step is configuring the judge model. The choice of model and its invocation settings directly affect how criteria are interpreted and how consistent evaluation results are. + +This guide walks through how to configure a judge model and run built-in eval templates using Phoenix Evals. + +Follow along with the following code assets: + + + + Companion TypeScript project with runnable examples + + + Companion Python project with runnable examples + + + +TODO: \ + +--- + +## Configure Core LLM Setup +Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. + +Across both the Python and TypeScript evals libraries, a judge model is represented as a reusable configuration object. This object describes how Phoenix connects to a model provider, including the provider name, model identifier, credentials, and any SDK-specific client configuration. + +Invocation behavior (temperature, token limits, or other generation controls) is configured separately on the evaluator. This separation makes it possible to reuse the same judge model across multiple evals while tuning behavior per evaluation. + +The example below illustrates this separation by configuring a judge model independently of any specific evaluator: + + + + ```python + from phoenix.evals.llm import LLM + + llm = LLM( + provider="openai", + model="gpt-4o", + client="openai", + ) + ``` + + + ```typescript + import { openai } from "@ai-sdk/openai"; + + const base_model = openai("gpt-4o-mini"); + ``` + + +In practice, this means you can adjust how a model is called for one eval without affecting others, while keeping provider configuration centralized. + +## Built-In Eval Templates in Phoenix + +Phoenix includes a set of built-in eval templates that cover common evaluation tasks such as relevance, correctness, faithfulness, summarization quality, and toxicity. These templates encode a predefined rubric, structured outputs, and defaults that work well for LLM-as-a-judge workflows. + +You can find all [built in templates](https://arize.com/docs/phoenix/evaluation/pre-built-metrics) here. + +Built-in templates are a good choice when you want reliable signal quickly without designing a rubric from scratch, especially early in iteration or when establishing a baseline. + +The example below shows how to instantiate a built-in Correctness eval template using a configured judge model: + +The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: + + + ```python + from phoenix.evals.metrics import CorrectnessEvaluator + + correctness_eval = CorrectnessEvaluator(llm=llm) + print(correctness_eval.describe()) + ``` + + + ```typescript + import { createCorrectnessEvaluator } from "@arizeai/phoenix-evals"; + + const evaluator = createCorrectnessEvaluator({ + model: base_model as any, + }); + ``` + + +Once defined, built-in evaluators can be run on tabular data or trace-derived examples and logged back to Phoenix like any other eval. Because they return structured outputs, results can be compared across runs and combined with other evaluations. + +## Running Evals on Phoenix Traces + +With a judge model and evaluator defined, the next step is running evals on real application data. A common workflow is evaluating traced executions and attaching results back to spans in Phoenix. + +**1. Export trace spans** + +Start by exporting spans from a Phoenix project into a tabular structure: + + + + ```python + from phoenix.client import Client + + client = Client() + spans_df = client.spans.get_spans_dataframe(project_identifier="agno_travel_agent") + agent_spans = spans_df[spans_df['span_kind'] == 'AGENT'] + agent_spans + ``` + + + ```typescript + import { getSpans } from "@arizeai/phoenix-client/spans"; + + const projectName = + process.env.PHOENIX_PROJECT_NAME || "langchain-travel-agent"; + const { spans } = await getSpans({ project: { projectName }, limit: 500 }); + ``` + + +Each row represents a span and includes identifiers and attributes captured during execution. + +**2. Prepare Evaluator Inputs** +Next, select or transform fields from the exported spans so they match the evaluator’s expected inputs. This often involves extracting nested attributes such as: + +Ex. `attributes.input.value` & `attributes.output.value` + +Input mappings help bridge differences between how data is stored in traces and what evaluators expect. + + + + ```python + from phoenix.evals import bind_evaluator + + bound_evaluator = bind_evaluator( + evaluator=correctness_eval, + input_mapping={ + "input": "attributes.input.value", + "output": "attributes.output.value", + } + ) + ``` + + + We may need to manipulate the data a little bit here to make it easier to pass into the evaluator. We can first define some helper functions. + ```typescript + const toStr = (v: unknown) => + typeof v === "string" ? v : v != null ? JSON.stringify(v) : null; + + function getInputOutput(span: any) { + const attrs = span.attributes ?? {}; + const input = toStr(attrs["input.value"] ?? attrs["input"]); + const output = toStr(attrs["output.value"] ?? attrs["output"]); + return { input, output }; + } + + const parentSpans: { spanId: string; input: string; output: string }[] = []; + for (const s of spans) { + const name = (s as any).name ?? (s as any).span_name; + if (name !== "LangGraph") continue; + const { input, output } = getInputOutput(s); + const spanId = + (s as any).context?.span_id ?? (s as any).span_id ?? (s as any).id; + if (input && output && spanId) { + parentSpans.push({ spanId: String(spanId), input, output }); + } + } + ``` + + + +**3. Run evals on the prepared data** + +Once the evaluation dataframe is prepared, you can run evals in batch using the same APIs used for any tabular data. + + + + ```python + from phoenix.evals import evaluate_dataframe + from phoenix.trace import suppress_tracing + with suppress_tracing(): + results_df = evaluate_dataframe(agent_spans, [bound_evaluator]) + ``` + + + ```typescript + const spanAnnotations = await Promise.all( + parentSpans.map(async ({ spanId, input, output }) => { + const r = await evaluator.evaluate({ input, output }); + console.log(r.explanation); + return { + spanId, + name: "correctness" as const, + label: r.label, + score: r.score, + explanation: r.explanation ?? undefined, + annotatorKind: "LLM" as const, + metadata: { evaluator: "correctness", input, output }, + }; + }), + ); + ``` + + + +**4. Log results back to Phoenix** + +Finally, log evaluation results back to Phoenix as span annotations. Phoenix uses span identifiers to associate eval outputs with the correct execution. + + + ```python + from phoenix.evals.utils import to_annotation_dataframe + + evaluations = to_annotation_dataframe(dataframe=results_df) + Client().spans.log_span_annotations_dataframe(dataframe=evaluations) + ``` + + + ```typescript + import { logSpanAnnotations } from "@arizeai/phoenix-client/spans"; + + await logSpanAnnotations({ spanAnnotations, sync: true }); + ``` + + +Once logged, eval results appear alongside traces in the Phoenix UI, making it possible to analyze execution behavior and quality together. + +--- +With built-in evals running on traced data, you can now: + +* Inspect failures and edge cases + +* Compare behavior across runs + +* Use eval results as inputs to datasets and experiments + +This completes the core loop from tracing → evaluation → analysis. + +## What’s Next + +At this point, you’ve seen how to run evaluations using Phoenix’s built-in eval templates and attach quality signals to real application executions. This provides a fast way to measure behavior and establish baselines using predefined criteria. + +In the next guides, we’ll build on this foundation by customizing different parts of the evaluation workflow. Specifically, the next page walks through how to define a custom LLM judge, including how to configure model behavior and connect to different providers or endpoints. From there, we’ll move into customizing evaluation templates and defining application-specific criteria. + +Together, these guides show how to move from out-of-the-box evaluations to fully customized evals tailored to your application. \ No newline at end of file diff --git a/tutorials/quickstarts/agno_agent_for_evals.ipynb b/tutorials/quickstarts/agno_agent_for_evals.ipynb index dd46d91612b..c26acc3cc04 100644 --- a/tutorials/quickstarts/agno_agent_for_evals.ipynb +++ b/tutorials/quickstarts/agno_agent_for_evals.ipynb @@ -30,7 +30,13 @@ "\n", "Next, we’ll define a set of basic tools that provide destination information, estimate trip budgets, and suggest local activities.\n", "\n", - "Finally, we’ll build and run our agent, viewing the resulting trace outputs in Phoenix to understand how the agent uses its tools and reasoning." + "For this base agent, we’ll build and run our agent, viewing the resulting trace outputs in Phoenix to understand how the agent uses its tools and reasoning.\n", + "\n", + "We'll then follow along through the Evals Tutorials:\n", + "- Configure a core LLM & run a built in eval \n", + "- Configure a custom endpoint LLM \n", + "- Create a custom eval \n", + "- Code Evals" ] }, { @@ -50,12 +56,12 @@ "id": "HzvQoYIksr30" }, "source": [ - "# Set up keys and dependenies" + "## Set up keys and dependenies" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -63,9 +69,17 @@ "id": "1XtfV7qF6HKg", "outputId": "70de22d9-591e-4b47-ca33-209070dac3a1" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], "source": [ - "%pip install -qqqqqq arize-phoenix-otel agno openai openinference-instrumentation-agno openinference-instrumentation-openai httpx" + "%pip install -qqqqqq arize-phoenix-otel arize-phoenix-evals agno openai openinference-instrumentation-agno openinference-instrumentation-openai httpx" ] }, { @@ -84,7 +98,6 @@ "from getpass import getpass\n", "\n", "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\"🔑 Enter your OpenAI API Key: \")\n", - "\n", "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\"🔑 Enter your Tavily API Key: \")" ] }, @@ -94,12 +107,12 @@ "id": "AFdPHLMFuEsl" }, "source": [ - "# Setup tracing" + "## Setup tracing" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "colab": { "base_uri": "https://localhost:8080/" @@ -107,7 +120,37 @@ "id": "Y8dSorscJDPT", "outputId": "957bb02a-3faa-4002-ce19-2ab2cf9fa077" }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'validate_default' attribute with value True was provided to the `Field()` function, which has no effect in the context it was used. 'validate_default' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type.\n", + " warnings.warn(\n", + "Overriding of current TracerProvider is not allowed\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "🔭 OpenTelemetry Tracing Details 🔭\n", + "| Phoenix Project: agno_travel_agent\n", + "| Span Processor: SimpleSpanProcessor\n", + "| Collector Endpoint: localhost:4317\n", + "| Transport: gRPC\n", + "| Transport Headers: {'user-agent': '****'}\n", + "| \n", + "| Using a default SpanProcessor. `add_span_processor` will overwrite this default.\n", + "| \n", + "| ⚠️ WARNING: It is strongly advised to use a BatchSpanProcessor in production environments.\n", + "| \n", + "| `register` has set this TracerProvider as the global OpenTelemetry default.\n", + "| To disable this behavior, call `register` with `set_global_tracer_provider=False`.\n", + "\n" + ] + } + ], "source": [ "from phoenix.otel import register\n", "\n", @@ -120,7 +163,7 @@ "id": "Gjd7wU9OuIAQ" }, "source": [ - "# Define tools" + "## Define tools" ] }, { @@ -134,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -197,7 +240,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "id": "tNgVS4Fk_QRR" }, @@ -240,7 +283,7 @@ "id": "o48IXEMJuJuI" }, "source": [ - "# Define agent" + "## Define agent" ] }, { @@ -254,7 +297,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "id": "Sb1jqHcU_R3r" }, @@ -283,7 +326,7 @@ "id": "HAKB1WBwuLh2" }, "source": [ - "# Run agent" + "## Run agent" ] }, { @@ -297,7 +340,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "colab": { "base_uri": "https://localhost:8080/", @@ -310,7 +353,32 @@ "id": "FVDKZT9x_U-5", "outputId": "5aad5802-b2d3-4d89-b692-d937839350c4" }, - "outputs": [], + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b27ab0afe69b4c54ab2bba38779be681", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Output()" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
\n"
+            ],
+            "text/plain": []
+          },
+          "metadata": {},
+          "output_type": "display_data"
+        }
+      ],
       "source": [
         "# --- Example usage ---\n",
         "destination = \"Tokyo\"\n",
@@ -327,6 +395,520 @@
         "    stream = True\n",
         ")"
       ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {},
+      "outputs": [
+        {
+          "data": {
+            "text/html": [
+              "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
namespan_kindparent_idstart_timeend_timestatus_codestatus_messageeventscontext.span_idcontext.trace_id...attributes.output.mime_typeattributes.llm.token_count.totalattributes.output.valueattributes.tool.descriptionattributes.tool.nameattributes.tool.parametersattributes.session.idattributes.graph.node.nameattributes.agnoattributes.graph.node.id
context.span_id
6ec80092737e54a4TripPlanner.runAGENTNaN2026-02-04 06:49:47.181465+00:002026-02-04 06:50:10.894976+00:00OK[]6ec80092737e54a492f134d5833282173f151500da1a1920...application/jsonNaN# 5-Day Food & Culture Trip to Tokyo\\n\\n## Ess...NaNNaNNone4fde62a2-cbd0-4e26-bb1c-65ac55a70e83TripPlanner{'agent': 'TripPlanner', 'tools': ['essential_...f31cc21c20c9bef2
\n", + "

1 rows × 32 columns

\n", + "
" + ], + "text/plain": [ + " name span_kind parent_id \\\n", + "context.span_id \n", + "6ec80092737e54a4 TripPlanner.run AGENT NaN \n", + "\n", + " start_time \\\n", + "context.span_id \n", + "6ec80092737e54a4 2026-02-04 06:49:47.181465+00:00 \n", + "\n", + " end_time status_code status_message \\\n", + "context.span_id \n", + "6ec80092737e54a4 2026-02-04 06:50:10.894976+00:00 OK \n", + "\n", + " events context.span_id context.trace_id \\\n", + "context.span_id \n", + "6ec80092737e54a4 [] 6ec80092737e54a4 92f134d5833282173f151500da1a1920 \n", + "\n", + " ... attributes.output.mime_type \\\n", + "context.span_id ... \n", + "6ec80092737e54a4 ... application/json \n", + "\n", + " attributes.llm.token_count.total \\\n", + "context.span_id \n", + "6ec80092737e54a4 NaN \n", + "\n", + " attributes.output.value \\\n", + "context.span_id \n", + "6ec80092737e54a4 # 5-Day Food & Culture Trip to Tokyo\\n\\n## Ess... \n", + "\n", + " attributes.tool.description attributes.tool.name \\\n", + "context.span_id \n", + "6ec80092737e54a4 NaN NaN \n", + "\n", + " attributes.tool.parameters \\\n", + "context.span_id \n", + "6ec80092737e54a4 None \n", + "\n", + " attributes.session.id \\\n", + "context.span_id \n", + "6ec80092737e54a4 4fde62a2-cbd0-4e26-bb1c-65ac55a70e83 \n", + "\n", + " attributes.graph.node.name \\\n", + "context.span_id \n", + "6ec80092737e54a4 TripPlanner \n", + "\n", + " attributes.agno \\\n", + "context.span_id \n", + "6ec80092737e54a4 {'agent': 'TripPlanner', 'tools': ['essential_... \n", + "\n", + " attributes.graph.node.id \n", + "context.span_id \n", + "6ec80092737e54a4 f31cc21c20c9bef2 \n", + "\n", + "[1 rows x 32 columns]" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from phoenix.client import Client\n", + "\n", + "client = Client()\n", + "spans_df = client.spans.get_spans_dataframe(project_identifier=\"agno_travel_agent\")\n", + "agent_spans = spans_df[spans_df['span_kind'] == 'AGENT']\n", + "agent_spans" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "agent_spans['attributes.output.value', 'attributes.input.value']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run evals with built-in eval templates & an OpenAI Model\n", + "\n", + "Let's first use a classic config for our LLM & built in template for our first eval. " + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals.llm import LLM\n", + "\n", + "llm = LLM(\n", + " provider=\"openai\",\n", + " model=\"gpt-4o\",\n", + " client=\"openai\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'name': 'correctness', 'kind': 'llm', 'direction': 'maximize', 'input_schema': {'properties': {'input': {'description': 'The input query or question.', 'title': 'Input', 'type': 'string'}, 'output': {'description': 'The response to evaluate for correctness.', 'title': 'Output', 'type': 'string'}}, 'required': ['input', 'output'], 'title': 'CorrectnessInputSchema', 'type': 'object'}}\n" + ] + } + ], + "source": [ + "from phoenix.evals.metrics import CorrectnessEvaluator\n", + "\n", + "correctness_eval = CorrectnessEvaluator(llm=llm)\n", + "\n", + "print(correctness_eval.describe())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "/var/folders/gg/2586gdl96294y9xs_3j3l7t00000gp/T/ipykernel_93648/1692309769.py:15: DeprecationWarning: Positional arguments for evaluate_dataframe are deprecated and will be removed in a future version. Please use keyword arguments instead.\n", + " result = evaluate_dataframe(agent_spans, [bound_evaluator])\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "6f50d9e705db465a880c6d654300127b", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Evaluating Dataframe | | 0/1 (0.0%) | ⏳ 00:00=18" }, "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/openai": { + "version": "2.0.89", + "resolved": "https://registry.npmjs.org/@ai-sdk/openai/-/openai-2.0.89.tgz", + "integrity": "sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "2.0.1", + "@ai-sdk/provider-utils": "3.0.20" }, - "peerDependenciesMeta": { - "zod": { - "optional": true - } + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@ai-sdk/provider": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider/-/provider-2.0.1.tgz", + "integrity": "sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng==", + "license": "Apache-2.0", + "dependencies": { + "json-schema": "^0.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ai-sdk/provider-utils": { + "version": "3.0.20", + "resolved": "https://registry.npmjs.org/@ai-sdk/provider-utils/-/provider-utils-3.0.20.tgz", + "integrity": "sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/provider": "2.0.1", + "@standard-schema/spec": "^1.0.0", + "eventsource-parser": "^3.0.6" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, + "node_modules/@anthropic-ai/sdk": { + "version": "0.35.0", + "resolved": "https://registry.npmjs.org/@anthropic-ai/sdk/-/sdk-0.35.0.tgz", + "integrity": "sha512-JxVuNIRLjcXZbDW/rJa3vSIoYB5c0wgIQUPsjueeqli9OJyCJpInj0UlvKSSk6R2oCYyg0y2M0H8n8Wyt0l1IA==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "^18.11.18", + "@types/node-fetch": "^2.6.4", + "abort-controller": "^3.0.0", + "agentkeepalive": "^4.2.1", + "form-data-encoder": "1.7.2", + "formdata-node": "^4.3.2", + "node-fetch": "^2.6.7" + } + }, + "node_modules/@anthropic-ai/sdk/node_modules/@types/node": { + "version": "18.19.130", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", + "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~5.26.4" } }, + "node_modules/@anthropic-ai/sdk/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT", + "optional": true + }, "node_modules/@arizeai/openinference-core": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@arizeai/openinference-core/-/openinference-core-2.0.5.tgz", @@ -57,6 +137,59 @@ "integrity": "sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==", "license": "Apache-2.0" }, + "node_modules/@arizeai/openinference-instrumentation-langchain": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-instrumentation-langchain/-/openinference-instrumentation-langchain-4.0.6.tgz", + "integrity": "sha512-yvA7ObrNUjhUN8y37lO+Cr8Ef7Bq6NKKoChXPOaKG/IufwAAcXUowdEC40gipUelS3k3AOgxcIU2rfP+7f+YyQ==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-core": "2.0.5", + "@arizeai/openinference-semantic-conventions": "2.1.7", + "@opentelemetry/api": "^1.9.0", + "@opentelemetry/core": "^1.25.1", + "@opentelemetry/instrumentation": "^0.46.0" + }, + "peerDependencies": { + "@langchain/core": "^1.0.0 || ^0.3.0 || ^0.2.0" + } + }, + "node_modules/@arizeai/openinference-instrumentation-langchain/node_modules/@arizeai/openinference-semantic-conventions": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@arizeai/openinference-semantic-conventions/-/openinference-semantic-conventions-2.1.7.tgz", + "integrity": "sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==", + "license": "Apache-2.0" + }, + "node_modules/@arizeai/openinference-instrumentation-langchain/node_modules/@opentelemetry/instrumentation": { + "version": "0.46.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz", + "integrity": "sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw==", + "license": "Apache-2.0", + "dependencies": { + "@types/shimmer": "^1.0.2", + "import-in-the-middle": "1.7.1", + "require-in-the-middle": "^7.1.1", + "semver": "^7.5.2", + "shimmer": "^1.2.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.3.0" + } + }, + "node_modules/@arizeai/openinference-instrumentation-langchain/node_modules/import-in-the-middle": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.7.1.tgz", + "integrity": "sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==", + "license": "Apache-2.0", + "dependencies": { + "acorn": "^8.8.2", + "acorn-import-assertions": "^1.9.0", + "cjs-module-lexer": "^1.2.2", + "module-details-from-path": "^1.0.3" + } + }, "node_modules/@arizeai/openinference-semantic-conventions": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@arizeai/openinference-semantic-conventions/-/openinference-semantic-conventions-1.1.0.tgz", @@ -83,6 +216,66 @@ "integrity": "sha512-KyBfwxkSusPvxHBaW/TJ0japEbXCNziW9o6/IRKiPu+gp5TMKIagV2NKvt47rWYa4Jc0Nl+SvAPm+yxkdJqVbg==", "license": "Apache-2.0" }, + "node_modules/@arizeai/phoenix-client": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@arizeai/phoenix-client/-/phoenix-client-5.7.0.tgz", + "integrity": "sha512-e0OAu3urr55KBi/Vo+w0gfFz5ylmsIA2VebTi7gNhWVUvWXb1B9bgMYMr6JOsQFMf8fCLnTKeA/hzLYge1bkww==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-semantic-conventions": "^1.1.0", + "@arizeai/openinference-vercel": "^2.3.1", + "@arizeai/phoenix-config": "0.1.0", + "@arizeai/phoenix-otel": "0.3.4", + "async": "^3.2.6", + "openapi-fetch": "^0.12.5", + "tiny-invariant": "^1.3.3", + "zod": "^3.24.3", + "zod-to-json-schema": "^3.24.3" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@anthropic-ai/sdk": "^0.35.0", + "ai": "^5.0.76", + "openai": "^6.10.0" + } + }, + "node_modules/@arizeai/phoenix-client/node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/@arizeai/phoenix-config": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@arizeai/phoenix-config/-/phoenix-config-0.1.0.tgz", + "integrity": "sha512-/tsZAnC6+KDFmXJNyTdKD/Z/9ItsqpoRdYTf+OqAo8ATkTBdjKg0q7MolbhhZWZAJ7AnBndPVT9uwK2Kp9reiA==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@arizeai/phoenix-evals": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@arizeai/phoenix-evals/-/phoenix-evals-0.7.0.tgz", + "integrity": "sha512-Z0e6uhT981gg8d967ZeIEbF9bpW/Cjph65fMdjpeLF1yWfFMJKsuiGi9d13snNrMurnQ8bOQUyLdBALHHhOnBA==", + "license": "Apache-2.0", + "dependencies": { + "@arizeai/openinference-core": "^2.0.0", + "@opentelemetry/api": "^1.9.0", + "ai": "^5.0.0", + "jsonpath-plus": "^10.3.0", + "mustache": "^4.2.0", + "zod": "^4.0.14" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/@arizeai/phoenix-otel": { "version": "0.3.4", "resolved": "https://registry.npmjs.org/@arizeai/phoenix-otel/-/phoenix-otel-0.3.4.tgz", @@ -100,15 +293,6 @@ "@opentelemetry/sdk-trace-node": "^1.30.1" } }, - "node_modules/@babel/runtime": { - "version": "7.28.6", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", - "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@cfworker/json-schema": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@cfworker/json-schema/-/json-schema-4.1.1.tgz", @@ -557,26 +741,34 @@ "node": ">=18" } }, - "node_modules/@langchain/anthropic": { - "version": "0.3.34", - "resolved": "https://registry.npmjs.org/@langchain/anthropic/-/anthropic-0.3.34.tgz", - "integrity": "sha512-8bOW1A2VHRCjbzdYElrjxutKNs9NSIxYRGtR+OJWVzluMqoKKh2NmmFrpPizEyqCUEG2tTq5xt6XA1lwfqMJRA==", + "node_modules/@jsep-plugin/assignment": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@jsep-plugin/assignment/-/assignment-1.3.0.tgz", + "integrity": "sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==", "license": "MIT", - "dependencies": { - "@anthropic-ai/sdk": "^0.65.0", - "fast-xml-parser": "^4.4.1" + "engines": { + "node": ">= 10.16.0" }, + "peerDependencies": { + "jsep": "^0.4.0||^1.0.0" + } + }, + "node_modules/@jsep-plugin/regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@jsep-plugin/regex/-/regex-1.0.4.tgz", + "integrity": "sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==", + "license": "MIT", "engines": { - "node": ">=18" + "node": ">= 10.16.0" }, "peerDependencies": { - "@langchain/core": ">=0.3.58 <0.4.0" + "jsep": "^0.4.0||^1.0.0" } }, "node_modules/@langchain/core": { - "version": "0.3.80", - "resolved": "https://registry.npmjs.org/@langchain/core/-/core-0.3.80.tgz", - "integrity": "sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@langchain/core/-/core-1.1.18.tgz", + "integrity": "sha512-vwzbtHUSZaJONBA1n9uQedZPfyFFZ6XzTggTpR28n8tiIg7e1NC/5dvGW/lGtR1Du1VwV9DvDHA5/bOrLe6cVg==", "license": "MIT", "dependencies": { "@cfworker/json-schema": "^4.0.2", @@ -584,49 +776,145 @@ "camelcase": "6", "decamelize": "1.2.0", "js-tiktoken": "^1.0.12", - "langsmith": "^0.3.67", + "langsmith": ">=0.4.0 <1.0.0", "mustache": "^4.2.0", "p-queue": "^6.6.2", - "p-retry": "4", "uuid": "^10.0.0", - "zod": "^3.25.32", - "zod-to-json-schema": "^3.22.3" + "zod": "^3.25.76 || ^4" }, "engines": { - "node": ">=18" + "node": ">=20" } }, - "node_modules/@langchain/openai": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-0.3.17.tgz", - "integrity": "sha512-uw4po32OKptVjq+CYHrumgbfh4NuD7LqyE+ZgqY9I/LrLc6bHLMc+sisHmI17vgek0K/yqtarI0alPJbzrwyag==", + "node_modules/@langchain/langgraph": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@langchain/langgraph/-/langgraph-1.1.3.tgz", + "integrity": "sha512-o/cEWeocDDSpyBI2MfX07LkNG4LzdRKxwcgUcbR4PyRzhxxCkeIZRCCYkXVQoDbdKqAczJa0D7+yjU9rmA5iHQ==", "license": "MIT", "dependencies": { - "js-tiktoken": "^1.0.12", - "openai": "^4.77.0", - "zod": "^3.22.4", - "zod-to-json-schema": "^3.22.3" + "@langchain/langgraph-checkpoint": "^1.0.0", + "@langchain/langgraph-sdk": "~1.5.5", + "@standard-schema/spec": "1.1.0", + "uuid": "^10.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@langchain/core": ">=0.3.29 <0.4.0" + "@langchain/core": "^1.0.1", + "zod": "^3.25.32 || ^4.2.0", + "zod-to-json-schema": "^3.x" + }, + "peerDependenciesMeta": { + "zod-to-json-schema": { + "optional": true + } } }, - "node_modules/@langchain/textsplitters": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@langchain/textsplitters/-/textsplitters-0.1.0.tgz", - "integrity": "sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==", + "node_modules/@langchain/langgraph-checkpoint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@langchain/langgraph-checkpoint/-/langgraph-checkpoint-1.0.0.tgz", + "integrity": "sha512-xrclBGvNCXDmi0Nz28t3vjpxSH6UYx6w5XAXSiiB1WEdc2xD2iY/a913I3x3a31XpInUW/GGfXXfePfaghV54A==", "license": "MIT", "dependencies": { - "js-tiktoken": "^1.0.12" + "uuid": "^10.0.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@langchain/core": ">=0.2.21 <0.4.0" + "@langchain/core": "^1.0.1" + } + }, + "node_modules/@langchain/langgraph-sdk": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@langchain/langgraph-sdk/-/langgraph-sdk-1.5.5.tgz", + "integrity": "sha512-SyiAs6TVXPWlt/8cI9pj/43nbIvclY3ytKqUFbL5MplCUnItetEyqvH87EncxyVF5D7iJKRZRfSVYBMmOZbjbQ==", + "license": "MIT", + "dependencies": { + "p-queue": "^9.0.1", + "p-retry": "^7.1.1", + "uuid": "^13.0.0" + }, + "peerDependencies": { + "@langchain/core": "^1.1.15", + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + }, + "peerDependenciesMeta": { + "@langchain/core": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@langchain/langgraph-sdk/node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "license": "MIT" + }, + "node_modules/@langchain/langgraph-sdk/node_modules/p-queue": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-9.1.0.tgz", + "integrity": "sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^5.0.1", + "p-timeout": "^7.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@langchain/langgraph-sdk/node_modules/p-timeout": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-7.0.1.tgz", + "integrity": "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==", + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@langchain/langgraph-sdk/node_modules/uuid": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-13.0.0.tgz", + "integrity": "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist-node/bin/uuid" + } + }, + "node_modules/@langchain/openai": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@langchain/openai/-/openai-1.2.4.tgz", + "integrity": "sha512-3ThBOIXAJ6eXuqGGO41XDgr4rp/qpl/RpZmGcjv1S3+CRLS4UQBgXkZEab7mun85HfdsUWLs/v1+pDwbMFixcA==", + "license": "MIT", + "dependencies": { + "js-tiktoken": "^1.0.12", + "openai": "^6.16.0", + "zod": "^3.25.76 || ^4" + }, + "engines": { + "node": ">=20" + }, + "peerDependencies": { + "@langchain/core": "^1.0.0" } }, "node_modules/@opentelemetry/api": { @@ -1046,6 +1334,12 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", "license": "BSD-3-Clause" }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "20.19.30", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.30.tgz", @@ -1060,17 +1354,12 @@ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.13.tgz", "integrity": "sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==", "license": "MIT", + "optional": true, "dependencies": { "@types/node": "*", "form-data": "^4.0.4" } }, - "node_modules/@types/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==", - "license": "MIT" - }, "node_modules/@types/shimmer": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@types/shimmer/-/shimmer-1.2.0.tgz", @@ -1083,11 +1372,21 @@ "integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==", "license": "MIT" }, + "node_modules/@vercel/oidc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vercel/oidc/-/oidc-3.1.0.tgz", + "integrity": "sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==", + "license": "Apache-2.0", + "engines": { + "node": ">= 20" + } + }, "node_modules/abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", "license": "MIT", + "optional": true, "dependencies": { "event-target-shim": "^5.0.0" }, @@ -1107,6 +1406,16 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "deprecated": "package has been renamed to acorn-import-attributes", + "license": "MIT", + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", @@ -1121,6 +1430,7 @@ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", "license": "MIT", + "optional": true, "dependencies": { "humanize-ms": "^1.2.1" }, @@ -1128,6 +1438,24 @@ "node": ">= 8.0.0" } }, + "node_modules/ai": { + "version": "5.0.125", + "resolved": "https://registry.npmjs.org/ai/-/ai-5.0.125.tgz", + "integrity": "sha512-M4gVfuxOP7eywi9zKbonVKGYMYV2IMuj9jki5/7FpogzNq+P9u7/ZvBivt4iu5A3z/V5BJojZ8vdBsEqbGnsHA==", + "license": "Apache-2.0", + "dependencies": { + "@ai-sdk/gateway": "2.0.31", + "@ai-sdk/provider": "2.0.1", + "@ai-sdk/provider-utils": "3.0.20", + "@opentelemetry/api": "1.9.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "zod": "^3.25.76 || ^4.1.8" + } + }, "node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", @@ -1140,17 +1468,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "license": "MIT" }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -1177,6 +1506,7 @@ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -1257,6 +1587,7 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", + "optional": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -1304,15 +1635,29 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=0.4.0" } }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", @@ -1327,6 +1672,7 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -1336,6 +1682,7 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -1345,6 +1692,7 @@ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0" }, @@ -1357,6 +1705,7 @@ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", + "optional": true, "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", @@ -1414,6 +1763,7 @@ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", + "optional": true, "engines": { "node": ">=6" } @@ -1424,22 +1774,13 @@ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", "license": "MIT" }, - "node_modules/fast-xml-parser": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.3.tgz", - "integrity": "sha512-RKihhV+SHsIUGXObeVy9AXiBbFwkVk7Syp8XgwN5U3JV416+Gwp/GO9i0JYKmikykgz/UHRrrV4ROuZEo/T0ig==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", "license": "MIT", - "dependencies": { - "strnum": "^1.1.1" - }, - "bin": { - "fxparser": "src/cli/cli.js" + "engines": { + "node": ">=18.0.0" } }, "node_modules/form-data": { @@ -1447,6 +1788,7 @@ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", "license": "MIT", + "optional": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -1462,13 +1804,15 @@ "version": "1.7.2", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz", "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/formdata-node": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz", "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==", "license": "MIT", + "optional": true, "dependencies": { "node-domexception": "1.0.0", "web-streams-polyfill": "4.0.0-beta.3" @@ -1506,6 +1850,7 @@ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", + "optional": true, "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", @@ -1530,6 +1875,7 @@ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "license": "MIT", + "optional": true, "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" @@ -1556,6 +1902,7 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -1577,6 +1924,7 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" }, @@ -1589,6 +1937,7 @@ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "license": "MIT", + "optional": true, "dependencies": { "has-symbols": "^1.0.3" }, @@ -1616,6 +1965,7 @@ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", + "optional": true, "dependencies": { "ms": "^2.0.0" } @@ -1647,6 +1997,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-network-error": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.3.0.tgz", + "integrity": "sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==", + "license": "MIT", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/js-tiktoken": { "version": "1.0.21", "resolved": "https://registry.npmjs.org/js-tiktoken/-/js-tiktoken-1.0.21.tgz", @@ -1656,139 +2018,62 @@ "base64-js": "^1.5.1" } }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "node_modules/jsep": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/jsep/-/jsep-1.4.0.tgz", + "integrity": "sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==", "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "engines": { + "node": ">= 10.16.0" } }, - "node_modules/json-schema-to-ts": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/json-schema-to-ts/-/json-schema-to-ts-3.1.1.tgz", - "integrity": "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g==", + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/jsonpath-plus": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/jsonpath-plus/-/jsonpath-plus-10.3.0.tgz", + "integrity": "sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.18.3", - "ts-algebra": "^2.0.0" + "@jsep-plugin/assignment": "^1.3.0", + "@jsep-plugin/regex": "^1.0.4", + "jsep": "^1.4.0" + }, + "bin": { + "jsonpath": "bin/jsonpath-cli.js", + "jsonpath-plus": "bin/jsonpath-cli.js" }, "engines": { - "node": ">=16" - } - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node": ">=18.0.0" } }, "node_modules/langchain": { - "version": "0.3.37", - "resolved": "https://registry.npmjs.org/langchain/-/langchain-0.3.37.tgz", - "integrity": "sha512-1jPsZ6xsxkcQPUvqRjvfuOLwZLLyt49hzcOK7OYAJovIkkOxd5gzK4Yw6giPUQ8g4XHyvULNlWBz+subdkcokw==", + "version": "1.2.16", + "resolved": "https://registry.npmjs.org/langchain/-/langchain-1.2.16.tgz", + "integrity": "sha512-gVLSNhP8It6vDMribkqyKIiq79F2kCPAk3L4nGRUzKvIK2XD0J1y6UkuzEKwJ48w5rEKYHI729qthBteXQHOmA==", "license": "MIT", "dependencies": { - "@langchain/openai": ">=0.1.0 <0.7.0", - "@langchain/textsplitters": ">=0.0.0 <0.2.0", - "js-tiktoken": "^1.0.12", - "js-yaml": "^4.1.0", - "jsonpointer": "^5.0.1", - "langsmith": "^0.3.67", - "openapi-types": "^12.1.3", - "p-retry": "4", + "@langchain/langgraph": "^1.1.2", + "@langchain/langgraph-checkpoint": "^1.0.0", + "langsmith": ">=0.4.0 <1.0.0", "uuid": "^10.0.0", - "yaml": "^2.2.1", - "zod": "^3.25.32" + "zod": "^3.25.76 || ^4" }, "engines": { - "node": ">=18" + "node": ">=20" }, "peerDependencies": { - "@langchain/anthropic": "*", - "@langchain/aws": "*", - "@langchain/cerebras": "*", - "@langchain/cohere": "*", - "@langchain/core": ">=0.3.58 <0.4.0", - "@langchain/deepseek": "*", - "@langchain/google-genai": "*", - "@langchain/google-vertexai": "*", - "@langchain/google-vertexai-web": "*", - "@langchain/groq": "*", - "@langchain/mistralai": "*", - "@langchain/ollama": "*", - "@langchain/xai": "*", - "axios": "*", - "cheerio": "*", - "handlebars": "^4.7.8", - "peggy": "^3.0.2", - "typeorm": "*" - }, - "peerDependenciesMeta": { - "@langchain/anthropic": { - "optional": true - }, - "@langchain/aws": { - "optional": true - }, - "@langchain/cerebras": { - "optional": true - }, - "@langchain/cohere": { - "optional": true - }, - "@langchain/deepseek": { - "optional": true - }, - "@langchain/google-genai": { - "optional": true - }, - "@langchain/google-vertexai": { - "optional": true - }, - "@langchain/google-vertexai-web": { - "optional": true - }, - "@langchain/groq": { - "optional": true - }, - "@langchain/mistralai": { - "optional": true - }, - "@langchain/ollama": { - "optional": true - }, - "@langchain/xai": { - "optional": true - }, - "axios": { - "optional": true - }, - "cheerio": { - "optional": true - }, - "handlebars": { - "optional": true - }, - "peggy": { - "optional": true - }, - "typeorm": { - "optional": true - } + "@langchain/core": "1.1.18" } }, "node_modules/langsmith": { - "version": "0.3.87", - "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.3.87.tgz", - "integrity": "sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==", + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/langsmith/-/langsmith-0.4.12.tgz", + "integrity": "sha512-YWt0jcGvKqjUgIvd78rd4QcdMss0lUkeUaqp0UpVRq7H2yNDx8H5jOUO/laWUmaPtWGgcip0qturykXe1g9Gqw==", "license": "MIT", "dependencies": { "@types/uuid": "^10.0.0", @@ -1830,6 +2115,7 @@ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.4" } @@ -1839,6 +2125,7 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "license": "MIT", + "optional": true, "engines": { "node": ">= 0.6" } @@ -1848,6 +2135,7 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", + "optional": true, "dependencies": { "mime-db": "1.52.0" }, @@ -1892,6 +2180,7 @@ } ], "license": "MIT", + "optional": true, "engines": { "node": ">=10.5.0" } @@ -1901,6 +2190,7 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "license": "MIT", + "optional": true, "dependencies": { "whatwg-url": "^5.0.0" }, @@ -1917,25 +2207,16 @@ } }, "node_modules/openai": { - "version": "4.104.0", - "resolved": "https://registry.npmjs.org/openai/-/openai-4.104.0.tgz", - "integrity": "sha512-p99EFNsA/yX6UhVO93f5kJsDRLAg+CTA2RBqdHK4RtK8u5IJw32Hyb2dTGKbnnFmnuoBv5r7Z2CURI9sGZpSuA==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/openai/-/openai-6.17.0.tgz", + "integrity": "sha512-NHRpPEUPzAvFOAFs9+9pC6+HCw/iWsYsKCMPXH5Kw7BpMxqd8g/A07/1o7Gx2TWtCnzevVRyKMRFqyiHyAlqcA==", "license": "Apache-2.0", - "dependencies": { - "@types/node": "^18.11.18", - "@types/node-fetch": "^2.6.4", - "abort-controller": "^3.0.0", - "agentkeepalive": "^4.2.1", - "form-data-encoder": "1.7.2", - "formdata-node": "^4.3.2", - "node-fetch": "^2.6.7" - }, "bin": { "openai": "bin/cli" }, "peerDependencies": { "ws": "^8.18.0", - "zod": "^3.23.8" + "zod": "^3.25 || ^4.0" }, "peerDependenciesMeta": { "ws": { @@ -1946,25 +2227,19 @@ } } }, - "node_modules/openai/node_modules/@types/node": { - "version": "18.19.130", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz", - "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==", + "node_modules/openapi-fetch": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.12.5.tgz", + "integrity": "sha512-FnAMWLt0MNL6ComcL4q/YbB1tUgyz5YnYtwA1+zlJ5xcucmK5RlWsgH1ynxmEeu8fGJkYjm8armU/HVpORc9lw==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "openapi-typescript-helpers": "^0.0.15" } }, - "node_modules/openai/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "license": "MIT" - }, - "node_modules/openapi-types": { - "version": "12.1.3", - "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", - "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "node_modules/openapi-typescript-helpers": { + "version": "0.0.15", + "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz", + "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==", "license": "MIT" }, "node_modules/p-finally": { @@ -1993,16 +2268,18 @@ } }, "node_modules/p-retry": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz", - "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-7.1.1.tgz", + "integrity": "sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==", "license": "MIT", "dependencies": { - "@types/retry": "0.12.0", - "retry": "^0.13.1" + "is-network-error": "^1.1.0" }, "engines": { - "node": ">=8" + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-timeout": { @@ -2091,15 +2368,6 @@ "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" } }, - "node_modules/retry": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", - "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/semver": { "version": "7.7.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", @@ -2124,18 +2392,6 @@ "integrity": "sha512-j7piyCjAeTDSjzTSQ7DokZtMNwNlEAyxqSZeCS+CXH7fJ4jx3FuJ/mTW3mE+6JLs4VJBbcll0Kjn+KXI5t21Iw==", "license": "MIT" }, - "node_modules/strnum": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", - "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -2160,17 +2416,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "license": "MIT" - }, - "node_modules/ts-algebra": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ts-algebra/-/ts-algebra-2.0.0.tgz", - "integrity": "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw==", - "license": "MIT" + "license": "MIT", + "optional": true }, "node_modules/tsx": { "version": "4.21.0", @@ -2230,6 +2487,7 @@ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz", "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==", "license": "MIT", + "optional": true, "engines": { "node": ">= 14" } @@ -2238,37 +2496,24 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "license": "BSD-2-Clause" + "license": "BSD-2-Clause", + "optional": true }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", "license": "MIT", + "optional": true, "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, - "node_modules/yaml": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz", - "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" diff --git a/tutorials/quickstarts/langchain-ts-quickstart/package.json b/tutorials/quickstarts/langchain-ts-quickstart/package.json index beffdab8e50..48256e85675 100644 --- a/tutorials/quickstarts/langchain-ts-quickstart/package.json +++ b/tutorials/quickstarts/langchain-ts-quickstart/package.json @@ -5,14 +5,21 @@ "type": "module", "scripts": { "start": "npx tsx src/index.ts", - "build": "tsc" + "build": "tsc", + "pre_built_evals": "npx tsx src/pre_built_evals.ts", + "custom_evals": "npx tsx src/custom_evals.ts" }, "dependencies": { - "@arizeai/phoenix-otel": "^0.3.0", - "@langchain/anthropic": "^0.3.0", - "@langchain/core": "^0.3.0", - "@langchain/openai": "^0.3.0", - "langchain": "^0.3.0" + "@ai-sdk/openai": "^2.0.63", + "@arizeai/openinference-instrumentation-langchain": "^4.0.6", + "@arizeai/phoenix-client": "5.7.0", + "@arizeai/phoenix-evals": "^0.7.0", + "@arizeai/phoenix-otel": "^0.3.4", + "@langchain/core": "1.1.18", + "@langchain/openai": "1.2.4", + "dotenv": "^17.2.3", + "langchain": "1.2.16", + "zod": "^4.3.6" }, "devDependencies": { "@types/node": "^20.19.30", diff --git a/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml b/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml index e20541755fb..358b5c863e4 100644 --- a/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml +++ b/tutorials/quickstarts/langchain-ts-quickstart/pnpm-lock.yaml @@ -8,18 +8,39 @@ importers: .: dependencies: + '@ai-sdk/openai': + specifier: ^2.0.63 + version: 2.0.89(zod@4.3.6) + '@arizeai/openinference-instrumentation-langchain': + specifier: ^4.0.6 + version: 4.0.6(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))) + '@arizeai/phoenix-client': + specifier: 5.8.0 + version: 5.8.0(@opentelemetry/api@1.9.0) + '@arizeai/phoenix-evals': + specifier: ^0.8.0 + version: 0.8.0 '@arizeai/phoenix-otel': - specifier: ^0.3.0 + specifier: ^0.3.4 version: 0.3.4 + '@langchain/core': + specifier: 1.1.18 + version: 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + '@langchain/openai': + specifier: 1.2.4 + version: 1.2.4(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))) + dotenv: + specifier: ^17.2.3 + version: 17.2.3 langchain: - specifier: ^0.3.0 - version: 0.3.37(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + specifier: 1.2.16 + version: 1.2.16(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))(zod-to-json-schema@3.25.1(zod@4.3.6)) zod: - specifier: ^3.25.76 - version: 3.25.76 + specifier: ^4.3.6 + version: 4.3.6 devDependencies: '@types/node': - specifier: ^20.0.0 + specifier: ^20.19.30 version: 20.19.30 tsx: specifier: ^4.0.0 @@ -30,9 +51,39 @@ importers: packages: + '@ai-sdk/gateway@2.0.31': + resolution: {integrity: sha512-HcglYbIFqKhUYqK5qSNc2RwYxVyuhADy2R/8HMSTaUqHVFfUIFyCyDHeuNBxJcSDtHVMebPdn6Bxa0YogeiwcA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/openai@2.0.89': + resolution: {integrity: sha512-4+qWkBCbL9HPKbgrUO/F2uXZ8GqrYxHa8SWEYIzxEJ9zvWw3ISr3t1/27O1i8MGSym+PzEyHBT48EV4LAwWaEw==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider-utils@3.0.20': + resolution: {integrity: sha512-iXHVe0apM2zUEzauqJwqmpC37A5rihrStAih5Ks+JE32iTe4LZ58y17UGBjpQQTCRw9YxMeo2UFLxLpBluyvLQ==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + + '@ai-sdk/provider@2.0.1': + resolution: {integrity: sha512-KCUwswvsC5VsW2PWFqF8eJgSCu5Ysj7m1TxiHTVA6g7k360bk0RNQENT8KTMAYEs+8fWPD3Uu4dEmzGHc+jGng==} + engines: {node: '>=18'} + + '@anthropic-ai/sdk@0.35.0': + resolution: {integrity: sha512-JxVuNIRLjcXZbDW/rJa3vSIoYB5c0wgIQUPsjueeqli9OJyCJpInj0UlvKSSk6R2oCYyg0y2M0H8n8Wyt0l1IA==} + '@arizeai/openinference-core@2.0.5': resolution: {integrity: sha512-BnufYaFqmG9twkz/9DHX9WTcOs7YvVAYaufau5tdjOT1c0Y8niJwmNWzV36phNPg3c7SmdD5OYLuzeAUN0T3pQ==} + '@arizeai/openinference-instrumentation-langchain@4.0.6': + resolution: {integrity: sha512-yvA7ObrNUjhUN8y37lO+Cr8Ef7Bq6NKKoChXPOaKG/IufwAAcXUowdEC40gipUelS3k3AOgxcIU2rfP+7f+YyQ==} + peerDependencies: + '@langchain/core': ^1.0.0 || ^0.3.0 || ^0.2.0 + '@arizeai/openinference-semantic-conventions@1.1.0': resolution: {integrity: sha512-rxRYnUWjt28DlVXnWukcQAyGhPYQ3ckmKrjEdUjmUNnvvv4k8Dabbp5h6AEjNy7YzN9jL2smNRJnbLIVtkrLEg==} @@ -44,6 +95,18 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.7.0 <2.0.0' + '@arizeai/phoenix-client@5.8.0': + resolution: {integrity: sha512-YmTNDzw5tcP4Tdiaup+9t64HMTXmuEZTOBpPVhSkfo4T8/9yYB1fBw/rLDF9iDC+YEMPIuOWjY2oIn9CH6rm9A==} + engines: {node: '>=18'} + + '@arizeai/phoenix-config@0.1.0': + resolution: {integrity: sha512-/tsZAnC6+KDFmXJNyTdKD/Z/9ItsqpoRdYTf+OqAo8ATkTBdjKg0q7MolbhhZWZAJ7AnBndPVT9uwK2Kp9reiA==} + engines: {node: '>=18'} + + '@arizeai/phoenix-evals@0.8.0': + resolution: {integrity: sha512-ucVYZYlpqqTlnkPX7HYgZDLEHElmwPVJb/GJBbrbL8DqcgYgCtyVE6fC44WKOT+aqcvFDjXsyZvDk2oZKiTODA==} + engines: {node: '>=18'} + '@arizeai/phoenix-otel@0.3.4': resolution: {integrity: sha512-ocN9gnv7Owp6/mvCpmyOlf6vLv5yE8DV0v/JF3/LjXeIEv+ueuwMvfPycPFrAujvOBv0iGm+CWoA+PGA+tnsYA==} @@ -206,21 +269,58 @@ packages: cpu: [x64] os: [win32] - '@langchain/core@0.3.80': - resolution: {integrity: sha512-vcJDV2vk1AlCwSh3aBm/urQ1ZrlXFFBocv11bz/NBUfLWD5/UDNMzwPdaAd2dKvNmTWa9FM2lirLU3+JCf4cRA==} - engines: {node: '>=18'} + '@jsep-plugin/assignment@1.3.0': + resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 - '@langchain/openai@0.6.17': - resolution: {integrity: sha512-JVSzD+FL5v/2UQxKd+ikB1h4PQOtn0VlK8nqW2kPp0fshItCv4utrjBKXC/rubBnSXoRTyonBINe8QRZ6OojVQ==} + '@jsep-plugin/regex@1.0.4': + resolution: {integrity: sha512-q7qL4Mgjs1vByCaTnDFcBnV9HS7GVPJX5vyVoCgZHNSC9rjwIlmbXG5sUuorR5ndfHAIlJ8pVStxvjXHbNvtUg==} + engines: {node: '>= 10.16.0'} + peerDependencies: + jsep: ^0.4.0||^1.0.0 + + '@langchain/core@1.1.18': + resolution: {integrity: sha512-vwzbtHUSZaJONBA1n9uQedZPfyFFZ6XzTggTpR28n8tiIg7e1NC/5dvGW/lGtR1Du1VwV9DvDHA5/bOrLe6cVg==} + engines: {node: '>=20'} + + '@langchain/langgraph-checkpoint@1.0.0': + resolution: {integrity: sha512-xrclBGvNCXDmi0Nz28t3vjpxSH6UYx6w5XAXSiiB1WEdc2xD2iY/a913I3x3a31XpInUW/GGfXXfePfaghV54A==} engines: {node: '>=18'} peerDependencies: - '@langchain/core': '>=0.3.68 <0.4.0' + '@langchain/core': ^1.0.1 - '@langchain/textsplitters@0.1.0': - resolution: {integrity: sha512-djI4uw9rlkAb5iMhtLED+xJebDdAG935AdP4eRTB02R7OB/act55Bj9wsskhZsvuyQRpO4O1wQOp85s6T6GWmw==} + '@langchain/langgraph-sdk@1.5.5': + resolution: {integrity: sha512-SyiAs6TVXPWlt/8cI9pj/43nbIvclY3ytKqUFbL5MplCUnItetEyqvH87EncxyVF5D7iJKRZRfSVYBMmOZbjbQ==} + peerDependencies: + '@langchain/core': ^1.1.15 + react: ^18 || ^19 + react-dom: ^18 || ^19 + peerDependenciesMeta: + '@langchain/core': + optional: true + react: + optional: true + react-dom: + optional: true + + '@langchain/langgraph@1.1.3': + resolution: {integrity: sha512-o/cEWeocDDSpyBI2MfX07LkNG4LzdRKxwcgUcbR4PyRzhxxCkeIZRCCYkXVQoDbdKqAczJa0D7+yjU9rmA5iHQ==} engines: {node: '>=18'} peerDependencies: - '@langchain/core': '>=0.2.21 <0.4.0' + '@langchain/core': ^1.0.1 + zod: ^3.25.32 || ^4.2.0 + zod-to-json-schema: ^3.x + peerDependenciesMeta: + zod-to-json-schema: + optional: true + + '@langchain/openai@1.2.4': + resolution: {integrity: sha512-3ThBOIXAJ6eXuqGGO41XDgr4rp/qpl/RpZmGcjv1S3+CRLS4UQBgXkZEab7mun85HfdsUWLs/v1+pDwbMFixcA==} + engines: {node: '>=20'} + peerDependencies: + '@langchain/core': ^1.0.0 '@opentelemetry/api-logs@0.57.2': resolution: {integrity: sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A==} @@ -254,6 +354,12 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation@0.46.0': + resolution: {integrity: sha512-a9TijXZZbk0vI5TGLZl+0kxyFfrXHhX6Svtz7Pp2/VBlCSKrazuULEyoJQrOknJyFWNMEmbbJgOciHCCpQcisw==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + '@opentelemetry/instrumentation@0.57.2': resolution: {integrity: sha512-BdBGhQBh8IjZ2oIIX6F2/Q3LKm/FDDKi6ccYKcBTeilh6SNdNKveDOLk73BkSJjQLJk6qe4Yh+hHw1UPhCDdrg==} engines: {node: '>=14'} @@ -358,18 +464,38 @@ packages: '@protobufjs/utf8@1.1.0': resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@types/node-fetch@2.6.13': + resolution: {integrity: sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw==} + + '@types/node@18.19.130': + resolution: {integrity: sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==} + '@types/node@20.19.30': resolution: {integrity: sha512-WJtwWJu7UdlvzEAUm484QNg5eAoq5QR08KDNx7g45Usrs2NtOPiX8ugDqmKdXkyL03rBqU5dYNYVQetEpBHq2g==} - '@types/retry@0.12.0': - resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} - '@types/shimmer@1.2.0': resolution: {integrity: sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg==} '@types/uuid@10.0.0': resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + '@vercel/oidc@3.1.0': + resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} + engines: {node: '>= 20'} + + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + + acorn-import-assertions@1.9.0: + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + deprecated: package has been renamed to acorn-import-attributes + peerDependencies: + acorn: ^8 + acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -380,6 +506,16 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + + ai@5.0.125: + resolution: {integrity: sha512-M4gVfuxOP7eywi9zKbonVKGYMYV2IMuj9jki5/7FpogzNq+P9u7/ZvBivt4iu5A3z/V5BJojZ8vdBsEqbGnsHA==} + engines: {node: '>=18'} + peerDependencies: + zod: ^3.25.76 || ^4.1.8 + ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -388,12 +524,19 @@ packages: resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} engines: {node: '>=10'} - argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + camelcase@6.3.0: resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} engines: {node: '>=10'} @@ -412,6 +555,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + console-table-printer@2.15.0: resolution: {integrity: sha512-SrhBq4hYVjLCkBVOWaTzceJalvn5K1Zq5aQA6wXC/cYjI3frKWNPEMK3sZsJfNNQApvCQmgBcc13ZKmFj8qExw==} @@ -428,14 +575,64 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} + engines: {node: '>=12'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + esbuild@0.27.2: resolution: {integrity: sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==} engines: {node: '>=18'} hasBin: true + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + eventemitter3@5.0.4: + resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + + eventsource-parser@3.0.6: + resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} + engines: {node: '>=18.0.0'} + + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + + form-data@4.0.5: + resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} + engines: {node: '>= 6'} + + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -444,95 +641,77 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-tsconfig@4.13.1: resolution: {integrity: sha512-EoY1N2xCn44xU6750Sx7OjOIT59FkmstNc3X6y5xpz7D5cBtZRe/3pSlTkDJgqsOk3WwZPkWfonhhUJfttQo3w==} + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + import-in-the-middle@1.15.0: resolution: {integrity: sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA==} + import-in-the-middle@1.7.1: + resolution: {integrity: sha512-1LrZPDtW+atAxH42S6288qyDFNQ2YCty+2mxEPRtfazH6Z5QwkaBSTS2ods7hnVJioF6rkRfNoA6A/MstpFXLg==} + is-core-module@2.16.1: resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} engines: {node: '>= 0.4'} + is-network-error@1.3.0: + resolution: {integrity: sha512-6oIwpsgRfnDiyEDLMay/GqCl3HoAtH5+RUKW29gYkL0QA+ipzpDLA16yQs7/RHCSu+BwgbJaOUqa4A99qNVQVw==} + engines: {node: '>=16'} + js-tiktoken@1.0.21: resolution: {integrity: sha512-biOj/6M5qdgx5TKjDnFT1ymSpM5tbd3ylwDtrQvFQSu0Z7bBYko2dF+W/aUkXUPuk6IVpRxk/3Q2sHOzGlS36g==} - js-yaml@4.1.1: - resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} - hasBin: true + jsep@1.4.0: + resolution: {integrity: sha512-B7qPcEVE3NVkmSJbaYxvv4cHkVW7DQsZz13pUMrfS8z8Q/BuShN+gcTXrUlPiGqM2/t/EEaI030bpxMqY8gMlw==} + engines: {node: '>= 10.16.0'} - jsonpointer@5.0.1: - resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} - engines: {node: '>=0.10.0'} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - langchain@0.3.37: - resolution: {integrity: sha512-1jPsZ6xsxkcQPUvqRjvfuOLwZLLyt49hzcOK7OYAJovIkkOxd5gzK4Yw6giPUQ8g4XHyvULNlWBz+subdkcokw==} - engines: {node: '>=18'} + jsonpath-plus@10.3.0: + resolution: {integrity: sha512-8TNmfeTCk2Le33A3vRRwtuworG/L5RrgMvdjhKZxvyShO+mBu2fP50OWUjRLNtvw344DdDarFh9buFAZs5ujeA==} + engines: {node: '>=18.0.0'} + hasBin: true + + langchain@1.2.16: + resolution: {integrity: sha512-gVLSNhP8It6vDMribkqyKIiq79F2kCPAk3L4nGRUzKvIK2XD0J1y6UkuzEKwJ48w5rEKYHI729qthBteXQHOmA==} + engines: {node: '>=20'} peerDependencies: - '@langchain/anthropic': '*' - '@langchain/aws': '*' - '@langchain/cerebras': '*' - '@langchain/cohere': '*' - '@langchain/core': '>=0.3.58 <0.4.0' - '@langchain/deepseek': '*' - '@langchain/google-genai': '*' - '@langchain/google-vertexai': '*' - '@langchain/google-vertexai-web': '*' - '@langchain/groq': '*' - '@langchain/mistralai': '*' - '@langchain/ollama': '*' - '@langchain/xai': '*' - axios: '*' - cheerio: '*' - handlebars: ^4.7.8 - peggy: ^3.0.2 - typeorm: '*' - peerDependenciesMeta: - '@langchain/anthropic': - optional: true - '@langchain/aws': - optional: true - '@langchain/cerebras': - optional: true - '@langchain/cohere': - optional: true - '@langchain/deepseek': - optional: true - '@langchain/google-genai': - optional: true - '@langchain/google-vertexai': - optional: true - '@langchain/google-vertexai-web': - optional: true - '@langchain/groq': - optional: true - '@langchain/mistralai': - optional: true - '@langchain/ollama': - optional: true - '@langchain/xai': - optional: true - axios: - optional: true - cheerio: - optional: true - handlebars: - optional: true - peggy: - optional: true - typeorm: - optional: true + '@langchain/core': 1.1.18 - langsmith@0.3.87: - resolution: {integrity: sha512-XXR1+9INH8YX96FKWc5tie0QixWz6tOqAsAKfcJyPkE0xPep+NDz0IQLR32q4bn10QK3LqD2HN6T3n6z1YLW7Q==} + langsmith@0.4.12: + resolution: {integrity: sha512-YWt0jcGvKqjUgIvd78rd4QcdMss0lUkeUaqp0UpVRq7H2yNDx8H5jOUO/laWUmaPtWGgcip0qturykXe1g9Gqw==} peerDependencies: '@opentelemetry/api': '*' '@opentelemetry/exporter-trace-otlp-proto': '*' @@ -551,6 +730,18 @@ packages: long@5.3.2: resolution: {integrity: sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} @@ -561,20 +752,37 @@ packages: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true - openai@5.12.2: - resolution: {integrity: sha512-xqzHHQch5Tws5PcKR2xsZGX9xtch+JQFz5zb14dGqlshmmDAFBFEWmeIpf7wVqWV+w7Emj7jRgkNJakyKE0tYQ==} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + deprecated: Use your platform's native DOMException instead + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + openai@6.17.0: + resolution: {integrity: sha512-NHRpPEUPzAvFOAFs9+9pC6+HCw/iWsYsKCMPXH5Kw7BpMxqd8g/A07/1o7Gx2TWtCnzevVRyKMRFqyiHyAlqcA==} hasBin: true peerDependencies: ws: ^8.18.0 - zod: ^3.23.8 + zod: ^3.25 || ^4.0 peerDependenciesMeta: ws: optional: true zod: optional: true - openapi-types@12.1.3: - resolution: {integrity: sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==} + openapi-fetch@0.12.5: + resolution: {integrity: sha512-FnAMWLt0MNL6ComcL4q/YbB1tUgyz5YnYtwA1+zlJ5xcucmK5RlWsgH1ynxmEeu8fGJkYjm8armU/HVpORc9lw==} + + openapi-typescript-helpers@0.0.15: + resolution: {integrity: sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw==} p-finally@1.0.0: resolution: {integrity: sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==} @@ -584,14 +792,22 @@ packages: resolution: {integrity: sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==} engines: {node: '>=8'} - p-retry@4.6.2: - resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} - engines: {node: '>=8'} + p-queue@9.1.0: + resolution: {integrity: sha512-O/ZPaXuQV29uSLbxWBGGZO1mCQXV2BLIwUr59JUU9SoH76mnYvtms7aafH/isNSNGwuEfP6W/4xD0/TJXxrizw==} + engines: {node: '>=20'} + + p-retry@7.1.1: + resolution: {integrity: sha512-J5ApzjyRkkf601HpEeykoiCvzHQjWxPAHhyjFcEUP2SWq0+35NKh8TLhpLw+Dkq5TZBFvUM6UigdE9hIVYTl5w==} + engines: {node: '>=20'} p-timeout@3.2.0: resolution: {integrity: sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==} engines: {node: '>=8'} + p-timeout@7.0.1: + resolution: {integrity: sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg==} + engines: {node: '>=20'} + path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} @@ -611,10 +827,6 @@ packages: engines: {node: '>= 0.4'} hasBin: true - retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - semver@7.7.3: resolution: {integrity: sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==} engines: {node: '>=10'} @@ -634,6 +846,12 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tsx@4.21.0: resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} engines: {node: '>=18.0.0'} @@ -644,6 +862,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.21.0: resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} @@ -651,11 +872,20 @@ packages: resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} hasBin: true - yaml@2.8.2: - resolution: {integrity: sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==} - engines: {node: '>= 14.6'} + uuid@13.0.0: + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} hasBin: true + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + zod-to-json-schema@3.25.1: resolution: {integrity: sha512-pM/SU9d3YAggzi6MtR4h7ruuQlqKtad8e9S0fmxcMi+ueAK5Korys/aWcV9LIIHTVbj01NdzxcnXSN+O74ZIVA==} peerDependencies: @@ -664,14 +894,81 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + snapshots: + '@ai-sdk/gateway@2.0.31(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.1 + '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) + '@vercel/oidc': 3.1.0 + zod: 3.25.76 + optional: true + + '@ai-sdk/gateway@2.0.31(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 2.0.1 + '@ai-sdk/provider-utils': 3.0.20(zod@4.3.6) + '@vercel/oidc': 3.1.0 + zod: 4.3.6 + + '@ai-sdk/openai@2.0.89(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 2.0.1 + '@ai-sdk/provider-utils': 3.0.20(zod@4.3.6) + zod: 4.3.6 + + '@ai-sdk/provider-utils@3.0.20(zod@3.25.76)': + dependencies: + '@ai-sdk/provider': 2.0.1 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 3.25.76 + optional: true + + '@ai-sdk/provider-utils@3.0.20(zod@4.3.6)': + dependencies: + '@ai-sdk/provider': 2.0.1 + '@standard-schema/spec': 1.1.0 + eventsource-parser: 3.0.6 + zod: 4.3.6 + + '@ai-sdk/provider@2.0.1': + dependencies: + json-schema: 0.4.0 + + '@anthropic-ai/sdk@0.35.0': + dependencies: + '@types/node': 18.19.130 + '@types/node-fetch': 2.6.13 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + optional: true + '@arizeai/openinference-core@2.0.5': dependencies: '@arizeai/openinference-semantic-conventions': 2.1.7 '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@arizeai/openinference-instrumentation-langchain@4.0.6(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))': + dependencies: + '@arizeai/openinference-core': 2.0.5 + '@arizeai/openinference-semantic-conventions': 2.1.7 + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.46.0(@opentelemetry/api@1.9.0) + transitivePeerDependencies: + - supports-color + '@arizeai/openinference-semantic-conventions@1.1.0': {} '@arizeai/openinference-semantic-conventions@2.1.7': {} @@ -683,6 +980,38 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@arizeai/phoenix-client@5.8.0(@opentelemetry/api@1.9.0)': + dependencies: + '@arizeai/openinference-semantic-conventions': 1.1.0 + '@arizeai/openinference-vercel': 2.5.5(@opentelemetry/api@1.9.0) + '@arizeai/phoenix-config': 0.1.0 + '@arizeai/phoenix-otel': 0.3.4 + async: 3.2.6 + openapi-fetch: 0.12.5 + tiny-invariant: 1.3.3 + zod: 3.25.76 + zod-to-json-schema: 3.25.1(zod@3.25.76) + optionalDependencies: + '@anthropic-ai/sdk': 0.35.0 + ai: 5.0.125(zod@3.25.76) + openai: 6.17.0(zod@3.25.76) + transitivePeerDependencies: + - '@opentelemetry/api' + - encoding + - supports-color + - ws + + '@arizeai/phoenix-config@0.1.0': {} + + '@arizeai/phoenix-evals@0.8.0': + dependencies: + '@arizeai/openinference-core': 2.0.5 + '@opentelemetry/api': 1.9.0 + ai: 5.0.125(zod@4.3.6) + jsonpath-plus: 10.3.0 + mustache: 4.2.0 + zod: 4.3.6 + '@arizeai/phoenix-otel@0.3.4': dependencies: '@arizeai/openinference-semantic-conventions': 1.1.0 @@ -777,39 +1106,67 @@ snapshots: '@esbuild/win32-x64@0.27.2': optional: true - '@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))': + '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@jsep-plugin/regex@1.0.4(jsep@1.4.0)': + dependencies: + jsep: 1.4.0 + + '@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))': dependencies: '@cfworker/json-schema': 4.1.1 ansi-styles: 5.2.0 camelcase: 6.3.0 decamelize: 1.2.0 js-tiktoken: 1.0.21 - langsmith: 0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + langsmith: 0.4.12(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) mustache: 4.2.0 p-queue: 6.6.2 - p-retry: 4.6.2 uuid: 10.0.0 - zod: 3.25.76 - zod-to-json-schema: 3.25.1(zod@3.25.76) + zod: 4.3.6 transitivePeerDependencies: - '@opentelemetry/api' - '@opentelemetry/exporter-trace-otlp-proto' - '@opentelemetry/sdk-trace-base' - openai - '@langchain/openai@0.6.17(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))': + '@langchain/langgraph-checkpoint@1.0.0(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))': dependencies: - '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) - js-tiktoken: 1.0.21 - openai: 5.12.2(zod@3.25.76) - zod: 3.25.76 + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + uuid: 10.0.0 + + '@langchain/langgraph-sdk@1.5.5(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))': + dependencies: + p-queue: 9.1.0 + p-retry: 7.1.1 + uuid: 13.0.0 + optionalDependencies: + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + + '@langchain/langgraph@1.1.3(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))(zod-to-json-schema@3.25.1(zod@4.3.6))(zod@4.3.6)': + dependencies: + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + '@langchain/langgraph-checkpoint': 1.0.0(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))) + '@langchain/langgraph-sdk': 1.5.5(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))) + '@standard-schema/spec': 1.1.0 + uuid: 10.0.0 + zod: 4.3.6 + optionalDependencies: + zod-to-json-schema: 3.25.1(zod@4.3.6) transitivePeerDependencies: - - ws + - react + - react-dom - '@langchain/textsplitters@0.1.0(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))': + '@langchain/openai@1.2.4(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))': dependencies: - '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) js-tiktoken: 1.0.21 + openai: 6.17.0(zod@4.3.6) + zod: 4.3.6 + transitivePeerDependencies: + - ws '@opentelemetry/api-logs@0.57.2': dependencies: @@ -840,6 +1197,17 @@ snapshots: '@opentelemetry/resources': 1.30.1(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation@0.46.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@types/shimmer': 1.2.0 + import-in-the-middle: 1.7.1 + require-in-the-middle: 7.5.2 + semver: 7.7.3 + shimmer: 1.2.1 + transitivePeerDependencies: + - supports-color + '@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0)': dependencies: '@opentelemetry/api': 1.9.0 @@ -948,32 +1316,85 @@ snapshots: '@protobufjs/utf8@1.1.0': {} + '@standard-schema/spec@1.1.0': {} + + '@types/node-fetch@2.6.13': + dependencies: + '@types/node': 20.19.30 + form-data: 4.0.5 + optional: true + + '@types/node@18.19.130': + dependencies: + undici-types: 5.26.5 + optional: true + '@types/node@20.19.30': dependencies: undici-types: 6.21.0 - '@types/retry@0.12.0': {} - '@types/shimmer@1.2.0': {} '@types/uuid@10.0.0': {} + '@vercel/oidc@3.1.0': {} + + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + optional: true + + acorn-import-assertions@1.9.0(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + acorn-import-attributes@1.9.5(acorn@8.15.0): dependencies: acorn: 8.15.0 acorn@8.15.0: {} + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + optional: true + + ai@5.0.125(zod@3.25.76): + dependencies: + '@ai-sdk/gateway': 2.0.31(zod@3.25.76) + '@ai-sdk/provider': 2.0.1 + '@ai-sdk/provider-utils': 3.0.20(zod@3.25.76) + '@opentelemetry/api': 1.9.0 + zod: 3.25.76 + optional: true + + ai@5.0.125(zod@4.3.6): + dependencies: + '@ai-sdk/gateway': 2.0.31(zod@4.3.6) + '@ai-sdk/provider': 2.0.1 + '@ai-sdk/provider-utils': 3.0.20(zod@4.3.6) + '@opentelemetry/api': 1.9.0 + zod: 4.3.6 + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 ansi-styles@5.2.0: {} - argparse@2.0.1: {} + async@3.2.6: {} + + asynckit@0.4.0: + optional: true base64-js@1.5.1: {} + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + optional: true + camelcase@6.3.0: {} chalk@4.1.2: @@ -989,6 +1410,11 @@ snapshots: color-name@1.1.4: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + optional: true + console-table-printer@2.15.0: dependencies: simple-wcswidth: 1.1.2 @@ -999,6 +1425,37 @@ snapshots: decamelize@1.2.0: {} + delayed-stream@1.0.0: + optional: true + + dotenv@17.2.3: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + optional: true + + es-define-property@1.0.1: + optional: true + + es-errors@1.3.0: + optional: true + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + optional: true + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + optional: true + esbuild@0.27.2: optionalDependencies: '@esbuild/aix-ppc64': 0.27.2 @@ -1028,23 +1485,84 @@ snapshots: '@esbuild/win32-ia32': 0.27.2 '@esbuild/win32-x64': 0.27.2 + event-target-shim@5.0.1: + optional: true + eventemitter3@4.0.7: {} + eventemitter3@5.0.4: {} + + eventsource-parser@3.0.6: {} + + form-data-encoder@1.7.2: + optional: true + + form-data@4.0.5: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + optional: true + + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + optional: true + fsevents@2.3.3: optional: true function-bind@1.1.2: {} + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + optional: true + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + optional: true + get-tsconfig@4.13.1: dependencies: resolve-pkg-maps: 1.0.0 + gopd@1.2.0: + optional: true + has-flag@4.0.0: {} + has-symbols@1.1.0: + optional: true + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + optional: true + hasown@2.0.2: dependencies: function-bind: 1.1.2 + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + optional: true + import-in-the-middle@1.15.0: dependencies: acorn: 8.15.0 @@ -1052,42 +1570,51 @@ snapshots: cjs-module-lexer: 1.4.3 module-details-from-path: 1.0.4 + import-in-the-middle@1.7.1: + dependencies: + acorn: 8.15.0 + acorn-import-assertions: 1.9.0(acorn@8.15.0) + cjs-module-lexer: 1.4.3 + module-details-from-path: 1.0.4 + is-core-module@2.16.1: dependencies: hasown: 2.0.2 + is-network-error@1.3.0: {} + js-tiktoken@1.0.21: dependencies: base64-js: 1.5.1 - js-yaml@4.1.1: - dependencies: - argparse: 2.0.1 + jsep@1.4.0: {} - jsonpointer@5.0.1: {} + json-schema@0.4.0: {} - langchain@0.3.37(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)): + jsonpath-plus@10.3.0: dependencies: - '@langchain/core': 0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) - '@langchain/openai': 0.6.17(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))) - '@langchain/textsplitters': 0.1.0(@langchain/core@0.3.80(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76))) - js-tiktoken: 1.0.21 - js-yaml: 4.1.1 - jsonpointer: 5.0.1 - langsmith: 0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)) - openapi-types: 12.1.3 - p-retry: 4.6.2 + '@jsep-plugin/assignment': 1.3.0(jsep@1.4.0) + '@jsep-plugin/regex': 1.0.4(jsep@1.4.0) + jsep: 1.4.0 + + langchain@1.2.16(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))(zod-to-json-schema@3.25.1(zod@4.3.6)): + dependencies: + '@langchain/core': 1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) + '@langchain/langgraph': 1.1.3(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)))(zod-to-json-schema@3.25.1(zod@4.3.6))(zod@4.3.6) + '@langchain/langgraph-checkpoint': 1.0.0(@langchain/core@1.1.18(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6))) + langsmith: 0.4.12(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)) uuid: 10.0.0 - yaml: 2.8.2 - zod: 3.25.76 + zod: 4.3.6 transitivePeerDependencies: - '@opentelemetry/api' - '@opentelemetry/exporter-trace-otlp-proto' - '@opentelemetry/sdk-trace-base' - openai - - ws + - react + - react-dom + - zod-to-json-schema - langsmith@0.3.87(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@5.12.2(zod@3.25.76)): + langsmith@0.4.12(@opentelemetry/api@1.9.0)(@opentelemetry/exporter-trace-otlp-proto@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(openai@6.17.0(zod@4.3.6)): dependencies: '@types/uuid': 10.0.0 chalk: 4.1.2 @@ -1099,21 +1626,49 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/exporter-trace-otlp-proto': 0.57.2(@opentelemetry/api@1.9.0) '@opentelemetry/sdk-trace-base': 1.30.1(@opentelemetry/api@1.9.0) - openai: 5.12.2(zod@3.25.76) + openai: 6.17.0(zod@4.3.6) long@5.3.2: {} + math-intrinsics@1.1.0: + optional: true + + mime-db@1.52.0: + optional: true + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + optional: true + module-details-from-path@1.0.4: {} ms@2.1.3: {} mustache@4.2.0: {} - openai@5.12.2(zod@3.25.76): + node-domexception@1.0.0: + optional: true + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + optional: true + + openai@6.17.0(zod@3.25.76): optionalDependencies: zod: 3.25.76 + optional: true + + openai@6.17.0(zod@4.3.6): + optionalDependencies: + zod: 4.3.6 + + openapi-fetch@0.12.5: + dependencies: + openapi-typescript-helpers: 0.0.15 - openapi-types@12.1.3: {} + openapi-typescript-helpers@0.0.15: {} p-finally@1.0.0: {} @@ -1122,15 +1677,21 @@ snapshots: eventemitter3: 4.0.7 p-timeout: 3.2.0 - p-retry@4.6.2: + p-queue@9.1.0: + dependencies: + eventemitter3: 5.0.4 + p-timeout: 7.0.1 + + p-retry@7.1.1: dependencies: - '@types/retry': 0.12.0 - retry: 0.13.1 + is-network-error: 1.3.0 p-timeout@3.2.0: dependencies: p-finally: 1.0.0 + p-timeout@7.0.1: {} + path-parse@1.0.7: {} protobufjs@7.5.4: @@ -1164,8 +1725,6 @@ snapshots: path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - retry@0.13.1: {} - semver@7.7.3: {} shimmer@1.2.1: {} @@ -1178,6 +1737,11 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + tiny-invariant@1.3.3: {} + + tr46@0.0.3: + optional: true + tsx@4.21.0: dependencies: esbuild: 0.27.2 @@ -1187,14 +1751,36 @@ snapshots: typescript@5.9.3: {} + undici-types@5.26.5: + optional: true + undici-types@6.21.0: {} uuid@10.0.0: {} - yaml@2.8.2: {} + uuid@13.0.0: {} + + web-streams-polyfill@4.0.0-beta.3: + optional: true + + webidl-conversions@3.0.1: + optional: true + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + optional: true zod-to-json-schema@3.25.1(zod@3.25.76): dependencies: zod: 3.25.76 + zod-to-json-schema@3.25.1(zod@4.3.6): + dependencies: + zod: 4.3.6 + optional: true + zod@3.25.76: {} + + zod@4.3.6: {} diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts new file mode 100644 index 00000000000..35fd169d8f1 --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts @@ -0,0 +1,126 @@ +import "dotenv/config"; +import { createClassificationEvaluator } from "@arizeai/phoenix-evals"; +import { createOpenAI } from "@ai-sdk/openai"; +import { getSpans, logSpanAnnotations } from "@arizeai/phoenix-client/spans"; + +const EVAL_NAME = "custom_correctness"; +const AGENT_SPAN_NAME = "LangGraph"; +const PROJECT_NAME = + process.env.PHOENIX_PROJECT_NAME ?? "langchain-travel-agent"; +const FIREWORKS_MODEL = + "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507"; + +const correctnessTemplate = ` +You are an expert evaluator judging whether a travel planner agent's response is correct. The agent is a friendly travel planner that must combine multiple tools to create a trip plan with: (1) essential info, (2) budget breakdown, and (3) local flavor/experiences. + +CORRECT - The response: +- Accurately addresses the user's destination, duration, and stated interests +- Includes essential travel info (e.g., weather, best time to visit, key attractions, etiquette) for the destination +- Includes a budget or cost breakdown appropriate to the destination and trip duration +- Includes local experiences, cultural highlights, or authentic recommendations matching the user's interests +- Is factually accurate, logically consistent, and helpful for planning the trip +- Uses precise, travel-appropriate terminology + +INCORRECT - The response contains any of: +- Factual errors about the destination, costs, or local info +- Missing essential info when the user asked for a full trip plan +- Missing or irrelevant budget information for the given destination/duration +- Missing or generic local experiences that do not match the user's interests +- Wrong destination, duration, or interests addressed +- Contradictions, misleading statements, or unhelpful/off-topic content + +[BEGIN DATA] +************ +[User Input]: +{{input}} + +************ +[Travel Plan]: +{{output}} +************ +[END DATA] + +Focus on factual accuracy and completeness of the trip plan (essentials, budget, local flavor). Is the output correct or incorrect? +`; + +function toString(v: unknown): string | null { + if (typeof v === "string") return v; + if (v != null) return JSON.stringify(v); + return null; +} + +interface SpanLike { + name?: string; + span_name?: string; + attributes?: Record; + context?: { span_id?: string }; + span_id?: string; + id?: string; +} + +function getInputOutput(span: SpanLike): { + input: string | null; + output: string | null; +} { + const attrs = span.attributes ?? {}; + const input = toString(attrs["input.value"] ?? attrs["input"]); + const output = toString(attrs["output.value"] ?? attrs["output"]); + return { input, output }; +} + +function getSpanId(span: SpanLike): string | null { + const id = span.context?.span_id ?? span.span_id ?? span.id; + return id != null ? String(id) : null; +} + +async function main() { + const llm = createOpenAI({ + baseURL: "https://api.fireworks.ai/inference/v1", + apiKey: process.env.FIREWORKS_API_KEY, + }).chat(FIREWORKS_MODEL); + + const evaluator = createClassificationEvaluator({ + model: llm as Parameters[0]["model"], + promptTemplate: correctnessTemplate, + choices: { correct: 1, incorrect: 0 }, + name: EVAL_NAME, + }); + + const { spans } = await getSpans({ + project: { projectName: PROJECT_NAME }, + limit: 500, + }); + + const toEvaluate: { spanId: string; input: string; output: string }[] = []; + for (const s of spans as SpanLike[]) { + if ((s.name ?? s.span_name) !== AGENT_SPAN_NAME) continue; + const { input, output } = getInputOutput(s); + const spanId = getSpanId(s); + if (input && output && spanId) toEvaluate.push({ spanId, input, output }); + } + + const spanAnnotations = await Promise.all( + toEvaluate.map(async ({ spanId, input, output }) => { + const { label, score, explanation } = await evaluator.evaluate({ + input, + output, + }); + return { + spanId, + name: EVAL_NAME as "custom_correctness", + label, + score, + explanation, + annotatorKind: "LLM" as const, + metadata: { evaluator: EVAL_NAME, input, output }, + }; + }), + ); + + await logSpanAnnotations({ spanAnnotations, sync: true }); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts index f17c1ea6d17..2f8ff040160 100644 --- a/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/index.ts @@ -1,101 +1,76 @@ -/** - * Simple LangChain TypeScript Application - * - * This demonstrates a basic LangChain chain with: - * - Prompt templates - * - LLM integration - * - Phoenix tracing - * - * Run with: npm start - */ +import "dotenv/config"; +import { register } from "@arizeai/phoenix-otel"; +import { LangChainInstrumentation } from "@arizeai/openinference-instrumentation-langchain"; +import * as CallbackManagerModule from "@langchain/core/callbacks/manager"; -// Import instrumentation first - this must be at the top! -import "./instrumentation.js"; +const provider = register({ + projectName: "langchain-travel-agent", +}); + +const lcInstrumentation = new LangChainInstrumentation(); +lcInstrumentation.manuallyInstrument(CallbackManagerModule); -import { ChatOpenAI } from "@langchain/openai"; -import { ChatAnthropic } from "@langchain/anthropic"; -import { PromptTemplate } from "@langchain/core/prompts"; -import { StringOutputParser } from "@langchain/core/output_parsers"; -import { RunnableSequence } from "@langchain/core/runnables"; +import { createAgent } from "langchain"; +import { travelTools } from "./tools"; async function main() { - // Check for API key (supports both OpenAI and Anthropic) - if (!process.env.OPENAI_API_KEY && !process.env.ANTHROPIC_API_KEY) { - console.error("❌ Error: No API key found"); - console.error(" Please set one of:"); - console.error(" - export OPENAI_API_KEY=your-key-here"); - console.error(" - export ANTHROPIC_API_KEY=your-key-here"); + if (!process.env.OPENAI_API_KEY) { + console.error("❌ Error: OPENAI_API_KEY environment variable is not set"); process.exit(1); } - console.log("=".repeat(60)); - console.log("LangChain TypeScript Quickstart"); - console.log("=".repeat(60)); - console.log(""); - - // Initialize the LLM based on available API key - const llm = process.env.ANTHROPIC_API_KEY - ? new ChatAnthropic({ - modelName: "claude-3-5-sonnet-20241022", - temperature: 0.7, - }) - : new ChatOpenAI({ - modelName: "gpt-3.5-turbo", - temperature: 0.7, - }); - - // Create a prompt template - const prompt = PromptTemplate.fromTemplate( - "You are a helpful assistant. Answer the following question in a friendly and concise way.\n\nQuestion: {question}\n\nAnswer:" - ); + if (!process.env.TAVILY_API_KEY) { + console.error("❌ Error: TAVILY_API_KEY environment variable is not set"); + process.exit(1); + } - // Create a simple chain: prompt -> llm -> parser - const chain = RunnableSequence.from([ - prompt, - llm, - new StringOutputParser(), - ]); + const agent = createAgent({ + model: "openai:gpt-3.5-turbo", + systemPrompt: `You are a travel planner. You must produce a trip plan that includes exactly three sections, each backed by a tool call. - console.log("Running LangChain chain with Phoenix tracing...\n"); +RULES: +1. You MUST call all three tools for every trip plan: essential_info, budget_basics, and local_flavor. Call them with the user's destination, duration, and interests—do not guess or substitute. +2. Use only information returned by the tools. Do not invent facts, prices, or recommendations. +3. Structure your reply strictly as: (a) Essentials — weather, best time to visit, key attractions, etiquette; (b) Budget — cost breakdown for the given duration; (c) Local flavor — experiences matching the user's stated interests. +4. Keep the total response under 800 words. Be concise and professional; no filler or unsupported claims.`, + tools: travelTools, + }); - // Example questions - const questions = [ - "What is the capital of France?", - "Explain quantum computing in simple terms.", - "What are the benefits of TypeScript?", + const queries: Array<{ + destination: string; + duration: string; + interests: string; + }> = [ + { destination: "Ireland", duration: "5 days", interests: "food, culture" }, + { destination: "Japan", duration: "7 days", interests: "temples, cuisine" }, + { destination: "Portugal", duration: "3 days", interests: "beaches, wine" }, ]; - // Process multiple questions through the chain - for (let i = 0; i < questions.length; i++) { - const question = questions[i]; - console.log(`📝 Question ${i + 1}: ${question}`); - console.log(" Processing..."); - + for (let i = 0; i < queries.length; i++) { + const { destination, duration, interests } = queries[i]; + const query = ` +Plan a ${duration} trip to ${destination}. +Focus on ${interests}. +Include essential info, budget breakdown, and local experiences. +`; + console.log( + `\n--- Query ${i + 1}/${queries.length}: ${duration} in ${destination} ---\n`, + ); try { - const response = await chain.invoke({ question }); - console.log(` ✅ Answer: ${response}\n`); + const response = await agent.invoke({ + messages: [{ role: "user", content: query }], + }); + const lastMessage = response.messages[response.messages.length - 1]; + console.log(lastMessage.content); } catch (error) { - console.error(` ❌ Error: ${error}\n`); + console.error(`❌ Error on query ${i + 1}: ${error}\n`); } - - // Small delay between requests - await new Promise((resolve) => setTimeout(resolve, 500)); } - console.log("=".repeat(60)); - console.log("✅ All questions processed!"); - console.log(""); - console.log("👀 Open Phoenix UI at http://localhost:6006"); - console.log(""); - console.log("What to look for:"); - console.log(" - Each chain invocation creates a trace"); - console.log(" - The trace includes the prompt, LLM call, and response"); - console.log(" - You can see token usage, latency, and other metrics"); - console.log("=".repeat(60)); + await provider.forceFlush(); } main().catch((error) => { console.error("Fatal error:", error); process.exit(1); }); - diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/pre_built_evals.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/pre_built_evals.ts new file mode 100644 index 00000000000..c94f01bfbba --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/pre_built_evals.ts @@ -0,0 +1,71 @@ +import "dotenv/config"; +import { createCorrectnessEvaluator } from "@arizeai/phoenix-evals"; +import { openai, createOpenAI } from "@ai-sdk/openai"; +import { getSpans, logSpanAnnotations } from "@arizeai/phoenix-client/spans"; + +const toStr = (v: unknown) => + typeof v === "string" ? v : v != null ? JSON.stringify(v) : null; + +function getInputOutput(span: any) { + const attrs = span.attributes ?? {}; + const input = toStr(attrs["input.value"] ?? attrs["input"]); + const output = toStr(attrs["output.value"] ?? attrs["output"]); + return { input, output }; +} + +async function main() { + const base_model = openai("gpt-4o-mini"); + + // **** Uncomment below for a custom endpoint LLM & Change Model in createCorrectnessEvaluator() **** // + + // const fireworks = createOpenAI({ + // baseURL: "https://api.fireworks.ai/inference/v1", + // apiKey: process.env.FIREWORKS_API_KEY, + // }); + // const custom_llm = fireworks.chat( + // "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", + // ); + + const evaluator = createCorrectnessEvaluator({ + model: base_model as any, + }); + + const projectName = + process.env.PHOENIX_PROJECT_NAME || "langchain-travel-agent"; + + const { spans } = await getSpans({ project: { projectName }, limit: 500 }); + + const parentSpans: { spanId: string; input: string; output: string }[] = []; + for (const s of spans) { + const name = (s as any).name ?? (s as any).span_name; + if (name !== "LangGraph") continue; + const { input, output } = getInputOutput(s); + const spanId = + (s as any).context?.span_id ?? (s as any).span_id ?? (s as any).id; + if (input && output && spanId) { + parentSpans.push({ spanId: String(spanId), input, output }); + } + } + + const spanAnnotations = await Promise.all( + parentSpans.map(async ({ spanId, input, output }) => { + const r = await evaluator.evaluate({ input, output }); + return { + spanId, + name: "correctness" as const, + label: r.label, + score: r.score, + explanation: r.explanation ?? undefined, + annotatorKind: "LLM" as const, + metadata: { evaluator: "correctness", input, output }, + }; + }), + ); + + await logSpanAnnotations({ spanAnnotations, sync: true }); +} + +main().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/tools.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/tools.ts new file mode 100644 index 00000000000..114a7de108a --- /dev/null +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/tools.ts @@ -0,0 +1,152 @@ +import { StructuredTool } from "@langchain/core/tools"; +import * as z from "zod"; + +function compact(text: string, limit: number = 200): string { + const cleaned = text.split(/\s+/).join(" "); + return cleaned.length <= limit + ? cleaned + : cleaned.slice(0, limit).split(" ").slice(0, -1).join(" "); +} + +async function searchApi(query: string): Promise { + const tavilyKey = process.env.TAVILY_API_KEY; + + if (!tavilyKey) { + throw new Error( + "TAVILY_API_KEY environment variable is not set. Please set it with: export TAVILY_API_KEY=your-key-here", + ); + } + + try { + const response = await fetch("https://api.tavily.com/search", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + api_key: tavilyKey, + query: query, + max_results: 3, + search_depth: "basic", + include_answer: true, + }), + }); + + if (!response.ok) { + throw new Error( + `Tavily API error: ${response.status} ${response.statusText}`, + ); + } + + const data = (await response.json()) as { + answer?: string; + results?: Array<{ content?: string }>; + }; + const answer = data.answer || ""; + const snippets = (data.results || []).map((r) => r.content || "").join(" "); + const combined = `${answer} ${snippets}`.trim(); + return combined.slice(0, 400) || null; + } catch (error) { + throw error; + } +} + +const destinationSchema = z.string().min(1, "Destination is required").max(100); +const durationSchema = z + .string() + .regex(/^\d+\s*days?$/i, "Duration must be like '3 days' or '7 days'"); +const interestsSchema = z.string().min(1, "Interests are required").max(200); + +class EssentialInfoTool extends StructuredTool { + name = "essential_info"; + description = + "Required. Fetches weather, best time to visit, top attractions, and etiquette for a destination. Call this first when building a trip plan. Do not use for budget or local experiences."; + schema = z.object({ + destination: destinationSchema.describe( + "The travel destination (e.g., 'Japan', 'Portugal'). Required.", + ), + }); + + async _call({ destination }: { destination: string }): Promise { + const dest = destination.trim(); + if (!dest) return "Error: destination is required."; + const query = `${dest} travel essentials weather best time top attractions etiquette`; + const result = await searchApi(query); + if (result) { + return `${dest} essentials: ${compact(result)}`; + } + return `${dest} is a popular travel destination. Expect local culture, cuisine, and landmarks worth exploring.`; + } +} + +class BudgetBasicsTool extends StructuredTool { + name = "budget_basics"; + description = + "Required. Fetches travel cost breakdown (lodging, food, transport, activities) for a destination and trip duration. Call with the exact duration the user asked for (e.g., '5 days'). Do not use for essentials or local experiences."; + schema = z.object({ + destination: destinationSchema.describe( + "The travel destination. Required.", + ), + duration: durationSchema.describe( + "Trip duration in the form 'N days' (e.g., '5 days', '7 days'). Required.", + ), + }); + + async _call({ + destination, + duration, + }: { + destination: string; + duration: string; + }): Promise { + const dest = destination.trim(); + const dur = duration.trim(); + if (!dest || !dur) return "Error: destination and duration are required."; + const query = `${dest} travel budget average daily costs ${dur}`; + const result = await searchApi(query); + if (result) { + return `${dest} budget (${dur}): ${compact(result)}`; + } + return `Budget for ${dur} in ${dest} depends on lodging, meals, transport, and attractions.`; + } +} + +class LocalFlavorTool extends StructuredTool { + name = "local_flavor"; + description = + "Required. Fetches authentic local experiences and cultural highlights for a destination. Call with the user's stated interests (e.g., 'food, culture', 'beaches, wine'). Do not use for essentials or budget."; + schema = z.object({ + destination: destinationSchema.describe( + "The travel destination. Required.", + ), + interests: interestsSchema.describe( + "The user's interests (e.g., 'food, culture', 'beaches, wine'). Required—use the exact interests from the request.", + ), + }); + + async _call({ + destination, + interests, + }: { + destination: string; + interests: string; + }): Promise { + const dest = destination.trim(); + const intr = interests.trim() || "local culture"; + if (!dest) return "Error: destination is required."; + const query = `${dest} authentic local experiences ${intr}`; + const result = await searchApi(query); + if (result) { + return `${dest} ${intr}: ${compact(result)}`; + } + return `Explore ${dest}'s unique ${intr} through markets, neighborhoods, and local eateries.`; + } +} + +export const essentialInfoTool = new EssentialInfoTool(); +export const budgetBasicsTool = new BudgetBasicsTool(); +export const localFlavorTool = new LocalFlavorTool(); + +export const travelTools = [ + essentialInfoTool, + budgetBasicsTool, + localFlavorTool, +]; diff --git a/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json b/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json index 4a9ef80449d..dd5050266f0 100644 --- a/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json +++ b/tutorials/quickstarts/langchain-ts-quickstart/tsconfig.json @@ -3,7 +3,7 @@ "target": "ES2022", "module": "ESNext", "lib": ["ES2022"], - "moduleResolution": "node", + "moduleResolution": "bundler", "outDir": "./dist", "rootDir": "./src", "strict": true, @@ -13,7 +13,8 @@ "resolveJsonModule": true, "declaration": true, "declarationMap": true, - "sourceMap": true + "sourceMap": true, + "noErrorTruncation": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] From 80a6dc51636b9ccc2be7f7539031d68dd4be0b62 Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Wed, 4 Feb 2026 18:53:48 -0800 Subject: [PATCH 5/8] add in review feedback --- docs.json | 2 - .../tutorials/a/configure-your-llm.mdx | 102 ------------- .../evaluation/tutorials/a/run-your-evals.mdx | 101 ------------- .../tutorials/a/use-custom-eval-template.mdx | 131 ----------------- .../a/use-pre-build-eval-template.mdx | 85 ----------- .../tutorials/customize-eval-template.mdx | 20 +-- .../tutorials/customize-your-llm-endpoint.mdx | 139 +----------------- .../run-evals-with-built-in-evals.mdx | 10 +- .../quickstarts/agno_agent_for_evals.ipynb | 4 +- .../src/custom_evals.ts | 13 +- 10 files changed, 18 insertions(+), 589 deletions(-) delete mode 100644 docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx delete mode 100644 docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx delete mode 100644 docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx delete mode 100644 docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx diff --git a/docs.json b/docs.json index f9bc6a01535..28831fdd4f6 100644 --- a/docs.json +++ b/docs.json @@ -152,8 +152,6 @@ "docs/phoenix/evaluation/tutorials/customize-eval-template" ] }, - "docs/phoenix/evaluation/typescript-quickstart", - "docs/phoenix/evaluation/python-quickstart", { "group": "Overview: Evals", "pages": [ diff --git a/docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx b/docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx deleted file mode 100644 index 454865266f7..00000000000 --- a/docs/phoenix/evaluation/tutorials/a/configure-your-llm.mdx +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Configure Your LLM" ---- - -## Why do Evals Matter? - -Evaluations let you measure how well an LLM application performs according to defined criteria, rather than relying on subjective judgment. Traces and raw outputs show what an LLM application produced during a run, but they don’t tell you whether the result meets your expectations. Without a way to score quality, such as relevance, correctness, or other task-specific criteria, it’s difficult to compare runs, detect regressions, or verify that changes actually improved behavior. - -Human labeling is the traditional approach, but it does not scale well across frequent iterations or large datasets. Phoenix Evals supports using an LLM as a judge to automate semantic quality assessments, making it possible to evaluate many outputs consistently. Evals in Phoenix are built from lightweight, composable Python components and are designed to work across multiple model providers via adapter layers. - -At its core, an LLM as a Judge eval combines three things: - -1. **The judge model**: the LLM that makes the judgment -2. **A prompt template or rubric**: the criteria you want judged -3. **Your data**: the examples you want to score - -Once you have defined what you want to evaluate and which data you want to run on, the next step is choosing and configuring the judge model. The model and its invocation settings directly affect how criteria are interpreted and how consistent your eval results are. - -We’ll now walk through how to pick and configure that model using the Phoenix evals library! - ---- - -## Option 1: Core LLM Setup - -Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. - -In the Python evals library, judge models are represented by the LLM class. An LLM describes a specific provider and model configuration and can be reused across multiple evaluators. Phoenix uses adapter layers to wrap provider SDKs so that different models can be used through the same interface. - -When you create an LLM, you specify how Phoenix connects to the model provider. This includes details such as the provider name, model identifier, credentials, and any SDK-specific client configuration. These settings are concerned only with connectivity and authentication. - -How the model behaves during evaluation is configured separately. Evaluators specify invocation parameters, such as sampling temperature or maximum token limits, that control how the judge model generates outputs for a particular eval. Keeping these concerns separate makes it easier to reuse the same judge model across different evals while tuning behavior per task. - -The example below illustrates this separation between model configuration and evaluator behavior: - -```python -from phoenix.evals.llm import LLM -from phoenix.evals import ClassificationEvaluator - -# Configure the judge model (connectivity) -judge_llm = LLM( - provider="openai", - model="gpt-4o", - api_key="YOUR_API_KEY", - timeout=30.0, -) - -# Configure the evaluator (invocation behavior) -eval_for_relevance = ClassificationEvaluator( - name="relevance_eval", - prompt_template=( - "Is this answer relevant to the question?\n" - "Question: {input}\n" - "Answer: {output}" - ), - llm=judge_llm, - temperature=0.0, - max_tokens=150, - choices={"irrelevant": 0, "relevant": 1}, -) -``` - -In practice, this means you can change how a model is called for one eval without affecting others, while keeping provider configuration centralized. - -## Option 2: Custom Endpoint (Self-Hosted or OpenAI-Compatible) - -In addition to standard hosted providers, Phoenix also supports evaluating against **custom or self-**hosted endpoints that are compatible with an existing provider SDK. - -Any keyword arguments passed when creating an `LLM` are forwarded to the underlying client SDK. For OpenAI-compatible endpoints, this includes parameters such as `base_url`, `api_key`, and `api_version`. This allows Phoenix to connect to internal or private inference services that expose the same API surface. - -The same separation of concerns applies when using custom endpoints. Connectivity details live on the `LLM`, while generation behavior continues to be controlled by the evaluator. This makes it possible to reuse the same eval definitions regardless of where the judge model is hosted. - -A minimal example of configuring a custom OpenAI-compatible endpoint looks like this: - -```python -from phoenix.evals.llm import LLM - -custom_llm = LLM( - provider="openai", - model="my-self-hosted", - api_key="MY_INTERNAL_KEY", - base_url="https://internal-inference.local/v1", - api_version="2025-01-01", -) -``` - -With this setup, any evaluator that uses `custom_llm` will route judge requests to your custom endpoint while still respecting evaluator-level settings such as temperature and token limits. - -## **Best Practices for Judge Models** - -Judge models are not user-facing. Their role is to apply a rubric consistently, not to generate creative or varied responses. When configuring a judge model, prioritize stability and repeatability over expressiveness. - -### **Favor consistency over creativity** - -Judge models should produce the same judgment when given the same input. Variability makes it harder to compare results across runs or to detect regressions. In most cases, configure the judge with a sampling temperature of 0.0 (or as low as the provider allows) to minimize randomness and improve consistency. - -### **Prefer categorical judgments** - -For most evaluation tasks, categorical outputs are more reliable than numeric ratings. Asking a model to reason about scales or relative magnitudes introduces additional variability and tends to correlate less well with human judgment. Phoenix Evals recommends using categorical labels for judging outputs and mapping them to numeric values only if needed downstream. - -## **Next Steps** - -With the judge model configured, the next step is defining how that model should make judgments. In the following section, we’ll cover how to write a judge prompt or template, including how to express evaluation criteria clearly and structure outputs so they can be scored consistently. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx b/docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx deleted file mode 100644 index 8ef349f1aed..00000000000 --- a/docs/phoenix/evaluation/tutorials/a/run-your-evals.mdx +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: "How to Run Evals" ---- - -## Running Evals - -Now that you have defined what you want to evaluate and how the judge should make decisions, the final piece is the data. With a judge model and an eval template in place, you are ready to actually run your evaluator and produce quality signals. - -Phoenix evaluators can be executed in a few different ways depending on your workflow: - -- Single examples – During development or testing, you can call an evaluator’s `.evaluate()` method on a single record to see how it behaves with one input. This lets you quickly iterate on templates and check edge cases without preparing a full dataset. -- Batch mode – For real evaluation workloads, you run evaluators over many examples at once using tabular data structures such as pandas DataFrames. This is the standard execution path for scoring large collections of examples and for logging results back to Phoenix. - -Whether your examples come from a dataset, an experiment, or exported trace spans, the core execution model in Phoenix is the same: prepare structured data, run evaluators against it, and examine the scores and execution details. - -The sections below walk through the most common ways to run evals and connect results back to Phoenix. - ---- - -## Running Evals in Batch on a DataFrame - -For scoring many examples at once, Phoenix provides dedicated batch execution APIs that operate on pandas DataFrames. This is the standard path for real evaluation workloads. - -Phoenix exposes: - -- `evaluate_dataframe` — Synchronous batch execution -- `async_evaluate_dataframe` — Asynchronous execution with concurrency controls - -Both accept a DataFrame and a list of evaluators, and return a new DataFrame with evaluation results added. For each evaluator, the output includes: - -- A `{score_name}_score` column with the serialized score or `None` if the evaluation failed -- An `{evaluator_name}_execution_details` column with execution metadata (status, duration, exceptions) - -Before running batch evals, make sure evaluator inputs are mapped to your dataframe columns (see Input Mappings below). If an evaluation fails for a row, the execution details make it clear why, and the corresponding score will be `None`. - -Here’s a minimal illustration of synchronous batch evals: - -```python -from phoenix.evals import evaluate_dataframe - -# `df` is a pandas DataFrame with columns matching your evaluator inputs -results_df = evaluate_dataframe(df, [my_evaluator]) -print(results_df.head()) -``` - -Batch evaluation makes it straightforward to score large datasets, filter by quality results, and prepare for logging or experiment comparisons. - -## DataFrames, Datasets, and Experiments - -Although Phoenix supports higher-level abstractions like Datasets and Experiments, all evaluator executions run over tabular data. Behind the scenes, these abstractions resolve to DataFrames, so the same batch APIs apply regardless of source. - -If your examples originate from: - -- A Phoenix Dataset -- A Phoenix Experiment -- Logs or traces exported from Phoenix - -… you can transform them into a DataFrame and run evals in the same way. This unified model keeps eval execution consistent and predictable across different contexts. - -## Running Evals on Phoenix Traces - -We'll now walk through how to run evals on real trace data. Follow along with the following notebook to have traces ingested into Phoenix. - -TODO: \ - -Evaluations are especially useful on traced executions because they let you attach quality signals directly to spans. - -Once we have some trace data, we can start follow the typical workflow for trace evaluations: - -1. Export trace spans into a dataframe. - - ```python - from phoenix.client import Client - - spans_df = Client().spans.get_spans_dataframe(project_name="agno_travel_agent") - ``` -2. Select or transform fields from the spans so they match evaluator inputs (e.g., mapping nested attributes like `attributes.input.value`). - - ```python - TODO - ``` -3. Run batch evals on the prepared dataframe using the same APIs shown earlier. First I will define our evaluator. - - ```python - TODO - ``` -4. Log evaluation results back to Phoenix as span annotations. Phoenix uses the span identifier to attach annotations correctly. - -```python -from phoenix.client import Client - -Client().spans.log_span_annotations_dataframe( - dataframe=eval_df, - annotation_name="relevance", - annotator_kind="LLM", -) -``` - -Once logged, evaluations appear alongside traces in the Phoenix UI, letting you analyze execution behavior and quality side-by-side. - -That's it! You've successfully logged evaluations using trace data. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx b/docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx deleted file mode 100644 index 7a19c11826e..00000000000 --- a/docs/phoenix/evaluation/tutorials/a/use-custom-eval-template.mdx +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: "Create a Custom Eval Template" ---- - -## Why Define Your Own Eval Template? - -Built-in eval templates are designed to cover common evaluation patterns, but they cannot account for all application-specific requirements. When built-ins are insufficient, defining a custom eval template allows you to make evaluation criteria explicit and aligned with how success is defined in your system. - -Custom templates encode task constraints, domain knowledge, and product expectations directly into the evaluation logic. When evaluation criteria reflect real-world requirements, the resulting eval signal is more meaningful and easier to act on. - -This page focuses on defining a custom eval template: how to structure it, what information to include, and how to make judgments consistent. - ---- - -## Structuring a Custom Eval Template - -Eval templates are most effective when they follow the same order in which a judge model processes information. In practice, this means establishing context first, defining the evaluation criteria, presenting the data to be evaluated, and specifying the allowed outcomes. - -The sections below walk through this structure. - -## Defining the Judge’s Role and Evaluation Criteria - -Eval templates typically begin by establishing who the judge is and what task it is performing. This sets the frame for how the rest of the prompt should be interpreted. - -For example, many templates start by positioning the judge as an expert reviewer or evaluator for a specific task. This is followed by a clear description of what should be evaluated and what criteria should be applied. - -A good eval prompt acts as a rubric, not a question. It should narrowly define what counts as correct, relevant, or acceptable for your use case. Vague or open-ended instructions make judgments harder to reproduce across runs. - -In practice, this means: - -- Stating the evaluation task clearly -- Describing the criteria the judge should apply -- Avoiding subjective or underspecified language - -The goal is to remove ambiguity so the same output is judged the same way every time. - -## Defining the Data the Judge Sees - -After defining the evaluation criteria, the template presents the data to be evaluated. This section determines what information the judge receives and how it is structured. - -In most cases, the judge needs: - -- The **input** that produced the output (for example, a user query) -- The **output** being evaluated - -Some evaluations also require additional context, such as retrieved documents, reference material, or system instructions. This information should be included only when it is necessary for making a correct judgment. - -Inputs should be clearly labeled and consistently formatted. Many templates use a delimited block (for example, a `BEGIN DATA / END DATA` section) to make boundaries explicit and reduce ambiguity. - -## Choosing Evaluation Outputs - -Once the judge’s role, criteria, and inputs are defined, the final step is specifying what the evaluation should return. - -In Phoenix, most LLM-as-a-judge evals use **classification-style outputs**. These return a discrete label for each example, making results easy to compare, aggregate, and analyze across runs. - -Classification outputs work well when: - -- Outcomes can be expressed as a small set of categories -- Judgments must remain consistent across many examples -- Results will be used for filtering, comparisons, or experiments - -Common examples include: - -- `correct` / `incorrect` -- `relevant` / `irrelevant` -- `pass` / `fail` - -Other output formats are possible, but categorical labels tend to be the most stable and interpretable starting point. They also integrate cleanly with Phoenix’s tooling for logging, visualization, and comparison. - -## Best Practices for Eval Templates - -Eval templates are sensitive to wording. Small changes can significantly affect evaluation behavior, so templates should be written deliberately and kept focused. - -### Be explicit about criteria - -Avoid vague instructions such as “judge whether this is good” or “rate the quality.” Instead, specify exactly what the judge should evaluate and what should be ignored. If correctness depends on particular facts, constraints, or assumptions, include them directly in the template. - -Explicit criteria reduce ambiguity and improve consistency across runs. - -### Prefer categorical judgments - -For most evaluation tasks, categorical outcomes are more reliable than numeric scores. Labels such as `correct` / `incorrect` or `relevant` / `irrelevant` are easier for a judge to apply consistently and easier to interpret downstream. - -Numeric scoring introduces additional complexity by requiring the judge to reason about scale and relative magnitude. Numeric scores can be useful in limited cases, but only when each value has a clear, unambiguous definition. If numeric outputs are used, the template must explicitly describe what each score represents and how to choose between them. Without strict definitions, numeric scores tend to drift and become difficult to compare. - -## Example: A Complete Custom Eval Template - -The example below defines a classification-style eval template that determines whether an answer correctly addresses a user’s question. It follows the same structure described above. - -```python -from phoenix.evals import ClassificationEvaluator - -correctness_template = """ -You are an expert evaluator assessing whether an answer correctly addresses a user's question. - -Apply the following criteria: -- The answer must directly address the question. -- The answer must be factually consistent with the information provided. -- Irrelevant or partially correct answers should be marked as incorrect. - -[BEGIN DATA] -************ -[Question]: -{input} - -************ -[Answer]: -{output} -************ -[END DATA] - -Return only one of the following labels: -- correct -- incorrect -""" - -correctness_eval = ClassificationEvaluator( - name="correctness", - prompt_template=correctness_template, - choices={"incorrect": 0, "correct": 1}, -) -``` - -This template makes the evaluation logic explicit: - -- The judge’s role and task are clearly defined -- Evaluation criteria are stated upfront -- Inputs are structured and labeled -- Outputs are constrained to a fixed set of labels - -Because the template is explicit and focused, the same output is likely to be judged consistently across runs. This makes eval results easier to trust, compare, and iterate on. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx b/docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx deleted file mode 100644 index 27c4612cd28..00000000000 --- a/docs/phoenix/evaluation/tutorials/a/use-pre-build-eval-template.mdx +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: "Use Built-In Eval Templates" ---- - -## Why Do Eval Templates Matter? - -Eval templates define what you are evaluating and how that evaluation should be applied. They capture the criteria a judge model uses, the form of the result (such as a label or score), and the assumptions behind the judgment. Even with a well-configured judge model, an evaluation is only as good as its template. - -Templates also provide consistency. Without clearly defined criteria, the same output can be judged differently across runs, making results difficult to compare. The template ensures that every example is evaluated using the same rules. - -A helpful way to think about this is by analogy. If you ask an LLM to “write a story,” the result could be any genre. If you ask for a “short fairy tale with a clear moral,” the output becomes much more predictable. Eval templates work the same way: the more specific the criteria, the more reliable the evaluation. - -Phoenix includes built-in eval templates that encode common evaluation patterns and best practices, allowing you to get reliable signals without designing a rubric from scratch. - ---- - -## Built-In Eval Templates in Phoenix - -Phoenix includes a set of built-in eval templates that cover many common evaluation tasks, such as relevance, faithfulness, summarization quality, and toxicity. These templates are designed to be used as building blocks: they encode a clear evaluation rubric, a structured output format, and defaults that work well with LLM-as-a-judge workflows. - -The table below highlights some of the most commonly used built-in templates. Each template is designed for a specific evaluation goal and returns a well-defined output that can be logged, analyzed, and compared across runs. - -> **Note:**\ -> Built-in templates focus on providing a strong default. They are intentionally opinionated in how criteria are defined and how outputs are structured, which helps produce more consistent results out of the box. - -| | | | -| :----------------: | :-------------: | :-------------: | -| Faithfulness | Q&A Correctness | Frustration | -| Tool Selection | Tool Invocation | Code Generation | -| Document Relevance | SQL Generation | Summarization | - -## When to Use a Built-In Template - -Built-in eval templates are a good choice when: - -- You are evaluating a common task (for example, relevance or correctness) -- You want fast, reliable signal without designing a rubric from scratch -- You are early in iteration and want to establish a baseline - -These templates are especially useful for exploratory analysis, regression detection, and experiment comparisons, where consistency across many runs is more important than fine-grained customization. - -## How to Use a Built-In Template - -Using a built-in eval template follows the same workflow as any other Phoenix eval. You select the template that matches your evaluation goal, configure the judge model you want to use, and then run the evaluator on your data. - -Built-in templates are designed to work with standard Phoenix evaluator interfaces, so they can be run on datasets, dataframes, or trace-derived data in the same way as custom evaluators. This means you can introduce them into an existing evaluation workflow without changing how data is loaded or how results are logged. - -In practice, using a built-in template typically involves: - -- Choosing a template that matches the quality dimension you want to evaluate -- Providing or reusing a configured judge model -- Mapping your data fields to the inputs expected by the template -- Running the evaluation in batch and inspecting the resulting scores or labels - -The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: - -```python -from phoenix.evals import ClassificationEvaluator -from phoenix.evals.metrics import CorrectnessEvaluator - -# Create the evaluator -correctness_eval = CorrectnessEvaluator(llm=llm) - -# Inspect the evaluator's requirements -print(correctness_eval.describe()) -``` - -Once defined, this evaluator can be run on a dataframe or trace-derived dataset and logged to Phoenix like any other eval. Because the template returns structured outputs, its results can be compared across runs and combined with other evaluations. - -## When to Customize - -Built-in eval templates are designed to cover common evaluation patterns, but they are not intended to fit every use case. As your application evolves, you may need more control over how quality is defined and measured. - -Some common reasons to customize an eval include: - -- You need to evaluate application-specific behavior that is not captured by a generic rubric -- You want to enforce strict formatting, structural, or policy constraints -- You need to distinguish between multiple types of failure rather than a single pass/fail outcome -- You want to align eval behavior more closely with how humans review outputs in practice - -Built-in templates are still a good starting point in these cases. Many teams begin with a built-in template to establish a baseline, inspect failures in Phoenix, and then adapt the template into a custom evaluator. - -## What’s Next - -In the next section, we’ll walk through how to create a custom LLM as a Judge template and the best practices surround how to craft it, and how to create a resuable evaluator in Phoenix. \ No newline at end of file diff --git a/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx index cae36db6443..adeab739ca2 100644 --- a/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx +++ b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx @@ -15,9 +15,6 @@ Follow along with the following code assets: Companion Python project with runnable examples - -TODO: \ - --- ## How Custom Evaluators Work @@ -117,7 +114,7 @@ By making these criteria explicit, the resulting evaluation signal is more infor ## Create the Custom Evaluator -Once the template is defined, you can create a custom evaluator using any supported judge model. This example uses a custom OpenAI-compatible endpoint, but the same pattern applies regardless of where the model is hosted. +Once the template is defined, you can create a custom evaluator using any supported judge model. This example uses a built in, classic OpenAI LLM model, but you can use any judge model. @@ -125,11 +122,10 @@ Once the template is defined, you can create a custom evaluator using any suppor from phoenix.evals import ClassificationEvaluator from phoenix.evals.llm import LLM - custom_llm = LLM( + llm = LLM( provider="openai", - model="accounts/fireworks/models/qwen3-235b-a22b-instruct-2507", - base_url="https://api.fireworks.ai/inference/v1", - api_key=os.environ.get("FIREWORKS_API_KEY"), + model="gpt-4o", + client="openai", ) custom_correctness_evaluator = ClassificationEvaluator( @@ -143,13 +139,9 @@ Once the template is defined, you can create a custom evaluator using any suppor ```typescript import { createClassificationEvaluator } from "@arizeai/phoenix-evals"; - import { createOpenAI } from "@ai-sdk/openai"; - - const llm = createOpenAI({ - baseURL: "https://api.fireworks.ai/inference/v1", - apiKey: process.env.FIREWORKS_API_KEY, - }).chat(FIREWORKS_MODEL); + import { openai } from "@ai-sdk/openai"; + const base_model = openai("gpt-4o-mini"); const EVAL_NAME = "custom_correctness"; const evaluator = createClassificationEvaluator({ model: llm as Parameters[0]["model"], diff --git a/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx b/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx index 88997bf8aaa..4cec78eccda 100644 --- a/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx +++ b/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint.mdx @@ -28,8 +28,6 @@ Follow along with the following code assets: -TODO: \ - --- ## Using Custom or OpenAI-Compatible Judge Models @@ -109,143 +107,10 @@ Once defined, built-in evaluators can be run on tabular data or trace-derived ex ## Running Evals on Phoenix Traces -With a judge model and evaluator defined, the workflow for running evals on real application data is unchanged. - -A common pattern is evaluating traced executions and attaching results back to spans in Phoenix. - -**1. Export trace spans** - -Start by exporting spans from a Phoenix project into a tabular structure: - - - - ```python - from phoenix.client import Client - - client = Client() - spans_df = client.spans.get_spans_dataframe(project_identifier="agno_travel_agent") - agent_spans = spans_df[spans_df['span_kind'] == 'AGENT'] - agent_spans - ``` - - - ```typescript - import { getSpans } from "@arizeai/phoenix-client/spans"; - - const projectName = - process.env.PHOENIX_PROJECT_NAME || "langchain-travel-agent"; - const { spans } = await getSpans({ project: { projectName }, limit: 500 }); - ``` - - -Each row represents a span and includes identifiers and attributes captured during execution. - -**2. Prepare Evaluator Inputs** -Next, select or transform fields from the exported spans so they match the evaluator’s expected inputs. This often involves extracting nested attributes such as: - -Ex. `attributes.input.value` & `attributes.output.value` - -Input mappings help bridge differences between how data is stored in traces and what evaluators expect. - - - - ```python - from phoenix.evals import bind_evaluator - - bound_evaluator = bind_evaluator( - evaluator=correctness_eval, - input_mapping={ - "input": "attributes.input.value", - "output": "attributes.output.value", - } - ) - ``` - - - We may need to manipulate the data a little bit here to make it easier to pass into the evaluator. We can first define some helper functions. - ```typescript - const toStr = (v: unknown) => - typeof v === "string" ? v : v != null ? JSON.stringify(v) : null; - - function getInputOutput(span: any) { - const attrs = span.attributes ?? {}; - const input = toStr(attrs["input.value"] ?? attrs["input"]); - const output = toStr(attrs["output.value"] ?? attrs["output"]); - return { input, output }; - } - - const parentSpans: { spanId: string; input: string; output: string }[] = []; - for (const s of spans) { - const name = (s as any).name ?? (s as any).span_name; - if (name !== "LangGraph") continue; - const { input, output } = getInputOutput(s); - const spanId = - (s as any).context?.span_id ?? (s as any).span_id ?? (s as any).id; - if (input && output && spanId) { - parentSpans.push({ spanId: String(spanId), input, output }); - } - } - ``` - - - -**3. Run evals on the prepared data** - -Once the evaluation dataframe is prepared, you can run evals in batch using the same APIs used for any tabular data. - - - - ```python - from phoenix.evals import evaluate_dataframe - from phoenix.trace import suppress_tracing - with suppress_tracing(): - results_df = evaluate_dataframe(agent_spans, [bound_evaluator]) - ``` - - - ```typescript - const spanAnnotations = await Promise.all( - parentSpans.map(async ({ spanId, input, output }) => { - const r = await evaluator.evaluate({ input, output }); - console.log(r.explanation); - return { - spanId, - name: "correctness" as const, - label: r.label, - score: r.score, - explanation: r.explanation ?? undefined, - annotatorKind: "LLM" as const, - metadata: { evaluator: "correctness", input, output }, - }; - }), - ); - ``` - - - -**4. Log results back to Phoenix** +The workflow is the same as on [the previous page](/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals#running-evals-on-phoenix-traces): export spans, prepare evaluator inputs, run evals, and log results back to Phoenix. Only the judge model configuration changes; the steps for running evals on traced data are unchanged. -Finally, log evaluation results back to Phoenix as span annotations. Phoenix uses span identifiers to associate eval outputs with the correct execution. - - - ```python - from phoenix.evals.utils import to_annotation_dataframe - - evaluations = to_annotation_dataframe(dataframe=results_df) - Client().spans.log_span_annotations_dataframe(dataframe=evaluations) - ``` - - - ```typescript - import { logSpanAnnotations } from "@arizeai/phoenix-client/spans"; - - await logSpanAnnotations({ spanAnnotations, sync: true }); - ``` - - -Once logged, eval results appear alongside traces in the Phoenix UI, making it possible to analyze execution behavior and quality together. +--- ---- ## **Best Practices for Judge Models** Judge models are not user-facing. Their role is to apply a rubric consistently, not to generate creative or varied responses. When configuring a judge model, prioritize stability and repeatability over expressiveness. diff --git a/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx b/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx index 473c420b4f3..56200b7689f 100644 --- a/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx +++ b/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals.mdx @@ -2,7 +2,7 @@ title: "Run Evals With Built-In Eval Templates" --- -This guide walks through how to run evaluations using Phoenix’s built-in eval templates. You’ll configure a judge model, select a pre-built evaluation, and run it on real data—specifically, data derived from Phoenix traces. +This guide is part of a sequence: it starts with built-in eval templates, then moves to customizing the judge model, then to defining your own evaluation criteria. Here you configure a judge model, select a pre-built evaluation, and run it on real data—specifically, data derived from Phoenix traces. The goal is to go from traced application executions to structured quality signals that can be inspected, compared, and logged back to Phoenix. This guide assumes you already have tracing in place and focuses on using evals to measure correctness and behavior. @@ -29,12 +29,10 @@ Follow along with the following code assets: -TODO: \ - --- ## Configure Core LLM Setup -Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. +Evals need an LLM to act as the judge—the model that applies the rubric to your data. Configuring that judge is the first step. Phoenix Evals is provider-agnostic. You can run evaluations using any supported LLM provider without changing how your evaluators are written. Across both the Python and TypeScript evals libraries, a judge model is represented as a reusable configuration object. This object describes how Phoenix connects to a model provider, including the provider name, model identifier, credentials, and any SDK-specific client configuration. @@ -72,8 +70,6 @@ You can find all [built in templates](https://arize.com/docs/phoenix/evaluation/ Built-in templates are a good choice when you want reliable signal quickly without designing a rubric from scratch, especially early in iteration or when establishing a baseline. -The example below shows how to instantiate a built-in Correctness eval template using a configured judge model: - The example below shows a minimal setup using the built-in Correctness eval template with a configured judge model: @@ -98,7 +94,7 @@ Once defined, built-in evaluators can be run on tabular data or trace-derived ex ## Running Evals on Phoenix Traces -With a judge model and evaluator defined, the next step is running evals on real application data. A common workflow is evaluating traced executions and attaching results back to spans in Phoenix. +With a judge model and evaluator defined, the next step is running evals on real application data. A common workflow is evaluating traced executions and attaching results back to spans in Phoenix. Once attached, you can inspect failures and edge cases in the UI, compare behavior across runs, and use eval results as inputs to datasets and experiments. **1. Export trace spans** diff --git a/tutorials/quickstarts/agno_agent_for_evals.ipynb b/tutorials/quickstarts/agno_agent_for_evals.ipynb index c26acc3cc04..879db93b68b 100644 --- a/tutorials/quickstarts/agno_agent_for_evals.ipynb +++ b/tutorials/quickstarts/agno_agent_for_evals.ipynb @@ -867,7 +867,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -875,7 +875,7 @@ "\n", "custom_correctness_evaluator = ClassificationEvaluator(\n", " name = \"custom_correctness\",\n", - " llm = custom_llm,\n", + " llm = llm,\n", " prompt_template=CUSTOM_CORRECTNESS_TEMPLATE,\n", " choices={\"correct\": 1, \"incorrect\": 0}\n", ")" diff --git a/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts b/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts index 35fd169d8f1..605e58c8161 100644 --- a/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts +++ b/tutorials/quickstarts/langchain-ts-quickstart/src/custom_evals.ts @@ -1,14 +1,12 @@ import "dotenv/config"; import { createClassificationEvaluator } from "@arizeai/phoenix-evals"; -import { createOpenAI } from "@ai-sdk/openai"; +import { openai } from "@ai-sdk/openai"; import { getSpans, logSpanAnnotations } from "@arizeai/phoenix-client/spans"; const EVAL_NAME = "custom_correctness"; const AGENT_SPAN_NAME = "LangGraph"; const PROJECT_NAME = process.env.PHOENIX_PROJECT_NAME ?? "langchain-travel-agent"; -const FIREWORKS_MODEL = - "accounts/fireworks/models/qwen3-235b-a22b-instruct-2507"; const correctnessTemplate = ` You are an expert evaluator judging whether a travel planner agent's response is correct. The agent is a friendly travel planner that must combine multiple tools to create a trip plan with: (1) essential info, (2) budget breakdown, and (3) local flavor/experiences. @@ -74,13 +72,12 @@ function getSpanId(span: SpanLike): string | null { } async function main() { - const llm = createOpenAI({ - baseURL: "https://api.fireworks.ai/inference/v1", - apiKey: process.env.FIREWORKS_API_KEY, - }).chat(FIREWORKS_MODEL); + const base_model = openai("gpt-4o-mini"); const evaluator = createClassificationEvaluator({ - model: llm as Parameters[0]["model"], + model: base_model as Parameters< + typeof createClassificationEvaluator + >[0]["model"], promptTemplate: correctnessTemplate, choices: { correct: 1, incorrect: 0 }, name: EVAL_NAME, From 7763835bf92ecfffc76c1fe024e51d404f233e1b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 5 Feb 2026 02:57:46 +0000 Subject: [PATCH 6/8] chore: update sitemap.xml --- docs/phoenix/sitemap.xml | 92 ++++++++++++++++++---------------------- sitemap.xml | 92 ++++++++++++++++++---------------------- 2 files changed, 84 insertions(+), 100 deletions(-) diff --git a/docs/phoenix/sitemap.xml b/docs/phoenix/sitemap.xml index 4548a0f044c..326de0618ae 100644 --- a/docs/phoenix/sitemap.xml +++ b/docs/phoenix/sitemap.xml @@ -173,28 +173,16 @@ 2026-01-27T22:36:31+00:00
- https://arize.com/docs/phoenix/evaluation/tutorials/configure-your-llm - 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template - 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/tutorials/use-custom-eval-template - 2026-01-30T17:01:41+00:00 - - - https://arize.com/docs/phoenix/evaluation/tutorials/run-your-evals - 2026-01-30T17:01:41+00:00 - - - https://arize.com/docs/phoenix/evaluation/typescript-quickstart - 2026-01-27T22:36:31+00:00 - - - https://arize.com/docs/phoenix/evaluation/python-quickstart - 2026-01-27T22:36:31+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/customize-eval-template + 2026-02-05T02:57:46+00:00 https://arize.com/docs/phoenix/evaluation/llm-evals @@ -237,68 +225,72 @@ 2026-01-27T22:36:31+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals + 2026-02-05T02:57:46+00:00 + + + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/code-metrics + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/faithfulness - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/faithfulness + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/correctness - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/q-and-a-on-retrieved-data + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/document-relevance - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/retrieval-rag-relevance + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-selection - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/summarization-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-invocation - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/code-generation-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/hallucination - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/toxicity + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/exact-match - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/ai-vs-human-groundtruth + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/matches-regex - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/reference-link-evals + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/precision-recall-fscore - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/user-frustration + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/q-and-a-on-retrieved-data - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/sql-generation-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/retrieval-rag-relevance - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/tool-calling-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/summarization-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-path-convergence + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/toxicity - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-planning + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/sql-generation-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-reflection + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-calling-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/audio-emotion-detection + 2026-02-05T02:57:46+00:00 https://arize.com/docs/phoenix/datasets-and-experiments/tutorial/defining-the-dataset diff --git a/sitemap.xml b/sitemap.xml index 4548a0f044c..326de0618ae 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -173,28 +173,16 @@ 2026-01-27T22:36:31+00:00 - https://arize.com/docs/phoenix/evaluation/tutorials/configure-your-llm - 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/run-evals-with-built-in-evals + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/tutorials/use-pre-build-eval-template - 2026-01-30T17:01:41+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/customize-your-llm-endpoint + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/tutorials/use-custom-eval-template - 2026-01-30T17:01:41+00:00 - - - https://arize.com/docs/phoenix/evaluation/tutorials/run-your-evals - 2026-01-30T17:01:41+00:00 - - - https://arize.com/docs/phoenix/evaluation/typescript-quickstart - 2026-01-27T22:36:31+00:00 - - - https://arize.com/docs/phoenix/evaluation/python-quickstart - 2026-01-27T22:36:31+00:00 + https://arize.com/docs/phoenix/evaluation/tutorials/customize-eval-template + 2026-02-05T02:57:46+00:00 https://arize.com/docs/phoenix/evaluation/llm-evals @@ -237,68 +225,72 @@ 2026-01-27T22:36:31+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals + 2026-02-05T02:57:46+00:00 + + + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/code-metrics + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/faithfulness - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/faithfulness + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/correctness - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/q-and-a-on-retrieved-data + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/document-relevance - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/retrieval-rag-relevance + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-selection - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/summarization-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-invocation - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/code-generation-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/hallucination - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/toxicity + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/exact-match - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/ai-vs-human-groundtruth + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/matches-regex - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/reference-link-evals + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/precision-recall-fscore - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/user-frustration + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/q-and-a-on-retrieved-data - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/sql-generation-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/retrieval-rag-relevance - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/tool-calling-eval + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/summarization-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-path-convergence + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/toxicity - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-planning + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/sql-generation-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/agent-reflection + 2026-02-05T02:57:46+00:00 - https://arize.com/docs/phoenix/evaluation/pre-built-metrics/tool-calling-eval - 2026-01-29T22:42:03+00:00 + https://arize.com/docs/phoenix/evaluation/running-pre-tested-evals/audio-emotion-detection + 2026-02-05T02:57:46+00:00 https://arize.com/docs/phoenix/datasets-and-experiments/tutorial/defining-the-dataset From e1a4c835a135411051cf04be57468213a34833f8 Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Wed, 4 Feb 2026 19:31:15 -0800 Subject: [PATCH 7/8] clean notebook --- .../tutorials/customize-eval-template.mdx | 4 +- .../quickstarts/agno_agent_for_evals.ipynb | 1578 ++++++----------- 2 files changed, 562 insertions(+), 1020 deletions(-) diff --git a/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx index adeab739ca2..8142b54d320 100644 --- a/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx +++ b/docs/phoenix/evaluation/tutorials/customize-eval-template.mdx @@ -130,7 +130,7 @@ Once the template is defined, you can create a custom evaluator using any suppor custom_correctness_evaluator = ClassificationEvaluator( name = "custom_correctness", - llm = custom_llm, + llm = llm, prompt_template=CUSTOM_CORRECTNESS_TEMPLATE, choices={"correct": 1, "incorrect": 0} ) @@ -144,7 +144,7 @@ Once the template is defined, you can create a custom evaluator using any suppor const base_model = openai("gpt-4o-mini"); const EVAL_NAME = "custom_correctness"; const evaluator = createClassificationEvaluator({ - model: llm as Parameters[0]["model"], + model: base_model as Parameters[0]["model"], promptTemplate: correctnessTemplate, choices: { correct: 1, incorrect: 0 }, name: EVAL_NAME, diff --git a/tutorials/quickstarts/agno_agent_for_evals.ipynb b/tutorials/quickstarts/agno_agent_for_evals.ipynb index 879db93b68b..b1b68d0c471 100644 --- a/tutorials/quickstarts/agno_agent_for_evals.ipynb +++ b/tutorials/quickstarts/agno_agent_for_evals.ipynb @@ -1,1020 +1,562 @@ { - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "id": "zw-BimTKswh4" - }, - "source": [ - "
\n", - "

\n", - " \"phoenix\n", - "
\n", - " Docs\n", - " |\n", - " GitHub\n", - " |\n", - " Community\n", - "

\n", - "
\n", - "

Agno Travel Agent Tracing Project

" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "l8EbE_41szw0" - }, - "source": [ - "We will create a simple travel agent powered by the Agno framework and OpenAI models. We’ll begin by installing the necessary OpenInference packages and setting up tracing with Arize.\n", - "\n", - "Next, we’ll define a set of basic tools that provide destination information, estimate trip budgets, and suggest local activities.\n", - "\n", - "For this base agent, we’ll build and run our agent, viewing the resulting trace outputs in Phoenix to understand how the agent uses its tools and reasoning.\n", - "\n", - "We'll then follow along through the Evals Tutorials:\n", - "- Configure a core LLM & run a built in eval \n", - "- Configure a custom endpoint LLM \n", - "- Create a custom eval \n", - "- Code Evals" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Gxe7vsT9hKHX" - }, - "source": [ - "You will need to install Arize Phoenix in your terminal (`pip install arize-phoenix`) an OpenAI API key, and a free [Tavily](https://auth.tavily.com/) API Key.\n", - "\n", - "Ensure you have `phoenix serve` running in your terminal prior to running the following cells. " - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "HzvQoYIksr30" - }, - "source": [ - "## Set up keys and dependenies" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "1XtfV7qF6HKg", - "outputId": "70de22d9-591e-4b47-ca33-209070dac3a1" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install -qqqqqq arize-phoenix-otel arize-phoenix-evals agno openai openinference-instrumentation-agno openinference-instrumentation-openai httpx" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "hAapTFAi-35H", - "outputId": "1df61df2-4291-4c4e-b4f2-59fb78970eda" - }, - "outputs": [], - "source": [ - "import os\n", - "from getpass import getpass\n", - "\n", - "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\"🔑 Enter your OpenAI API Key: \")\n", - "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\"🔑 Enter your Tavily API Key: \")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "AFdPHLMFuEsl" - }, - "source": [ - "## Setup tracing" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/" - }, - "id": "Y8dSorscJDPT", - "outputId": "957bb02a-3faa-4002-ce19-2ab2cf9fa077" - }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/Library/Frameworks/Python.framework/Versions/3.13/lib/python3.13/site-packages/pydantic/_internal/_generate_schema.py:2249: UnsupportedFieldAttributeWarning: The 'validate_default' attribute with value True was provided to the `Field()` function, which has no effect in the context it was used. 'validate_default' is field-specific metadata, and can only be attached to a model field using `Annotated` metadata or by assignment. This may have happened because an `Annotated` type alias using the `type` statement was used, or if the `Field()` function was attached to a single member of a union type.\n", - " warnings.warn(\n", - "Overriding of current TracerProvider is not allowed\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "🔭 OpenTelemetry Tracing Details 🔭\n", - "| Phoenix Project: agno_travel_agent\n", - "| Span Processor: SimpleSpanProcessor\n", - "| Collector Endpoint: localhost:4317\n", - "| Transport: gRPC\n", - "| Transport Headers: {'user-agent': '****'}\n", - "| \n", - "| Using a default SpanProcessor. `add_span_processor` will overwrite this default.\n", - "| \n", - "| ⚠️ WARNING: It is strongly advised to use a BatchSpanProcessor in production environments.\n", - "| \n", - "| `register` has set this TracerProvider as the global OpenTelemetry default.\n", - "| To disable this behavior, call `register` with `set_global_tracer_provider=False`.\n", - "\n" - ] - } - ], - "source": [ - "from phoenix.otel import register\n", - "\n", - "tracer_provider = register(project_name=\"agno_travel_agent\", auto_instrument=True)" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "Gjd7wU9OuIAQ" - }, - "source": [ - "## Define tools" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "mnRbOa8tg_B7" - }, - "source": [ - "First, we’ll define a few helper functions to support our tools. In particular, we’ll use Tavily Search to help the tools gather general information about each destination." - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 211 - }, - "id": "H3gLnYV2_KhS", - "outputId": "d24cc345-4cf7-43c3-da38-3f6fc3876ac9" - }, - "outputs": [], - "source": [ - "# --- Helper functions for tools ---\n", - "import httpx\n", - "\n", - "def _search_api(query: str) -> str | None:\n", - " \"\"\"Try Tavily search first, fall back to None.\"\"\"\n", - " tavily_key = os.getenv(\"TAVILY_API_KEY\")\n", - " if not tavily_key:\n", - " return None\n", - " try:\n", - " resp = httpx.post(\n", - " \"https://api.tavily.com/search\",\n", - " json={\n", - " \"api_key\": tavily_key,\n", - " \"query\": query,\n", - " \"max_results\": 3,\n", - " \"search_depth\": \"basic\",\n", - " \"include_answer\": True,\n", - " },\n", - " timeout=8,\n", - " )\n", - " data = resp.json()\n", - " answer = data.get(\"answer\") or \"\"\n", - " snippets = [r.get(\"content\", \"\") for r in data.get(\"results\", [])]\n", - " combined = \" \".join([answer] + snippets).strip()\n", - " return combined[:400] if combined else None\n", - " except Exception:\n", - " return None\n", - "\n", - "\n", - "def _compact(text: str, limit: int = 200) -> str:\n", - " \"\"\"Compact text for cleaner outputs.\"\"\"\n", - " cleaned = \" \".join(text.split())\n", - " return cleaned if len(cleaned) <= limit else cleaned[:limit].rsplit(\" \", 1)[0]\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "B4fxzijBgLG5" - }, - "source": [ - "Our agent will have access to three tools, which we’ll continue to enhance in upcoming labs:\n", - "\n", - "1. Essential Info – Provides key travel details about the destination, such as weather and general conditions.\n", - "\n", - "2. Budget Basics – Offers insights into travel costs and helps plan budgets based on selected activities.\n", - "\n", - "3. Local Flavor – Recommends unique local experiences and cultural highlights." - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": { - "id": "tNgVS4Fk_QRR" - }, - "outputs": [], - "source": [ - "from agno.tools import tool\n", - "\n", - "@tool\n", - "def essential_info(destination: str) -> str:\n", - " \"\"\"Get basic travel info (weather, best time, attractions, etiquette).\"\"\"\n", - " q = f\"{destination} travel essentials weather best time top attractions etiquette\"\n", - " s = _search_api(q)\n", - " if s:\n", - " return f\"{destination} essentials: {_compact(s)}\"\n", - "\n", - " return f\"{destination} is a popular travel destination. Expect local culture, cuisine, and landmarks worth exploring.\"\n", - "\n", - "@tool\n", - "def budget_basics(destination: str, duration: str) -> str:\n", - " \"\"\"Summarize travel cost categories.\"\"\"\n", - " q = f\"{destination} travel budget average daily costs {duration}\"\n", - " s = _search_api(q)\n", - " if s:\n", - " return f\"{destination} budget ({duration}): {_compact(s)}\"\n", - " return f\"Budget for {duration} in {destination} depends on lodging, meals, transport, and attractions.\"\n", - "\n", - "@tool\n", - "def local_flavor(destination: str, interests: str = \"local culture\") -> str:\n", - " \"\"\"Suggest authentic local experiences.\"\"\"\n", - " q = f\"{destination} authentic local experiences {interests}\"\n", - " s = _search_api(q)\n", - " if s:\n", - " return f\"{destination} {interests}: {_compact(s)}\"\n", - " return f\"Explore {destination}'s unique {interests} through markets, neighborhoods, and local eateries.\"\n" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "o48IXEMJuJuI" - }, - "source": [ - "## Define agent" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "0hCYAqOShX-c" - }, - "source": [ - "Next, we’ll construct our agent. The Agno framework makes this process straightforward by allowing us to easily define key parameters such as the model, instructions, and tools." - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": { - "id": "Sb1jqHcU_R3r" - }, - "outputs": [], - "source": [ - "from agno.agent import Agent\n", - "from agno.models.openai import OpenAIChat\n", - "\n", - "trip_agent = Agent(\n", - " name=\"TripPlanner\",\n", - " role=\"AI Travel Assistant\",\n", - " model=OpenAIChat(id=\"gpt-4.1\"),\n", - " instructions=(\n", - " \"You are a friendly and knowledgeable travel planner. \"\n", - " \"Combine multiple tools to create a trip plan including essentials, budget, and local flavor. \"\n", - " \"Keep the tone natural, clear, and under 1000 words.\"\n", - " ),\n", - " markdown=True,\n", - " tools=[essential_info, budget_basics, local_flavor],\n", - ")" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "HAKB1WBwuLh2" - }, - "source": [ - "## Run agent" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "id": "I6ZbhUKghmtG" - }, - "source": [ - "Finally, we are ready to run our agent! Run this cell to see an example in action." - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "metadata": { - "colab": { - "base_uri": "https://localhost:8080/", - "height": 1000, - "referenced_widgets": [ - "9b9ebc48bdad4ef78068eff7a43c6b9e", - "0c6e8d6fc75d43b9ae44f1c066b49d77" - ] - }, - "id": "FVDKZT9x_U-5", - "outputId": "5aad5802-b2d3-4d89-b692-d937839350c4" - }, - "outputs": [ - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "b27ab0afe69b4c54ab2bba38779be681", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Output()" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "
\n"
-            ],
-            "text/plain": []
-          },
-          "metadata": {},
-          "output_type": "display_data"
-        }
-      ],
-      "source": [
-        "# --- Example usage ---\n",
-        "destination = \"Tokyo\"\n",
-        "duration = \"5 days\"\n",
-        "interests = \"food, culture\"\n",
-        "\n",
-        "query = f\"\"\"\n",
-        "Plan a {duration} trip to {destination}.\n",
-        "Focus on {interests}.\n",
-        "Include essential info, budget breakdown, and local experiences.\n",
-        "\"\"\"\n",
-        "trip_agent.print_response(\n",
-        "    query,\n",
-        "    stream = True\n",
-        ")"
-      ]
-    },
-    {
-      "cell_type": "code",
-      "execution_count": null,
-      "metadata": {},
-      "outputs": [
-        {
-          "data": {
-            "text/html": [
-              "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
namespan_kindparent_idstart_timeend_timestatus_codestatus_messageeventscontext.span_idcontext.trace_id...attributes.output.mime_typeattributes.llm.token_count.totalattributes.output.valueattributes.tool.descriptionattributes.tool.nameattributes.tool.parametersattributes.session.idattributes.graph.node.nameattributes.agnoattributes.graph.node.id
context.span_id
6ec80092737e54a4TripPlanner.runAGENTNaN2026-02-04 06:49:47.181465+00:002026-02-04 06:50:10.894976+00:00OK[]6ec80092737e54a492f134d5833282173f151500da1a1920...application/jsonNaN# 5-Day Food & Culture Trip to Tokyo\\n\\n## Ess...NaNNaNNone4fde62a2-cbd0-4e26-bb1c-65ac55a70e83TripPlanner{'agent': 'TripPlanner', 'tools': ['essential_...f31cc21c20c9bef2
\n", - "

1 rows × 32 columns

\n", - "
" - ], - "text/plain": [ - " name span_kind parent_id \\\n", - "context.span_id \n", - "6ec80092737e54a4 TripPlanner.run AGENT NaN \n", - "\n", - " start_time \\\n", - "context.span_id \n", - "6ec80092737e54a4 2026-02-04 06:49:47.181465+00:00 \n", - "\n", - " end_time status_code status_message \\\n", - "context.span_id \n", - "6ec80092737e54a4 2026-02-04 06:50:10.894976+00:00 OK \n", - "\n", - " events context.span_id context.trace_id \\\n", - "context.span_id \n", - "6ec80092737e54a4 [] 6ec80092737e54a4 92f134d5833282173f151500da1a1920 \n", - "\n", - " ... attributes.output.mime_type \\\n", - "context.span_id ... \n", - "6ec80092737e54a4 ... application/json \n", - "\n", - " attributes.llm.token_count.total \\\n", - "context.span_id \n", - "6ec80092737e54a4 NaN \n", - "\n", - " attributes.output.value \\\n", - "context.span_id \n", - "6ec80092737e54a4 # 5-Day Food & Culture Trip to Tokyo\\n\\n## Ess... \n", - "\n", - " attributes.tool.description attributes.tool.name \\\n", - "context.span_id \n", - "6ec80092737e54a4 NaN NaN \n", - "\n", - " attributes.tool.parameters \\\n", - "context.span_id \n", - "6ec80092737e54a4 None \n", - "\n", - " attributes.session.id \\\n", - "context.span_id \n", - "6ec80092737e54a4 4fde62a2-cbd0-4e26-bb1c-65ac55a70e83 \n", - "\n", - " attributes.graph.node.name \\\n", - "context.span_id \n", - "6ec80092737e54a4 TripPlanner \n", - "\n", - " attributes.agno \\\n", - "context.span_id \n", - "6ec80092737e54a4 {'agent': 'TripPlanner', 'tools': ['essential_... \n", - "\n", - " attributes.graph.node.id \n", - "context.span_id \n", - "6ec80092737e54a4 f31cc21c20c9bef2 \n", - "\n", - "[1 rows x 32 columns]" - ] - }, - "execution_count": null, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "from phoenix.client import Client\n", - "\n", - "client = Client()\n", - "spans_df = client.spans.get_spans_dataframe(project_identifier=\"agno_travel_agent\")\n", - "agent_spans = spans_df[spans_df['span_kind'] == 'AGENT']\n", - "agent_spans" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "agent_spans['attributes.output.value', 'attributes.input.value']" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Run evals with built-in eval templates & an OpenAI Model\n", - "\n", - "Let's first use a classic config for our LLM & built in template for our first eval. " - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "metadata": {}, - "outputs": [], - "source": [ - "from phoenix.evals.llm import LLM\n", - "\n", - "llm = LLM(\n", - " provider=\"openai\",\n", - " model=\"gpt-4o\",\n", - " client=\"openai\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'name': 'correctness', 'kind': 'llm', 'direction': 'maximize', 'input_schema': {'properties': {'input': {'description': 'The input query or question.', 'title': 'Input', 'type': 'string'}, 'output': {'description': 'The response to evaluate for correctness.', 'title': 'Output', 'type': 'string'}}, 'required': ['input', 'output'], 'title': 'CorrectnessInputSchema', 'type': 'object'}}\n" - ] - } - ], - "source": [ - "from phoenix.evals.metrics import CorrectnessEvaluator\n", - "\n", - "correctness_eval = CorrectnessEvaluator(llm=llm)\n", - "\n", - "print(correctness_eval.describe())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/var/folders/gg/2586gdl96294y9xs_3j3l7t00000gp/T/ipykernel_93648/1692309769.py:15: DeprecationWarning: Positional arguments for evaluate_dataframe are deprecated and will be removed in a future version. Please use keyword arguments instead.\n", - " result = evaluate_dataframe(agent_spans, [bound_evaluator])\n" - ] - }, - { - "data": { - "application/vnd.jupyter.widget-view+json": { - "model_id": "6f50d9e705db465a880c6d654300127b", - "version_major": 2, - "version_minor": 0 - }, - "text/plain": [ - "Evaluating Dataframe | | 0/1 (0.0%) | ⏳ 00:00▰▱▱▱▱▱▱ Thinking...\n┏━ Message ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n \n \n Plan a 5 days trip to Tokyo. \n Focus on food, culture. \n Include essential info, budget breakdown, and local experiences. \n \n \n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n┏━ Response (17.6s) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n \n ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \n5-Day Tokyo Trip: Food & Culture Focus\n ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ \n \n \n Essential Info \n \n Best Time to Visit: November is ideal—mild weather and autumn foliage. \n Key Attractions: Meiji Shrine, Senso-ji Temple, Ueno Park, teamLab Borderless, Tsukiji Market, Shibuya & \n Harajuku. \n Etiquette Tips: Bow as a greeting, speak quietly on public transport, remove shoes in homes and some \n restaurants, and avoid eating while walking. \n Getting Around: Efficient subways & trains; get a prepaid Suica/Pasmo card for convenience. \n \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n \n Budget Breakdown (5 Days, Per Person) \n \n \n Category Estimated Range \n ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \n Accommodation $60 – $300/night \n Food $30 – $100/day \n Local Transit $7 – $15/day \n Activities $20 – $100/day \n Total $650 – $1800 \n \n \n Budget stays (hostels/capsules) vs. mid-range (business hotels) account for cost spread. Splurges (Michelin \n meals, private tours) will increase this. \n Cash is widely used, but credit cards are accepted in many places. \n \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n \n Authentic Local Experiences \n \n Food \n \n Try an omakase sushi dinner in Tsukiji or Ginza. \n Join a Japanese cooking class—learn to make ramen or wagashi (sweets). \n Hop izakayas in Shinjuku’s Omoide Yokocho and Golden Gai. \n Savor street food at Ameya-Yokocho (Ueno) or Takeshita Street (Harajuku). \n \n Culture \n \n Experience a traditional tea ceremony in Asakusa. \n Visit the Edo-Tokyo Museum or Nezu Museum for art and history. \n Explore Yanaka for old Tokyo vibes and crafts. \n See Meiji Shrine (walk through Yoyogi Park), and Senso-ji (Asakusa's iconic temple). \n \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n \n Sample 5-Day Itinerary \n \n Day 1: Historic Asakusa & Ueno \n \n Senso-ji Temple, Nakamise Street snacks, Ameya-Yokocho Market \n Ueno Park (museums if interested) \n \n Day 2: Shibuya & Harajuku Youth Culture \n \n Scramble crossing, Hachiko Statue \n Takeshita Street crepes, quirky shops \n Meiji Shrine, Yoyogi Park \n \n Day 3: Foodie Focus in Tsukiji & Ginza \n \n Fresh sushi breakfast/lunch at Tsukiji Market \n Cooking class nearby \n Stroll luxury flagship stores and Kabuki-za Theatre in Ginza \n \n Day 4: Day Trip or Museums \n \n Edo-Tokyo Museum, teamLab Planets/Borderless, or Ghibli Museum (advance booking) \n Explore old neighborhoods in Yanaka \n \n Day 5: Nightlife & Izakayas \n \n Shinjuku: Omoide Yokocho (tiny bars, yakitori) \n Golden Gai for drinks and late-night bites \n Late walk in illuminated Shinjuku/Kabukicho \n \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n \n Quick Tips \n \n Reserve popular restaurants/tours early: They fill up fast! \n Cash is king for small eats & market stalls. \n Transportation: Use Google Maps or a transit app for trains. \n \n ─────────────────────────────────────────────────────────────────────────────────────────────────────────────── \n Enjoy the rhythm of Tokyo—blend tradition and trend, and bring an appetite! If you’d like more specifics \n (restaurant recs, booking links), let me know! \n \n┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n\n", - "text/plain": "\u001b[32m▰▱▱▱▱▱▱\u001b[0m Thinking...\n\u001b[36m┏━\u001b[0m\u001b[36m Message \u001b[0m\u001b[36m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[36m━┓\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mPlan a 5 days trip to Tokyo.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mFocus on food, culture.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[32mInclude essential info, budget breakdown, and local experiences.\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┃\u001b[0m \u001b[36m┃\u001b[0m\n\u001b[36m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n\u001b[34m┏━\u001b[0m\u001b[34m Response (17.6s) \u001b[0m\u001b[34m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[34m━┓\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┃ \u001b[1m5-Day Tokyo Trip: Food & Culture Focus\u001b[0m ┃ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mEssential Info\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mBest Time to Visit\u001b[0m: November is ideal—mild weather and autumn foliage. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mKey Attractions\u001b[0m: Meiji Shrine, Senso-ji Temple, Ueno Park, teamLab Borderless, Tsukiji Market, Shibuya & \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mHarajuku. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mEtiquette Tips\u001b[0m: Bow as a greeting, speak quietly on public transport, remove shoes in homes and some \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mrestaurants, and avoid eating while walking. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mGetting Around\u001b[0m: Efficient subways & trains; get a prepaid Suica/Pasmo card for convenience. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mBudget Breakdown (5 Days, Per Person)\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1m \u001b[0m\u001b[1mCategory\u001b[0m\u001b[1m \u001b[0m\u001b[1m \u001b[0m \u001b[1m \u001b[0m\u001b[1m Estimated Range\u001b[0m\u001b[1m \u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Accommodation $60 – $300/night \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Food $30 – $100/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Local Transit $7 – $15/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Activities $20 – $100/day \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mTotal\u001b[0m \u001b[1m$650 – $1800\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mBudget stays\u001b[0m (hostels/capsules) vs. mid-range (business hotels) account for cost spread. Splurges (Michelin \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m \u001b[0mmeals, private tours) will increase this. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mCash is widely used, but credit cards are accepted in many places. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mAuthentic Local Experiences\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mFood\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mTry an omakase sushi dinner in Tsukiji or Ginza. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mJoin a Japanese cooking class—learn to make ramen or wagashi (sweets). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mHop izakayas in Shinjuku’s Omoide Yokocho and Golden Gai. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSavor street food at Ameya-Yokocho (Ueno) or Takeshita Street (Harajuku). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mCulture\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExperience a traditional tea ceremony in Asakusa. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mVisit the Edo-Tokyo Museum or Nezu Museum for art and history. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExplore Yanaka for old Tokyo vibes and crafts. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSee Meiji Shrine (walk through Yoyogi Park), and Senso-ji (Asakusa's iconic temple). \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mSample 5-Day Itinerary\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 1: Historic Asakusa & Ueno\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mSenso-ji Temple, Nakamise Street snacks, Ameya-Yokocho Market \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mUeno Park (museums if interested) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 2: Shibuya & Harajuku Youth Culture\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mScramble crossing, Hachiko Statue \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mTakeshita Street crepes, quirky shops \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mMeiji Shrine, Yoyogi Park \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 3: Foodie Focus in Tsukiji & Ginza\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mFresh sushi breakfast/lunch at Tsukiji Market \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mCooking class nearby \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mStroll luxury flagship stores and Kabuki-za Theatre in Ginza \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 4: Day Trip or Museums\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mEdo-Tokyo Museum, teamLab Planets/Borderless, or Ghibli Museum (advance booking) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mExplore old neighborhoods in Yanaka \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1mDay 5: Nightlife & Izakayas\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mShinjuku: Omoide Yokocho (tiny bars, yakitori) \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mGolden Gai for drinks and late-night bites \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0mLate walk in illuminated Shinjuku/Kabukicho \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;4mQuick Tips\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mReserve popular restaurants/tours early:\u001b[0m They fill up fast! \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mCash is king\u001b[0m for small eats & market stalls. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[1;33m • \u001b[0m\u001b[1mTransportation:\u001b[0m Use Google Maps or a transit app for trains. \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[33m───────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m Enjoy the rhythm of Tokyo—blend tradition and trend, and bring an appetite! If you’d like more specifics \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m (restaurant recs, booking links), let me know! \u001b[34m┃\u001b[0m\n\u001b[34m┃\u001b[0m \u001b[34m┃\u001b[0m\n\u001b[34m┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\u001b[0m\n" - }, - "metadata": {}, - "output_type": "display_data" - } - ] - } - } - } - } - }, - "nbformat": 4, - "nbformat_minor": 0 + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "id": "zw-BimTKswh4" + }, + "source": [ + "
\n", + "

\n", + " \"phoenix\n", + "
\n", + " Docs\n", + " |\n", + " GitHub\n", + " |\n", + " Community\n", + "

\n", + "
\n", + "

Agno Travel Agent Tracing Project

" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "l8EbE_41szw0" + }, + "source": [ + "We will create a simple travel agent powered by the Agno framework and OpenAI models. We’ll begin by installing the necessary OpenInference packages and setting up tracing with Arize.\n", + "\n", + "Next, we’ll define a set of basic tools that provide destination information, estimate trip budgets, and suggest local activities.\n", + "\n", + "For this base agent, we’ll build and run our agent, viewing the resulting trace outputs in Phoenix to understand how the agent uses its tools and reasoning.\n", + "\n", + "We'll then follow along through the Evals Tutorials:\n", + "- Configure a core LLM & run a built in eval \n", + "- Configure a custom endpoint LLM \n", + "- Create a custom eval \n", + "- Code Evals" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Gxe7vsT9hKHX" + }, + "source": [ + "You will need to install Arize Phoenix in your terminal (`pip install arize-phoenix`) an OpenAI API key, and a free [Tavily](https://auth.tavily.com/) API Key.\n", + "\n", + "Ensure you have `phoenix serve` running in your terminal prior to running the following cells. " + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HzvQoYIksr30" + }, + "source": [ + "## Set up keys and dependenies" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "%pip install -qqqqqq arize-phoenix-otel arize-phoenix-evals agno openai openinference-instrumentation-agno openinference-instrumentation-openai httpx" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "from getpass import getpass\n", + "\n", + "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\"🔑 Enter your OpenAI API Key: \")\n", + "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\"🔑 Enter your Tavily API Key: \")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "AFdPHLMFuEsl" + }, + "source": [ + "## Setup tracing" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.otel import register\n", + "\n", + "tracer_provider = register(project_name=\"agno_travel_agent\", auto_instrument=True)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "Gjd7wU9OuIAQ" + }, + "source": [ + "## Define tools" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "mnRbOa8tg_B7" + }, + "source": [ + "First, we’ll define a few helper functions to support our tools. In particular, we’ll use Tavily Search to help the tools gather general information about each destination." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# --- Helper functions for tools ---\n", + "import httpx\n", + "\n", + "def _search_api(query: str) -> str | None:\n", + " \"\"\"Try Tavily search first, fall back to None.\"\"\"\n", + " tavily_key = os.getenv(\"TAVILY_API_KEY\")\n", + " if not tavily_key:\n", + " return None\n", + " try:\n", + " resp = httpx.post(\n", + " \"https://api.tavily.com/search\",\n", + " json={\n", + " \"api_key\": tavily_key,\n", + " \"query\": query,\n", + " \"max_results\": 3,\n", + " \"search_depth\": \"basic\",\n", + " \"include_answer\": True,\n", + " },\n", + " timeout=8,\n", + " )\n", + " data = resp.json()\n", + " answer = data.get(\"answer\") or \"\"\n", + " snippets = [r.get(\"content\", \"\") for r in data.get(\"results\", [])]\n", + " combined = \" \".join([answer] + snippets).strip()\n", + " return combined[:400] if combined else None\n", + " except Exception:\n", + " return None\n", + "\n", + "\n", + "def _compact(text: str, limit: int = 200) -> str:\n", + " \"\"\"Compact text for cleaner outputs.\"\"\"\n", + " cleaned = \" \".join(text.split())\n", + " return cleaned if len(cleaned) <= limit else cleaned[:limit].rsplit(\" \", 1)[0]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "B4fxzijBgLG5" + }, + "source": [ + "Our agent will have access to three tools, which we’ll continue to enhance in upcoming labs:\n", + "\n", + "1. Essential Info – Provides key travel details about the destination, such as weather and general conditions.\n", + "\n", + "2. Budget Basics – Offers insights into travel costs and helps plan budgets based on selected activities.\n", + "\n", + "3. Local Flavor – Recommends unique local experiences and cultural highlights." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from agno.tools import tool\n", + "\n", + "@tool\n", + "def essential_info(destination: str) -> str:\n", + " \"\"\"Get basic travel info (weather, best time, attractions, etiquette).\"\"\"\n", + " q = f\"{destination} travel essentials weather best time top attractions etiquette\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} essentials: {_compact(s)}\"\n", + "\n", + " return f\"{destination} is a popular travel destination. Expect local culture, cuisine, and landmarks worth exploring.\"\n", + "\n", + "@tool\n", + "def budget_basics(destination: str, duration: str) -> str:\n", + " \"\"\"Summarize travel cost categories.\"\"\"\n", + " q = f\"{destination} travel budget average daily costs {duration}\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} budget ({duration}): {_compact(s)}\"\n", + " return f\"Budget for {duration} in {destination} depends on lodging, meals, transport, and attractions.\"\n", + "\n", + "@tool\n", + "def local_flavor(destination: str, interests: str = \"local culture\") -> str:\n", + " \"\"\"Suggest authentic local experiences.\"\"\"\n", + " q = f\"{destination} authentic local experiences {interests}\"\n", + " s = _search_api(q)\n", + " if s:\n", + " return f\"{destination} {interests}: {_compact(s)}\"\n", + " return f\"Explore {destination}'s unique {interests} through markets, neighborhoods, and local eateries.\"\n" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "o48IXEMJuJuI" + }, + "source": [ + "## Define agent" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "0hCYAqOShX-c" + }, + "source": [ + "Next, we’ll construct our agent. The Agno framework makes this process straightforward by allowing us to easily define key parameters such as the model, instructions, and tools." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from agno.agent import Agent\n", + "from agno.models.openai import OpenAIChat\n", + "\n", + "trip_agent = Agent(\n", + " name=\"TripPlanner\",\n", + " role=\"AI Travel Assistant\",\n", + " model=OpenAIChat(id=\"gpt-4.1\"),\n", + " instructions=(\n", + " \"You are a friendly and knowledgeable travel planner. \"\n", + " \"Combine multiple tools to create a trip plan including essentials, budget, and local flavor. \"\n", + " \"Keep the tone natural, clear, and under 1000 words.\"\n", + " ),\n", + " markdown=True,\n", + " tools=[essential_info, budget_basics, local_flavor],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "HAKB1WBwuLh2" + }, + "source": [ + "## Run agent" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "id": "I6ZbhUKghmtG" + }, + "source": [ + "Finally, we are ready to run our agent! Run this cell to see an example in action." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# --- Example usage ---\n", + "destination = \"Tokyo\"\n", + "duration = \"5 days\"\n", + "interests = \"food, culture\"\n", + "\n", + "query = f\"\"\"\n", + "Plan a {duration} trip to {destination}.\n", + "Focus on {interests}.\n", + "Include essential info, budget breakdown, and local experiences.\n", + "\"\"\"\n", + "trip_agent.print_response(\n", + " query,\n", + " stream = True\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.client import Client\n", + "\n", + "client = Client()\n", + "spans_df = client.spans.get_spans_dataframe(project_identifier=\"agno_travel_agent\")\n", + "agent_spans = spans_df[spans_df['span_kind'] == 'AGENT']\n", + "agent_spans" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "agent_spans['attributes.output.value', 'attributes.input.value']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run evals with built-in eval templates & an OpenAI Model\n", + "\n", + "Let's first use a classic config for our LLM & built in template for our first eval. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals.llm import LLM\n", + "\n", + "llm = LLM(\n", + " provider=\"openai\",\n", + " model=\"gpt-4o\",\n", + " client=\"openai\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals.metrics import CorrectnessEvaluator\n", + "\n", + "correctness_eval = CorrectnessEvaluator(llm=llm)\n", + "\n", + "print(correctness_eval.describe())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals import bind_evaluator, evaluate_dataframe\n", + "from phoenix.trace import suppress_tracing\n", + "\n", + "bound_evaluator = bind_evaluator(\n", + " evaluator=correctness_eval,\n", + " input_mapping={\n", + " \"input\": \"attributes.input.value\",\n", + " \"output\": \"attributes.output.value\",\n", + " }\n", + ")\n", + "\n", + "with suppress_tracing():\n", + " results_df = evaluate_dataframe(agent_spans, [bound_evaluator])\n", + "print(results_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals.utils import to_annotation_dataframe\n", + "\n", + "evaluations = to_annotation_dataframe(dataframe=results_df)\n", + "\n", + "Client().spans.log_span_annotations_dataframe(dataframe=evaluations)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Run evals with built-in eval templates with a Custom Model\n", + "\n", + "Let's now create a custom config for our LLM & re-run this built in template using the same evaluator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "\n", + "os.environ[\"FIREWORKS_API_KEY\"] = globals().get(\"FIREWORKS_API_KEY\") or getpass(\"🔑 Enter your Fireworks API Key: \")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals.llm import LLM\n", + "\n", + "custom_llm = LLM(\n", + " provider=\"openai\",\n", + " model=\"accounts/fireworks/models/qwen3-235b-a22b-instruct-2507\",\n", + " base_url=\"https://api.fireworks.ai/inference/v1\",\n", + " api_key=os.environ.get(\"FIREWORKS_API_KEY\"),\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals import bind_evaluator, evaluate_dataframe\n", + "from phoenix.evals.metrics import CorrectnessEvaluator\n", + "from phoenix.trace import suppress_tracing\n", + "\n", + "correctness_eval = CorrectnessEvaluator(llm=custom_llm)\n", + "\n", + "bound_evaluator = bind_evaluator(\n", + " evaluator=correctness_eval,\n", + " input_mapping={\n", + " \"input\": \"attributes.input.value\",\n", + " \"output\": \"attributes.output.value\",\n", + " }\n", + ")\n", + "\n", + "with suppress_tracing():\n", + " results_df = evaluate_dataframe(agent_spans, [bound_evaluator])\n", + "print(results_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "evaluations = to_annotation_dataframe(dataframe=results_df)\n", + "Client().spans.log_span_annotations_dataframe(dataframe=evaluations)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Create a Custom Evaluator \n", + "\n", + "Let's now create a custom evaluator & use the custom LLM config we just created. We can keep on the same idea of correctness, but let's add more application specific context to it. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "CUSTOM_CORRECTNESS_TEMPLATE = \"\"\"You are an expert evaluator judging whether a travel planner agent's response is correct. The agent is a friendly travel planner that must combine multiple tools to create a trip plan with: (1) essential info, (2) budget breakdown, and (3) local flavor/experiences.\n", + "\n", + "CORRECT - The response:\n", + "- Accurately addresses the user's destination, duration, and stated interests\n", + "- Includes essential travel info (e.g., weather, best time to visit, key attractions, etiquette) for the destination\n", + "- Includes a budget or cost breakdown appropriate to the destination and trip duration\n", + "- Includes local experiences, cultural highlights, or authentic recommendations matching the user's interests\n", + "- Is factually accurate, logically consistent, and helpful for planning the trip\n", + "- Uses precise, travel-appropriate terminology\n", + "\n", + "INCORRECT - The response contains any of:\n", + "- Factual errors about the destination, costs, or local info\n", + "- Missing essential info when the user asked for a full trip plan\n", + "- Missing or irrelevant budget information for the given destination/duration\n", + "- Missing or generic local experiences that do not match the user's interests\n", + "- Wrong destination, duration, or interests addressed\n", + "- Contradictions, misleading statements, or unhelpful/off-topic content\n", + "\n", + "[BEGIN DATA]\n", + "************\n", + "[User Input]:\n", + "{{input}}\n", + "\n", + "************\n", + "[Travel Plan]:\n", + "{{output}}\n", + "************\n", + "[END DATA]\n", + "\n", + "Focus on factual accuracy and completeness of the trip plan (essentials, budget, local flavor). Is the output correct or incorrect?\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from phoenix.evals import ClassificationEvaluator\n", + "\n", + "custom_correctness_evaluator = ClassificationEvaluator(\n", + " name = \"custom_correctness\",\n", + " llm = llm,\n", + " prompt_template=CUSTOM_CORRECTNESS_TEMPLATE,\n", + " choices={\"correct\": 1, \"incorrect\": 0}\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "bound_evaluator = bind_evaluator(\n", + " evaluator=custom_correctness_evaluator,\n", + " input_mapping={\n", + " \"input\": \"attributes.input.value\",\n", + " \"output\": \"attributes.output.value\",\n", + " }\n", + ")\n", + "\n", + "with suppress_tracing():\n", + " results_df = evaluate_dataframe(agent_spans, [bound_evaluator])\n", + "print(results_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "evaluations = to_annotation_dataframe(dataframe=results_df)\n", + "Client().spans.log_span_annotations_dataframe(dataframe=evaluations)" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 0 } From 1e95ff57b23fbcf87cf8b2b4018498f59728de17 Mon Sep 17 00:00:00 2001 From: Srilakshmi Chavali Date: Wed, 4 Feb 2026 19:35:08 -0800 Subject: [PATCH 8/8] run ruff --- .../quickstarts/agno_agent_for_evals.ipynb | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/tutorials/quickstarts/agno_agent_for_evals.ipynb b/tutorials/quickstarts/agno_agent_for_evals.ipynb index b1b68d0c471..ba0016ff8f4 100644 --- a/tutorials/quickstarts/agno_agent_for_evals.ipynb +++ b/tutorials/quickstarts/agno_agent_for_evals.ipynb @@ -77,8 +77,12 @@ "import os\n", "from getpass import getpass\n", "\n", - "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\"🔑 Enter your OpenAI API Key: \")\n", - "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\"🔑 Enter your Tavily API Key: \")" + "os.environ[\"OPENAI_API_KEY\"] = globals().get(\"OPENAI_API_KEY\") or getpass(\n", + " \"🔑 Enter your OpenAI API Key: \"\n", + ")\n", + "os.environ[\"TAVILY_API_KEY\"] = globals().get(\"TAVILY_API_KEY\") or getpass(\n", + " \"🔑 Enter your Tavily API Key: \"\n", + ")" ] }, { @@ -128,6 +132,7 @@ "# --- Helper functions for tools ---\n", "import httpx\n", "\n", + "\n", "def _search_api(query: str) -> str | None:\n", " \"\"\"Try Tavily search first, fall back to None.\"\"\"\n", " tavily_key = os.getenv(\"TAVILY_API_KEY\")\n", @@ -157,7 +162,7 @@ "def _compact(text: str, limit: int = 200) -> str:\n", " \"\"\"Compact text for cleaner outputs.\"\"\"\n", " cleaned = \" \".join(text.split())\n", - " return cleaned if len(cleaned) <= limit else cleaned[:limit].rsplit(\" \", 1)[0]\n" + " return cleaned if len(cleaned) <= limit else cleaned[:limit].rsplit(\" \", 1)[0]" ] }, { @@ -183,6 +188,7 @@ "source": [ "from agno.tools import tool\n", "\n", + "\n", "@tool\n", "def essential_info(destination: str) -> str:\n", " \"\"\"Get basic travel info (weather, best time, attractions, etiquette).\"\"\"\n", @@ -193,6 +199,7 @@ "\n", " return f\"{destination} is a popular travel destination. Expect local culture, cuisine, and landmarks worth exploring.\"\n", "\n", + "\n", "@tool\n", "def budget_basics(destination: str, duration: str) -> str:\n", " \"\"\"Summarize travel cost categories.\"\"\"\n", @@ -202,6 +209,7 @@ " return f\"{destination} budget ({duration}): {_compact(s)}\"\n", " return f\"Budget for {duration} in {destination} depends on lodging, meals, transport, and attractions.\"\n", "\n", + "\n", "@tool\n", "def local_flavor(destination: str, interests: str = \"local culture\") -> str:\n", " \"\"\"Suggest authentic local experiences.\"\"\"\n", @@ -209,7 +217,7 @@ " s = _search_api(q)\n", " if s:\n", " return f\"{destination} {interests}: {_compact(s)}\"\n", - " return f\"Explore {destination}'s unique {interests} through markets, neighborhoods, and local eateries.\"\n" + " return f\"Explore {destination}'s unique {interests} through markets, neighborhoods, and local eateries.\"" ] }, { @@ -287,10 +295,7 @@ "Focus on {interests}.\n", "Include essential info, budget breakdown, and local experiences.\n", "\"\"\"\n", - "trip_agent.print_response(\n", - " query,\n", - " stream = True\n", - ")" + "trip_agent.print_response(query, stream=True)" ] }, { @@ -303,7 +308,7 @@ "\n", "client = Client()\n", "spans_df = client.spans.get_spans_dataframe(project_identifier=\"agno_travel_agent\")\n", - "agent_spans = spans_df[spans_df['span_kind'] == 'AGENT']\n", + "agent_spans = spans_df[spans_df[\"span_kind\"] == \"AGENT\"]\n", "agent_spans" ] }, @@ -313,7 +318,7 @@ "metadata": {}, "outputs": [], "source": [ - "agent_spans['attributes.output.value', 'attributes.input.value']" + "agent_spans[\"attributes.output.value\", \"attributes.input.value\"]" ] }, { @@ -367,7 +372,7 @@ " input_mapping={\n", " \"input\": \"attributes.input.value\",\n", " \"output\": \"attributes.output.value\",\n", - " }\n", + " },\n", ")\n", "\n", "with suppress_tracing():\n", @@ -405,7 +410,9 @@ "source": [ "import os\n", "\n", - "os.environ[\"FIREWORKS_API_KEY\"] = globals().get(\"FIREWORKS_API_KEY\") or getpass(\"🔑 Enter your Fireworks API Key: \")" + "os.environ[\"FIREWORKS_API_KEY\"] = globals().get(\"FIREWORKS_API_KEY\") or getpass(\n", + " \"🔑 Enter your Fireworks API Key: \"\n", + ")" ] }, { @@ -441,7 +448,7 @@ " input_mapping={\n", " \"input\": \"attributes.input.value\",\n", " \"output\": \"attributes.output.value\",\n", - " }\n", + " },\n", ")\n", "\n", "with suppress_tracing():\n", @@ -515,10 +522,10 @@ "from phoenix.evals import ClassificationEvaluator\n", "\n", "custom_correctness_evaluator = ClassificationEvaluator(\n", - " name = \"custom_correctness\",\n", - " llm = llm,\n", + " name=\"custom_correctness\",\n", + " llm=llm,\n", " prompt_template=CUSTOM_CORRECTNESS_TEMPLATE,\n", - " choices={\"correct\": 1, \"incorrect\": 0}\n", + " choices={\"correct\": 1, \"incorrect\": 0},\n", ")" ] }, @@ -533,7 +540,7 @@ " input_mapping={\n", " \"input\": \"attributes.input.value\",\n", " \"output\": \"attributes.output.value\",\n", - " }\n", + " },\n", ")\n", "\n", "with suppress_tracing():\n",