From b7623fcd7104995021a213997c718c611e01e185 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 14:19:50 -0500 Subject: [PATCH 1/7] example cookbook based on Helicone example --- parea/cookbook/img/trace_log_view.png | Bin 0 -> 208641 bytes parea/cookbook/tracing_with_Parea_sdk.ipynb | 136 ++++---- ...ing_with_function_calling_and_chains.ipynb | 305 ++++++++++++++++++ pyproject.toml | 2 +- 4 files changed, 374 insertions(+), 69 deletions(-) create mode 100644 parea/cookbook/img/trace_log_view.png create mode 100644 parea/cookbook/tracing_with_function_calling_and_chains.ipynb diff --git a/parea/cookbook/img/trace_log_view.png b/parea/cookbook/img/trace_log_view.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2ab8cbfc38ab4c1c3b8c190741cb5af940415d GIT binary patch literal 208641 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∾;6s54;ivA^ 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﫮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 literal 0 HcmV?d00001 diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index 0c42e97c..b34190fa 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -117,40 +117,40 @@ "\n", "\n", "def argument_generator(query: str, additional_description: str = \"\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", - " llm_inputs={\"argument\": argument},\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", + " llm_inputs={\"argument\": argument},\n", + " )\n", + " ).content\n", "\n", "\n", "def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "# Non deployed version\n", @@ -209,9 +209,9 @@ "\n", "@trace\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism)" + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism)" ] }, { @@ -251,8 +251,8 @@ ], "source": [ "result1 = argument_chain(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(result1)" ] @@ -302,10 +302,10 @@ "\n", "@trace\n", "def argument_chain2(query: str, additional_description: str = \"\") -> tuple[str, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism), trace_id" ] }, { @@ -331,8 +331,8 @@ ], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(trace_id)" ] @@ -424,30 +424,30 @@ "\n", "# let's return the full CompletionResponse to see what other information is returned\n", "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", " )\n", + " )\n", "\n", "\n", "@trace\n", "def argument_chain3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism)\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism)\n", "\n", "\n", "result2 = argument_chain3(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))" ], @@ -498,14 +498,14 @@ "\n", "# you can also add metadata and tags via the decorator\n", "@trace(\n", - " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", - " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", + " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", + " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", ")\n", "def argument_chain_tags_metadata(query: str, additional_description: str = \"\") -> Tuple[CompletionResponse, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism), trace_id" ] }, { @@ -515,17 +515,17 @@ "from attrs import asdict\n", "\n", "result2, trace_id = argument_chain_tags_metadata(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=trace_id,\n", - " score=0.7, # 0.0 (bad) to 1.0 (good)\n", - " target=\"Coffee is wonderful. End of story.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=trace_id,\n", + " score=0.7, # 0.0 (bad) to 1.0 (good)\n", + " target=\"Coffee is wonderful. End of story.\",\n", + " )\n", ")" ], "metadata": { diff --git a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb new file mode 100644 index 00000000..93e55b96 --- /dev/null +++ b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb @@ -0,0 +1,305 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "formattedRanges": [], + "cell_id": "d9114afabb54438ea6c7f68a68bf6fb5", + "deepnote_cell_type": "text-cell-h1" + }, + "source": [ + "# Tracing with Function Calls and Chains" + ], + "block_group": "53e88a688fb843c381543ca9b45c9d76" + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import json\n", + "import os\n", + "from typing import List, Dict, Any, Union\n", + "\n", + "from parea import Parea\n", + "from parea.schemas.models import Completion, LLMInputs, Message, ModelParams\n", + "from parea.utils.trace_utils import trace, trace_insert\n", + "\n", + "p = Parea(api_key=os.environ[\"PAREA_API_KEY\"])" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": 5, + "outputs": [], + "source": [ + "LIMIT = 2 # limit any loops to 2 iterations for demo purposes\n", + "\n", + "COURSE_FUNCTIONS = [\n", + " {\n", + " \"name\": \"generate_course_outline\",\n", + " \"description\": \"Generates a course outline\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"Description\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The description of the course\"\n", + " },\n", + " \"chapters\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The title of the chapter\"\n", + " },\n", + " \"description\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The summary of the chapter\"\n", + " },\n", + " },\n", + " \"required\": [\"name\", \"description\"]\n", + " },\n", + " \"description\": \"The chapters included in the course\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT\n", + " }\n", + " },\n", + " \"required\": [\"Description\", \"chapters\"]\n", + " },\n", + "\n", + " }\n", + "]\n", + "\n", + "CHAPTER_FUNCTIONS = [\n", + " {\n", + " \"name\": \"generate_chapter_outline\",\n", + " \"description\": \"Generates a chapter outline\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The title of the chapter\"\n", + " },\n", + " \"description\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The summary of the chapter\"\n", + " },\n", + " \"sections\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The title of the section\"\n", + " },\n", + " \"description\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The summary of the section\"\n", + " },\n", + " },\n", + " \"required\": [\"name\", \"description\"]\n", + " },\n", + " \"description\": \"The sections included in the chapter\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT\n", + " }\n", + " },\n", + " \"required\": [\"name\", \"description\", \"sections\"]\n", + " },\n", + " }\n", + "]" + ], + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2023-12-09T19:18:33.559895Z", + "start_time": "2023-12-09T19:18:33.291059Z" + } + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "USER = \"alice@bob.com\"\n", + "\n", + "\n", + "# Create a reusable call lmm helper function \n", + "# Parea SDK is automatically traced\n", + "def call_llm(messages: List[Dict[str, str]], name: str = \"LLM Call\") -> str:\n", + " return p.completion(\n", + " Completion(\n", + " llm_configuration=LLMInputs(\n", + " model=\"gpt-3.5-turbo-1106\",\n", + " model_params=ModelParams(temp=0.0, max_length=512),\n", + " messages=[Message(**m) for m in messages],\n", + " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", + " ),\n", + " end_user_identifier=USER,\n", + " trace_name=name,\n", + " )\n", + " ).content\n", + "\n", + "\n", + "# Helper function to get function call arguments if they exists\n", + "def get_function_call_or_content(response: str) -> Union[str, Dict[str, Any]]:\n", + " # Function calls are returned in triple backticks\n", + " parsed_response = response.replace(\"```\", \"\")\n", + " # return function call or content string\n", + " try:\n", + " return json.loads(parsed_response).get(\"arguments\")\n", + " except Exception as e:\n", + " return parsed_response" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "# PROMPTS\n", + "\n", + "def get_course(topic: str):\n", + " _course_outline = call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", + " name=f\"Create {topic} Course Outline\",\n", + " )\n", + " course_outline = get_function_call_or_content(_course_outline)\n", + " print(json.dumps(course_outline, indent=4))\n", + " return course_outline\n", + "\n", + "\n", + "# I want to group all llm calls into one trace, \n", + "# so I add the trace decorator to create a parent trace, \n", + "# each call_llm will be a child span\n", + "@trace(name=\"Get Chapters\")\n", + "def get_chapters(course_outline: Dict[str, str]):\n", + " chapter_outlines = course_outline.get(\"chapters\", [])\n", + " chapters = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\n", + " \"role\": \"user\",\n", + " \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"\n", + " }],\n", + " name=f\"Create Chapter {idx}\"\n", + " )\n", + " )\n", + " for idx, chapter in enumerate(chapter_outlines, start=1)\n", + " ]\n", + " return chapters[:LIMIT]\n", + "\n", + "\n", + "@trace\n", + "def get_sections(chapter: Dict[str, str]):\n", + " chapter_name = chapter.get('name', 'section')\n", + " # I want the trace name to be dynamic based on the chapter param, \n", + " # so I can use Parea trace_insert helper method to add dynamic data\n", + " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", + "\n", + " section_outlines = chapter.get(\"sections\", [])\n", + " sections = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\n", + " \"role\": \"user\",\n", + " \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"\n", + " }],\n", + " name=f\"Create Section {idx}\"\n", + " )\n", + " )\n", + " for idx, section in enumerate(section_outlines, start=1)\n", + " ]\n", + " return sections[:LIMIT]" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "@trace(name=\"Get Sections\")\n", + "def get_all_sections(chapters: List[Dict[str, str]]):\n", + " return [get_sections(chapter) for chapter in chapters]\n", + "\n", + "\n", + "@trace\n", + "def run_creation(topic: str):\n", + " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", + " course_outline = get_course(topic)\n", + " chapters = get_chapters(course_outline)\n", + " sections = get_all_sections(chapters)\n", + " return sections\n", + "\n", + "\n", + "@trace(name=\"Generate Courses for Topics\")\n", + "def main(topics):\n", + " for topic in topics:\n", + " print(f\"\\n New Topic: {topic} \\n\")\n", + " run_creation(topic)" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "main([\"Artificial Intelligence\", \"Machine Learning\", \"Deep Learning\"])" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Trace Log View in UI\n", + "\n", + "![TraceView](img/trace_log_view.png)" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [], + "metadata": { + "collapsed": false + } + } + ], + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "deepnote": {}, + "orig_nbformat": 2, + "deepnote_notebook_id": "27ae7c4c406747b5b5936b15081cdaec", + "deepnote_execution_queue": [], + "kernelspec": { + "name": "python3", + "language": "python", + "display_name": "Python 3 (ipykernel)" + } + } +} diff --git a/pyproject.toml b/pyproject.toml index 1f9f1f3d..cbc7ba49 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,7 +6,7 @@ build-backend = "poetry.core.masonry.api" [tool.poetry] name = "parea-ai" packages = [{ include = "parea" }] -version = "0.2.20" +version = "0.2.21a0" description = "Parea python sdk" readme = "README.md" authors = ["joel-parea-ai "] From f604638556f5e01f9ea80111912f84f781831853 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 14:33:43 -0500 Subject: [PATCH 2/7] add new models costs --- parea/cookbook/tracing_with_Parea_sdk.ipynb | 136 +++++----- ...ing_with_function_calling_and_chains.ipynb | 247 ++++++++---------- parea/wrapper/openai.py | 142 ++++++---- 3 files changed, 272 insertions(+), 253 deletions(-) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index b34190fa..0c42e97c 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -117,40 +117,40 @@ "\n", "\n", "def argument_generator(query: str, additional_description: str = \"\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", - " llm_inputs={\"argument\": argument},\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", + " llm_inputs={\"argument\": argument},\n", + " )\n", + " ).content\n", "\n", "\n", "def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "# Non deployed version\n", @@ -209,9 +209,9 @@ "\n", "@trace\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism)" + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism)" ] }, { @@ -251,8 +251,8 @@ ], "source": [ "result1 = argument_chain(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(result1)" ] @@ -302,10 +302,10 @@ "\n", "@trace\n", "def argument_chain2(query: str, additional_description: str = \"\") -> tuple[str, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism), trace_id" ] }, { @@ -331,8 +331,8 @@ ], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(trace_id)" ] @@ -424,30 +424,30 @@ "\n", "# let's return the full CompletionResponse to see what other information is returned\n", "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", " )\n", - " )\n", "\n", "\n", "@trace\n", "def argument_chain3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism)\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism)\n", "\n", "\n", "result2 = argument_chain3(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))" ], @@ -498,14 +498,14 @@ "\n", "# you can also add metadata and tags via the decorator\n", "@trace(\n", - " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", - " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", + " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", + " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", ")\n", "def argument_chain_tags_metadata(query: str, additional_description: str = \"\") -> Tuple[CompletionResponse, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism), trace_id" ] }, { @@ -515,17 +515,17 @@ "from attrs import asdict\n", "\n", "result2, trace_id = argument_chain_tags_metadata(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=trace_id,\n", - " score=0.7, # 0.0 (bad) to 1.0 (good)\n", - " target=\"Coffee is wonderful. End of story.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=trace_id,\n", + " score=0.7, # 0.0 (bad) to 1.0 (good)\n", + " target=\"Coffee is wonderful. End of story.\",\n", + " )\n", ")" ], "metadata": { diff --git a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb index 93e55b96..b77e41cd 100644 --- a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb +++ b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb @@ -39,82 +39,60 @@ "LIMIT = 2 # limit any loops to 2 iterations for demo purposes\n", "\n", "COURSE_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_course_outline\",\n", - " \"description\": \"Generates a course outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"Description\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The description of the course\"\n", - " },\n", - " \"chapters\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_course_outline\",\n", + " \"description\": \"Generates a course outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The title of the chapter\"\n", - " },\n", - " \"description\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The summary of the chapter\"\n", - " },\n", + " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", + " \"chapters\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The chapters included in the course\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"]\n", - " },\n", - " \"description\": \"The chapters included in the course\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT\n", - " }\n", - " },\n", - " \"required\": [\"Description\", \"chapters\"]\n", - " },\n", - "\n", - " }\n", + " \"required\": [\"Description\", \"chapters\"],\n", + " },\n", + " }\n", "]\n", "\n", "CHAPTER_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_chapter_outline\",\n", - " \"description\": \"Generates a chapter outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"name\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The title of the chapter\"\n", - " },\n", - " \"description\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The summary of the chapter\"\n", - " },\n", - " \"sections\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_chapter_outline\",\n", + " \"description\": \"Generates a chapter outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The title of the section\"\n", - " },\n", - " \"description\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"The summary of the section\"\n", - " },\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"sections\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The sections included in the chapter\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"]\n", - " },\n", - " \"description\": \"The sections included in the chapter\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT\n", - " }\n", - " },\n", - " \"required\": [\"name\", \"description\", \"sections\"]\n", - " },\n", - " }\n", + " \"required\": [\"name\", \"description\", \"sections\"],\n", + " },\n", + " }\n", "]" ], "metadata": { @@ -133,32 +111,32 @@ "USER = \"alice@bob.com\"\n", "\n", "\n", - "# Create a reusable call lmm helper function \n", + "# Create a reusable call lmm helper function\n", "# Parea SDK is automatically traced\n", "def call_llm(messages: List[Dict[str, str]], name: str = \"LLM Call\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " llm_configuration=LLMInputs(\n", - " model=\"gpt-3.5-turbo-1106\",\n", - " model_params=ModelParams(temp=0.0, max_length=512),\n", - " messages=[Message(**m) for m in messages],\n", - " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", - " ),\n", - " end_user_identifier=USER,\n", - " trace_name=name,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " llm_configuration=LLMInputs(\n", + " model=\"gpt-3.5-turbo-1106\",\n", + " model_params=ModelParams(temp=0.0, max_length=512),\n", + " messages=[Message(**m) for m in messages],\n", + " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", + " ),\n", + " end_user_identifier=USER,\n", + " trace_name=name,\n", + " )\n", + " ).content\n", "\n", "\n", "# Helper function to get function call arguments if they exists\n", "def get_function_call_or_content(response: str) -> Union[str, Dict[str, Any]]:\n", - " # Function calls are returned in triple backticks\n", - " parsed_response = response.replace(\"```\", \"\")\n", - " # return function call or content string\n", - " try:\n", - " return json.loads(parsed_response).get(\"arguments\")\n", - " except Exception as e:\n", - " return parsed_response" + " # Function calls are returned in triple backticks\n", + " parsed_response = response.replace(\"```\", \"\")\n", + " # return function call or content string\n", + " try:\n", + " return json.loads(parsed_response).get(\"arguments\")\n", + " except Exception as e:\n", + " return parsed_response" ], "metadata": { "collapsed": false @@ -171,58 +149,53 @@ "source": [ "# PROMPTS\n", "\n", + "\n", "def get_course(topic: str):\n", - " _course_outline = call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", - " name=f\"Create {topic} Course Outline\",\n", - " )\n", - " course_outline = get_function_call_or_content(_course_outline)\n", - " print(json.dumps(course_outline, indent=4))\n", - " return course_outline\n", + " _course_outline = call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", + " name=f\"Create {topic} Course Outline\",\n", + " )\n", + " course_outline = get_function_call_or_content(_course_outline)\n", + " print(json.dumps(course_outline, indent=4))\n", + " return course_outline\n", "\n", "\n", - "# I want to group all llm calls into one trace, \n", - "# so I add the trace decorator to create a parent trace, \n", + "# I want to group all llm calls into one trace,\n", + "# so I add the trace decorator to create a parent trace,\n", "# each call_llm will be a child span\n", "@trace(name=\"Get Chapters\")\n", "def get_chapters(course_outline: Dict[str, str]):\n", - " chapter_outlines = course_outline.get(\"chapters\", [])\n", - " chapters = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\n", - " \"role\": \"user\",\n", - " \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"\n", - " }],\n", - " name=f\"Create Chapter {idx}\"\n", - " )\n", - " )\n", - " for idx, chapter in enumerate(chapter_outlines, start=1)\n", - " ]\n", - " return chapters[:LIMIT]\n", + " chapter_outlines = course_outline.get(\"chapters\", [])\n", + " chapters = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", + " name=f\"Create Chapter {idx}\",\n", + " )\n", + " )\n", + " for idx, chapter in enumerate(chapter_outlines, start=1)\n", + " ]\n", + " return chapters[:LIMIT]\n", "\n", "\n", "@trace\n", "def get_sections(chapter: Dict[str, str]):\n", - " chapter_name = chapter.get('name', 'section')\n", - " # I want the trace name to be dynamic based on the chapter param, \n", - " # so I can use Parea trace_insert helper method to add dynamic data\n", - " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", + " chapter_name = chapter.get(\"name\", \"section\")\n", + " # I want the trace name to be dynamic based on the chapter param,\n", + " # so I can use Parea trace_insert helper method to add dynamic data\n", + " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", "\n", - " section_outlines = chapter.get(\"sections\", [])\n", - " sections = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\n", - " \"role\": \"user\",\n", - " \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"\n", - " }],\n", - " name=f\"Create Section {idx}\"\n", - " )\n", - " )\n", - " for idx, section in enumerate(section_outlines, start=1)\n", - " ]\n", - " return sections[:LIMIT]" + " section_outlines = chapter.get(\"sections\", [])\n", + " sections = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", + " name=f\"Create Section {idx}\",\n", + " )\n", + " )\n", + " for idx, section in enumerate(section_outlines, start=1)\n", + " ]\n", + " return sections[:LIMIT]" ], "metadata": { "collapsed": false @@ -235,23 +208,23 @@ "source": [ "@trace(name=\"Get Sections\")\n", "def get_all_sections(chapters: List[Dict[str, str]]):\n", - " return [get_sections(chapter) for chapter in chapters]\n", + " return [get_sections(chapter) for chapter in chapters]\n", "\n", "\n", "@trace\n", "def run_creation(topic: str):\n", - " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", - " course_outline = get_course(topic)\n", - " chapters = get_chapters(course_outline)\n", - " sections = get_all_sections(chapters)\n", - " return sections\n", + " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", + " course_outline = get_course(topic)\n", + " chapters = get_chapters(course_outline)\n", + " sections = get_all_sections(chapters)\n", + " return sections\n", "\n", "\n", "@trace(name=\"Generate Courses for Topics\")\n", "def main(topics):\n", - " for topic in topics:\n", - " print(f\"\\n New Topic: {topic} \\n\")\n", - " run_creation(topic)" + " for topic in topics:\n", + " print(f\"\\n New Topic: {topic} \\n\")\n", + " run_creation(topic)" ], "metadata": { "collapsed": false diff --git a/parea/wrapper/openai.py b/parea/wrapper/openai.py index ea482284..ff762516 100644 --- a/parea/wrapper/openai.py +++ b/parea/wrapper/openai.py @@ -1,7 +1,8 @@ -from typing import Any, AsyncIterator, Callable, Dict, Iterator, Optional, Sequence, Union +from typing import Any, Callable, Dict, Optional, Union import json from collections import defaultdict +from collections.abc import AsyncIterator, Iterator, Sequence import openai from openai import __version__ as openai_version @@ -21,38 +22,87 @@ def convert_to_openai_object(**kwargs): from ..utils.trace_utils import trace_data from .wrapper import Wrapper -MODEL_COST_MAPPING: Dict[str, float] = { - "gpt-4": 0.03, - "gpt-4-0314": 0.03, - "gpt-4-0613": 0.03, - "gpt-4-completion": 0.06, - "gpt-4-0314-completion": 0.06, - "gpt-4-0613-completion": 0.06, - "gpt-4-32k": 0.06, - "gpt-4-32k-0314": 0.06, - "gpt-4-32k-0613": 0.06, - "gpt-4-32k-completion": 0.12, - "gpt-4-32k-0314-completion": 0.12, - "gpt-4-32k-0613-completion": 0.12, - "gpt-3.5-turbo": 0.0015, - "gpt-3.5-turbo-0301": 0.0015, - "gpt-3.5-turbo-0613": 0.0015, - "gpt-3.5-turbo-16k": 0.003, - "gpt-3.5-turbo-16k-0613": 0.003, - "gpt-3.5-turbo-completion": 0.002, - "gpt-3.5-turbo-0301-completion": 0.002, - "gpt-3.5-turbo-0613-completion": 0.004, - "gpt-3.5-turbo-16k-completion": 0.004, - "gpt-3.5-turbo-16k-0613-completion": 0.004, - "text-ada-001": 0.0004, - "ada": 0.0004, - "text-babbage-001": 0.0005, - "babbage": 0.0005, - "text-curie-001": 0.002, - "curie": 0.002, - "text-davinci-003": 0.02, - "text-davinci-002": 0.02, - "code-davinci-002": 0.02, +OPENAI_MODEL_INFO: dict[str, dict[str, Union[float, int, dict[str, int]]]] = { + "gpt-3.5-turbo": { + "prompt": 1.5, + "completion": 2.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 4096}, + }, + "gpt-3.5-turbo-0301": { + "prompt": 1.5, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 4096}, + }, + "gpt-3.5-turbo-0613": { + "prompt": 1.5, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 4096}, + }, + "gpt-3.5-turbo-16k": { + "prompt": 3.0, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 16385, "max_prompt_tokens": 16385}, + }, + "gpt-3.5-turbo-16k-0301": { + "prompt": 3.0, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 16385, "max_prompt_tokens": 16385}, + }, + "gpt-3.5-turbo-16k-0613": { + "prompt": 3.0, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 16385, "max_prompt_tokens": 16385}, + }, + "gpt-3.5-turbo-1106": { + "prompt": 1.0, + "completion": 2.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 4096}, + }, + "gpt-3.5-turbo-instruct": { + "prompt": 1.5, + "completion": 4.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 4096}, + }, + "gpt-4": { + "prompt": 30.0, + "completion": 60.0, + "token_limit": {"max_completion_tokens": 8192, "max_prompt_tokens": 8192}, + }, + "gpt-4-0314": { + "prompt": 30.0, + "completion": 60.0, + "token_limit": {"max_completion_tokens": 8192, "max_prompt_tokens": 8192}, + }, + "gpt-4-0613": { + "prompt": 30.0, + "completion": 60.0, + "token_limit": {"max_completion_tokens": 8192, "max_prompt_tokens": 8192}, + }, + "gpt-4-32k": { + "prompt": 60.0, + "completion": 120.0, + "token_limit": {"max_completion_tokens": 32768, "max_prompt_tokens": 32768}, + }, + "gpt-4-32k-0314": { + "prompt": 60.0, + "completion": 120.0, + "token_limit": {"max_completion_tokens": 32768, "max_prompt_tokens": 32768}, + }, + "gpt-4-32k-0613": { + "prompt": 60.0, + "completion": 120.0, + "token_limit": {"max_completion_tokens": 32768, "max_prompt_tokens": 32768}, + }, + "gpt-4-vision-preview": { + "prompt": 30.0, + "completion": 60.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 128000}, + }, + "gpt-4-1106-preview": { + "prompt": 10.0, + "completion": 30.0, + "token_limit": {"max_completion_tokens": 4096, "max_prompt_tokens": 128000}, + }, } @@ -77,7 +127,7 @@ def init(self, log: Callable, cache: Cache = None): ) @staticmethod - def resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], response: Optional[Any]) -> Optional[Any]: + def resolver(trace_id: str, _args: Sequence[Any], kwargs: dict[str, Any], response: Optional[Any]) -> Optional[Any]: if response: output = OpenAIWrapper._get_output(response) if openai_version.startswith("0."): @@ -101,8 +151,8 @@ def resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], respon model_rate = OpenAIWrapper.get_model_cost(model) model_completion_rate = OpenAIWrapper.get_model_cost(model, is_completion=True) - prompt_cost = model_rate * (input_tokens / 1000) - completion_cost = model_completion_rate * (output_tokens / 1000) + prompt_cost = (model_rate / 1000) * (input_tokens / 1000) + completion_cost = (model_completion_rate / 1000) * (output_tokens / 1000) total_cost = sum([prompt_cost, completion_cost]) trace_data.get()[trace_id].configuration = llm_configuration @@ -114,7 +164,7 @@ def resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], respon return response @staticmethod - def gen_resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], response: Iterator[Any], final_log) -> Iterator[Any]: + def gen_resolver(trace_id: str, _args: Sequence[Any], kwargs: dict[str, Any], response: Iterator[Any], final_log) -> Iterator[Any]: llm_configuration = OpenAIWrapper._kwargs_to_llm_configuration(kwargs) trace_data.get()[trace_id].configuration = llm_configuration @@ -131,7 +181,7 @@ def gen_resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], re final_log() @staticmethod - async def agen_resolver(trace_id: str, _args: Sequence[Any], kwargs: Dict[str, Any], response: AsyncIterator[Any], final_log) -> AsyncIterator[Any]: + async def agen_resolver(trace_id: str, _args: Sequence[Any], kwargs: dict[str, Any], response: AsyncIterator[Any], final_log) -> AsyncIterator[Any]: llm_configuration = OpenAIWrapper._kwargs_to_llm_configuration(kwargs) trace_data.get()[trace_id].configuration = llm_configuration @@ -196,25 +246,21 @@ def _format_function_call(response_message) -> str: @staticmethod def get_model_cost(model_name: str, is_completion: bool = False) -> float: model_name = model_name.lower() - - if model_name.startswith("gpt-4") and is_completion: - model_name += "-completion" - - cost = MODEL_COST_MAPPING.get(model_name, None) + cost = OPENAI_MODEL_INFO.get(model_name, {}).get("completion" if is_completion else "prompt", None) if cost is None: - msg = f"Unknown model: {model_name}. " f"Please provide a valid OpenAI model name. " f"Known models are: {', '.join(MODEL_COST_MAPPING.keys())}" + msg = f"Unknown model: {model_name}. " f"Please provide a valid OpenAI model name. " f"Known models are: {', '.join(OPENAI_MODEL_INFO.keys())}" raise ValueError(msg) return cost @staticmethod - def convert_kwargs_to_cache_request(_args: Sequence[Any], kwargs: Dict[str, Any]) -> CacheRequest: + def convert_kwargs_to_cache_request(_args: Sequence[Any], kwargs: dict[str, Any]) -> CacheRequest: return CacheRequest( configuration=OpenAIWrapper._kwargs_to_llm_configuration(kwargs), ) @staticmethod - def _convert_cache_to_response(_args: Sequence[Any], kwargs: Dict[str, Any], cache_response: TraceLog) -> OpenAIObject: + def _convert_cache_to_response(_args: Sequence[Any], kwargs: dict[str, Any], cache_response: TraceLog) -> OpenAIObject: content = cache_response.output message = {"role": "assistant"} try: @@ -248,7 +294,7 @@ def _convert_cache_to_response(_args: Sequence[Any], kwargs: Dict[str, Any], cac ) @staticmethod - def convert_cache_to_response(_args: Sequence[Any], kwargs: Dict[str, Any], cache_response: TraceLog) -> Union[OpenAIObject, Iterator[OpenAIObject]]: + def convert_cache_to_response(_args: Sequence[Any], kwargs: dict[str, Any], cache_response: TraceLog) -> Union[OpenAIObject, Iterator[OpenAIObject]]: response = OpenAIWrapper._convert_cache_to_response(_args, kwargs, cache_response) if kwargs.get("stream", False): return iter([response]) @@ -256,7 +302,7 @@ def convert_cache_to_response(_args: Sequence[Any], kwargs: Dict[str, Any], cach return response @staticmethod - def aconvert_cache_to_response(_args: Sequence[Any], kwargs: Dict[str, Any], cache_response: TraceLog) -> Union[OpenAIObject, AsyncIterator[OpenAIObject]]: + def aconvert_cache_to_response(_args: Sequence[Any], kwargs: dict[str, Any], cache_response: TraceLog) -> Union[OpenAIObject, AsyncIterator[OpenAIObject]]: response = OpenAIWrapper._convert_cache_to_response(_args, kwargs, cache_response) if kwargs.get("stream", False): From 76414b8b1fc52fe009d0b0bc6f0d5a91577e0528 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 15:07:01 -0500 Subject: [PATCH 3/7] update other cookbook examples --- parea/cookbook/tracing_with_Parea_sdk.ipynb | 138 ++++++------ ...ing_with_function_calling_and_chains.ipynb | 213 +++++++++--------- .../tracing_with_open_ai_endpoint_directly.py | 6 +- .../tracing_with_openai_with_functions.py | 2 +- parea/wrapper/openai.py | 13 +- 5 files changed, 190 insertions(+), 182 deletions(-) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index b34190fa..cf7ca43e 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -117,44 +117,44 @@ "\n", "\n", "def argument_generator(query: str, additional_description: str = \"\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", - " llm_inputs={\"argument\": argument},\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", + " llm_inputs={\"argument\": argument},\n", + " )\n", + " ).content\n", "\n", "\n", "def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "# Non deployed version\n", - "# from parea.schemas.models import LLMInputs, Message, ModelParams, Role\n", + "# from parea.schemas.logs import LLMInputs, Message, ModelParams, Role\n", "\n", "\n", "# def argument_generator(query: str, additional_description: str = \"\") -> str:\n", @@ -209,9 +209,9 @@ "\n", "@trace\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism)" + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism)" ] }, { @@ -251,8 +251,8 @@ ], "source": [ "result1 = argument_chain(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(result1)" ] @@ -302,10 +302,10 @@ "\n", "@trace\n", "def argument_chain2(query: str, additional_description: str = \"\") -> tuple[str, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism), trace_id" ] }, { @@ -331,8 +331,8 @@ ], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(trace_id)" ] @@ -424,30 +424,30 @@ "\n", "# let's return the full CompletionResponse to see what other information is returned\n", "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", " )\n", - " )\n", "\n", "\n", "@trace\n", "def argument_chain3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism)\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism)\n", "\n", "\n", "result2 = argument_chain3(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))" ], @@ -498,14 +498,14 @@ "\n", "# you can also add metadata and tags via the decorator\n", "@trace(\n", - " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", - " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", + " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", + " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", ")\n", "def argument_chain_tags_metadata(query: str, additional_description: str = \"\") -> Tuple[CompletionResponse, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism), trace_id" ] }, { @@ -515,17 +515,17 @@ "from attrs import asdict\n", "\n", "result2, trace_id = argument_chain_tags_metadata(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=trace_id,\n", - " score=0.7, # 0.0 (bad) to 1.0 (good)\n", - " target=\"Coffee is wonderful. End of story.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=trace_id,\n", + " score=0.7, # 0.0 (bad) to 1.0 (good)\n", + " target=\"Coffee is wonderful. End of story.\",\n", + " )\n", ")" ], "metadata": { diff --git a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb index 1da2fbec..126d201e 100644 --- a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb +++ b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb @@ -22,7 +22,8 @@ "from typing import List, Dict, Any, Union\n", "\n", "from parea import Parea\n", - "from parea.schemas.models import Completion, LLMInputs, Message, ModelParams\n", + "from parea.schemas.log import LLMInputs, Message, ModelParams\n", + "from parea.schemas.models import Completion\n", "from parea.utils.trace_utils import trace, trace_insert\n", "\n", "p = Parea(api_key=os.environ[\"PAREA_API_KEY\"])" @@ -39,60 +40,60 @@ "LIMIT = 2 # limit any loops to 2 iterations for demo purposes\n", "\n", "COURSE_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_course_outline\",\n", - " \"description\": \"Generates a course outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", - " \"chapters\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_course_outline\",\n", + " \"description\": \"Generates a course outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", + " \"chapters\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The chapters included in the course\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The chapters included in the course\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", + " \"required\": [\"Description\", \"chapters\"],\n", " },\n", - " },\n", - " \"required\": [\"Description\", \"chapters\"],\n", - " },\n", - " }\n", + " }\n", "]\n", "\n", "CHAPTER_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_chapter_outline\",\n", - " \"description\": \"Generates a chapter outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", - " \"sections\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_chapter_outline\",\n", + " \"description\": \"Generates a chapter outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"sections\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The sections included in the chapter\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The sections included in the chapter\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", + " \"required\": [\"name\", \"description\", \"sections\"],\n", " },\n", - " },\n", - " \"required\": [\"name\", \"description\", \"sections\"],\n", - " },\n", - " }\n", + " }\n", "]" ], "metadata": { @@ -114,29 +115,29 @@ "# Create a reusable call lmm helper function\n", "# Parea SDK is automatically traced\n", "def call_llm(messages: List[Dict[str, str]], name: str = \"LLM Call\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " llm_configuration=LLMInputs(\n", - " model=\"gpt-3.5-turbo-1106\",\n", - " model_params=ModelParams(temp=0.0, max_length=512),\n", - " messages=[Message(**m) for m in messages],\n", - " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", - " ),\n", - " end_user_identifier=USER,\n", - " trace_name=name,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " llm_configuration=LLMInputs(\n", + " model=\"gpt-3.5-turbo-1106\",\n", + " model_params=ModelParams(temp=0.0, max_length=512),\n", + " messages=[Message(**m) for m in messages],\n", + " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", + " ),\n", + " end_user_identifier=USER,\n", + " trace_name=name,\n", + " )\n", + " ).content\n", "\n", "\n", "# Helper function to get function call arguments if they exists\n", "def get_function_call_or_content(response: str) -> Union[str, Dict[str, Any]]:\n", - " # Function calls are returned in triple backticks\n", - " parsed_response = response.replace(\"```\", \"\")\n", - " # return function call or content string\n", - " try:\n", - " return json.loads(parsed_response).get(\"arguments\")\n", - " except Exception as e:\n", - " return parsed_response" + " # Function calls are returned in triple backticks\n", + " parsed_response = response.replace(\"```\", \"\")\n", + " # return function call or content string\n", + " try:\n", + " return json.loads(parsed_response).get(\"arguments\")\n", + " except Exception as e:\n", + " return parsed_response" ], "metadata": { "collapsed": false @@ -151,13 +152,13 @@ "\n", "\n", "def get_course(topic: str):\n", - " _course_outline = call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", - " name=f\"Create {topic} Course Outline\",\n", - " )\n", - " course_outline = get_function_call_or_content(_course_outline)\n", - " print(json.dumps(course_outline, indent=4))\n", - " return course_outline\n", + " _course_outline = call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", + " name=f\"Create {topic} Course Outline\",\n", + " )\n", + " course_outline = get_function_call_or_content(_course_outline)\n", + " print(json.dumps(course_outline, indent=4))\n", + " return course_outline\n", "\n", "\n", "# I want to group all llm calls into one trace,\n", @@ -165,39 +166,37 @@ "# each call_llm will be a child span\n", "@trace(name=\"Get Chapters\")\n", "def get_chapters(course_outline: Dict[str, str]):\n", - " chapter_outlines = course_outline.get(\"chapters\", [])\n", - " chapters = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\",\n", - " \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", - " name=f\"Create Chapter {idx}\",\n", - " )\n", - " )\n", - " for idx, chapter in enumerate(chapter_outlines, start=1)\n", - " ]\n", - " return chapters[:LIMIT]\n", + " chapter_outlines = course_outline.get(\"chapters\", [])\n", + " chapters = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", + " name=f\"Create Chapter {idx}\",\n", + " )\n", + " )\n", + " for idx, chapter in enumerate(chapter_outlines, start=1)\n", + " ]\n", + " return chapters[:LIMIT]\n", "\n", "\n", "@trace\n", "def get_sections(chapter: Dict[str, str]):\n", - " chapter_name = chapter.get(\"name\", \"section\")\n", - " # I want the trace name to be dynamic based on the chapter param,\n", - " # so I can use Parea trace_insert helper method to add dynamic data\n", - " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", + " chapter_name = chapter.get(\"name\", \"section\")\n", + " # I want the trace name to be dynamic based on the chapter param,\n", + " # so I can use Parea trace_insert helper method to add dynamic data\n", + " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", "\n", - " section_outlines = chapter.get(\"sections\", [])\n", - " sections = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\",\n", - " \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", - " name=f\"Create Section {idx}\",\n", - " )\n", - " )\n", - " for idx, section in enumerate(section_outlines, start=1)\n", - " ]\n", - " return sections[:LIMIT]" + " section_outlines = chapter.get(\"sections\", [])\n", + " sections = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", + " name=f\"Create Section {idx}\",\n", + " )\n", + " )\n", + " for idx, section in enumerate(section_outlines, start=1)\n", + " ]\n", + " return sections[:LIMIT]" ], "metadata": { "collapsed": false @@ -210,23 +209,23 @@ "source": [ "@trace(name=\"Get Sections\")\n", "def get_all_sections(chapters: List[Dict[str, str]]):\n", - " return [get_sections(chapter) for chapter in chapters]\n", + " return [get_sections(chapter) for chapter in chapters]\n", "\n", "\n", "@trace\n", "def run_creation(topic: str):\n", - " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", - " course_outline = get_course(topic)\n", - " chapters = get_chapters(course_outline)\n", - " sections = get_all_sections(chapters)\n", - " return sections\n", + " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", + " course_outline = get_course(topic)\n", + " chapters = get_chapters(course_outline)\n", + " sections = get_all_sections(chapters)\n", + " return sections\n", "\n", "\n", "@trace(name=\"Generate Courses for Topics\")\n", "def main(topics):\n", - " for topic in topics:\n", - " print(f\"\\n New Topic: {topic} \\n\")\n", - " run_creation(topic)" + " for topic in topics:\n", + " print(f\"\\n New Topic: {topic} \\n\")\n", + " run_creation(topic)" ], "metadata": { "collapsed": false diff --git a/parea/cookbook/tracing_with_open_ai_endpoint_directly.py b/parea/cookbook/tracing_with_open_ai_endpoint_directly.py index 14cd4656..8274d5d8 100644 --- a/parea/cookbook/tracing_with_open_ai_endpoint_directly.py +++ b/parea/cookbook/tracing_with_open_ai_endpoint_directly.py @@ -15,14 +15,14 @@ openai.api_key = os.getenv("OPENAI_API_KEY") -p = Parea(api_key=os.getenv("PAREA_API_KEY")) +p = Parea(api_key=os.getenv("DEV_API_KEY")) def call_llm(data: list[dict], model: str = "gpt-3.5-turbo", temperature: float = 0.0) -> str: - return openai.ChatCompletion.create(model=model, temperature=temperature, messages=data).choices[0].message["content"] + return openai.chat.completions.create(model=model, temperature=temperature, messages=data).choices[0].message.content -def random_eval(inputs: Dict[str, str], output, target: Optional[str] = None) -> float: +def random_eval(inputs: dict[str, str], output=None, target: Optional[str] = None) -> float: # return random number between 0 and 1 return random.random() diff --git a/parea/cookbook/tracing_with_openai_with_functions.py b/parea/cookbook/tracing_with_openai_with_functions.py index 7702aaf4..bf7c3d0e 100644 --- a/parea/cookbook/tracing_with_openai_with_functions.py +++ b/parea/cookbook/tracing_with_openai_with_functions.py @@ -140,7 +140,7 @@ def provide_user_specific_recommendations(user_input, user_id, functions) -> tup food_preference = customer_profile.get("preferences", {}).get("food", [])[0] if customer_profile.get("preferences", {}).get("food") else None - response = openai.ChatCompletion.create( + response = openai.chat.completions.create( model="gpt-3.5-turbo", messages=[ { diff --git a/parea/wrapper/openai.py b/parea/wrapper/openai.py index 629e6c23..10add123 100644 --- a/parea/wrapper/openai.py +++ b/parea/wrapper/openai.py @@ -1,6 +1,7 @@ -from typing import Any, Callable, Dict, Optional, Union +from typing import Any, Callable, Optional, Union import json +import os from collections import defaultdict from collections.abc import AsyncIterator, Iterator, Sequence @@ -17,12 +18,16 @@ def convert_to_openai_object(**kwargs): return OpenAIObject(**kwargs) +from dotenv import load_dotenv + from ..cache.cache import Cache from ..schemas.log import LLMInputs, ModelParams from ..schemas.models import CacheRequest, TraceLog from ..utils.trace_utils import trace_data from .wrapper import Wrapper +load_dotenv() + OPENAI_MODEL_INFO: dict[str, dict[str, Union[float, int, dict[str, int]]]] = { "gpt-3.5-turbo": { "prompt": 1.5, @@ -108,10 +113,14 @@ def convert_to_openai_object(**kwargs): class OpenAIWrapper: + openai.api_key = os.getenv("OPENAI_API_KEY") if openai_version.startswith("0."): original_methods = {"ChatCompletion.create": openai.ChatCompletion.create, "ChatCompletion.acreate": openai.ChatCompletion.acreate} else: - original_methods = {"chat.completions.create": openai.chat.completions.create} + try: + original_methods = {"chat.completions.create": openai.chat.completions.create} + except openai.OpenAIError: + original_methods = {} def init(self, log: Callable, cache: Cache = None): Wrapper( From d803734aadc455bdd0e280d7b4c14635a4eeacbf Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 15:08:31 -0500 Subject: [PATCH 4/7] prepatch --- parea/cookbook/tracing_with_Parea_sdk.ipynb | 136 ++++++------ ...ing_with_function_calling_and_chains.ipynb | 210 +++++++++--------- 2 files changed, 174 insertions(+), 172 deletions(-) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index cf7ca43e..5556186c 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -117,40 +117,40 @@ "\n", "\n", "def argument_generator(query: str, additional_description: str = \"\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", - " llm_inputs={\"argument\": argument},\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", + " llm_inputs={\"argument\": argument},\n", + " )\n", + " ).content\n", "\n", "\n", "def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "# Non deployed version\n", @@ -209,9 +209,9 @@ "\n", "@trace\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism)" + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism)" ] }, { @@ -251,8 +251,8 @@ ], "source": [ "result1 = argument_chain(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(result1)" ] @@ -302,10 +302,10 @@ "\n", "@trace\n", "def argument_chain2(query: str, additional_description: str = \"\") -> tuple[str, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism), trace_id" ] }, { @@ -331,8 +331,8 @@ ], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(trace_id)" ] @@ -424,30 +424,30 @@ "\n", "# let's return the full CompletionResponse to see what other information is returned\n", "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", " )\n", + " )\n", "\n", "\n", "@trace\n", "def argument_chain3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism)\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism)\n", "\n", "\n", "result2 = argument_chain3(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))" ], @@ -498,14 +498,14 @@ "\n", "# you can also add metadata and tags via the decorator\n", "@trace(\n", - " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", - " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", + " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", + " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", ")\n", "def argument_chain_tags_metadata(query: str, additional_description: str = \"\") -> Tuple[CompletionResponse, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism), trace_id" ] }, { @@ -515,17 +515,17 @@ "from attrs import asdict\n", "\n", "result2, trace_id = argument_chain_tags_metadata(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=trace_id,\n", - " score=0.7, # 0.0 (bad) to 1.0 (good)\n", - " target=\"Coffee is wonderful. End of story.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=trace_id,\n", + " score=0.7, # 0.0 (bad) to 1.0 (good)\n", + " target=\"Coffee is wonderful. End of story.\",\n", + " )\n", ")" ], "metadata": { diff --git a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb index 126d201e..a3156a66 100644 --- a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb +++ b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb @@ -40,60 +40,60 @@ "LIMIT = 2 # limit any loops to 2 iterations for demo purposes\n", "\n", "COURSE_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_course_outline\",\n", - " \"description\": \"Generates a course outline\",\n", - " \"parameters\": {\n", + " {\n", + " \"name\": \"generate_course_outline\",\n", + " \"description\": \"Generates a course outline\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", + " \"chapters\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", - " \"chapters\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", - " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The chapters included in the course\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", - " },\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", " },\n", - " \"required\": [\"Description\", \"chapters\"],\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The chapters included in the course\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", " },\n", - " }\n", + " },\n", + " \"required\": [\"Description\", \"chapters\"],\n", + " },\n", + " }\n", "]\n", "\n", "CHAPTER_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_chapter_outline\",\n", - " \"description\": \"Generates a chapter outline\",\n", - " \"parameters\": {\n", + " {\n", + " \"name\": \"generate_chapter_outline\",\n", + " \"description\": \"Generates a chapter outline\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"sections\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", - " \"sections\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", - " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The sections included in the chapter\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", - " },\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", " },\n", - " \"required\": [\"name\", \"description\", \"sections\"],\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The sections included in the chapter\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", " },\n", - " }\n", + " },\n", + " \"required\": [\"name\", \"description\", \"sections\"],\n", + " },\n", + " }\n", "]" ], "metadata": { @@ -115,29 +115,29 @@ "# Create a reusable call lmm helper function\n", "# Parea SDK is automatically traced\n", "def call_llm(messages: List[Dict[str, str]], name: str = \"LLM Call\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " llm_configuration=LLMInputs(\n", - " model=\"gpt-3.5-turbo-1106\",\n", - " model_params=ModelParams(temp=0.0, max_length=512),\n", - " messages=[Message(**m) for m in messages],\n", - " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", - " ),\n", - " end_user_identifier=USER,\n", - " trace_name=name,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " llm_configuration=LLMInputs(\n", + " model=\"gpt-3.5-turbo-1106\",\n", + " model_params=ModelParams(temp=0.0, max_length=512),\n", + " messages=[Message(**m) for m in messages],\n", + " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", + " ),\n", + " end_user_identifier=USER,\n", + " trace_name=name,\n", + " )\n", + " ).content\n", "\n", "\n", "# Helper function to get function call arguments if they exists\n", "def get_function_call_or_content(response: str) -> Union[str, Dict[str, Any]]:\n", - " # Function calls are returned in triple backticks\n", - " parsed_response = response.replace(\"```\", \"\")\n", - " # return function call or content string\n", - " try:\n", - " return json.loads(parsed_response).get(\"arguments\")\n", - " except Exception as e:\n", - " return parsed_response" + " # Function calls are returned in triple backticks\n", + " parsed_response = response.replace(\"```\", \"\")\n", + " # return function call or content string\n", + " try:\n", + " return json.loads(parsed_response).get(\"arguments\")\n", + " except Exception as e:\n", + " return parsed_response" ], "metadata": { "collapsed": false @@ -152,13 +152,13 @@ "\n", "\n", "def get_course(topic: str):\n", - " _course_outline = call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", - " name=f\"Create {topic} Course Outline\",\n", - " )\n", - " course_outline = get_function_call_or_content(_course_outline)\n", - " print(json.dumps(course_outline, indent=4))\n", - " return course_outline\n", + " _course_outline = call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", + " name=f\"Create {topic} Course Outline\",\n", + " )\n", + " course_outline = get_function_call_or_content(_course_outline)\n", + " print(json.dumps(course_outline, indent=4))\n", + " return course_outline\n", "\n", "\n", "# I want to group all llm calls into one trace,\n", @@ -166,37 +166,39 @@ "# each call_llm will be a child span\n", "@trace(name=\"Get Chapters\")\n", "def get_chapters(course_outline: Dict[str, str]):\n", - " chapter_outlines = course_outline.get(\"chapters\", [])\n", - " chapters = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", - " name=f\"Create Chapter {idx}\",\n", - " )\n", - " )\n", - " for idx, chapter in enumerate(chapter_outlines, start=1)\n", - " ]\n", - " return chapters[:LIMIT]\n", + " chapter_outlines = course_outline.get(\"chapters\", [])\n", + " chapters = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\",\n", + " \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", + " name=f\"Create Chapter {idx}\",\n", + " )\n", + " )\n", + " for idx, chapter in enumerate(chapter_outlines, start=1)\n", + " ]\n", + " return chapters[:LIMIT]\n", "\n", "\n", "@trace\n", "def get_sections(chapter: Dict[str, str]):\n", - " chapter_name = chapter.get(\"name\", \"section\")\n", - " # I want the trace name to be dynamic based on the chapter param,\n", - " # so I can use Parea trace_insert helper method to add dynamic data\n", - " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", + " chapter_name = chapter.get(\"name\", \"section\")\n", + " # I want the trace name to be dynamic based on the chapter param,\n", + " # so I can use Parea trace_insert helper method to add dynamic data\n", + " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", "\n", - " section_outlines = chapter.get(\"sections\", [])\n", - " sections = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", - " name=f\"Create Section {idx}\",\n", - " )\n", - " )\n", - " for idx, section in enumerate(section_outlines, start=1)\n", - " ]\n", - " return sections[:LIMIT]" + " section_outlines = chapter.get(\"sections\", [])\n", + " sections = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\",\n", + " \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", + " name=f\"Create Section {idx}\",\n", + " )\n", + " )\n", + " for idx, section in enumerate(section_outlines, start=1)\n", + " ]\n", + " return sections[:LIMIT]" ], "metadata": { "collapsed": false @@ -209,23 +211,23 @@ "source": [ "@trace(name=\"Get Sections\")\n", "def get_all_sections(chapters: List[Dict[str, str]]):\n", - " return [get_sections(chapter) for chapter in chapters]\n", + " return [get_sections(chapter) for chapter in chapters]\n", "\n", "\n", "@trace\n", "def run_creation(topic: str):\n", - " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", - " course_outline = get_course(topic)\n", - " chapters = get_chapters(course_outline)\n", - " sections = get_all_sections(chapters)\n", - " return sections\n", + " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", + " course_outline = get_course(topic)\n", + " chapters = get_chapters(course_outline)\n", + " sections = get_all_sections(chapters)\n", + " return sections\n", "\n", "\n", "@trace(name=\"Generate Courses for Topics\")\n", "def main(topics):\n", - " for topic in topics:\n", - " print(f\"\\n New Topic: {topic} \\n\")\n", - " run_creation(topic)" + " for topic in topics:\n", + " print(f\"\\n New Topic: {topic} \\n\")\n", + " run_creation(topic)" ], "metadata": { "collapsed": false From 357d3646b1802d8f2c1728151d82924c06f3da2f Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 15:12:31 -0500 Subject: [PATCH 5/7] move eval from example --- .../tracing_with_open_ai_endpoint_directly.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/parea/cookbook/tracing_with_open_ai_endpoint_directly.py b/parea/cookbook/tracing_with_open_ai_endpoint_directly.py index 8274d5d8..5cae2819 100644 --- a/parea/cookbook/tracing_with_open_ai_endpoint_directly.py +++ b/parea/cookbook/tracing_with_open_ai_endpoint_directly.py @@ -1,7 +1,4 @@ -from typing import Dict, Optional - import os -import random from datetime import datetime import openai @@ -22,12 +19,7 @@ def call_llm(data: list[dict], model: str = "gpt-3.5-turbo", temperature: float return openai.chat.completions.create(model=model, temperature=temperature, messages=data).choices[0].message.content -def random_eval(inputs: dict[str, str], output=None, target: Optional[str] = None) -> float: - # return random number between 0 and 1 - return random.random() - - -@trace(eval_funcs=[random_eval]) +@trace def argumentor(query: str, additional_description: str = "") -> str: return call_llm( [ @@ -56,7 +48,7 @@ def critic(argument: str) -> str: ) -@trace(eval_funcs=[random_eval]) +@trace def refiner(query: str, additional_description: str, argument: str, criticism: str) -> str: return call_llm( [ @@ -76,7 +68,7 @@ def refiner(query: str, additional_description: str, argument: str, criticism: s ) -@trace(eval_funcs=[random_eval], access_output_of_func=lambda x: x[0]) +@trace def argument_chain(query: str, additional_description: str = "") -> tuple[str, str]: trace_id = get_current_trace_id() argument = argumentor(query, additional_description) From 3a08a1a18a9928d05caa68371575898ba8462c54 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 15:13:47 -0500 Subject: [PATCH 6/7] codestyle --- parea/cookbook/tracing_with_Parea_sdk.ipynb | 136 ++++++------ ...ing_with_function_calling_and_chains.ipynb | 210 +++++++++--------- 2 files changed, 172 insertions(+), 174 deletions(-) diff --git a/parea/cookbook/tracing_with_Parea_sdk.ipynb b/parea/cookbook/tracing_with_Parea_sdk.ipynb index 5556186c..cf7ca43e 100644 --- a/parea/cookbook/tracing_with_Parea_sdk.ipynb +++ b/parea/cookbook/tracing_with_Parea_sdk.ipynb @@ -117,40 +117,40 @@ "\n", "\n", "def argument_generator(query: str, additional_description: str = \"\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-tbFUZ5rRaXshj8o5Opfyr\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "def critic(argument: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", - " llm_inputs={\"argument\": argument},\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-iAuVLFHy6VypfGZxwAWW0\",\n", + " llm_inputs={\"argument\": argument},\n", + " )\n", + " ).content\n", "\n", "\n", "def refiner(query: str, additional_description: str, current_arg: str, criticism: str) -> str:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", + " ).content\n", "\n", "\n", "# Non deployed version\n", @@ -209,9 +209,9 @@ "\n", "@trace\n", "def argument_chain(query: str, additional_description: str = \"\") -> str:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism)" + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism)" ] }, { @@ -251,8 +251,8 @@ ], "source": [ "result1 = argument_chain(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(result1)" ] @@ -302,10 +302,10 @@ "\n", "@trace\n", "def argument_chain2(query: str, additional_description: str = \"\") -> tuple[str, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner(query, additional_description, argument, criticism), trace_id" ] }, { @@ -331,8 +331,8 @@ ], "source": [ "result, trace_id = argument_chain2(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(trace_id)" ] @@ -424,30 +424,30 @@ "\n", "# let's return the full CompletionResponse to see what other information is returned\n", "def refiner2(query: str, additional_description: str, current_arg: str, criticism: str) -> CompletionResponse:\n", - " return p.completion(\n", - " Completion(\n", - " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", - " llm_inputs={\n", - " \"additional_description\": additional_description,\n", - " \"date\": f\"{datetime.now()}\",\n", - " \"query\": query,\n", - " \"argument\": current_arg,\n", - " \"criticism\": criticism,\n", - " },\n", + " return p.completion(\n", + " Completion(\n", + " deployment_id=\"p-rEjM4X10rJomOD8Rj9gzJ\",\n", + " llm_inputs={\n", + " \"additional_description\": additional_description,\n", + " \"date\": f\"{datetime.now()}\",\n", + " \"query\": query,\n", + " \"argument\": current_arg,\n", + " \"criticism\": criticism,\n", + " },\n", + " )\n", " )\n", - " )\n", "\n", "\n", "@trace\n", "def argument_chain3(query: str, additional_description: str = \"\") -> CompletionResponse:\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism)\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism)\n", "\n", "\n", "result2 = argument_chain3(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))" ], @@ -498,14 +498,14 @@ "\n", "# you can also add metadata and tags via the decorator\n", "@trace(\n", - " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", - " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", + " tags=[\"cookbook-example-deployed\", \"feedback_tracked-deployed\"],\n", + " metadata={\"source\": \"python-sdk\", \"deployed\": \"True\"},\n", ")\n", "def argument_chain_tags_metadata(query: str, additional_description: str = \"\") -> Tuple[CompletionResponse, str]:\n", - " trace_id = get_current_trace_id() # get parent's trace_id\n", - " argument = argument_generator(query, additional_description)\n", - " criticism = critic(argument)\n", - " return refiner2(query, additional_description, argument, criticism), trace_id" + " trace_id = get_current_trace_id() # get parent's trace_id\n", + " argument = argument_generator(query, additional_description)\n", + " criticism = critic(argument)\n", + " return refiner2(query, additional_description, argument, criticism), trace_id" ] }, { @@ -515,17 +515,17 @@ "from attrs import asdict\n", "\n", "result2, trace_id = argument_chain_tags_metadata(\n", - " \"Whether coffee is good for you.\",\n", - " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", + " \"Whether coffee is good for you.\",\n", + " additional_description=\"Provide a concise, few sentence argument on why coffee is good for you.\",\n", ")\n", "print(json.dumps(asdict(result2), indent=2))\n", "\n", "p.record_feedback(\n", - " FeedbackRequest(\n", - " trace_id=trace_id,\n", - " score=0.7, # 0.0 (bad) to 1.0 (good)\n", - " target=\"Coffee is wonderful. End of story.\",\n", - " )\n", + " FeedbackRequest(\n", + " trace_id=trace_id,\n", + " score=0.7, # 0.0 (bad) to 1.0 (good)\n", + " target=\"Coffee is wonderful. End of story.\",\n", + " )\n", ")" ], "metadata": { diff --git a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb index a3156a66..126d201e 100644 --- a/parea/cookbook/tracing_with_function_calling_and_chains.ipynb +++ b/parea/cookbook/tracing_with_function_calling_and_chains.ipynb @@ -40,60 +40,60 @@ "LIMIT = 2 # limit any loops to 2 iterations for demo purposes\n", "\n", "COURSE_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_course_outline\",\n", - " \"description\": \"Generates a course outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", - " \"chapters\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_course_outline\",\n", + " \"description\": \"Generates a course outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"Description\": {\"type\": \"string\", \"description\": \"The description of the course\"},\n", + " \"chapters\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The chapters included in the course\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The chapters included in the course\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", + " \"required\": [\"Description\", \"chapters\"],\n", " },\n", - " },\n", - " \"required\": [\"Description\", \"chapters\"],\n", - " },\n", - " }\n", + " }\n", "]\n", "\n", "CHAPTER_FUNCTIONS = [\n", - " {\n", - " \"name\": \"generate_chapter_outline\",\n", - " \"description\": \"Generates a chapter outline\",\n", - " \"parameters\": {\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", - " \"sections\": {\n", - " \"type\": \"array\",\n", - " \"items\": {\n", + " {\n", + " \"name\": \"generate_chapter_outline\",\n", + " \"description\": \"Generates a chapter outline\",\n", + " \"parameters\": {\n", " \"type\": \"object\",\n", " \"properties\": {\n", - " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", - " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the chapter\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the chapter\"},\n", + " \"sections\": {\n", + " \"type\": \"array\",\n", + " \"items\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"name\": {\"type\": \"string\", \"description\": \"The title of the section\"},\n", + " \"description\": {\"type\": \"string\", \"description\": \"The summary of the section\"},\n", + " },\n", + " \"required\": [\"name\", \"description\"],\n", + " },\n", + " \"description\": \"The sections included in the chapter\",\n", + " \"minItems\": 1,\n", + " \"maxItems\": LIMIT,\n", + " },\n", " },\n", - " \"required\": [\"name\", \"description\"],\n", - " },\n", - " \"description\": \"The sections included in the chapter\",\n", - " \"minItems\": 1,\n", - " \"maxItems\": LIMIT,\n", + " \"required\": [\"name\", \"description\", \"sections\"],\n", " },\n", - " },\n", - " \"required\": [\"name\", \"description\", \"sections\"],\n", - " },\n", - " }\n", + " }\n", "]" ], "metadata": { @@ -115,29 +115,29 @@ "# Create a reusable call lmm helper function\n", "# Parea SDK is automatically traced\n", "def call_llm(messages: List[Dict[str, str]], name: str = \"LLM Call\") -> str:\n", - " return p.completion(\n", - " Completion(\n", - " llm_configuration=LLMInputs(\n", - " model=\"gpt-3.5-turbo-1106\",\n", - " model_params=ModelParams(temp=0.0, max_length=512),\n", - " messages=[Message(**m) for m in messages],\n", - " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", - " ),\n", - " end_user_identifier=USER,\n", - " trace_name=name,\n", - " )\n", - " ).content\n", + " return p.completion(\n", + " Completion(\n", + " llm_configuration=LLMInputs(\n", + " model=\"gpt-3.5-turbo-1106\",\n", + " model_params=ModelParams(temp=0.0, max_length=512),\n", + " messages=[Message(**m) for m in messages],\n", + " functions=COURSE_FUNCTIONS + CHAPTER_FUNCTIONS,\n", + " ),\n", + " end_user_identifier=USER,\n", + " trace_name=name,\n", + " )\n", + " ).content\n", "\n", "\n", "# Helper function to get function call arguments if they exists\n", "def get_function_call_or_content(response: str) -> Union[str, Dict[str, Any]]:\n", - " # Function calls are returned in triple backticks\n", - " parsed_response = response.replace(\"```\", \"\")\n", - " # return function call or content string\n", - " try:\n", - " return json.loads(parsed_response).get(\"arguments\")\n", - " except Exception as e:\n", - " return parsed_response" + " # Function calls are returned in triple backticks\n", + " parsed_response = response.replace(\"```\", \"\")\n", + " # return function call or content string\n", + " try:\n", + " return json.loads(parsed_response).get(\"arguments\")\n", + " except Exception as e:\n", + " return parsed_response" ], "metadata": { "collapsed": false @@ -152,13 +152,13 @@ "\n", "\n", "def get_course(topic: str):\n", - " _course_outline = call_llm(\n", - " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", - " name=f\"Create {topic} Course Outline\",\n", - " )\n", - " course_outline = get_function_call_or_content(_course_outline)\n", - " print(json.dumps(course_outline, indent=4))\n", - " return course_outline\n", + " _course_outline = call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a course outline on {topic}\"}],\n", + " name=f\"Create {topic} Course Outline\",\n", + " )\n", + " course_outline = get_function_call_or_content(_course_outline)\n", + " print(json.dumps(course_outline, indent=4))\n", + " return course_outline\n", "\n", "\n", "# I want to group all llm calls into one trace,\n", @@ -166,39 +166,37 @@ "# each call_llm will be a child span\n", "@trace(name=\"Get Chapters\")\n", "def get_chapters(course_outline: Dict[str, str]):\n", - " chapter_outlines = course_outline.get(\"chapters\", [])\n", - " chapters = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\",\n", - " \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", - " name=f\"Create Chapter {idx}\",\n", - " )\n", - " )\n", - " for idx, chapter in enumerate(chapter_outlines, start=1)\n", - " ]\n", - " return chapters[:LIMIT]\n", + " chapter_outlines = course_outline.get(\"chapters\", [])\n", + " chapters = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"Generate a chapter outline on {chapter.get('name')}, with description {chapter.get('description')}\"}],\n", + " name=f\"Create Chapter {idx}\",\n", + " )\n", + " )\n", + " for idx, chapter in enumerate(chapter_outlines, start=1)\n", + " ]\n", + " return chapters[:LIMIT]\n", "\n", "\n", "@trace\n", "def get_sections(chapter: Dict[str, str]):\n", - " chapter_name = chapter.get(\"name\", \"section\")\n", - " # I want the trace name to be dynamic based on the chapter param,\n", - " # so I can use Parea trace_insert helper method to add dynamic data\n", - " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", + " chapter_name = chapter.get(\"name\", \"section\")\n", + " # I want the trace name to be dynamic based on the chapter param,\n", + " # so I can use Parea trace_insert helper method to add dynamic data\n", + " trace_insert({\"trace_name\": f\"Get {chapter_name} Sections\"})\n", "\n", - " section_outlines = chapter.get(\"sections\", [])\n", - " sections = [\n", - " get_function_call_or_content(\n", - " call_llm(\n", - " messages=[{\"role\": \"user\",\n", - " \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", - " name=f\"Create Section {idx}\",\n", - " )\n", - " )\n", - " for idx, section in enumerate(section_outlines, start=1)\n", - " ]\n", - " return sections[:LIMIT]" + " section_outlines = chapter.get(\"sections\", [])\n", + " sections = [\n", + " get_function_call_or_content(\n", + " call_llm(\n", + " messages=[{\"role\": \"user\", \"content\": f\"\"\"Generate a section outline on {section['name']}, with description {section['description']}\"\"\"}],\n", + " name=f\"Create Section {idx}\",\n", + " )\n", + " )\n", + " for idx, section in enumerate(section_outlines, start=1)\n", + " ]\n", + " return sections[:LIMIT]" ], "metadata": { "collapsed": false @@ -211,23 +209,23 @@ "source": [ "@trace(name=\"Get Sections\")\n", "def get_all_sections(chapters: List[Dict[str, str]]):\n", - " return [get_sections(chapter) for chapter in chapters]\n", + " return [get_sections(chapter) for chapter in chapters]\n", "\n", "\n", "@trace\n", "def run_creation(topic: str):\n", - " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", - " course_outline = get_course(topic)\n", - " chapters = get_chapters(course_outline)\n", - " sections = get_all_sections(chapters)\n", - " return sections\n", + " trace_insert({\"trace_name\": f\"Course on {topic}\"})\n", + " course_outline = get_course(topic)\n", + " chapters = get_chapters(course_outline)\n", + " sections = get_all_sections(chapters)\n", + " return sections\n", "\n", "\n", "@trace(name=\"Generate Courses for Topics\")\n", "def main(topics):\n", - " for topic in topics:\n", - " print(f\"\\n New Topic: {topic} \\n\")\n", - " run_creation(topic)" + " for topic in topics:\n", + " print(f\"\\n New Topic: {topic} \\n\")\n", + " run_creation(topic)" ], "metadata": { "collapsed": false From 74840e62e12224cb40e7d79491151a40e1d64cb8 Mon Sep 17 00:00:00 2001 From: Joel Alexander Date: Sat, 9 Dec 2023 15:16:40 -0500 Subject: [PATCH 7/7] fix readme --- README.md | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index a33c2def..38c9307d 100644 --- a/README.md +++ b/README.md @@ -28,17 +28,21 @@ poetry add parea-ai ## Evaluating Your LLM App -You can evaluate any step of your LLM app by wrapping it with a decorator, called `trace`, and specifying the evaluation function(s). -The scores associated with the traces will be logged to the Parea [dashboard](https://app.parea.ai/logs) and/or in a local CSV file if you don't have a Parea API key. - -Evaluation functions receive an argument `log` (of type [Log](parea/schemas/models.py)) and should return a -float between 0 (bad) and 1 (good) inclusive. You don't need to start from scratch, there are pre-defined evaluation functions for [general purpose](parea/evals/general.py), +You can evaluate any step of your LLM app by wrapping it with a decorator, called `trace`, and specifying the evaluation +function(s). +The scores associated with the traces will be logged to the Parea [dashboard](https://app.parea.ai/logs) and/or in a +local CSV file if you don't have a Parea API key. + +Evaluation functions receive an argument `log` (of type [Log](parea/schemas/models.py)) and should return a +float between 0 (bad) and 1 (good) inclusive. You don't need to start from scratch, there are pre-defined evaluation +functions for [general purpose](parea/evals/general.py), [chat](parea/evals/chat.py), [RAG](parea/evals/rag.py), and [summarization](parea/evals/summary.py) apps :) -You can define evaluation functions locally or use the ones you have deployed to Parea's [Test Hub](https://app.parea.ai/test-hub). +You can define evaluation functions locally or use the ones you have deployed to +Parea's [Test Hub](https://app.parea.ai/test-hub). If you choose the latter option, the evaluation happens asynchronously and non-blocking. -A fully locally working cookbook can be found [here](parea/cookbook/tracing_and_evaluating_openai_endpoint.py). +A fully locally working cookbook can be found [here](parea/cookbook/tracing_and_evaluating_openai_endpoint.py). Alternatively, you can add the following code to your codebase to get started: ```python @@ -62,7 +66,8 @@ def function_to_evaluate(*args, **kwargs) -> ...: ## Debugging Chains & Agents You can iterate on your chains & agents much faster by using a local cache. This will allow you to make changes to your -code & prompts without waiting for all previous, valid LLM responses. Simply add these two lines to the beginning your code and start +code & prompts without waiting for all previous, valid LLM responses. Simply add these two lines to the beginning your +code and start [a local redis cache](https://redis.io/docs/getting-started/install-stack/): ```python @@ -71,14 +76,15 @@ from parea import init, RedisCache init(cache=RedisCache()) ``` -Above will use the default redis cache at `localhost:6379` with no password. You can also specify your redis database by: +Above will use the default redis cache at `localhost:6379` with no password. You can also specify your redis database +by: ```python from parea import init, RedisCache cache = RedisCache( host=os.getenv("REDIS_HOST", "localhost"), # default value - port=int(os.getenv("REDIS_PORT", 6379)), # default value + port=int(os.getenv("REDIS_PORT", 6379)), # default value password=os.getenv("REDIS_PASSWORT", None) # default value ) init(cache=cache) @@ -88,21 +94,24 @@ If you set `cache = None` for `init`, no cache will be used. ### Benchmark your LLM app across many inputs -You can benchmark your LLM app across many inputs by using the `benchmark` command. This will run your the entry point +You can benchmark your LLM app across many inputs by using the `benchmark` command. This will run your the entry point of your app with the specified inputs and create a report with the results. ```bash parea benchmark --func app:main --csv_path benchmark.csv ``` -The CSV file will be used to fill in the arguments to your function. The report will be a CSV file of all the traces. If you -set your Parea API key, the traces will also be logged to the Parea dashboard. Note, for this feature you need to have a +The CSV file will be used to fill in the arguments to your function. The report will be a CSV file of all the traces. If +you +set your Parea API key, the traces will also be logged to the Parea dashboard. Note, for this feature you need to have a redis cache running. Please, raise a GitHub issue if you would like to use this feature without a redis cache. ### Automatically log all your LLM call traces -You can automatically log all your LLM traces to the Parea dashboard by setting the `PAREA_API_KEY` environment variable or specifying it in the `init` function. -This will help you debug issues your customers are facing by stepping through the LLM call traces and recreating the issue +You can automatically log all your LLM traces to the Parea dashboard by setting the `PAREA_API_KEY` environment variable +or specifying it in the `init` function. +This will help you debug issues your customers are facing by stepping through the LLM call traces and recreating the +issue in your local setup & code. ```python @@ -114,7 +123,6 @@ init( ) ``` - ## Use a deployed prompt ```python @@ -195,7 +203,7 @@ temperature = 0.0 # define your OpenAI call as you would normally and we'll automatically log the results def main(): - openai.ChatCompletion.create(model=model, temperature=temperature, messages=messages).choices[0].message["content"] + openai.chat.completions.create(model=model, temperature=temperature, messages=messages).choices[0].message.content ``` ### Open source community features