chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel import Kernel
|
||||
from semantic_kernel.agents import AgentGroupChat, ChatCompletionAgent
|
||||
from semantic_kernel.agents.strategies import (
|
||||
KernelFunctionSelectionStrategy,
|
||||
KernelFunctionTerminationStrategy,
|
||||
)
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.contents import ChatHistoryTruncationReducer
|
||||
from semantic_kernel.functions import KernelFunctionFromPrompt
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
agent group chat that utilizes a Reviewer Chat Completion
|
||||
Agent along with a Writer Chat Completion Agent to
|
||||
complete a user's task.
|
||||
|
||||
This is the full code sample for the Semantic Kernel Learn Site: How-To: Coordinate Agent Collaboration
|
||||
using Agent Group Chat
|
||||
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/examples/example-agent-collaboration?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
# Define agent names
|
||||
REVIEWER_NAME = "Reviewer"
|
||||
WRITER_NAME = "Writer"
|
||||
|
||||
|
||||
def create_kernel() -> Kernel:
|
||||
"""Creates a Kernel instance with an Azure OpenAI ChatCompletion service."""
|
||||
kernel = Kernel()
|
||||
kernel.add_service(service=AzureChatCompletion(credential=AzureCliCredential()))
|
||||
return kernel
|
||||
|
||||
|
||||
async def main():
|
||||
# Create a single kernel instance for all agents.
|
||||
kernel = create_kernel()
|
||||
|
||||
# Create ChatCompletionAgents using the same kernel.
|
||||
agent_reviewer = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name=REVIEWER_NAME,
|
||||
instructions="""
|
||||
Your responsibility is to review and identify how to improve user provided content.
|
||||
If the user has provided input or direction for content already provided, specify how to address this input.
|
||||
Never directly perform the correction or provide an example.
|
||||
Once the content has been updated in a subsequent response, review it again until it is satisfactory.
|
||||
|
||||
RULES:
|
||||
- Only identify suggestions that are specific and actionable.
|
||||
- Verify previous suggestions have been addressed.
|
||||
- Never repeat previous suggestions.
|
||||
""",
|
||||
)
|
||||
|
||||
agent_writer = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name=WRITER_NAME,
|
||||
instructions="""
|
||||
Your sole responsibility is to rewrite content according to review suggestions.
|
||||
- Always apply all review directions.
|
||||
- Always revise the content in its entirety without explanation.
|
||||
- Never address the user.
|
||||
""",
|
||||
)
|
||||
|
||||
# Define a selection function to determine which agent should take the next turn.
|
||||
selection_function = KernelFunctionFromPrompt(
|
||||
function_name="selection",
|
||||
prompt=f"""
|
||||
Examine the provided RESPONSE and choose the next participant.
|
||||
State only the name of the chosen participant without explanation.
|
||||
Never choose the participant named in the RESPONSE.
|
||||
|
||||
Choose only from these participants:
|
||||
- {REVIEWER_NAME}
|
||||
- {WRITER_NAME}
|
||||
|
||||
Rules:
|
||||
- If RESPONSE is user input, it is {REVIEWER_NAME}'s turn.
|
||||
- If RESPONSE is by {REVIEWER_NAME}, it is {WRITER_NAME}'s turn.
|
||||
- If RESPONSE is by {WRITER_NAME}, it is {REVIEWER_NAME}'s turn.
|
||||
|
||||
RESPONSE:
|
||||
{{{{$lastmessage}}}}
|
||||
""",
|
||||
)
|
||||
|
||||
# Define a termination function where the reviewer signals completion with "yes".
|
||||
termination_keyword = "yes"
|
||||
|
||||
termination_function = KernelFunctionFromPrompt(
|
||||
function_name="termination",
|
||||
prompt=f"""
|
||||
Examine the RESPONSE and determine whether the content has been deemed satisfactory.
|
||||
If the content is satisfactory, respond with a single word without explanation: {termination_keyword}.
|
||||
If specific suggestions are being provided, it is not satisfactory.
|
||||
If no correction is suggested, it is satisfactory.
|
||||
|
||||
RESPONSE:
|
||||
{{{{$lastmessage}}}}
|
||||
""",
|
||||
)
|
||||
|
||||
history_reducer = ChatHistoryTruncationReducer(target_count=1)
|
||||
|
||||
# Create the AgentGroupChat with selection and termination strategies.
|
||||
chat = AgentGroupChat(
|
||||
agents=[agent_reviewer, agent_writer],
|
||||
selection_strategy=KernelFunctionSelectionStrategy(
|
||||
initial_agent=agent_reviewer,
|
||||
function=selection_function,
|
||||
kernel=kernel,
|
||||
result_parser=lambda result: str(result.value[0]).strip() if result.value[0] is not None else WRITER_NAME,
|
||||
history_variable_name="lastmessage",
|
||||
history_reducer=history_reducer,
|
||||
),
|
||||
termination_strategy=KernelFunctionTerminationStrategy(
|
||||
agents=[agent_reviewer],
|
||||
function=termination_function,
|
||||
kernel=kernel,
|
||||
result_parser=lambda result: termination_keyword in str(result.value[0]).lower(),
|
||||
history_variable_name="lastmessage",
|
||||
maximum_iterations=10,
|
||||
history_reducer=history_reducer,
|
||||
),
|
||||
)
|
||||
|
||||
print(
|
||||
"Ready! Type your input, or 'exit' to quit, 'reset' to restart the conversation. "
|
||||
"You may pass in a file path using @<path_to_file>."
|
||||
)
|
||||
|
||||
is_complete = False
|
||||
while not is_complete:
|
||||
print()
|
||||
user_input = input("User > ").strip()
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() == "exit":
|
||||
is_complete = True
|
||||
break
|
||||
|
||||
if user_input.lower() == "reset":
|
||||
await chat.reset()
|
||||
print("[Conversation has been reset]")
|
||||
continue
|
||||
|
||||
# Try to grab files from the script's current directory
|
||||
if user_input.startswith("@") and len(user_input) > 1:
|
||||
file_name = user_input[1:]
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
file_path = os.path.join(script_dir, file_name)
|
||||
try:
|
||||
if not os.path.exists(file_path):
|
||||
print(f"Unable to access file: {file_path}")
|
||||
continue
|
||||
with open(file_path, encoding="utf-8") as file:
|
||||
user_input = file.read()
|
||||
except Exception:
|
||||
print(f"Unable to access file: {file_path}")
|
||||
continue
|
||||
|
||||
# Add the current user_input to the chat
|
||||
await chat.add_chat_message(message=user_input)
|
||||
|
||||
try:
|
||||
async for response in chat.invoke():
|
||||
if response is None or not response.name:
|
||||
continue
|
||||
print()
|
||||
print(f"# {response.name.upper()}:\n{response.content}")
|
||||
except Exception as e:
|
||||
print(f"Error during chat invocation: {e}")
|
||||
|
||||
# Reset the chat's complete flag for the new conversation round.
|
||||
chat.is_complete = False
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,157 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
import os
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
|
||||
from semantic_kernel.contents import StreamingFileReferenceContent
|
||||
|
||||
logging.basicConfig(level=logging.ERROR)
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
OpenAI assistant agent that utilizes the code interpreter
|
||||
to analyze uploaded files.
|
||||
|
||||
This is the full code sample for the Semantic Kernel Learn Site: How-To: Open AI Assistant Agent Code Interpreter
|
||||
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/examples/example-assistant-code?pivots=programming-language-python
|
||||
""" # noqa: E501
|
||||
|
||||
# Let's form the file paths that we will later pass to the assistant
|
||||
csv_file_path_1 = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
|
||||
"resources",
|
||||
"PopulationByAdmin1.csv",
|
||||
)
|
||||
|
||||
csv_file_path_2 = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
|
||||
"resources",
|
||||
"PopulationByCountry.csv",
|
||||
)
|
||||
|
||||
|
||||
async def download_file_content(agent: AzureAssistantAgent, file_id: str):
|
||||
try:
|
||||
# Fetch the content of the file using the provided method
|
||||
response_content = await agent.client.files.content(file_id)
|
||||
|
||||
# Get the current working directory of the file
|
||||
current_directory = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
# Define the path to save the image in the current directory
|
||||
file_path = os.path.join(
|
||||
current_directory, # Use the current directory of the file
|
||||
f"{file_id}.png", # You can modify this to use the actual filename with proper extension
|
||||
)
|
||||
|
||||
# Save content to a file asynchronously
|
||||
with open(file_path, "wb") as file:
|
||||
file.write(response_content.content)
|
||||
|
||||
print(f"File saved to: {file_path}")
|
||||
except Exception as e:
|
||||
print(f"An error occurred while downloading file {file_id}: {str(e)}")
|
||||
|
||||
|
||||
async def download_response_image(agent: AzureAssistantAgent, file_ids: list[str]):
|
||||
if file_ids:
|
||||
# Iterate over file_ids and download each one
|
||||
for file_id in file_ids:
|
||||
await download_file_content(agent, file_id)
|
||||
|
||||
|
||||
async def main():
|
||||
# Create the client using Azure OpenAI resources and configuration
|
||||
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
|
||||
|
||||
# Upload the files to the client
|
||||
file_ids: list[str] = []
|
||||
for path in [csv_file_path_1, csv_file_path_2]:
|
||||
with open(path, "rb") as file:
|
||||
file = await client.files.create(file=file, purpose="assistants")
|
||||
file_ids.append(file.id)
|
||||
|
||||
# Get the code interpreter tool and resources
|
||||
code_interpreter_tools, code_interpreter_tool_resources = AzureAssistantAgent.configure_code_interpreter_tool(
|
||||
file_ids=file_ids
|
||||
)
|
||||
|
||||
# Create the assistant definition
|
||||
definition = await client.beta.assistants.create(
|
||||
model=AzureOpenAISettings().chat_deployment_name,
|
||||
instructions="""
|
||||
Analyze the available data to provide an answer to the user's question.
|
||||
Always format response using markdown.
|
||||
Always include a numerical index that starts at 1 for any lists or tables.
|
||||
Always sort lists in ascending order.
|
||||
""",
|
||||
name="SampleAssistantAgent",
|
||||
tools=code_interpreter_tools,
|
||||
tool_resources=code_interpreter_tool_resources,
|
||||
)
|
||||
|
||||
# Create the agent using the client and the assistant definition
|
||||
agent = AzureAssistantAgent(
|
||||
client=client,
|
||||
definition=definition,
|
||||
)
|
||||
|
||||
thread: AssistantAgentThread = None
|
||||
|
||||
try:
|
||||
is_complete: bool = False
|
||||
file_ids: list[str] = []
|
||||
while not is_complete:
|
||||
user_input = input("User:> ")
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() == "exit":
|
||||
is_complete = True
|
||||
break
|
||||
|
||||
is_code = False
|
||||
last_role = None
|
||||
async for response in agent.invoke_stream(messages=user_input, thread=thread):
|
||||
current_is_code = response.metadata.get("code", False)
|
||||
|
||||
if current_is_code:
|
||||
if not is_code:
|
||||
print("\n\n```python")
|
||||
is_code = True
|
||||
print(response.content, end="", flush=True)
|
||||
else:
|
||||
if is_code:
|
||||
print("\n```")
|
||||
is_code = False
|
||||
last_role = None
|
||||
if hasattr(response, "role") and response.role is not None and last_role != response.role:
|
||||
print(f"\n# {response.role}: ", end="", flush=True)
|
||||
last_role = response.role
|
||||
print(response.content, end="", flush=True)
|
||||
file_ids.extend([
|
||||
item.file_id for item in response.items if isinstance(item, StreamingFileReferenceContent)
|
||||
])
|
||||
thread = response.thread
|
||||
if is_code:
|
||||
print("```\n")
|
||||
print()
|
||||
|
||||
await download_response_image(agent, file_ids)
|
||||
file_ids.clear()
|
||||
|
||||
finally:
|
||||
print("\nCleaning up resources...")
|
||||
[await client.files.delete(file_id) for file_id in file_ids]
|
||||
await thread.delete() if thread else None
|
||||
await client.beta.assistants.delete(agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,118 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import AssistantAgentThread, AzureAssistantAgent
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureOpenAISettings
|
||||
from semantic_kernel.contents import StreamingAnnotationContent
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
OpenAI assistant agent that utilizes the vector store
|
||||
to answer questions based on the uploaded documents.
|
||||
|
||||
This is the full code sample for the Semantic Kernel Learn Site: How-To: Open AI Assistant Agent File Search
|
||||
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/examples/example-assistant-search?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
|
||||
def get_filepath_for_filename(filename: str) -> str:
|
||||
base_directory = os.path.join(
|
||||
os.path.dirname(os.path.dirname(os.path.realpath(__file__))),
|
||||
"resources",
|
||||
)
|
||||
return os.path.join(base_directory, filename)
|
||||
|
||||
|
||||
filenames = [
|
||||
"Grimms-The-King-of-the-Golden-Mountain.txt",
|
||||
"Grimms-The-Water-of-Life.txt",
|
||||
"Grimms-The-White-Snake.txt",
|
||||
]
|
||||
|
||||
|
||||
async def main():
|
||||
# Create the client using Azure OpenAI resources and configuration
|
||||
client = AzureAssistantAgent.create_client(credential=AzureCliCredential())
|
||||
|
||||
# Upload the files to the client
|
||||
file_ids: list[str] = []
|
||||
for path in [get_filepath_for_filename(filename) for filename in filenames]:
|
||||
with open(path, "rb") as file:
|
||||
file = await client.files.create(file=file, purpose="assistants")
|
||||
file_ids.append(file.id)
|
||||
|
||||
vector_store = await client.vector_stores.create(
|
||||
name="assistant_search",
|
||||
file_ids=file_ids,
|
||||
)
|
||||
|
||||
# Get the file search tool and resources
|
||||
file_search_tools, file_search_tool_resources = AzureAssistantAgent.configure_file_search_tool(
|
||||
vector_store_ids=vector_store.id
|
||||
)
|
||||
|
||||
# Create the assistant definition
|
||||
definition = await client.beta.assistants.create(
|
||||
model=AzureOpenAISettings().chat_deployment_name,
|
||||
instructions="""
|
||||
The document store contains the text of fictional stories.
|
||||
Always analyze the document store to provide an answer to the user's question.
|
||||
Never rely on your knowledge of stories not included in the document store.
|
||||
Always format response using markdown.
|
||||
""",
|
||||
name="SampleAssistantAgent",
|
||||
tools=file_search_tools,
|
||||
tool_resources=file_search_tool_resources,
|
||||
)
|
||||
|
||||
# Create the agent using the client and the assistant definition
|
||||
agent = AzureAssistantAgent(
|
||||
client=client,
|
||||
definition=definition,
|
||||
)
|
||||
|
||||
thread: AssistantAgentThread = None
|
||||
|
||||
try:
|
||||
is_complete: bool = False
|
||||
while not is_complete:
|
||||
user_input = input("User:> ")
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() == "exit":
|
||||
is_complete = True
|
||||
break
|
||||
|
||||
footnotes: list[StreamingAnnotationContent] = []
|
||||
async for response in agent.invoke_stream(messages=user_input, thread=thread):
|
||||
footnotes.extend([item for item in response.items if isinstance(item, StreamingAnnotationContent)])
|
||||
|
||||
print(f"{response.content}", end="", flush=True)
|
||||
if not thread:
|
||||
thread = response.thread
|
||||
|
||||
print()
|
||||
|
||||
if len(footnotes) > 0:
|
||||
for footnote in footnotes:
|
||||
print(
|
||||
f"\n`{footnote.quote}` => {footnote.file_id} "
|
||||
f"(Index: {footnote.start_index} - {footnote.end_index})"
|
||||
)
|
||||
|
||||
finally:
|
||||
print("\nCleaning up resources...")
|
||||
[await client.files.delete(file_id) for file_id in file_ids]
|
||||
await client.vector_stores.delete(vector_store.id)
|
||||
await thread.delete() if thread else None
|
||||
await client.beta.assistants.delete(agent.id)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,88 @@
|
||||
# Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from datetime import datetime
|
||||
|
||||
from azure.identity import AzureCliCredential
|
||||
|
||||
from semantic_kernel.agents import ChatCompletionAgent, ChatHistoryAgentThread
|
||||
from semantic_kernel.connectors.ai import FunctionChoiceBehavior
|
||||
from semantic_kernel.connectors.ai.open_ai import AzureChatCompletion
|
||||
from semantic_kernel.functions import KernelArguments
|
||||
from semantic_kernel.kernel import Kernel
|
||||
|
||||
# Adjust the sys.path so we can use the GitHubPlugin and GitHubSettings classes
|
||||
# This is so we can run the code from the samples/learn_resources/agent_docs directory
|
||||
# If you are running code from your own project, you may not need need to do this.
|
||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
|
||||
|
||||
from plugins.GithubPlugin.github import GitHubPlugin, GitHubSettings # noqa: E402
|
||||
|
||||
"""
|
||||
The following sample demonstrates how to create a simple,
|
||||
ChatCompletionAgent to use a GitHub plugin to interact
|
||||
with the GitHub API.
|
||||
|
||||
This is the full code sample for the Semantic Kernel Learn Site: How-To: Chat Completion Agent
|
||||
|
||||
https://learn.microsoft.com/semantic-kernel/frameworks/agent/examples/example-chat-agent?pivots=programming-language-python
|
||||
"""
|
||||
|
||||
|
||||
async def main():
|
||||
kernel = Kernel()
|
||||
|
||||
# Add the AzureChatCompletion AI Service to the Kernel
|
||||
service_id = "agent"
|
||||
kernel.add_service(AzureChatCompletion(service_id=service_id, credential=AzureCliCredential()))
|
||||
|
||||
settings = kernel.get_prompt_execution_settings_from_service_id(service_id=service_id)
|
||||
# Configure the function choice behavior to auto invoke kernel functions
|
||||
settings.function_choice_behavior = FunctionChoiceBehavior.Auto()
|
||||
|
||||
# Set your GitHub Personal Access Token (PAT) value here
|
||||
gh_settings = GitHubSettings(token="") # nosec
|
||||
kernel.add_plugin(plugin=GitHubPlugin(gh_settings), plugin_name="GithubPlugin")
|
||||
|
||||
current_time = datetime.now().isoformat()
|
||||
|
||||
# Create the agent
|
||||
agent = ChatCompletionAgent(
|
||||
kernel=kernel,
|
||||
name="SampleAssistantAgent",
|
||||
instructions=f"""
|
||||
You are an agent designed to query and retrieve information from a single GitHub repository in a read-only
|
||||
manner.
|
||||
You are also able to access the profile of the active user.
|
||||
|
||||
Use the current date and time to provide up-to-date details or time-sensitive responses.
|
||||
|
||||
The repository you are querying is a public repository with the following name: microsoft/semantic-kernel
|
||||
|
||||
The current date and time is: {current_time}.
|
||||
""",
|
||||
arguments=KernelArguments(settings=settings),
|
||||
)
|
||||
|
||||
thread: ChatHistoryAgentThread = None
|
||||
is_complete: bool = False
|
||||
while not is_complete:
|
||||
user_input = input("User:> ")
|
||||
if not user_input:
|
||||
continue
|
||||
|
||||
if user_input.lower() == "exit":
|
||||
is_complete = True
|
||||
break
|
||||
|
||||
arguments = KernelArguments(now=datetime.now().strftime("%Y-%m-%d %H:%M"))
|
||||
|
||||
async for response in agent.invoke(messages=user_input, thread=thread, arguments=arguments):
|
||||
print(f"{response.content}")
|
||||
thread = response.thread
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user