Azure-Samples / ai-rag-chat-evaluator

Tools for evaluation of RAG Chat Apps using Azure AI Evaluate SDK and OpenAI
MIT License
162 stars 58 forks source link

Use Evaluations app whene the login is required in the chat app #82

Closed biancat821 closed 1 month ago

biancat821 commented 2 months ago

This issue is for a:

- [ ] bug report -> please search issues before submitting
- [ ] feature request
- [X] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)

Minimal steps to reproduce

I would like to use this app where the chat app has the optional login enabled, setting azd env set AZURE_USE_AUTHENTICATION true Which settings do I have to change to allow the Evaluations app accessing the chat app if the login is required?

Any log messages given by the failure

None

Expected/desired behavior

The Evaluations app should work as when the optional login is disabled.

OS and Version?

I am using Windows 11 but everything is deployed on Azure.

biancat821 commented 1 month ago

I managed to solve this issue by adding a new method called _gettoken in the "evaluate" function that retreive a token that allows the access to the chat, with login enabled.

To use this new method you need:

For _clientid and _clientsecret check https://learn.microsoft.com/en-us/answers/questions/834401/hi-i-want-my-client-id-and-client-secret-key

The _clientsecret key is visible only when it is created therefore it is likely that you need to add a new one, check https://techcommunity.microsoft.com/t5/microsoft-defender-for-identity/app-secret-application-secret-azure-ad-azure-ad-app-secrets/m-p/3775325

The _gettoken method to retrieve the token

def get_token(tenant_id:str, client_id: str, client_secret: str):

    token_url = "https://login.microsoftonline.com/{tenant_id}/oauth2/token"

    data = {
        'grant_type': 'client_credentials',
        'client_id': client_id,
        'client_secret': client_secret,
        'resource': "api://" + client_id
    }

    # Make a POST request to the token endpoint
    response = requests.post(token_url.format(tenant_id=tenant_id), data=data)

    # Check if the request was successful
    if response.status_code == 200:
        # Extract the access token from the response
        access_token = response.json()['access_token']
        return access_token
    else:
        return -1

In the _runevaluation function before calling the _send_question_totarget you have to add

...
logger.info("Getting token...")    
    try:
        token = get_token(tenant_id, client_id, client_secret)
    except Exception as e:
        logger.error("Failed to get token: \n%s", e)
        return False
...
...

Then you have to modify the two calls to the function _send_question_totarget adding the retrieved token

target_data = send_question_to_target(
            "What information is in your knowledge base?", "So much", target_url, token, target_parameters, raise_error=True
        )

Finally you have to modify the _send_question_totarget as follows:

def send_question_to_target(question: str, truth: str, target_url: str, access_token: str, parameters: dict = {}, raise_error=False):
    headers = {"Content-Type": "application/json",
               "Authorization": "Bearer " + access_token  # Include the access token in the Authorization header
               }
   ...
   ...

Here below you may find a script that test the retrieval of the token. You have just to modify the _tenandid, _client_id_, _clientsecret.

import requests

# Your Azure AD tenant ID
tenant_id = your_tenant_id

# Your Azure AD application (client) ID
client_id = your_client_id

# Your Azure AD application (client) secret
client_secret = your_client_secret

# Azure AD OAuth 2.0 token endpoint
token_url = "https://login.microsoftonline.com/{tenant_id}/oauth2/token"

# Request body parameters
data = {
    'grant_type': 'client_credentials',
    'client_id': client_id,
    'client_secret': client_secret,
    'resource': "api://" + client_id
}

# Make a POST request to the token endpoint
response = requests.post(token_url.format(tenant_id=tenant_id), data=data)

# Check if the request was successful
if response.status_code == 200:
    # Extract the access token from the response
    access_token = response.json()['access_token']
    print("Access Token:", access_token)
else:
    print("Failed to retrieve access token. Status code:", response.status_code)