mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Python: Fix AI Search Tool Sample and improve AI Search Exceptions (#1206)
* Python: Fix AI Search Tool Sample and improve AI Search Exceptions * Python: Fix AI Search Tool Test --------- Co-authored-by: Dmytro Struk <13853051+dmytrostruk@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
e032fe3993
commit
350cdfc1cd
@@ -949,7 +949,7 @@ class AzureAIAgentClient(BaseChatClient):
|
||||
azs_conn_id = await self.project_client.connections.get_default(
|
||||
ConnectionType.AZURE_AI_SEARCH
|
||||
)
|
||||
except HttpResponseError as err:
|
||||
except ValueError as err:
|
||||
raise ServiceInitializationError(
|
||||
"No default Azure AI Search connection found in the Azure AI Project. "
|
||||
"Please create one or provide vector store inputs for the file search tool.",
|
||||
|
||||
@@ -1067,8 +1067,8 @@ async def test_azure_ai_chat_client_prep_tools_file_search_no_connection(mock_ai
|
||||
|
||||
file_search_tool = HostedFileSearchTool(additional_properties={"index_name": "test-index"})
|
||||
|
||||
# Mock connections.get_default to raise HttpResponseError
|
||||
mock_ai_project_client.connections.get_default = AsyncMock(side_effect=HttpResponseError("No connection found"))
|
||||
# Mock connections.get_default to raise ValueError
|
||||
mock_ai_project_client.connections.get_default = AsyncMock(side_effect=ValueError("No connection found"))
|
||||
|
||||
with pytest.raises(ServiceInitializationError, match="No default Azure AI Search connection found"):
|
||||
await chat_client._prep_tools([file_search_tool]) # type: ignore
|
||||
|
||||
@@ -53,9 +53,7 @@ async def main():
|
||||
resolver = A2ACardResolver(httpx_client=http_client, base_url=a2a_agent_host)
|
||||
|
||||
# Get agent card
|
||||
agent_card = await resolver.get_agent_card(
|
||||
relative_card_path="/.well-known/agent.json"
|
||||
)
|
||||
agent_card = await resolver.get_agent_card(relative_card_path="/.well-known/agent.json")
|
||||
print(f"Found agent: {agent_card.name} - {agent_card.description}")
|
||||
|
||||
# Create A2A agent instance
|
||||
|
||||
@@ -43,9 +43,7 @@ async def main() -> None:
|
||||
):
|
||||
agent = chat_client.create_agent(
|
||||
name="CodingAgent",
|
||||
instructions=(
|
||||
"You are a helpful assistant that can write and execute Python code to solve problems."
|
||||
),
|
||||
instructions=("You are a helpful assistant that can write and execute Python code to solve problems."),
|
||||
tools=HostedCodeInterpreterTool(),
|
||||
)
|
||||
query = "Generate the factorial of 100 using python code, show the code and execute it."
|
||||
|
||||
@@ -63,12 +63,24 @@ async def main() -> None:
|
||||
response = await agent.run(user_input)
|
||||
print(f"# Agent: {response.text}")
|
||||
|
||||
# 5. Cleanup: Delete the vector store and file
|
||||
try:
|
||||
if vector_store:
|
||||
await client.project_client.agents.vector_stores.delete(vector_store.id)
|
||||
if file:
|
||||
await client.project_client.agents.files.delete(file.id)
|
||||
except Exception:
|
||||
# Ignore cleanup errors to avoid masking issues
|
||||
pass
|
||||
finally:
|
||||
# 5. Cleanup: Delete the vector store and file
|
||||
# 6. Cleanup: Delete the vector store and file in case of eariler failure to prevent orphaned resources.
|
||||
|
||||
# Refreshing the client is required since chat agent closes it
|
||||
client = AzureAIAgentClient(async_credential=AzureCliCredential())
|
||||
try:
|
||||
if vector_store is not None:
|
||||
if vector_store:
|
||||
await client.project_client.agents.vector_stores.delete(vector_store.id)
|
||||
if file is not None:
|
||||
if file:
|
||||
await client.project_client.agents.files.delete(file.id)
|
||||
except Exception:
|
||||
# Ignore cleanup errors to avoid masking issues
|
||||
|
||||
+6
-2
@@ -261,11 +261,15 @@ class PolicyEngine(Executor):
|
||||
|
||||
@handler
|
||||
async def handle_policy_request(
|
||||
self, request: PolicyCheckRequest, ctx: WorkflowContext[RequestResponse[PolicyCheckRequest, Any] | PolicyCheckRequest]
|
||||
self,
|
||||
request: PolicyCheckRequest,
|
||||
ctx: WorkflowContext[RequestResponse[PolicyCheckRequest, Any] | PolicyCheckRequest],
|
||||
) -> None:
|
||||
"""Handle POLICY requests from sub-workflows and apply rules."""
|
||||
policy_request = request
|
||||
print(f"🛡️ POLICY interceptor checking: {policy_request.amount} {policy_request.resource_type}, policy={policy_request.policy_type}")
|
||||
print(
|
||||
f"🛡️ POLICY interceptor checking: {policy_request.amount} {policy_request.resource_type}, policy={policy_request.policy_type}"
|
||||
)
|
||||
|
||||
quota_limit = self.quota.get(policy_request.resource_type, 0)
|
||||
|
||||
|
||||
+2
-6
@@ -182,7 +182,7 @@ class SmartEmailOrchestrator(Executor):
|
||||
async def handle_domain_request(
|
||||
self,
|
||||
request: DomainCheckRequest,
|
||||
ctx: WorkflowContext[RequestResponse[DomainCheckRequest, bool] | DomainCheckRequest]
|
||||
ctx: WorkflowContext[RequestResponse[DomainCheckRequest, bool] | DomainCheckRequest],
|
||||
) -> None:
|
||||
"""Handle requests from sub-workflows."""
|
||||
print(f"🔍 Parent intercepting domain check for: {request.domain}")
|
||||
@@ -190,11 +190,7 @@ class SmartEmailOrchestrator(Executor):
|
||||
if request.domain in self.approved_domains:
|
||||
print(f"✅ Domain '{request.domain}' is pre-approved locally!")
|
||||
# Send response back to sub-workflow
|
||||
response = RequestResponse(
|
||||
data=True,
|
||||
original_request=request,
|
||||
request_id=request.request_id
|
||||
)
|
||||
response = RequestResponse(data=True, original_request=request, request_id=request.request_id)
|
||||
await ctx.send_message(response, target_id=request.source_executor_id)
|
||||
else:
|
||||
print(f"❓ Domain '{request.domain}' unknown, forwarding to external service...")
|
||||
|
||||
@@ -65,6 +65,7 @@ class CommonEvents(Enum):
|
||||
EXIT_REQUESTED = "ExitRequested"
|
||||
START_PROCESS = "StartProcess"
|
||||
|
||||
|
||||
######################################################################
|
||||
# region Semantic Kernel Process Framework path
|
||||
######################################################################
|
||||
@@ -153,6 +154,7 @@ async def run_semantic_kernel_process_example() -> None:
|
||||
assert c_step_state.state.current_cycle == 3 # nosec
|
||||
print(f"Final State Check: CStepState current cycle: {c_step_state.state.current_cycle}")
|
||||
|
||||
|
||||
######################################################################
|
||||
# region Agent Framework workflow path
|
||||
######################################################################
|
||||
|
||||
@@ -50,6 +50,7 @@ class ProcessEvents(Enum):
|
||||
OUTPUT_READY_PUBLIC = "OutputReadyPublic"
|
||||
OUTPUT_READY_INTERNAL = "OutputReadyInternal"
|
||||
|
||||
|
||||
######################################################################
|
||||
# region Semantic Kernel nested process path
|
||||
######################################################################
|
||||
@@ -152,6 +153,7 @@ async def run_semantic_kernel_nested_process() -> None:
|
||||
raise RuntimeError("RepeatStep state missing")
|
||||
assert repeat_state.state.last_message == "Test Test Test Test" # nosec
|
||||
|
||||
|
||||
######################################################################
|
||||
# region Agent Framework nested workflow path
|
||||
######################################################################
|
||||
@@ -260,6 +262,7 @@ async def run_agent_framework_nested_workflow(initial_message: str) -> Sequence[
|
||||
|
||||
return results
|
||||
|
||||
|
||||
######################################################################
|
||||
# endregion
|
||||
######################################################################
|
||||
|
||||
Reference in New Issue
Block a user