-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Python: using agents as KernelFunctions #10828
Closed
Closed
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
180 changes: 180 additions & 0 deletions
180
python/samples/concepts/auto_function_calling/chat_completion_with_agent_as_function.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,180 @@ | ||
# Copyright (c) Microsoft. All rights reserved. | ||
|
||
import asyncio | ||
|
||
from samples.concepts.setup.chat_completion_services import Services, get_chat_completion_service_and_request_settings | ||
from semantic_kernel import Kernel | ||
from semantic_kernel.agents.chat_completion.chat_completion_agent import ChatCompletionAgent | ||
from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceBehavior | ||
from semantic_kernel.contents import ChatHistory | ||
from semantic_kernel.filters.functions.function_invocation_context import FunctionInvocationContext | ||
|
||
""" | ||
This sample demonstrates how to build a conversational chatbot | ||
using Semantic Kernel, featuring auto function calling, | ||
using agents as functions, this includes letting a chat interaction | ||
call an agent, and giving one agent another agent to do things. | ||
""" | ||
|
||
# System message defining the behavior and persona of the chat bot. | ||
system_message = """ | ||
You are a chat bot. Your name is Mosscap and | ||
you have one goal: figure out what people need. | ||
Your full name, should you need to know it, is | ||
Splendid Speckled Mosscap. You communicate | ||
effectively, but you tend to answer with long | ||
flowery prose. You are also a math wizard, | ||
especially for adding and subtracting. | ||
You also excel at joke telling, where your tone is often sarcastic. | ||
Once you have the answer I am looking for, | ||
you will return a full answer to me as soon as possible. | ||
""" | ||
|
||
|
||
# Define the auto function invocation filter that will be used by the kernel | ||
async def function_invocation_filter(context: FunctionInvocationContext, next): | ||
"""A filter that will be called for each function call in the response.""" | ||
if "task" not in context.arguments: | ||
await next(context) | ||
return | ||
print(f" Agent {context.function.name} called with task: {context.arguments['task']}") | ||
await next(context) | ||
print(f" Response from agent {context.function.name}: {context.result.value}") | ||
|
||
|
||
# Create and configure the kernel. | ||
kernel = Kernel() | ||
kernel.add_filter("function_invocation", function_invocation_filter) | ||
|
||
# You can select from the following chat completion services that support function calling: | ||
# - Services.OPENAI | ||
# - Services.AZURE_OPENAI | ||
# - Services.AZURE_AI_INFERENCE | ||
# - Services.ANTHROPIC | ||
# - Services.BEDROCK | ||
# - Services.GOOGLE_AI | ||
# - Services.MISTRAL_AI | ||
# - Services.OLLAMA | ||
# - Services.ONNX | ||
# - Services.VERTEX_AI | ||
# - Services.DEEPSEEK | ||
# Please make sure you have configured your environment correctly for the selected chat completion service. | ||
chat_completion_service, request_settings = get_chat_completion_service_and_request_settings(Services.OPENAI) | ||
|
||
# Configure the function choice behavior. Here, we set it to Auto, where auto_invoke=True by default. | ||
# With `auto_invoke=True`, the model will automatically choose and call functions as needed. | ||
request_settings.function_choice_behavior = FunctionChoiceBehavior.Auto(filters={"excluded_plugins": ["ChatBot"]}) | ||
|
||
# Create a chat history to store the system message, initial messages, and the conversation. | ||
history = ChatHistory() | ||
history.add_system_message(system_message) | ||
|
||
REVIEWER_NAME = "ArtDirector" | ||
REVIEWER_INSTRUCTIONS = """ | ||
You are an art director who has opinions about copywriting born of a love for David Ogilvy. | ||
You ask one of the copy-writing agents for a piece of copy, which you then review. | ||
The goal is to determine if the given copy is acceptable to print. | ||
If so, respond with the created copy. | ||
If not, do not return, but ask a copywriter again for copy, providing the returned copy and feedback. | ||
""" | ||
|
||
COPYWRITER_NAME = "CopyWriter" | ||
COPYWRITER_INSTRUCTIONS = """ | ||
You are a copywriter with ten years of experience and are known for brevity and a dry humor. | ||
The goal is to refine and decide on the single best copy as an expert in the field. | ||
Only provide a single proposal per response. | ||
You're laser focused on the goal at hand. | ||
Don't waste time with chit chat. | ||
Consider suggestions when refining an idea. | ||
""" | ||
|
||
writer_agent = ChatCompletionAgent( | ||
service=chat_completion_service, | ||
name=COPYWRITER_NAME, | ||
description="This agent can write copy about any topic.", | ||
instructions=COPYWRITER_INSTRUCTIONS, | ||
) | ||
reviewer_agent = ChatCompletionAgent( | ||
service=chat_completion_service, | ||
name=REVIEWER_NAME, | ||
description="This agent can review copy and provide feedback, he does has copy writers available.", | ||
instructions=REVIEWER_INSTRUCTIONS, | ||
plugins=[writer_agent], | ||
) | ||
|
||
reviewer_agent.kernel.add_filter("function_invocation", function_invocation_filter) | ||
|
||
kernel.add_plugins([reviewer_agent]) | ||
|
||
|
||
async def chat() -> bool: | ||
""" | ||
Continuously prompt the user for input and show the assistant's response. | ||
Type 'exit' to exit. | ||
""" | ||
try: | ||
user_input = input("User:> ") | ||
except (KeyboardInterrupt, EOFError): | ||
print("\n\nExiting chat...") | ||
return False | ||
|
||
if user_input.lower().strip() == "exit": | ||
print("\n\nExiting chat...") | ||
return False | ||
history.add_user_message(user_input) | ||
# Handle non-streaming responses | ||
result = await chat_completion_service.get_chat_message_content( | ||
chat_history=history, settings=request_settings, kernel=kernel | ||
) | ||
|
||
# Update the chat history with the user's input and the assistant's response | ||
if result: | ||
print(f"Mosscap:> {result}") | ||
history.add_message(result) | ||
|
||
return True | ||
|
||
|
||
""" | ||
Sample output: | ||
Welcome to the chat bot! | ||
Type 'exit' to exit. | ||
Try to get some copy written by the copy writer, make sure to ask it is reviewed.). | ||
User:> write a slogan for electric vehicles | ||
Mosscap:> Ah, the realm of electric vehicles, where the whispers of sustainability dance with the vibrant hum of | ||
innovation! How about this for a slogan: | ||
|
||
"Drive the Future: Silent, Smart, and Sustainable!" | ||
|
||
This phrase encapsulates the essence of electric vehicles, inviting all to embrace a journey that is not only | ||
forward-thinking but also harmoniously aligned with the gentle rhythms of our planet. Would you like to explore | ||
more options or perhaps delve into another aspect of this electrifying topic? | ||
User:> ask the art director for it | ||
Agent ArtDirector called with task: Create a slogan for electric vehicles that captures their innovative and | ||
sustainable essence. | ||
Agent CopyWriter called with task: Create a slogan for electric vehicles that captures their innovative and | ||
sustainable essence. | ||
Response from agent CopyWriter: "Drive the Future: Silent, Smart, Sustainable." | ||
Response from agent ArtDirector: "Drive the Future: Silent, Smart, Sustainable." | ||
Mosscap:> The Art Director has conjured forth a splendid slogan for electric vehicles: | ||
|
||
"Drive the Future: Silent, Smart, Sustainable." | ||
|
||
This phrase beautifully encapsulates the innovative spirit and eco-friendly nature of electric vehicles. | ||
If you seek further refinement or wish to explore additional ideas, simply let me know, and I shall be at your service! | ||
""" | ||
|
||
|
||
async def main() -> None: | ||
print( | ||
"Welcome to the chat bot!\n" | ||
" Type 'exit' to exit.\n" | ||
" Try to get some copy written by the copy writer, make sure to ask it is reviewed.)." | ||
) | ||
chatting = True | ||
while chatting: | ||
chatting = await chat() | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
This is not going to work with other types of agents except the chat completion agent.
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.
For my info, why not? I saw get_response is a abstract method so should be available on every agent, or are the args different?
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.
The args are different.