-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
changes to tool as per review advice #12
base: master
Are you sure you want to change the base?
Changes from 5 commits
b3019f4
53547ce
cbf782c
dea4c62
6df6b6f
3b0f4e1
6162d18
62f1b6c
ad1cbef
ea56f04
d2cc1a6
dcc52e5
42418e8
590058e
e14bc59
5165fc6
dacaad9
a2f1569
cba8963
b27e2ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,114 @@ | ||||||||||||||
from __future__ import annotations | ||||||||||||||
|
||||||||||||||
import logging | ||||||||||||||
import os | ||||||||||||||
from typing import Any, Dict, Optional | ||||||||||||||
|
||||||||||||||
from langchain_core.callbacks import CallbackManagerForToolRun | ||||||||||||||
from langchain_core.tools import BaseTool | ||||||||||||||
|
||||||||||||||
logger = logging.getLogger(__name__) | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
class AzureTranslateTool(BaseTool): | ||||||||||||||
""" | ||||||||||||||
A tool that interacts with the Azure Translator API using the SDK. | ||||||||||||||
|
||||||||||||||
This tool queries the Azure Translator API to translate text between | ||||||||||||||
languages. It requires an API key and endpoint, which can be set up as | ||||||||||||||
described in the Azure Translator API documentation: | ||||||||||||||
https://learn.microsoft.com/en-us/azure/ai-services/translator/ | ||||||||||||||
translator-text-apis?tabs=python | ||||||||||||||
""" | ||||||||||||||
|
||||||||||||||
translate_client: Any = None | ||||||||||||||
default_language: str = "en" | ||||||||||||||
|
||||||||||||||
name: str = "azure_translator_tool" | ||||||||||||||
description: str = ( | ||||||||||||||
"A wrapper around Azure Translator API. Useful for translating text between " | ||||||||||||||
"languages. Input must be text (str). Ensure to install the " | ||||||||||||||
"azure-ai-translation-text package." | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
@classmethod | ||||||||||||||
def validate_environment(cls, values: Dict) -> Any: | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing model_validator (from pydantic import model_validator)
Suggested change
|
||||||||||||||
""" | ||||||||||||||
Validate that the required environment variables are set, and set up | ||||||||||||||
the client. | ||||||||||||||
""" | ||||||||||||||
try: | ||||||||||||||
from azure.ai.translation.text import TextTranslationClient | ||||||||||||||
from azure.core.credentials import AzureKeyCredential | ||||||||||||||
except ImportError: | ||||||||||||||
raise ImportError( | ||||||||||||||
"azure-ai-translation-text is not installed. " | ||||||||||||||
"Run `pip install azure-ai-translation-text` to install." | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
# Get environment variables | ||||||||||||||
translate_key = os.getenv("AZURE_TRANSLATE_API_KEY") | ||||||||||||||
translate_endpoint = os.getenv("AZURE_TRANSLATE_ENDPOINT") | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's leverage the helper function for env vars that the other tools use: # Get environment variables
azure_translate_key = get_from_dict_or_env(
values, "text_translation_key", "AZURE_TRANSLATE_API_KEY"
)
azure_translate_endpoint = get_from_dict_or_env(
values, "text_translation_endpoint", "AZURE_TRANSLATE_ENDPOINT"
)
region = get_from_dict_or_env(
values, "region", "AZURE_REGION"
) |
||||||||||||||
|
||||||||||||||
if not translate_key: | ||||||||||||||
raise ValueError( | ||||||||||||||
"AZURE_TRANSLATE_API_KEY is missing in environment variables" | ||||||||||||||
) | ||||||||||||||
if not translate_endpoint: | ||||||||||||||
raise ValueError( | ||||||||||||||
"AZURE_TRANSLATE_ENDPOINT is missing in environment variables" | ||||||||||||||
) | ||||||||||||||
|
||||||||||||||
# Set up the translation client in the values dict | ||||||||||||||
values["translate_client"] = TextTranslationClient( | ||||||||||||||
endpoint=translate_endpoint, credential=AzureKeyCredential(translate_key) | ||||||||||||||
) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I needed region to call the client successfully
Suggested change
|
||||||||||||||
|
||||||||||||||
return values | ||||||||||||||
|
||||||||||||||
def _translate_text(self, text: str, to_language: str = "en") -> str: | ||||||||||||||
""" | ||||||||||||||
Perform text translation using the Azure Translator API. | ||||||||||||||
|
||||||||||||||
Args: | ||||||||||||||
text (str): The text to be translated. | ||||||||||||||
to_language (str): The target language to translate to. | ||||||||||||||
|
||||||||||||||
Returns: | ||||||||||||||
str: The translation result. | ||||||||||||||
""" | ||||||||||||||
if not text: | ||||||||||||||
raise ValueError("Input text for translation is empty.") | ||||||||||||||
|
||||||||||||||
# Ensure that the translation client is initialized | ||||||||||||||
# by validating the environment | ||||||||||||||
if not self.translate_client: | ||||||||||||||
values = self.validate_environment({}) | ||||||||||||||
self.translate_client = values["translate_client"] | ||||||||||||||
|
||||||||||||||
body = [{"Text": text}] | ||||||||||||||
try: | ||||||||||||||
response = self.translate_client.translate( | ||||||||||||||
body=body, to_language=[to_language] | ||||||||||||||
) | ||||||||||||||
return response[0].translations[0].text | ||||||||||||||
except Exception as e: | ||||||||||||||
raise RuntimeError(f"Translation failed: {e}") | ||||||||||||||
|
||||||||||||||
def _run( | ||||||||||||||
self, | ||||||||||||||
query: str, | ||||||||||||||
run_manager: Optional[CallbackManagerForToolRun] = None, | ||||||||||||||
) -> str: | ||||||||||||||
""" | ||||||||||||||
Run the tool to perform translation. Always uses default language. | ||||||||||||||
|
||||||||||||||
Args: | ||||||||||||||
query (str): The text to be translated. | ||||||||||||||
run_manager (Optional[CallbackManagerForToolRun]): A callback manager | ||||||||||||||
for tracking the tool run. | ||||||||||||||
|
||||||||||||||
Returns: | ||||||||||||||
str: The translated text. | ||||||||||||||
""" | ||||||||||||||
return self._translate_text(query) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "code", | ||
"id": "initial_id", | ||
"metadata": { | ||
"collapsed": true, | ||
"jupyter": { | ||
"is_executing": true | ||
} | ||
}, | ||
"source": [ | ||
"\n", | ||
"import os\n", | ||
"from dotenv import load_dotenv\n", | ||
"from libs.community.langchain_community.tools.azure_ai_services.translate_tool import AzureTranslateTool\n", | ||
"from langchain_core.prompts import PromptTemplate\n", | ||
"\n", | ||
"load_dotenv()" | ||
], | ||
"outputs": [], | ||
"execution_count": null | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:47:56.337282Z", | ||
"start_time": "2024-10-10T02:47:56.322998Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": [ | ||
"translate_key = os.getenv('AZURE_TRANSLATE_API_KEY')\n", | ||
"translate_endpoint = os.getenv('AZURE_TRANSLATE_ENDPOINT')\n" | ||
], | ||
"id": "d16a2afc75afc1a4", | ||
"outputs": [], | ||
"execution_count": 9 | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:47:56.353227Z", | ||
"start_time": "2024-10-10T02:47:56.338283Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": "translator = AzureTranslateTool(translate_key=translate_key, translate_endpoint=translate_endpoint)", | ||
"id": "6a9a508bab82e582", | ||
"outputs": [], | ||
"execution_count": 10 | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:47:56.368993Z", | ||
"start_time": "2024-10-10T02:47:56.355229Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": [ | ||
"\n", | ||
"prompt = PromptTemplate(\n", | ||
" input_variables=['input'],\n", | ||
" template=\"You are a translation agent. Use the translation tool to translate the following input: {input}\"\n", | ||
")\n" | ||
], | ||
"id": "e4d08ff8441d3ac1", | ||
"outputs": [], | ||
"execution_count": 11 | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:47:56.384562Z", | ||
"start_time": "2024-10-10T02:47:56.369994Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": [ | ||
"def translate_text(input_text, target_language='es'):\n", | ||
" try:\n", | ||
" # Run the translation\n", | ||
" translated_text = translator._run(input_text, target_language)\n", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We shouldn't call the internal methods. I'd expect a user to invoke the tool directly or use an agent. translate_tool = AzureTranslateTool(
text_translation_key=os.environ["AZURE_TRANSLATE_API_KEY"],
text_translation_endpoint=os.environ["AZURE_TRANSLATE_ENDPOINT"],
region="westus2",
)
answer = translate_tool.invoke({"query": "hola mundo"})
print(answer) translate_tool = AzureTranslateTool(
text_translation_key=os.environ["AZURE_TRANSLATE_API_KEY"],
text_translation_endpoint=os.environ["AZURE_TRANSLATE_ENDPOINT"],
region="westus2",
)
tools = [translate_tool]
model = AzureChatOpenAI(
openai_api_version=os.environ["OPENAI_API_VERSION"],
azure_deployment=os.environ["COMPLETIONS_MODEL"],
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
api_key=os.environ["AZURE_OPENAI_API_KEY"],
)
agent = create_structured_chat_agent(model, tools, prompt)
agent_executor = AgentExecutor(
agent=agent, tools=tools, verbose=True, handle_parsing_errors=True
)
text = "hola mundo"
answer = agent_executor.invoke(
{"input": f"What does the text say in english? : {text}"}
)
print(answer) |
||
"\n", | ||
" # Format the result in a dictionary\n", | ||
" result = {\n", | ||
" 'input': input_text,\n", | ||
" 'output': translated_text\n", | ||
" }\n", | ||
" return result\n", | ||
"\n", | ||
" except Exception as e:\n", | ||
" # Log the error and return an error dictionary\n", | ||
" print(f\"Translation error: {e}\")\n", | ||
" return {'error': str(e)}\n" | ||
], | ||
"id": "4467f2ee18e2201b", | ||
"outputs": [], | ||
"execution_count": 12 | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:48:03.660147Z", | ||
"start_time": "2024-10-10T02:48:02.915399Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": [ | ||
"# Instantiate the AzureTranslateTool\n", | ||
"translator = AzureTranslateTool()\n", | ||
"\n", | ||
"# Sample text to translate\n", | ||
"sample_text = \"hi how are you?\"\n", | ||
"target_language = 'es'\n", | ||
"\n", | ||
"# Perform translation using the _translate_text method directly\n", | ||
"translated_text = translator._translate_text(sample_text, to_language=target_language)\n", | ||
"\n", | ||
"print(f\"Translated text: {translated_text}\")\n" | ||
], | ||
"id": "bb5b638111ce6ae9", | ||
"outputs": [ | ||
{ | ||
"name": "stdout", | ||
"output_type": "stream", | ||
"text": [ | ||
"Translated text: ¿Hola cómo estás?\n" | ||
] | ||
} | ||
], | ||
"execution_count": 14 | ||
}, | ||
{ | ||
"metadata": { | ||
"ExecuteTime": { | ||
"end_time": "2024-10-10T02:47:57.242259Z", | ||
"start_time": "2024-10-10T02:47:57.227198Z" | ||
} | ||
}, | ||
"cell_type": "code", | ||
"source": "", | ||
"id": "a026310fe89600af", | ||
"outputs": [], | ||
"execution_count": 13 | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 2 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython2", | ||
"version": "2.7.6" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think to be consistent between translate tools (especially if we decide to merge them), lets add the following:
text_translation_key: str = ""
text_translation_endpoint: str = ""
region: str = ""