From b2a53496034411353bf6d906886616564cdeb594 Mon Sep 17 00:00:00 2001 From: Alex Reibman Date: Wed, 21 Feb 2024 17:40:08 -0800 Subject: [PATCH 1/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 87fb1a0..734a49c 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Jaiqu -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![PyPI - Version](https://img.shields.io/pypi/v/tokencost) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) ![PyPI - Version](https://img.shields.io/pypi/v/jaiqu) [![X (formerly Twitter) Follow](https://img.shields.io/twitter/follow/AgentOpsAI)](https://x.com/agentopsai) Replicable, AI-generated JSON transformation queries. Transform any JSON into any schema automatically. From 57b40eb61a51df7041ea6f35cf4f03537f0f901d Mon Sep 17 00:00:00 2001 From: Howard Gil Date: Thu, 22 Feb 2024 12:34:22 -0800 Subject: [PATCH 2/8] WIP. Added notebook. Fixes to jq needed --- README.md | 6 +- implementation.ipynb | 188 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 3 deletions(-) create mode 100644 implementation.ipynb diff --git a/README.md b/README.md index 734a49c..ff64d48 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Building AI agents? Check out [AgentOps](https://agentops.ai/?jaiqu) ![Alt text](architecture.png) ### Features -* **Translate any schemam to any schema** AI agent automatically maps data from a source schema to a desired format by iteratively prompting GPT-4 to create valid jq query syntax. +* **Translate any schema to any schema** AI agent automatically maps data from a source schema to a desired format by iteratively prompting GPT-4 to create valid jq query syntax. * **Schema validation** Given a requirement schema, automatically validate whether the required data is present in the input json. * **Fuzzy term matching** Infers keys based on symantic similarity (i.e. datetime vs date_time). GPT-4 automaticlaly maps and translates input keys to desired output keys. @@ -59,12 +59,12 @@ input_json = { } # (Optional) Create hints so the agent knows what to look for in the input -key_hints="We are processing outputs of an containing an id, a date, and a model. All the required fields should be present in this input, but the names might be different. +key_hints="We are processing outputs of an containing an id, a date, and a model. All the required fields should be present in this input, but the names might be different." ``` Validating an input json contains all the information required in a schema ```python -schema_properties, valid = jaiqu.validate_schema(input_json, schema, key_hints) +schema_properties, valid = validate_schema(input_json, schema, key_hints) print(schema_properties) diff --git a/implementation.ipynb b/implementation.ipynb new file mode 100644 index 0000000..4df7da2 --- /dev/null +++ b/implementation.ipynb @@ -0,0 +1,188 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: openai in ./env/lib/python3.11/site-packages (1.12.0)\n", + "Requirement already satisfied: anyio<5,>=3.5.0 in ./env/lib/python3.11/site-packages (from openai) (4.3.0)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in ./env/lib/python3.11/site-packages (from openai) (1.9.0)\n", + "Requirement already satisfied: httpx<1,>=0.23.0 in ./env/lib/python3.11/site-packages (from openai) (0.27.0)\n", + "Requirement already satisfied: pydantic<3,>=1.9.0 in ./env/lib/python3.11/site-packages (from openai) (2.6.1)\n", + "Requirement already satisfied: sniffio in ./env/lib/python3.11/site-packages (from openai) (1.3.0)\n", + "Requirement already satisfied: tqdm>4 in ./env/lib/python3.11/site-packages (from openai) (4.66.2)\n", + "Requirement already satisfied: typing-extensions<5,>=4.7 in ./env/lib/python3.11/site-packages (from openai) (4.9.0)\n", + "Requirement already satisfied: idna>=2.8 in ./env/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai) (3.6)\n", + "Requirement already satisfied: certifi in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (2024.2.2)\n", + "Requirement already satisfied: httpcore==1.* in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (1.0.4)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in ./env/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.4.0 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (0.6.0)\n", + "Requirement already satisfied: pydantic-core==2.16.2 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (2.16.2)\n", + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", + "Requirement already satisfied: jaiqu in ./env/lib/python3.11/site-packages (0.0.1)\n", + "Requirement already satisfied: jq==1.6.0 in ./env/lib/python3.11/site-packages (from jaiqu) (1.6.0)\n", + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", + "Collecting jsonschema\n", + " Downloading jsonschema-4.21.1-py3-none-any.whl.metadata (7.8 kB)\n", + "Collecting attrs>=22.2.0 (from jsonschema)\n", + " Downloading attrs-23.2.0-py3-none-any.whl.metadata (9.5 kB)\n", + "Collecting jsonschema-specifications>=2023.03.6 (from jsonschema)\n", + " Downloading jsonschema_specifications-2023.12.1-py3-none-any.whl.metadata (3.0 kB)\n", + "Collecting referencing>=0.28.4 (from jsonschema)\n", + " Downloading referencing-0.33.0-py3-none-any.whl.metadata (2.7 kB)\n", + "Collecting rpds-py>=0.7.1 (from jsonschema)\n", + " Downloading rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl.metadata (4.1 kB)\n", + "Downloading jsonschema-4.21.1-py3-none-any.whl (85 kB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m85.5/85.5 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading attrs-23.2.0-py3-none-any.whl (60 kB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m60.8/60.8 kB\u001b[0m \u001b[31m7.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading jsonschema_specifications-2023.12.1-py3-none-any.whl (18 kB)\n", + "Downloading referencing-0.33.0-py3-none-any.whl (26 kB)\n", + "Downloading rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl (330 kB)\n", + "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m330.8/330.8 kB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mm eta \u001b[36m0:00:01\u001b[0m\n", + "\u001b[?25hInstalling collected packages: rpds-py, attrs, referencing, jsonschema-specifications, jsonschema\n", + "Successfully installed attrs-23.2.0 jsonschema-4.21.1 jsonschema-specifications-2023.12.1 referencing-0.33.0 rpds-py-0.18.0\n", + "\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", + "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/howardgil/Desktop/agentops/Jaiqu/env/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + } + ], + "source": [ + "import os\n", + "os.environ[\"OPENAI_API_KEY\"] = \"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\"\n", + "!pip install openai\n", + "!pip install jaiqu\n", + "#TODO add openai to requirements\n", + "#TODO add OPENAI_API_KEY to env\n", + "#TODO update so that validate_schema is available on init\n", + "#TODO add jsonschema to requirements\n", + "!pip install jsonschema\n", + "#TODO from jaiqu import validate_schema, translate_schema\n", + "from jaiqu.jaiqu import validate_schema, translate_schema" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "# TODO: Get from files\n", + "# Desired data format \n", + "schema = {\n", + " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"id\": {\n", + " \"type\": [\"string\", \"null\"],\n", + " \"description\": \"A unique identifier for the record.\"\n", + " },\n", + " \"date\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"A string describing the date.\"\n", + " },\n", + " \"model\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"A text field representing the model used.\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"id\",\n", + " \"date\"\n", + " ]\n", + "}\n", + "\n", + "# Provided data\n", + "input_json = {\n", + " \"call.id\": \"123\",\n", + " \"datetime\": \"2022-01-01\",\n", + " \"timestamp\": 1640995200,\n", + " \"Address\": \"123 Main St\",\n", + " \"user\": {\n", + " \"name\": \"John Doe\",\n", + " \"age\": 30,\n", + " \"contact\": \"john@email.com\"\n", + " }\n", + "}\n", + "\n", + "# (Optional) Create hints so the agent knows what to look for in the input\n", + "key_hints=\"We are processing outputs of an containing an id, a date, and a model. All the required fields should be present in this input, but the names might be different.\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "Validating schema: 100%|██████████| 3/3 [00:10<00:00, 3.64s/it, Key: model]" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'id': {'identified': True, 'key': 'call.id', 'message': '\"call.id\" | \"id\": The concepts are the same. The full key of \\'call.id\\' implies it is a unique identifier for the call, which matches the description of the \\'id\\' key. Therefore, the \\'call.id\\' field should count. Extracted key: `call.id`\\n', 'type': ['string', 'null'], 'description': 'A unique identifier for the record.', 'required': True}, 'date': {'identified': True, 'key': 'datetime', 'message': '\"date\" | \"datetime\": The field name \"date\" is not identical to \"datetime\", but both have the same concept that refers to date. Plus, the type of data (\\'string\\') and \\'description\\' of the data in the hint also refers to a form of date or time. Hence, it is reasonable to infer that \"datetime\" in the given schema contains date information. Extracted key: `datetime`', 'type': 'string', 'description': 'A string describing the date.', 'required': True}, 'model': {'identified': False, 'key': None, 'message': 'The \"model\" field is not present in the provided JSON schema. Despite going through each key in the JSON document, none of them describe or have any relevance to the \\'model\\' field as described \\'A text field representing the model used.\\'. Therefore, \\'model\\' does not appear to be available in the schema. Extracted key: `None`', 'type': 'string', 'description': 'A text field representing the model used.', 'required': False}}\n", + "True\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n" + ] + } + ], + "source": [ + "schema_properties, valid = validate_schema(input_json, schema, key_hints)\n", + "# TODO REMOVE jaiqu from schema_properties, valid = validate_schema(input_json, schema, key_hints)\n", + "\n", + "print(schema_properties)\n", + "print(valid)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "env", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 893488ca0af5870838b4a9789a47179e59fd3c61 Mon Sep 17 00:00:00 2001 From: Braelyn Boynton Date: Thu, 22 Feb 2024 12:43:05 -0800 Subject: [PATCH 3/8] clarify parameter types --- jaiqu/jaiqu.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jaiqu/jaiqu.py b/jaiqu/jaiqu.py index f9bba60..8ffce3b 100644 --- a/jaiqu/jaiqu.py +++ b/jaiqu/jaiqu.py @@ -6,8 +6,9 @@ from .helpers import identify_key, create_jq_string, repair_query, dict_to_jq_filter -def validate_schema(input_json, output_schema, key_hints=None) -> tuple[dict, bool]: +def validate_schema(input_json: dict, output_schema: dict, key_hints=None) -> tuple[dict, bool]: """Validates whether the required data in the output json schema is present in the input json.""" + """The input and output json should already be parsed into a dictionary""" results = {} valid = True with tqdm(total=len(output_schema['properties']), desc="Validating schema") as pbar: From 0ed68bceb6cdb1e3a0a7af4aa249a8cadac8f8ce Mon Sep 17 00:00:00 2001 From: Howard Gil Date: Thu, 22 Feb 2024 13:12:55 -0800 Subject: [PATCH 4/8] WIP. Fixing jq setup --- implementation.ipynb | 100 ++++++++++++++++++++++--------------------- jaiqu/__init__.py | 9 +++- jaiqu/helpers.py | 9 ++-- pyproject.toml | 8 ++-- requirements.txt | 3 ++ 5 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 requirements.txt diff --git a/implementation.ipynb b/implementation.ipynb index 4df7da2..1cb0e89 100644 --- a/implementation.ipynb +++ b/implementation.ipynb @@ -9,20 +9,32 @@ "name": "stdout", "output_type": "stream", "text": [ - "Requirement already satisfied: openai in ./env/lib/python3.11/site-packages (1.12.0)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in ./env/lib/python3.11/site-packages (from openai) (4.3.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in ./env/lib/python3.11/site-packages (from openai) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in ./env/lib/python3.11/site-packages (from openai) (0.27.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in ./env/lib/python3.11/site-packages (from openai) (2.6.1)\n", - "Requirement already satisfied: sniffio in ./env/lib/python3.11/site-packages (from openai) (1.3.0)\n", - "Requirement already satisfied: tqdm>4 in ./env/lib/python3.11/site-packages (from openai) (4.66.2)\n", - "Requirement already satisfied: typing-extensions<5,>=4.7 in ./env/lib/python3.11/site-packages (from openai) (4.9.0)\n", - "Requirement already satisfied: idna>=2.8 in ./env/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai) (3.6)\n", - "Requirement already satisfied: certifi in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (2024.2.2)\n", - "Requirement already satisfied: httpcore==1.* in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai) (1.0.4)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in ./env/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.4.0 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (0.6.0)\n", - "Requirement already satisfied: pydantic-core==2.16.2 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai) (2.16.2)\n", + "Requirement already satisfied: jq==1.6.0 in ./env/lib/python3.11/site-packages (from -r requirements.txt (line 1)) (1.6.0)\n", + "Collecting openai<2.0.0,>=1.12.0 (from -r requirements.txt (line 2))\n", + " Using cached openai-1.12.0-py3-none-any.whl.metadata (18 kB)\n", + "Collecting jsonschema==4.21.1 (from -r requirements.txt (line 3))\n", + " Using cached jsonschema-4.21.1-py3-none-any.whl.metadata (7.8 kB)\n", + "Requirement already satisfied: attrs>=22.2.0 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (23.2.0)\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (2023.12.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (0.33.0)\n", + "Requirement already satisfied: rpds-py>=0.7.1 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (0.18.0)\n", + "Requirement already satisfied: anyio<5,>=3.5.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.3.0)\n", + "Requirement already satisfied: distro<2,>=1.7.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.9.0)\n", + "Requirement already satisfied: httpx<1,>=0.23.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.27.0)\n", + "Requirement already satisfied: pydantic<3,>=1.9.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2.6.1)\n", + "Requirement already satisfied: sniffio in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.3.0)\n", + "Requirement already satisfied: tqdm>4 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.66.2)\n", + "Requirement already satisfied: typing-extensions<5,>=4.7 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.9.0)\n", + "Requirement already satisfied: idna>=2.8 in ./env/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (3.6)\n", + "Requirement already satisfied: certifi in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2024.2.2)\n", + "Requirement already satisfied: httpcore==1.* in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.0.4)\n", + "Requirement already satisfied: h11<0.15,>=0.13 in ./env/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.14.0)\n", + "Requirement already satisfied: annotated-types>=0.4.0 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.6.0)\n", + "Requirement already satisfied: pydantic-core==2.16.2 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2.16.2)\n", + "Using cached jsonschema-4.21.1-py3-none-any.whl (85 kB)\n", + "Using cached openai-1.12.0-py3-none-any.whl (226 kB)\n", + "Installing collected packages: openai, jsonschema\n", + "Successfully installed jsonschema-4.21.1 openai-1.12.0\n", "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", @@ -30,29 +42,6 @@ "Requirement already satisfied: jq==1.6.0 in ./env/lib/python3.11/site-packages (from jaiqu) (1.6.0)\n", "\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", - "Collecting jsonschema\n", - " Downloading jsonschema-4.21.1-py3-none-any.whl.metadata (7.8 kB)\n", - "Collecting attrs>=22.2.0 (from jsonschema)\n", - " Downloading attrs-23.2.0-py3-none-any.whl.metadata (9.5 kB)\n", - "Collecting jsonschema-specifications>=2023.03.6 (from jsonschema)\n", - " Downloading jsonschema_specifications-2023.12.1-py3-none-any.whl.metadata (3.0 kB)\n", - "Collecting referencing>=0.28.4 (from jsonschema)\n", - " Downloading referencing-0.33.0-py3-none-any.whl.metadata (2.7 kB)\n", - "Collecting rpds-py>=0.7.1 (from jsonschema)\n", - " Downloading rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl.metadata (4.1 kB)\n", - "Downloading jsonschema-4.21.1-py3-none-any.whl (85 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m85.5/85.5 kB\u001b[0m \u001b[31m2.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hDownloading attrs-23.2.0-py3-none-any.whl (60 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m60.8/60.8 kB\u001b[0m \u001b[31m7.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", - "\u001b[?25hDownloading jsonschema_specifications-2023.12.1-py3-none-any.whl (18 kB)\n", - "Downloading referencing-0.33.0-py3-none-any.whl (26 kB)\n", - "Downloading rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl (330 kB)\n", - "\u001b[2K \u001b[38;2;114;156;31m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m330.8/330.8 kB\u001b[0m \u001b[31m7.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0mm eta \u001b[36m0:00:01\u001b[0m\n", - "\u001b[?25hInstalling collected packages: rpds-py, attrs, referencing, jsonschema-specifications, jsonschema\n", - "Successfully installed attrs-23.2.0 jsonschema-4.21.1 jsonschema-specifications-2023.12.1 referencing-0.33.0 rpds-py-0.18.0\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" ] }, @@ -67,21 +56,29 @@ ], "source": [ "import os\n", - "os.environ[\"OPENAI_API_KEY\"] = \"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\"\n", - "!pip install openai\n", + "!pip install -r requirements.txt\n", "!pip install jaiqu\n", - "#TODO add openai to requirements\n", - "#TODO add OPENAI_API_KEY to env\n", + "\n", "#TODO update so that validate_schema is available on init\n", - "#TODO add jsonschema to requirements\n", - "!pip install jsonschema\n", "#TODO from jaiqu import validate_schema, translate_schema\n", - "from jaiqu.jaiqu import validate_schema, translate_schema" + "from jaiqu.jaiqu import validate_schema, translate_schema\n", + "from jaiqu import JaiQu\n", + "JaiQu.init(openai_api_key=\"\")" ] }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "# !pip uninstall openai\n", + "# !pip uninstall jsonschema" + ] + }, + { + "cell_type": "code", + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -129,21 +126,28 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "Validating schema: 100%|██████████| 3/3 [00:10<00:00, 3.64s/it, Key: model]" + "Validating schema: 0%| | 0/3 [00:00 str | None: """Extract the key from the response.""" key = response.split('`')[-2] @@ -57,7 +56,7 @@ def identify_key(key, value, input_schema, key_hints=None) -> tuple[Optional[str "content": f"Is `{key}` of type `{value}` present in the desired schema?:\n\n {input_schema}" }] - reasoning_response = client.chat.completions.create(messages=messages, + reasoning_response = JaiQu.openai_client.chat.completions.create(messages=messages, model="gpt-4", # logit_bias={2575: 100, 4139: 100}, # max_tokens=1 @@ -89,7 +88,7 @@ def create_jq_string(input_schema, key, value) -> str: "content": f"Write jq to extract the key `{key}`of type `{value['type']}`" }] - response = client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") + response = JaiQu.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") return str(response.choices[0].message.content) @@ -107,7 +106,7 @@ def repair_query(query, error, input_schema): Error: {error} Schema: {input_schema}"""}] - response = client.chat.completions.create(messages=messages, + response = JaiQu.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") return str(response.choices[0].message.content) diff --git a/pyproject.toml b/pyproject.toml index 6246593..4e2e59d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,9 @@ classifiers = [ "Operating System :: OS Independent", ] dependencies = [ - "jq==1.6.0" + "jq==1.6.0", + "openai~=1.12.0", + "jsonschema==4.21.1" ] [project.optional-dependencies] @@ -28,5 +30,5 @@ dev = [ ] [project.urls] -Homepage = "https://github.com/AgentOps-AI/tokencost" -Issues = "https://github.com/AgentOps-AI/tokencost/issues" \ No newline at end of file +Homepage = "https://github.com/AgentOps-AI/Jaiqu" +Issues = "https://github.com/AgentOps-AI/Jaiqu/issues" \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..dbdce18 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +jq==1.6.0 +openai>=1.12.0,<2.0.0 +jsonschema==4.21.1 \ No newline at end of file From fe45f935253c837707c0c73f9d78ac6a028d19c8 Mon Sep 17 00:00:00 2001 From: reibs Date: Thu, 22 Feb 2024 14:24:49 -0800 Subject: [PATCH 5/8] update init to correctly import --- jaiqu/__init__.py | 4 +++- jaiqu/helpers.py | 8 ++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/jaiqu/__init__.py b/jaiqu/__init__.py index 74985f4..654102c 100644 --- a/jaiqu/__init__.py +++ b/jaiqu/__init__.py @@ -1,6 +1,8 @@ from openai import OpenAI +from .jaiqu import validate_schema, translate_schema -class JaiQu: + +class LLM: openai_client = None @classmethod diff --git a/jaiqu/helpers.py b/jaiqu/helpers.py index a90577f..d8196e1 100644 --- a/jaiqu/helpers.py +++ b/jaiqu/helpers.py @@ -1,5 +1,5 @@ from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam -from jaiqu import JaiQu +from jaiqu import LLM from typing import Optional def to_key(response: str) -> str | None: @@ -56,7 +56,7 @@ def identify_key(key, value, input_schema, key_hints=None) -> tuple[Optional[str "content": f"Is `{key}` of type `{value}` present in the desired schema?:\n\n {input_schema}" }] - reasoning_response = JaiQu.openai_client.chat.completions.create(messages=messages, + reasoning_response = LLM.openai_client.chat.completions.create(messages=messages, model="gpt-4", # logit_bias={2575: 100, 4139: 100}, # max_tokens=1 @@ -88,7 +88,7 @@ def create_jq_string(input_schema, key, value) -> str: "content": f"Write jq to extract the key `{key}`of type `{value['type']}`" }] - response = JaiQu.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") + response = LLM.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") return str(response.choices[0].message.content) @@ -106,7 +106,7 @@ def repair_query(query, error, input_schema): Error: {error} Schema: {input_schema}"""}] - response = JaiQu.openai_client.chat.completions.create(messages=messages, + response = LLM.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") return str(response.choices[0].message.content) From c761e3fd58926507287445b66315ce482cbead22 Mon Sep 17 00:00:00 2001 From: reibs Date: Thu, 22 Feb 2024 14:36:01 -0800 Subject: [PATCH 6/8] added openai instead of LLM --- jaiqu/helpers.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/jaiqu/helpers.py b/jaiqu/helpers.py index d8196e1..723280c 100644 --- a/jaiqu/helpers.py +++ b/jaiqu/helpers.py @@ -1,6 +1,7 @@ from openai.types.chat.chat_completion_message_param import ChatCompletionMessageParam -from jaiqu import LLM from typing import Optional +from openai import OpenAI + def to_key(response: str) -> str | None: """Extract the key from the response.""" @@ -56,11 +57,11 @@ def identify_key(key, value, input_schema, key_hints=None) -> tuple[Optional[str "content": f"Is `{key}` of type `{value}` present in the desired schema?:\n\n {input_schema}" }] - reasoning_response = LLM.openai_client.chat.completions.create(messages=messages, - model="gpt-4", - # logit_bias={2575: 100, 4139: 100}, - # max_tokens=1 - ) + reasoning_response = OpenAI().chat.completions.create(messages=messages, + model="gpt-4", + # logit_bias={2575: 100, 4139: 100}, + # max_tokens=1 + ) completion = str(reasoning_response.choices[0].message.content) return (to_key(completion), completion) @@ -88,7 +89,7 @@ def create_jq_string(input_schema, key, value) -> str: "content": f"Write jq to extract the key `{key}`of type `{value['type']}`" }] - response = LLM.openai_client.chat.completions.create(messages=messages, model="gpt-4-0125-preview") + response = OpenAI().chat.completions.create(messages=messages, model="gpt-4-0125-preview") return str(response.choices[0].message.content) @@ -106,8 +107,8 @@ def repair_query(query, error, input_schema): Error: {error} Schema: {input_schema}"""}] - response = LLM.openai_client.chat.completions.create(messages=messages, - model="gpt-4-0125-preview") + response = OpenAI().chat.completions.create(messages=messages, + model="gpt-4-0125-preview") return str(response.choices[0].message.content) From 041b65d842e5a517e9a9160e8d37421136999576 Mon Sep 17 00:00:00 2001 From: reibs Date: Thu, 22 Feb 2024 15:07:44 -0800 Subject: [PATCH 7/8] update implementaiton notebook --- Example.ipynb | 327 +++++++++++++++++++++++++++++++++++++++++++ implementation.ipynb | 192 ------------------------- jaiqu/__init__.py | 10 -- 3 files changed, 327 insertions(+), 202 deletions(-) create mode 100644 Example.ipynb delete mode 100644 implementation.ipynb diff --git a/Example.ipynb b/Example.ipynb new file mode 100644 index 0000000..723dd09 --- /dev/null +++ b/Example.ipynb @@ -0,0 +1,327 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import json\n", + "import jq\n", + "from jaiqu import validate_schema, translate_schema" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Desired data format \n", + "\n", + "Create a `jsonschema` dictionary for the format of data you want. Data extracted from your input will be extracted into this format." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "schema = {\n", + " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"id\": {\n", + " \"type\": [\"string\", \"null\"],\n", + " \"description\": \"A unique identifier for the record.\"\n", + " },\n", + " \"date\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"A string describing the date.\"\n", + " },\n", + " \"model\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"A text field representing the model used.\"\n", + " }\n", + " },\n", + " \"required\": [\n", + " \"id\",\n", + " \"date\"\n", + " ]\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Sample input data\n", + "Provoide an input JSON dictionary containing the data you want to extract." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "input_json = {\n", + " \"call.id\": \"123\",\n", + " \"datetime\": \"2022-01-01\",\n", + " \"timestamp\": 1640995200,\n", + " \"Address\": \"123 Main St\",\n", + " \"user\": {\n", + " \"name\": \"John Doe\",\n", + " \"age\": 30,\n", + " \"contact\": \"john@email.com\"\n", + " }\n", + "}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### (Optional) Create hints\n", + "The jaiqu agent may not know certain concepts. For example, you might want to have some keys interpreted a certain way (i.e. interpret \"contact\" as \"email\"). For tricky interpretations, create hints." + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "key_hints = \"We are processing outputs of an containing an id and a date of a user.\"" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "16260aec353145dbb4055821841a64aa", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Validating schema: 0%| | 0/3 [00:00=1.12.0 (from -r requirements.txt (line 2))\n", - " Using cached openai-1.12.0-py3-none-any.whl.metadata (18 kB)\n", - "Collecting jsonschema==4.21.1 (from -r requirements.txt (line 3))\n", - " Using cached jsonschema-4.21.1-py3-none-any.whl.metadata (7.8 kB)\n", - "Requirement already satisfied: attrs>=22.2.0 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (23.2.0)\n", - "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (2023.12.1)\n", - "Requirement already satisfied: referencing>=0.28.4 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (0.33.0)\n", - "Requirement already satisfied: rpds-py>=0.7.1 in ./env/lib/python3.11/site-packages (from jsonschema==4.21.1->-r requirements.txt (line 3)) (0.18.0)\n", - "Requirement already satisfied: anyio<5,>=3.5.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.3.0)\n", - "Requirement already satisfied: distro<2,>=1.7.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.9.0)\n", - "Requirement already satisfied: httpx<1,>=0.23.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.27.0)\n", - "Requirement already satisfied: pydantic<3,>=1.9.0 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2.6.1)\n", - "Requirement already satisfied: sniffio in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.3.0)\n", - "Requirement already satisfied: tqdm>4 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.66.2)\n", - "Requirement already satisfied: typing-extensions<5,>=4.7 in ./env/lib/python3.11/site-packages (from openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (4.9.0)\n", - "Requirement already satisfied: idna>=2.8 in ./env/lib/python3.11/site-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (3.6)\n", - "Requirement already satisfied: certifi in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2024.2.2)\n", - "Requirement already satisfied: httpcore==1.* in ./env/lib/python3.11/site-packages (from httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (1.0.4)\n", - "Requirement already satisfied: h11<0.15,>=0.13 in ./env/lib/python3.11/site-packages (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.14.0)\n", - "Requirement already satisfied: annotated-types>=0.4.0 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (0.6.0)\n", - "Requirement already satisfied: pydantic-core==2.16.2 in ./env/lib/python3.11/site-packages (from pydantic<3,>=1.9.0->openai<2.0.0,>=1.12.0->-r requirements.txt (line 2)) (2.16.2)\n", - "Using cached jsonschema-4.21.1-py3-none-any.whl (85 kB)\n", - "Using cached openai-1.12.0-py3-none-any.whl (226 kB)\n", - "Installing collected packages: openai, jsonschema\n", - "Successfully installed jsonschema-4.21.1 openai-1.12.0\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n", - "Requirement already satisfied: jaiqu in ./env/lib/python3.11/site-packages (0.0.1)\n", - "Requirement already satisfied: jq==1.6.0 in ./env/lib/python3.11/site-packages (from jaiqu) (1.6.0)\n", - "\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.3.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m24.0\u001b[0m\n", - "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/howardgil/Desktop/agentops/Jaiqu/env/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - } - ], - "source": [ - "import os\n", - "!pip install -r requirements.txt\n", - "!pip install jaiqu\n", - "\n", - "#TODO update so that validate_schema is available on init\n", - "#TODO from jaiqu import validate_schema, translate_schema\n", - "from jaiqu.jaiqu import validate_schema, translate_schema\n", - "from jaiqu import JaiQu\n", - "JaiQu.init(openai_api_key=\"\")" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# !pip uninstall openai\n", - "# !pip uninstall jsonschema" - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "metadata": {}, - "outputs": [], - "source": [ - "# TODO: Get from files\n", - "# Desired data format \n", - "schema = {\n", - " \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n", - " \"type\": \"object\",\n", - " \"properties\": {\n", - " \"id\": {\n", - " \"type\": [\"string\", \"null\"],\n", - " \"description\": \"A unique identifier for the record.\"\n", - " },\n", - " \"date\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"A string describing the date.\"\n", - " },\n", - " \"model\": {\n", - " \"type\": \"string\",\n", - " \"description\": \"A text field representing the model used.\"\n", - " }\n", - " },\n", - " \"required\": [\n", - " \"id\",\n", - " \"date\"\n", - " ]\n", - "}\n", - "\n", - "# Provided data\n", - "input_json = {\n", - " \"call.id\": \"123\",\n", - " \"datetime\": \"2022-01-01\",\n", - " \"timestamp\": 1640995200,\n", - " \"Address\": \"123 Main St\",\n", - " \"user\": {\n", - " \"name\": \"John Doe\",\n", - " \"age\": 30,\n", - " \"contact\": \"john@email.com\"\n", - " }\n", - "}\n", - "\n", - "# (Optional) Create hints so the agent knows what to look for in the input\n", - "key_hints=\"We are processing outputs of an containing an id, a date, and a model. All the required fields should be present in this input, but the names might be different.\"\n" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "Validating schema: 0%| | 0/3 [00:00 Date: Thu, 22 Feb 2024 15:10:17 -0800 Subject: [PATCH 8/8] Update pyproject.toml --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 4e2e59d..f78ed08 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "jaiqu" -version = "0.0.1" +version = "0.0.2" authors = [ { name = "Alex Reibman", email = "areibman@gmail.com" } ] @@ -31,4 +31,4 @@ dev = [ [project.urls] Homepage = "https://github.com/AgentOps-AI/Jaiqu" -Issues = "https://github.com/AgentOps-AI/Jaiqu/issues" \ No newline at end of file +Issues = "https://github.com/AgentOps-AI/Jaiqu/issues"