Skip to content
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

Add decorator for function calling #1018

Merged
merged 44 commits into from
Dec 25, 2023

Conversation

davorrunje
Copy link
Collaborator

@davorrunje davorrunje commented Dec 18, 2023

Why are these changes needed?

Inspired by modern Python frameworks, an alternative method of registering functions using typing annotations and a function decorator could be added to the framework.

The principle can be illustrated in the following modified example in agentchat_function_call.ipynb notebook:

llm_config = {
   "config_list": config_list,
   "timeout": 120,
}
chatbot = autogen.AssistantAgent(
   name="chatbot",
   system_message="For coding tasks, only use the functions you have been provided with. Reply TERMINATE when the task is done.",
   llm_config=llm_config,
)

user_proxy = autogen.UserProxyAgent(
   name="user_proxy",
   is_termination_msg=lambda x: x.get("content", "") and x.get("content", "").rstrip().endswith("TERMINATE"),
   human_input_mode="NEVER",
   max_consecutive_auto_reply=10,
   code_execution_config={"work_dir": "coding"},
)

from typing import Annotated
from IPython import get_ipython

@user_proxy.register_for_execution()
@chatbot.register_for_llm(name="python", description="run cell in ipython and return the execution result.")
def exec_python(cell: Annotated[str, "Valid Python cell to execute."]):
   ...

@user_proxy.register_for_execution()
@chatbot.register_for_llm(name="sh", description="run a shell script and return the execution result.")
def exec_sh(script: Annotated[str, "Valid shell script to execute."]):
   return user_proxy.execute_code_blocks([("sh", script)])

user_proxy.initiate_chat(
   chatbot,
   message="Draw two agents chatting with each other with an example dialog. Don't add plt.show().",
)

The @agent.register_for_llm(...) function decorator reads the signature of the function and generates the function dictionary and calls ​​agent.update_function_signature(). The @agent.register_for_execution(...) function decorator wraps the function so it uses Pydantic.BaseModel.model_dump_json() to serialize output to string if needed and then calls agent.register_function() with the wrapped function.

The main advantage of this approach is the automatic generation of JSON schema from type hints in the signature of a decorated function. It is easy to use and results in much shorter and more understandable code. Alternatively, manually written JSON schemas are prone to errors and difficult to debug. If there is an error in the JSON schema, OpenAI API will silently ignore it and potentially produce incorrect parameters. Such mistakes are easy to make, a developer must remember to use 'string', 'integer', 'number', 'null' instead of appropriate Python base types. Encoding more complex JSON schemas involving tuples, lists, unions etc. is even more difficult. On the other hand, proposed decorators immediately raise an exception with an explanation of why the generation of the JSON schema failed.

Developers today are well versed in using decorators and type hints because of FastAPI and similar frameworks. Moreover, there is a strong preference for such a style as evidenced by the rising popularity of FastAPI and the decline of older Flask. Implementing decorators in the framework requires a somewhat deeper knowledge of Python, but using them feels natural and has proven easy to adopt by a wide range of developers.

Related issue number

Checks

@davorrunje
Copy link
Collaborator Author

@microsoft-github-policy-service agree company="AIRT Technologies"

@davorrunje
Copy link
Collaborator Author

@microsoft-github-policy-service agree company="AIRT Technologies"

@rickyloynd-microsoft
Copy link
Contributor

@davorrunje In the "Why are these changes needed?" section, can you add a description of the expected benefits of this PR? Will it make certain code more readable or easier to write? Also, how much do you anticipate this will increase the learning curve for repo users unfamiliar with python decorators?

@davorrunje
Copy link
Collaborator Author

@rickyloynd-microsoft I tried to summarize the discussion we had on Discord (https://discord.com/channels/1153072414184452236/1185807538801873016) in the "Why are these changes needed?" section. Please let me know if more info is needed.

Copy link
Collaborator

@qingyun-wu qingyun-wu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This decorator addition is very appealing and the documentation looks good to me now. Thanks @davorrunje!

@qingyun-wu qingyun-wu added this pull request to the merge queue Dec 25, 2023
Merged via the queue into microsoft:main with commit 4b5ec5a Dec 25, 2023
84 checks passed
@davorrunje
Copy link
Collaborator Author

This decorator addition is very appealing and the documentation looks good to me now. Thanks @davorrunje!

Thank you :) This is one of my favorite projects and I am glad if I can help.

I am not happy with the documentation, i will try to write a standalone page with more examples in a separate PR.

@ekzhu
Copy link
Collaborator

ekzhu commented Dec 25, 2023

@davorrunje thank you so much for your contribution!

@lestan
Copy link

lestan commented Dec 26, 2023

Is this feature in 0.2.2 or in the next version? I tried the example in the notebook and it's not working. I am on 0.2.2.

Error I'm getting is:
@user_proxy.register_for_execution() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'UserProxyAgent' object has no attribute 'register_for_execution'. Did you mean: 'register_function'?

Any suggestions? Thanks!

@rickyloynd-microsoft
Copy link
Contributor

Is this feature in 0.2.2 or in the next version? I tried the example in the notebook and it's not working. I am on 0.2.2.

Error I'm getting is: @user_proxy.register_for_execution() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ AttributeError: 'UserProxyAgent' object has no attribute 'register_for_execution'. Did you mean: 'register_function'?

Any suggestions? Thanks!

It will be in the next pip version, not 0.2.2.

@davorrunje
Copy link
Collaborator Author

@davorrunje thank you so much for your contribution!

@ekzhu it was a pleasure :)

whiskyboy pushed a commit to whiskyboy/autogen that referenced this pull request Apr 17, 2024
* raise content_filter error

* import error handling
whiskyboy pushed a commit to whiskyboy/autogen that referenced this pull request Apr 17, 2024
* add function decorator to converasble agent

* polishing

* polishing

* added function decorator to the notebook with async function calls

* added support for return type hint and JSON encoding of returned value if needed

* polishing

* polishing

* refactored async case

* Python 3.8 support added

* polishing

* polishing

* missing docs added

* refacotring and changes as requested

* getLogger

* documentation added

* test fix

* test fix

* added testing of agentchat_function_call_currency_calculator.ipynb to test_notebook.py

* added support for Pydantic parameters in function decorator

* polishing

* Update website/docs/Use-Cases/agent_chat.md

Co-authored-by: Li Jiang <bnujli@gmail.com>

* Update website/docs/Use-Cases/agent_chat.md

Co-authored-by: Li Jiang <bnujli@gmail.com>

* fixes problem with logprob parameter in openai.types.chat.chat_completion.Choice added by openai version 1.5.0

* get 100% code coverage on code added

* updated docs

* default values added to JSON schema

* serialization using json.dump() add for values not string or BaseModel

* added limit to openai version because of breaking changes in 1.5.0

* added line-by-line comments in docs to explain the process

* polishing

---------

Co-authored-by: Eric Zhu <ekzhu@users.noreply.github.com>
Co-authored-by: Li Jiang <bnujli@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants