Azure-Samples / Azure-Samples/ai-rag-chat-evaluator

promptflow not inheriting CLI credentials

Open
#111 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Python
Stars
335
Forks
114
Avg merge
3d 15h
Merged PRs (30d)
1

Description

> Please provide us with the following information:
> ---------------------------------------------------------------

### This issue is for a: (mark with an `x`)
```
- [ X] bug report -> please search issues before submitting
- [ ] feature request
- [ ] documentation issue or request
- [ ] regression (a behavior that used to work and stopped in a new release)
```

### Minimal steps to reproduce
1. run `az login` through command line
2. create groundtruth data using this framework's utilities
3. start a local chatbot
4. run evaluation using this framework's default utils

### Any log messages given by the failure
>
[19:26:20] INFO Running evaluation from config c:\tes\Use Case evaluate.py:227
46\ragEval\ai-rag-chat-evaluator-main\example_config.json
INFO Replaced results_dir in config with timestamp evaluate.py:215
INFO Using Azure OpenAI Service with Azure Developer CLI Credential service_setup.py:32
INFO Running evaluation using data from c:\tes\Use Case evaluate.py:91
46\ragEval\example_input\qa_jdTest.jsonl
INFO Limiting evaluation to 20 questions evaluate.py:94
INFO Sending a test question to the target to ensure it is running... evaluate.py:97
[19:26:26] INFO Successfully received response from target for question: "What information is evaluate.py:109
in your knowledge base?"
"answer": "The information in my knowledge base includes:

1...."
"context": "2023q3pillar3.pdf#page=4: Royal Bank of Canada (RB..."
INFO Sending a test chat completion to the GPT deployment to ensure it is running... evaluate.py:120
[19:26:28] INFO Successfully received response from GPT: "Hello! How can I help you today?" evaluate.py:127
INFO Starting evaluation... evaluate.py:130

