forked from langchain-ai/langchain
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Create an Azure face tool and unit tests * Update test file and create docs * Update cell order * Lint files * Correct spelling and types * Add suggested review changes
- Loading branch information
1 parent
bc1fd7b
commit 5ebf320
Showing
7 changed files
with
704 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 |
---|---|---|
@@ -0,0 +1,389 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"# `AzureAIFaceAnalysisTool`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Overview" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Integration details" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
">The `AzureAIFaceAnalysisTool` acts as a wrapper around the Azure AI Face Service/API. The Tool will detect faces is in an image \n", | ||
">and can supply the position of faces, as well as important features like eyes, pupils, head pose etc." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Tool features" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"This integration allows for the detection of faces using Azure's Face API. It supports various different models, but defaults to the latest. Furthermore, the user can configure which information they would like to be returned such as position of the faces and image quality of the faces." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Setup\n", | ||
"\n", | ||
"This section provides details about how the Azure AI Face integration works, including setup." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 1, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"import os\n", | ||
"\n", | ||
"from langchain import hub" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"We will use a prompt to instruct the model. LangChain prompts can be configured, but for simplicity, we will use a premade prompt from LangSmith. This requires an API key, which can be set up here after registration." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 2, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"LANGSMITH_KEY = os.environ[\"LANGSMITH_KEY\"]\n", | ||
"prompt = hub.pull(\"hwchase17/structured-chat-agent\", api_key=LANGSMITH_KEY)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Now we can use the `AzureAIFaceAnalysisTool` combined with a model, using `create_structured_chat_agent`." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 5, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"from langchain.agents import AgentExecutor, create_structured_chat_agent\n", | ||
"from langchain_community.tools.azure_ai_services.face_analysis import (\n", | ||
" AzureAIFaceAnalysisTool,\n", | ||
")\n", | ||
"from langchain_openai import AzureChatOpenAI" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### Credentials" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Credentials can be set by being passed as parameters and should be stored locally as environment variables." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 6, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"face_endpoint = os.environ[\"AZURE_AI_FACE_ENDPOINT\"]\n", | ||
"face_key = os.environ[\"AZURE_AI_FACE_KEY\"]" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Instantiation" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Credentials can be passed directly, but they can also be retrieved automatically by the constructor if environment variables named `AZURE_AI_FACE_ENDPOINT` and `AZURE_AI_FACE_KEY` are set." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 7, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"face = AzureAIFaceAnalysisTool(\n", | ||
" azure_ai_face_key=face_key,\n", | ||
" azure_ai_face_endpoint=face_endpoint,\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 8, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"tools = [face]\n", | ||
"\n", | ||
"model = AzureChatOpenAI(\n", | ||
" openai_api_version=os.environ[\"OPENAI_API_VERSION\"],\n", | ||
" azure_deployment=os.environ[\"COMPLETIONS_MODEL\"],\n", | ||
" azure_endpoint=os.environ[\"AZURE_OPENAI_ENDPOINT\"],\n", | ||
" api_key=os.environ[\"AZURE_OPENAI_API_KEY\"],\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Creating an `AgentExecutor` chain allows a model to use tools to assist in it's response." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 9, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"agent = create_structured_chat_agent(model, tools, prompt)\n", | ||
"\n", | ||
"agent_executor = AgentExecutor(\n", | ||
" agent=agent, tools=tools, verbose=True, handle_parsing_errors=True\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Invocation\n", | ||
"\n", | ||
"Get either a local file path or remote image url as input" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 21, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"image_path = \"../../example_data/face.jpg\"" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 22, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"input = image_path" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### [Invoke directly with args](/docs/concepts/#invoke-with-just-the-arguments)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"Firstly, the tool can be used by directly passing input as an argument." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 23, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"\"FACE: 1\\nfaceId: 9b31b927-24a5-405c-95a9-d76f457e7160\\nfaceRectangle: {'top': 760, 'left': 1159, 'width': 853, 'height': 1337}\\nfaceLandmarks: {'pupilLeft': {'x': 1293.2, 'y': 1319.9}, 'pupilRight': {'x': 1671.1, 'y': 1306.7}, 'noseTip': {'x': 1383.7, 'y': 1593.6}, 'mouthLeft': {'x': 1333.1, 'y': 1821.3}, 'mouthRight': {'x': 1614.4, 'y': 1823.6}, 'eyebrowLeftOuter': {'x': 1167.6, 'y': 1199.4}, 'eyebrowLeftInner': {'x': 1348.4, 'y': 1214.3}, 'eyeLeftOuter': {'x': 1237.2, 'y': 1321.2}, 'eyeLeftTop': {'x': 1294.7, 'y': 1286.6}, 'eyeLeftBottom': {'x': 1289.7, 'y': 1347.3}, 'eyeLeftInner': {'x': 1351.2, 'y': 1324.3}, 'eyebrowRightInner': {'x': 1522.6, 'y': 1201.8}, 'eyebrowRightOuter': {'x': 1826.9, 'y': 1196.0}, 'eyeRightInner': {'x': 1605.4, 'y': 1317.3}, 'eyeRightTop': {'x': 1662.8, 'y': 1268.2}, 'eyeRightBottom': {'x': 1672.7, 'y': 1335.6}, 'eyeRightOuter': {'x': 1743.3, 'y': 1305.7}, 'noseRootLeft': {'x': 1396.7, 'y': 1342.7}, 'noseRootRight': {'x': 1499.7, 'y': 1337.8}, 'noseLeftAlarTop': {'x': 1350.5, 'y': 1516.6}, 'noseRightAlarTop': {'x': 1522.3, 'y': 1518.2}, 'noseLeftAlarOutTip': {'x': 1321.3, 'y': 1611.3}, 'noseRightAlarOutTip': {'x': 1561.3, 'y': 1623.0}, 'upperLipTop': {'x': 1426.4, 'y': 1773.3}, 'upperLipBottom': {'x': 1428.9, 'y': 1811.0}, 'underLipTop': {'x': 1428.9, 'y': 1836.5}, 'underLipBottom': {'x': 1430.2, 'y': 1898.5}}\\nfaceAttributes: {'headPose': {'pitch': -12.9, 'roll': 1.3, 'yaw': -22.0}, 'qualityForRecognition': 'medium'}\\nrecognitionModel: recognition_04\\n\"" | ||
] | ||
}, | ||
"execution_count": 23, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"face.invoke({\"query\": input})" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"### [Invoke with ToolCall](/docs/concepts/#invoke-with-toolcall)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"By using `.invoke`, the model can be told what to do and assess if using the tools it was given would assist in it's response. Here we will use a remote url as input." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 10, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"image_path = \"https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Guy_Sebastian_2014.jpg/330px-Guy_Sebastian_2014.jpg\"\n", | ||
"input = image_path" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 11, | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"\n", | ||
"\n", | ||
"\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n", | ||
"\u001b[32;1m\u001b[1;3m{\n", | ||
" \"action\": \"azure_ai_face_analysis\",\n", | ||
" \"action_input\": {\n", | ||
" \"query\": \"https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Guy_Sebastian_2014.jpg/330px-Guy_Sebastian_2014.jpg\"\n", | ||
" }\n", | ||
"}\u001b[0m\u001b[36;1m\u001b[1;3mFACE: 1\n", | ||
"faceId: ab842360-a7fc-4570-8082-8f0928064141\n", | ||
"faceRectangle: {'top': 69, 'left': 47, 'width': 209, 'height': 266}\n", | ||
"faceLandmarks: {'pupilLeft': {'x': 101.5, 'y': 192.0}, 'pupilRight': {'x': 194.8, 'y': 183.8}, 'noseTip': {'x': 148.4, 'y': 237.3}, 'mouthLeft': {'x': 109.1, 'y': 265.7}, 'mouthRight': {'x': 199.8, 'y': 257.2}, 'eyebrowLeftOuter': {'x': 70.6, 'y': 174.6}, 'eyebrowLeftInner': {'x': 120.7, 'y': 175.5}, 'eyeLeftOuter': {'x': 85.3, 'y': 192.7}, 'eyeLeftTop': {'x': 102.7, 'y': 188.3}, 'eyeLeftBottom': {'x': 100.1, 'y': 195.2}, 'eyeLeftInner': {'x': 118.0, 'y': 191.7}, 'eyebrowRightInner': {'x': 168.4, 'y': 172.0}, 'eyebrowRightOuter': {'x': 225.9, 'y': 164.1}, 'eyeRightInner': {'x': 178.8, 'y': 186.5}, 'eyeRightTop': {'x': 193.0, 'y': 179.8}, 'eyeRightBottom': {'x': 195.7, 'y': 187.1}, 'eyeRightOuter': {'x': 211.6, 'y': 181.8}, 'noseRootLeft': {'x': 132.9, 'y': 196.0}, 'noseRootRight': {'x': 159.7, 'y': 194.0}, 'noseLeftAlarTop': {'x': 128.6, 'y': 222.3}, 'noseRightAlarTop': {'x': 168.8, 'y': 219.0}, 'noseLeftAlarOutTip': {'x': 120.7, 'y': 236.2}, 'noseRightAlarOutTip': {'x': 179.7, 'y': 231.9}, 'upperLipTop': {'x': 154.7, 'y': 261.4}, 'upperLipBottom': {'x': 153.4, 'y': 267.4}, 'underLipTop': {'x': 154.5, 'y': 281.0}, 'underLipBottom': {'x': 155.5, 'y': 291.9}}\n", | ||
"faceAttributes: {'headPose': {'pitch': -12.3, 'roll': -5.0, 'yaw': -1.5}, 'qualityForRecognition': 'high'}\n", | ||
"recognitionModel: recognition_04\n", | ||
"\u001b[0m\u001b[32;1m\u001b[1;3mAction:\n", | ||
"```\n", | ||
"{\n", | ||
" \"action\": \"Final Answer\",\n", | ||
" \"action_input\": \"The image contains one face. The faceId is ab842360-a7fc-4570-8082-8f0928064141, and the face is located at the rectangle with top: 69, left: 47, width: 209, and height: 266. The face has various landmarks and attributes, including a high quality for recognition.\"\n", | ||
"}\n", | ||
"```\u001b[0m\n", | ||
"\n", | ||
"\u001b[1m> Finished chain.\u001b[0m\n" | ||
] | ||
}, | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"{'input': 'Can you check the following image for faces : https://upload.wikimedia.org/wikipedia/commons/thumb/1/17/Guy_Sebastian_2014.jpg/330px-Guy_Sebastian_2014.jpg',\n", | ||
" 'output': 'The image contains one face. The faceId is ab842360-a7fc-4570-8082-8f0928064141, and the face is located at the rectangle with top: 69, left: 47, width: 209, and height: 266. The face has various landmarks and attributes, including a high quality for recognition.'}" | ||
] | ||
}, | ||
"execution_count": 11, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"agent_executor.invoke(\n", | ||
" {\"input\": f\"Can you check the following image for faces : {input}\"}\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## Chaining" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"When creating an `AgentExecutor` as described earlier, an execution chain is formed. The sequence of events will be printed using the given prompt, and actions will occur in a chain-like manner." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 26, | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"agent = create_structured_chat_agent(model, tools, prompt)\n", | ||
"\n", | ||
"agent_executor = AgentExecutor(\n", | ||
" agent=agent, tools=tools, verbose=True, handle_parsing_errors=True\n", | ||
")" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"## API reference" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"metadata": {}, | ||
"source": [ | ||
"[Azure AI Face python SDK](https://learn.microsoft.com/python/api/overview/azure/ai-vision-face-readme?view=azure-python-preview) | [Azure AI Face Overview](https://learn.microsoft.com/azure/ai-services/computer-vision/overview-identity)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"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.4" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 2 | ||
} |
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
Oops, something went wrong.