{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "

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

\n", "
\n", "

Using Projects with Phoenix

\n", "\n", "Projects provide a powerful way to organize your traces. For example, you can separate traces from test and prod environments, as well as entirely different applications to simplify the process of finding the traces that are important and doing analysis on them.\n", "\n", "In this tutorial, you will:\n", "- Build and trace a simple LlamaIndex application\n", "- Use projects to organize traces\n", "\n", "â„šī¸ This notebook requires an OpenAI API key." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 1. Install Dependencies and Import Libraries\n", "\n", "Install Phoenix, LlamaIndex, and OpenAI." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "!pip install \"arize-phoenix[evals,llama-index]\" \"openai>=1\" gcsfs nest-asyncio \"llama-index>=0.10.3\" 'httpx<0.28'" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import libraries." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import json\n", "import os\n", "from getpass import getpass\n", "from urllib.request import urlopen\n", "\n", "import nest_asyncio\n", "import openai\n", "import pandas as pd\n", "from gcsfs import GCSFileSystem\n", "from llama_index.core import (\n", " Settings,\n", " StorageContext,\n", " load_index_from_storage,\n", ")\n", "from llama_index.embeddings.openai import OpenAIEmbedding\n", "from llama_index.llms.openai import OpenAI\n", "from tqdm import tqdm\n", "\n", "import phoenix as px\n", "from phoenix.evals import (\n", " HallucinationEvaluator,\n", " OpenAIModel,\n", " QAEvaluator,\n", " RelevanceEvaluator,\n", " run_evals,\n", ")\n", "from phoenix.session.evaluation import get_qa_with_reference, get_retrieved_documents\n", "from phoenix.trace import DocumentEvaluations, SpanEvaluations\n", "\n", "nest_asyncio.apply() # needed for concurrent evals in notebook environments\n", "pd.set_option(\"display.max_colwidth\", 1000)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Configure the default project then Launch Phoenix\n", "\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "🚨 Phoenix is configured with environment variables. 🚨\n", "\n", "In this tutorial we want to change the default project we send traces to by modifying the `PHOENIX_PROJECT_NAME` environment variable defined blow." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "os.environ[\"PHOENIX_PROJECT_NAME\"] = \"DONT-SEND-TRACES-TO-THIS-PROJECT\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You can run Phoenix in the background to collect trace data emitted by any LlamaIndex application that has been instrumented with the `OpenInferenceTraceCallbackHandler`. Phoenix supports LlamaIndex's [one-click observability](https://gpt-index.readthedocs.io/en/latest/end_to_end_tutorials/one_click_observability.html) which will automatically instrument your LlamaIndex application! You can consult our [integration guide](https://docs.arize.com/phoenix/integrations/llamaindex) for a more detailed explanation of how to instrument your LlamaIndex application.\n", "\n", "Launch Phoenix and follow the instructions in the cell output to open the Phoenix UI (the UI should be empty because we have yet to run the LlamaIndex application)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "(session := px.launch_app()).view()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 3. Configure Your OpenAI API Key\n", "\n", "Set your OpenAI API key if it is not already set as an environment variable." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "if not (openai_api_key := os.getenv(\"OPENAI_API_KEY\")):\n", " openai_api_key = getpass(\"🔑 Enter your OpenAI API key: \")\n", "openai.api_key = openai_api_key\n", "os.environ[\"OPENAI_API_KEY\"] = openai_api_key" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 4. Build Your LlamaIndex Application" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This example uses a `RetrieverQueryEngine` over a pre-built index of the Arize documentation, but you can use whatever LlamaIndex application you like.\n", "\n", "Download our pre-built index of the Arize docs from cloud storage and instantiate your storage context." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "file_system = GCSFileSystem(project=\"public-assets-275721\")\n", "index_path = \"arize-phoenix-assets/datasets/unstructured/llm/llama-index/arize-docs/index/\"\n", "storage_context = StorageContext.from_defaults(\n", " fs=file_system,\n", " persist_dir=index_path,\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Enable Phoenix tracing via `LlamaIndexInstrumentor`. Phoenix uses OpenInference traces - an open-source standard for capturing and storing LLM application traces that enables LLM applications to seamlessly integrate with LLM observability solutions such as Phoenix." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from openinference.instrumentation.llama_index import LlamaIndexInstrumentor\n", "\n", "from phoenix.otel import register\n", "\n", "tracer_provider = register(endpoint=\"http://127.0.0.1:6006/v1/traces\")\n", "LlamaIndexInstrumentor().instrument(skip_dep_check=True, tracer_provider=tracer_provider)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are now ready to instantiate our query engine that will perform retrieval-augmented generation (RAG). Query engine is a generic interface in LlamaIndex that allows you to ask question over your data. A query engine takes in a natural language query, and returns a rich response. It is built on top of Retrievers. You can compose multiple query engines to achieve more advanced capability " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "Settings.llm = OpenAI(model=\"gpt-4-turbo-preview\")\n", "Settings.embed_model = OpenAIEmbedding(model=\"text-embedding-ada-002\")\n", "index = load_index_from_storage(\n", " storage_context,\n", ")\n", "query_engine = index.as_query_engine()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 5. Run Your Query Engine and View Your Traces in Phoenix\n", "\n", "By running a simple query, you can see your traces organized into the project you've configured!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "response = query_engine.query(\"What is Arize and how can it help me as an AI Engineer?\")\n", "print(response)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "queries_url = \"http://storage.googleapis.com/arize-phoenix-assets/datasets/unstructured/llm/context-retrieval/arize_docs_queries.jsonl\"\n", "queries = []\n", "with urlopen(queries_url) as response:\n", " for line in response:\n", " line = line.decode(\"utf-8\").strip()\n", " data = json.loads(line)\n", " queries.append(data[\"query\"])\n", "queries[:10]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We can run one sample query to look at the result in Phoenix" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "query_engine.query(queries[-1])" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(f\"🚀 Open the Phoenix UI if you haven't already: {session.url}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 6. Dynamically switch projects in a notebook\n", "\n", "When using notebook environments like Google colab and Jupyter Notebook, we can use the `using_project` context manager to send traces to a different project!" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from phoenix.trace import using_project\n", "\n", "with using_project(\"FORBIDDEN-PROJECT\"):\n", " for query in tqdm(queries[:5]):\n", " query_engine.query(query)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 7. Export and Evaluate Your Trace Data\n", "\n", "You can export your trace data from 📕 *specific projects* 📕 as a pandas dataframe for further analysis and evaluation.\n", "\n", "Modify the cell below to export data from a specific project." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "queries_df = get_qa_with_reference(px.Client())\n", "retrieved_documents_df = get_retrieved_documents(px.Client(), project_name=\"NOT-A-PROJECT\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, define your evaluation model and your evaluators.\n", "\n", "Evaluators are built on top of language models and prompt the LLM to assess the quality of responses, the relevance of retrieved documents, etc., and provide a quality signal even in the absence of human-labeled data. Pick an evaluator type and instantiate it with the language model you want to use to perform evaluations using our battle-tested evaluation templates." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "eval_model = OpenAIModel(\n", " model=\"gpt-4-turbo-preview\",\n", ")\n", "hallucination_evaluator = HallucinationEvaluator(eval_model)\n", "qa_correctness_evaluator = QAEvaluator(eval_model)\n", "relevance_evaluator = RelevanceEvaluator(eval_model)\n", "\n", "hallucination_eval_df, qa_correctness_eval_df = run_evals(\n", " dataframe=queries_df,\n", " evaluators=[hallucination_evaluator, qa_correctness_evaluator],\n", " provide_explanation=True,\n", ")\n", "relevance_eval_df = run_evals(\n", " dataframe=retrieved_documents_df,\n", " evaluators=[relevance_evaluator],\n", " provide_explanation=True,\n", ")[0]\n", "\n", "px.Client().log_evaluations(\n", " SpanEvaluations(eval_name=\"Hallucination\", dataframe=hallucination_eval_df),\n", " SpanEvaluations(eval_name=\"QA Correctness\", dataframe=qa_correctness_eval_df),\n", " DocumentEvaluations(eval_name=\"Relevance\", dataframe=relevance_eval_df),\n", ")" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 4 }