---------------------------------------------------------------------------
AuthenticationError Traceback (most recent call last)
File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\core\_prompty_utils.py:1191, in handle_openai_error_async..decorator..wrapper(*args, **kwargs)
[1190](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1190) try:
-> [1191](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1191) return await func(*args, **kwargs)
[1192](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1192) except (SystemErrorException, UserErrorException) as e:
[1193](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1193) # Throw inner wrapped exception directly

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\core\_flow.py:562, in AsyncPrompty.__call__(self, *args, **kwargs)
[561](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:561) timeout = kwargs.get("timeout", None)
--> [562](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:562) response = await send_request_to_llm(api_client, self._model.api, params, timeout)
[563](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:563) return format_llm_response(
[564](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:564) response=response,
[565](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:565) api=self._model.api,
(...)
[569](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:569) outputs=self._outputs,
[570](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_flow.py:570) )

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\openai\resources\chat\completions.py:1633, in AsyncCompletions.create(self, messages, model, audio, frequency_penalty, function_call, functions, logit_bias, logprobs, max_completion_tokens, max_tokens, metadata, modalities, n, parallel_tool_calls, presence_penalty, response_format, seed, service_tier, stop, store, stream, stream_options, temperature, tool_choice, tools, top_logprobs, top_p, user, extra_headers, extra_query, extra_body, timeout)
[1632](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1632) validate_response_format(response_format)
-> [1633](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1633) return await self._post(
[1634](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1634) "/chat/completions",
[1635](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1635) body=await async_maybe_transform(
[1636](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1636) {
[1637](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1637) "messages": messages,
[1638](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1638) "model": model,
[1639](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1639) "audio": audio,
[1640](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1640) "frequency_penalty": frequency_penalty,
[1641](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1641) "function_call": function_call,
[1642](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1642) "functions": functions,
[1643](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1643) "logit_bias": logit_bias,
[1644](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1644) "logprobs": logprobs,
[1645](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1645) "max_completion_tokens": max_completion_tokens,
[1646](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1646) "max_tokens": max_tokens,
[1647](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1647) "metadata": metadata,
[1648](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1648) "modalities": modalities,
[1649](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1649) "n": n,
[1650](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1650) "parallel_tool_calls": parallel_tool_calls,
[1651](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1651) "presence_penalty": presence_penalty,
[1652](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1652) "response_format": response_format,
[1653](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1653) "seed": seed,
[1654](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1654) "service_tier": service_tier,
[1655](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1655) "stop": stop,
[1656](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1656) "store": store,
[1657](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1657) "stream": stream,
[1658](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1658) "stream_options": stream_options,
[1659](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1659) "temperature": temperature,
[1660](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1660) "tool_choice": tool_choice,
[1661](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1661) "tools": tools,
[1662](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1662) "top_logprobs": top_logprobs,
[1663](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1663) "top_p": top_p,
[1664](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1664) "user": user,
[1665](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1665) },
[1666](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1666) completion_create_params.CompletionCreateParams,
[1667](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1667) ),
[1668](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1668) options=make_request_options(
[1669](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1669) extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout
[1670](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1670) ),
[1671](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1671) cast_to=ChatCompletion,
[1672](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1672) stream=stream or False,
[1673](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1673) stream_cls=AsyncStream[ChatCompletionChunk],
[1674](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/resources/chat/completions.py:1674) )

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\openai\_base_client.py:1838, in AsyncAPIClient.post(self, path, cast_to, body, files, options, stream, stream_cls)
[1835](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1835) opts = FinalRequestOptions.construct(
[1836](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1836) method="post", url=path, json_data=body, files=await async_to_httpx_files(files), **options
[1837](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1837) )
-> [1838](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1838) return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\openai\_base_client.py:1532, in AsyncAPIClient.request(self, cast_to, options, stream, stream_cls, remaining_retries)
[1530](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1530) retries_taken = 0
-> [1532](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1532) return await self._request(
[1533](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1533) cast_to=cast_to,
[1534](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1534) options=options,
[1535](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1535) stream=stream,
[1536](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1536) stream_cls=stream_cls,
[1537](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1537) retries_taken=retries_taken,
[1538](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1538) )

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\openai\_base_client.py:1633, in AsyncAPIClient._request(self, cast_to, options, stream, stream_cls, retries_taken)
[1632](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1632) log.debug("Re-raising status error")
-> [1633](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1633) raise self._make_status_error_from_response(err.response) from None
[1635](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1635) return await self._process_response(
[1636](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1636) cast_to=cast_to,
[1637](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1637) options=options,
(...)
[1641](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1641) retries_taken=retries_taken,
[1642](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/openai/_base_client.py:1642) )

AuthenticationError: Error code: 401 - {'error': {'code': 'PermissionDenied', 'message': 'Principal does not have access to API/Operation.'}}

During handling of the above exception, another exception occurred:

WrappedOpenAIError Traceback (most recent call last)
Cell In[37], [line 2](vscode-notebook-cell:?execution_count=37&line=2)
[1](vscode-notebook-cell:?execution_count=37&line=1) # Where the config_path is relative to working_dir
----> [2](vscode-notebook-cell:?execution_count=37&line=2) msftEval.evaluate.run_evaluate_from_config(working_dir = os.getcwd(),
[3](vscode-notebook-cell:?execution_count=37&line=3) config_path = "./ai-rag-chat-evaluator-main/example_config.json",
[4](vscode-notebook-cell:?execution_count=37&line=4) num_questions = 20,
[5](vscode-notebook-cell:?execution_count=37&line=5) target_url = "http://127.0.0.1:50505/chat")

