-
Notifications
You must be signed in to change notification settings - Fork 371
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
854 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5308,7 +5308,174 @@ | |
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 176, | ||
"execution_count": 6, | ||
"id": "664772c3-b9c5-411c-8a43-19fd29fb6b8d", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"72\n" | ||
] | ||
} | ||
], | ||
"source": [ | ||
"import yaml\n", | ||
"import jsonref\n", | ||
"from jsonref import replace_refs\n", | ||
"from langchain_core.documents.base import Document\n", | ||
"from copy import deepcopy\n", | ||
"from pprint import pprint\n", | ||
"\n", | ||
"with open(\"alloy.com.yaml\") as f:\n", | ||
" spec = f.read()\n", | ||
"\n", | ||
"def chunk_openapi_by_operation(openapi: str):\n", | ||
" parsed = yaml.safe_load(openapi)\n", | ||
"\n", | ||
" operations: (str, str) = []\n", | ||
" # 1) list all operations by (path, HTTP method)\n", | ||
" for path, methods in parsed['paths'].items():\n", | ||
" for method in methods.keys():\n", | ||
" # if method is not an HTTP method then skip\n", | ||
" if method.lower() not in ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace']:\n", | ||
" continue\n", | ||
" operations.append((path, method))\n", | ||
"\n", | ||
" # 2) create a chunk for every operation\n", | ||
"\n", | ||
" # 2.a) Dereference entire OpenAPI Spec\n", | ||
" dereferenced = replace_refs(parsed, lazy_load=False)\n", | ||
"\n", | ||
" chunks = []\n", | ||
" for operation in operations:\n", | ||
" path = operation[0]\n", | ||
" method = operation[1]\n", | ||
" chunk = deepcopy(dereferenced)\n", | ||
" if 'tags' in chunk['paths'][operation[0]][operation[1]]:\n", | ||
" tags = chunk['paths'][operation[0]][operation[1]]['tags']\n", | ||
"\n", | ||
" # first tag if possible\n", | ||
" if tags:\n", | ||
" tag_name = tags[0]\n", | ||
"\n", | ||
" # delete all tags on OAS except tag for this operation\n", | ||
" while len(chunk['tags']) > 1:\n", | ||
" for i in range(len(chunk['tags']) - 1, -1, -1):\n", | ||
" if chunk['tags'][i]['name'] != tag_name:\n", | ||
" chunk['tags'].pop(i)\n", | ||
"\n", | ||
" if \"summary\" in chunk['paths'][path][method]:\n", | ||
" summary = chunk['paths'][path][method]['summary']\n", | ||
" else:\n", | ||
" summary = \"\"\n", | ||
"\n", | ||
" if \"description\" in chunk['paths'][path][method]:\n", | ||
" description = chunk['paths'][path][method]['description']\n", | ||
" else:\n", | ||
" description = \"\"\n", | ||
"\n", | ||
" # delete other operations\n", | ||
" for other_operation in operations:\n", | ||
" if other_operation[0] == operation[0]:\n", | ||
" continue\n", | ||
" if other_operation[0] in chunk['paths']:\n", | ||
" del chunk['paths'][other_operation[0]]\n", | ||
"\n", | ||
" # delete empty paths\n", | ||
" for path in chunk['paths'].keys():\n", | ||
" if not chunk['paths'][path]:\n", | ||
" del chunk['paths'][path]\n", | ||
"\n", | ||
" # delete other operations under same path\n", | ||
" keys = list(chunk['paths'][operation[0]].keys())\n", | ||
" for method in keys:\n", | ||
" if operation[1] == method:\n", | ||
" continue\n", | ||
" del chunk['paths'][operation[0]][method]\n", | ||
"\n", | ||
" # delete all components besides securitySchemes (should be inlined from 2.a)\n", | ||
" if \"components\" in chunk:\n", | ||
" for key in chunk[\"components\"]:\n", | ||
" if key == \"securitySchemes\":\n", | ||
" continue\n", | ||
" del chunk['components'][key]\n", | ||
" \n", | ||
" chunks.append(({\n", | ||
" \"path\": operation[0],\n", | ||
" \"method\": operation[1],\n", | ||
" \"openapi\": yaml.dump(chunk),\n", | ||
" \"tag\": tag_name,\n", | ||
" \"summary\": summary,\n", | ||
" \"description\": description\n", | ||
" }))\n", | ||
" return list(map(lambda chunk: Document(page_content=chunk[\"openapi\"], metadata={\n", | ||
" \"path\": chunk[\"path\"],\n", | ||
" \"method\": chunk[\"method\"],\n", | ||
" \"tag\": chunk[\"tag\"],\n", | ||
" \"summary\": chunk[\"summary\"],\n", | ||
" \"description\": chunk[\"description\"]\n", | ||
" }), chunks))\n", | ||
"chunks = chunk_openapi_by_operation(spec)\n", | ||
"# for chunk in chunks:\n", | ||
"# print(len(yaml.safe_load(chunk.page_content)['paths']))\n", | ||
"print(len(chunks))" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"id": "10399fd6-23b5-4a6a-8a49-07e65d40b745", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stderr", | ||
"output_type": "stream", | ||
"text": [ | ||
"Existing running Phoenix instance detected! Shutting it down and starting a new instance...\n", | ||
"Attempting to instrument while already instrumented\n" | ||
] | ||
}, | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"🌍 To view the Phoenix app in your browser, visit http://localhost:6006/\n", | ||
"📺 To view the Phoenix app in a notebook, run `px.active_session().view()`\n", | ||
"📖 For more information on how to use Phoenix, check out https://docs.arize.com/phoenix\n" | ||
] | ||
}, | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"'http://localhost:6006/'" | ||
] | ||
}, | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"import phoenix as px\n", | ||
"\n", | ||
"# Launch phoenix\n", | ||
"session = px.launch_app()\n", | ||
"\n", | ||
"# Once you have started a Phoenix server, you can start your LangChain application with the OpenInferenceTracer as a callback. To do this, you will have to instrument your LangChain application with the tracer:\n", | ||
"\n", | ||
"from phoenix.trace.langchain import LangChainInstrumentor\n", | ||
"\n", | ||
"# By default, the traces will be exported to the locally running Phoenix server.\n", | ||
"LangChainInstrumentor().instrument()\n", | ||
"\n", | ||
"session.url" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"id": "bca59022-7be0-4d53-b8e3-f4d35c2887f3", | ||
"metadata": { | ||
"vscode": { | ||
|
@@ -5340,7 +5507,7 @@ | |
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 177, | ||
"execution_count": 9, | ||
"id": "1a884ea5-1d67-474f-b564-fec4bc9512c6", | ||
"metadata": { | ||
"editable": true, | ||
|
@@ -5388,7 +5555,7 @@ | |
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 190, | ||
"execution_count": 10, | ||
"id": "620a8315-69aa-42dc-892e-e7cc53b65807", | ||
"metadata": { | ||
"editable": true, | ||
|
@@ -5498,14 +5665,14 @@ | |
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 191, | ||
"execution_count": 12, | ||
"id": "e92f61a9-33dd-4ede-9c09-ba5ecd967004", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/markdown": [ | ||
"To create a journey application using the Alloy API in Python, you'll need to follow these steps. This includes setting up your environment, handling authentication, and making the API request. Below, I'll guide you through each step, including both authentication methods available: HTTP Basic and OAuth2.\n", | ||
"To create a Journey Application using the Alloy API in Python, you'll need to follow these steps. This involves setting up your environment, handling authentication, and making the API request with the necessary parameters.\n", | ||
"\n", | ||
"### Environment Setup\n", | ||
"\n", | ||
|
@@ -5517,25 +5684,25 @@ | |
"\n", | ||
"### Authentication\n", | ||
"\n", | ||
"The Alloy API provides two methods for authentication: HTTP Basic and OAuth2. Here's how you can handle each:\n", | ||
"The Alloy API provides two methods for authentication: Basic Authentication and OAuth2. Here's how you can handle both:\n", | ||
"\n", | ||
"#### 1. HTTP Basic Authentication\n", | ||
"#### 1. Basic Authentication\n", | ||
"\n", | ||
"For HTTP Basic Authentication, you'll need your workflow token and secret. These should be stored securely and not hard-coded in your scripts. It's a good practice to use environment variables.\n", | ||
"For Basic Authentication, you will need your workflow token and secret. These should be stored securely and not hard-coded in your scripts.\n", | ||
"\n", | ||
"```python\n", | ||
"import os\n", | ||
"import requests\n", | ||
"from requests.auth import HTTPBasicAuth\n", | ||
"import os\n", | ||
"\n", | ||
"# Environment variables for credentials\n", | ||
"# Environment variables for security credentials\n", | ||
"ALLOY_WORKFLOW_TOKEN = os.getenv('ALLOY_WORKFLOW_TOKEN')\n", | ||
"ALLOY_WORKFLOW_SECRET = os.getenv('ALLOY_WORKFLOW_SECRET')\n", | ||
"\n", | ||
"# API endpoint\n", | ||
"url = \"https://demo-qasandbox.alloy.co/v1/journeys/{journey_token}/applications\"\n", | ||
"\n", | ||
"# Replace {journey_token} with the actual journey token\n", | ||
"# Replace {journey_token} with your actual journey token\n", | ||
"url = url.format(journey_token=\"J-VCQoADBJxeHtmdAvFqoS\")\n", | ||
"\n", | ||
"# Request headers\n", | ||
|
@@ -5544,7 +5711,7 @@ | |
"}\n", | ||
"\n", | ||
"# Request body\n", | ||
"data = {\n", | ||
"payload = {\n", | ||
" \"entities\": [\n", | ||
" {\n", | ||
" \"branch_name\": \"persons\",\n", | ||
|
@@ -5554,7 +5721,6 @@ | |
" \"birth_date\": \"1990-01-25\",\n", | ||
" \"document_ssn\": 111223333,\n", | ||
" \"email_address\": \"[email protected]\",\n", | ||
" \"ip_address_v4\": \"42.206.213.70\",\n", | ||
" \"phone_number\": 8443825569,\n", | ||
" \"addresses\": [\n", | ||
" {\n", | ||
|
@@ -5566,57 +5732,50 @@ | |
" \"state\": \"NY\",\n", | ||
" \"type\": \"primary\"\n", | ||
" }\n", | ||
" ]\n", | ||
" ],\n", | ||
" \"gender\": \"male\"\n", | ||
" },\n", | ||
" \"entity_type\": \"person\",\n", | ||
" \"external_entity_id\": \"my_system_entity_id_123\"\n", | ||
" \"entity_type\": \"person\"\n", | ||
" }\n", | ||
" ]\n", | ||
"}\n", | ||
"\n", | ||
"# Make the request\n", | ||
"response = requests.post(url, json=data, headers=headers, auth=HTTPBasicAuth(ALLOY_WORKFLOW_TOKEN, ALLOY_WORKFLOW_SECRET))\n", | ||
"response = requests.post(url, json=payload, headers=headers, auth=HTTPBasicAuth(ALLOY_WORKFLOW_TOKEN, ALLOY_WORKFLOW_SECRET))\n", | ||
"\n", | ||
"# Print the response\n", | ||
"print(response.json())\n", | ||
"```\n", | ||
"\n", | ||
"#### 2. OAuth2 Authentication\n", | ||
"\n", | ||
"For OAuth2, you'll need to obtain a bearer token using the client credentials flow.\n", | ||
"For OAuth2, you'll need to obtain a bearer token using your client credentials first.\n", | ||
"\n", | ||
"```python\n", | ||
"# Function to get OAuth2 token\n", | ||
"def get_oauth2_token():\n", | ||
" token_url = \"https://demo-qasandbox.alloy.co/v1/oauth/bearer\"\n", | ||
" response = requests.post(token_url, auth=HTTPBasicAuth(ALLOY_WORKFLOW_TOKEN, ALLOY_WORKFLOW_SECRET))\n", | ||
" return response.json()['access_token']\n", | ||
"# Token endpoint\n", | ||
"token_url = \"https://demo-qasandbox.alloy.co/v1/oauth/bearer\"\n", | ||
"\n", | ||
"# Get the access token\n", | ||
"access_token = get_oauth2_token()\n", | ||
"# Obtain the bearer token\n", | ||
"token_response = requests.post(token_url, auth=HTTPBasicAuth(ALLOY_WORKFLOW_TOKEN, ALLOY_WORKFLOW_SECRET))\n", | ||
"access_token = token_response.json().get('access_token')\n", | ||
"\n", | ||
"# Headers with the bearer token\n", | ||
"headers = {\n", | ||
" \"Authorization\": f\"Bearer {access_token}\",\n", | ||
" \"Content-Type\": \"application/json\"\n", | ||
"}\n", | ||
"# Update headers with the bearer token\n", | ||
"headers['Authorization'] = f\"Bearer {access_token}\"\n", | ||
"\n", | ||
"# Make the request with OAuth2 token\n", | ||
"response = requests.post(url, json=data, headers=headers)\n", | ||
"response = requests.post(url, json=payload, headers=headers)\n", | ||
"\n", | ||
"# Print the response\n", | ||
"print(response.json())\n", | ||
"```\n", | ||
"\n", | ||
"### Making the API Request\n", | ||
"\n", | ||
"The request body should include all required fields as specified by your journey's configuration. In this example, I've included some typical fields such as personal information and address. Adjust the `data` dictionary according to the specific requirements of your journey configuration.\n", | ||
"The example above shows how to make a request to create a Journey Application. You need to replace placeholders with actual data like `journey_token`, and ensure the payload matches the required schema as per your journey's configuration.\n", | ||
"\n", | ||
"### Handling the Response\n", | ||
"\n", | ||
"The response from the API will provide details about the journey application created, including any identifiers and status information. Handle this response according to your application's logic, such as logging the result or triggering additional processes.\n", | ||
"\n", | ||
"This setup should help you integrate the Alloy API into your Python application effectively." | ||
"The response from the API will provide details about the created journey application, including tokens and status. Handle this response appropriately in your application to proceed with further actions or display the results to the user." | ||
], | ||
"text/plain": [ | ||
"<IPython.core.display.Markdown object>" | ||
|
Oops, something went wrong.