File c:\tes\Use Case 46\ragEval\ai-rag-chat-evaluator-main\scripts\evaluate.py:238, in run_evaluate_from_config(working_dir, config_path, num_questions, target_url)
[232](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:232) results_dir = working_dir / Path(config["results_dir"])
[234](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:234) # From Dev to trouleshoot
[235](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:235) # print(config)
[236](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:236) # print("service Setup looks like", service_setup.get_openai_config())
--> [238](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:238) evaluation_run_complete = run_evaluation(
[239](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:239) openai_config=service_setup.get_openai_config(),
[240](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:240) testdata_path=working_dir / Path(config["testdata_path"]),
[241](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:241) results_dir=results_dir,
[242](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:242) target_url=target_url or config["target_url"],
[243](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:243) target_parameters=config.get("target_parameters", {}),
[244](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:244) num_questions=num_questions,
[245](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:245) requested_metrics=config.get(
[246](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:246) "requested_metrics",
[247](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:247) ["gpt_groundedness", "gpt_relevance",
[248](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:248) "gpt_coherence", "answer_length", "latency"],
[249](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:249) ),
[250](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:250) target_response_answer_jmespath=config.get(
[251](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:251) "target_response_answer_jmespath"),
[252](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:252) target_response_context_jmespath=config.get(
[253](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:253) "target_response_context_jmespath"),
[254](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:254) )
[256](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:256) if evaluation_run_complete:
[257](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:257) results_config_path = results_dir / "config.json"

File c:\tes\Use Case 46\ragEval\ai-rag-chat-evaluator-main\scripts\evaluate.py:170, in run_evaluation(openai_config, testdata_path, results_dir, target_url, target_parameters, requested_metrics, num_questions, target_response_answer_jmespath, target_response_context_jmespath)
[168](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:168) questions_with_ratings = []
[169](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:169) for row in track(testdata, description="Processing..."):
--> [170](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:170) questions_with_ratings.append(evaluate_row(row))
[172](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:172) logger.info(
[173](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:173) "Evaluation calls have completed. Calculating overall metrics now...")
[174](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:174) # Make the results directory if it doesn't exist

File c:\tes\Use Case 46\ragEval\ai-rag-chat-evaluator-main\scripts\evaluate.py:157, in run_evaluation..evaluate_row(row)
[155](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:155) print(openai_config)
[156](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:156) print(help(metric.evaluator_fn))
--> [157](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:157) result = metric.evaluator_fn(openai_config=openai_config)(
[158](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:158) query=row["question"],
[159](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:159) response=output["answer"],
[160](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:160) context=output["context"],
[161](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:161) ground_truth=row["truth"],
[162](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:162) )
[163](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:163) output.update(result)
[165](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/evaluate.py:165) return output

File c:\tes\Use Case 46\ragEval\ai-rag-chat-evaluator-main\scripts\azureAi_evaluation\_evaluators\_groundedness\_groundedness.py:82, in GroundednessEvaluator.__call__(self, response, context, conversation, **kwargs)
[75](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:75) print(dir(self._flow))
[76](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:76) # print(self._model)
[77](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:77) # print(self._name)
[78](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:78) # print(self._parse_prompty)
[79](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:79) # print(f"response == {response}")
[80](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:80) # print(f"context == {context}")
[81](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:81) # print(f"conversation == {conversation}")
---> [82](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:82) tmpReturn = super().__call__(response=response, context=context,
[83](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:83) conversation=conversation, **kwargs)
[84](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:84) print("Post call, now return")
[85](file:///C:/tes/Use%20Case%2046/ragEval/ai-rag-chat-evaluator-main/scripts/azureAi_evaluation/_evaluators/_groundedness/_groundedness.py:85) return tmpReturn

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\azure\ai\evaluation\_evaluators\_common\_base_eval.py:65, in EvaluatorBase.__call__(self, **kwargs)
[54](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:54) def __call__(self, **kwargs) -> Dict:
[55](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:55) """Evaluate a given input. This method serves as a wrapper and is meant to be overridden by child classes for
[56](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:56) one main reason - to overwrite the method headers and docstring to include additional inputs as needed.
[57](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:57) The actual behavior of this function shouldn't change beyond adding more inputs to the
(...)
[63](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:63) :rtype: Dict
[64](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:64) """
---> [65](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:65) return async_run_allowing_running_loop(self._async_evaluator, **kwargs)

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\_utils\async_utils.py:94, in async_run_allowing_running_loop(async_func, *args, **kwargs)
[92](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:92) if _has_running_loop():
[93](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:93) with ThreadPoolExecutorWithContext() as executor:
---> [94](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:94) return executor.submit(lambda: asyncio.run(async_func(*args, **kwargs))).result()
[95](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:95) else:
[96](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:96) return asyncio.run(_invoke_async_with_sigint_handler(async_func, *args, **kwargs))

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\concurrent\futures\_base.py:456, in Future.result(self, timeout)
[454](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:454) raise CancelledError()
[455](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:455) elif self._state == FINISHED:
--> [456](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:456) return self.__get_result()
[457](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:457) else:
[458](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:458) raise TimeoutError()

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\concurrent\futures\_base.py:401, in Future.__get_result(self)
[399](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:399) if self._exception:
[400](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:400) try:
--> [401](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:401) raise self._exception
[402](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:402) finally:
[403](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:403) # Break a reference cycle with the exception in self._exception
[404](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/_base.py:404) self = None

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\concurrent\futures\thread.py:58, in _WorkItem.run(self)
[55](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/thread.py:55) return
[57](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/thread.py:57) try:
---> [58](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/thread.py:58) result = self.fn(*self.args, **self.kwargs)
[59](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/thread.py:59) except BaseException as exc:
[60](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/concurrent/futures/thread.py:60) self.future.set_exception(exc)

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\_utils\async_utils.py:94, in async_run_allowing_running_loop..()
[92](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:92) if _has_running_loop():
[93](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:93) with ThreadPoolExecutorWithContext() as executor:
---> [94](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:94) return executor.submit(lambda: asyncio.run(async_func(*args, **kwargs))).result()
[95](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:95) else:
[96](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/_utils/async_utils.py:96) return asyncio.run(_invoke_async_with_sigint_handler(async_func, *args, **kwargs))

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\asyncio\runners.py:190, in run(main, debug)
[186](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:186) raise RuntimeError(
[187](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:187) "asyncio.run() cannot be called from a running event loop")
[189](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:189) with Runner(debug=debug) as runner:
--> [190](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:190) return runner.run(main)

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\asyncio\runners.py:118, in Runner.run(self, coro, context)
[116](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:116) self._interrupt_count = 0
[117](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:117) try:
--> [118](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:118) return self._loop.run_until_complete(task)
[119](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:119) except exceptions.CancelledError:
[120](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/runners.py:120) if self._interrupt_count > 0:

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\asyncio\base_events.py:653, in BaseEventLoop.run_until_complete(self, future)
[650](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/base_events.py:650) if not future.done():
[651](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/base_events.py:651) raise RuntimeError('Event loop stopped before Future completed.')
--> [653](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/asyncio/base_events.py:653) return future.result()

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\azure\ai\evaluation\_evaluators\_common\_base_eval.py:302, in AsyncEvaluatorBase.__call__(self, query, response, context, conversation, **kwargs)
[300](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:300) if context is not None:
[301](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:301) kwargs["context"] = context
--> [302](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:302) return await self._real_call(**kwargs)

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\azure\ai\evaluation\_evaluators\_common\_base_eval.py:263, in EvaluatorBase._real_call(self, **kwargs)
[261](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:261) # Evaluate all inputs.
[262](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:262) for eval_input in eval_input_list:
--> [263](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:263) per_turn_results.append(await self._do_eval(eval_input))
[264](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:264) # Return results as-is if only one result was produced.
[266](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_eval.py:266) if len(per_turn_results) == 1:

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\azure\ai\evaluation\_evaluators\_common\_base_prompty_eval.py:72, in PromptyEvaluatorBase._do_eval(self, eval_input)
[61](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:61) @override
[62](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:62) async def _do_eval(self, eval_input: Dict) -> Dict:
[63](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:63) """Do a relevance evaluation.
[64](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:64)
[65](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:65) :param eval_input: The input to the evaluator. Expected to contain
(...)
[70](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:70) :rtype: Dict
[71](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:71) """
---> [72](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:72) llm_output = await self._flow(timeout=self.LLM_CALL_TIMEOUT, **eval_input)
[74](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:74) score = np.nan
[75](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/azure/ai/evaluation/_evaluators/_common/_base_prompty_eval.py:75) if llm_output:

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\tracing\_trace.py:488, in _traced_async..wrapped(*args, **kwargs)
[486](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/tracing/_trace.py:486) Tracer.push(trace)
[487](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/tracing/_trace.py:487) enrich_span_with_input(span, trace.inputs)
--> [488](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/tracing/_trace.py:488) output = await func(*args, **kwargs)
[489](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/tracing/_trace.py:489) output = handle_output(span, trace.inputs, output, trace_type)
[490](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/tracing/_trace.py:490) except Exception as e:

File c:\Users\JDENCH\.conda\envs\ragEval\Lib\site-packages\promptflow\core\_prompty_utils.py:1219, in handle_openai_error_async..decorator..wrapper(*args, **kwargs)
[1217](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1217) status_code = e.response.status_code
[1218](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1218) if status_code < 500 and status_code not in [429, 422]:
-> [1219](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1219) raise WrappedOpenAIError(e)
[1220](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1220) if isinstance(e, RateLimitError) and getattr(e, "type", None) == "insufficient_quota":
[1221](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1221) # Exit retry if this is quota insufficient error
[1222](file:///C:/Users/JDENCH/.conda/envs/ragEval/Lib/site-packages/promptflow/core/_prompty_utils.py:1222) logger.error(f"{type(e).__name__} with insufficient quota. Throw user error.")

WrappedOpenAIError: OpenAI API hits AuthenticationError: Principal does not have access to API/Operation. If you are using azure openai connection, please make sure you have proper role assignment on your azure openai resource. You can refer to https://learn.microsoft.com/en-us/azure/ai-services/openai/how-to/role-based-access-control

### Expected/desired behavior
> I would expect that the basic run functionality would produce results of an evaluation of the chatbot functionality based on the metrics requested. The evaluator starts and passes both tests which suggests the chatbot and GPT endpoints are accessible, but once the promptyflow call is used to make the metrics.__call__ -- this is when things trip up and suggests that the credentials are not properly inherited.

### OS and Version?
> - Promptflow Package Version: 1.16.1
- Operating System: Windows (Windows Server 2019 Datacenter)
- Python Version using `python --version`: Python 3.11.4

### Versions
> - Promptflow Package Version: 1.16.1
- Operating System: Windows (Windows Server 2019 Datacenter)
- Python Version using `python --version`: Python 3.11.4

### Mention any other details that might be useful
I am working from a context where API KEY is not used, my company does not share the API KEY but instead uses a roles based access using the Azure CLI / EntraID credentials and requires that tokens be captured from a call to azure cognitive services. The following is a minimal credentials instantiation script we run in our chatbot

# Use the current user identity to authenticate with Azure OpenAI, AI Search and Blob Storage (no secrets needed,
# just use 'az login' locally, and managed identity when deployed on Azure). If you need to use keys, use separate AzureKeyCredential instances with the
# keys for each service
# If you encounter a blocking error during a DefaultAzureCredential resolution, you can exclude the problematic credential by using a parameter (ex. exclude_shared_token_cache_credential=True)
credential_chain = (
# Azure CLI as default to test on VM so that the managed identity is not picked up
AzureCliCredential(),
# Try Managed Identity second, for the Web App.
ManagedIdentityCredential()
)
azure_credential = ChainedTokenCredential(*credential_chain)
# azure_credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True)

token_provider = get_bearer_token_provider(azure_credential, "https://cognitiveservices.azure.com/.default")
# Store on app.config for later use inside requests
openai_client = AsyncAzureOpenAI(
api_version="2024-03-01-preview",#
azure_endpoint=f"https://{AZURE_OPENAI_SERVICE}.openai.azure.com",
azure_ad_token_provider=token_provider,
)

> ---------------------------------------------------------------
> Thanks! We'll be in touch soon.

Contributor guide

Open the contributing guide

Research direction

Start with evaluate.py and service_setup.py, then inspect the promptflow call path shown in the traceback after running az login. Reproduce the evaluation with the listed groundtruth, local chatbot, and default utilities, and confirm that the Azure CLI credential is available to promptflow and the evaluation completes without AuthenticationError.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, python
Domain
authentication, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.