Skip to content

Commit a3030db

Browse files
authored
fix append_oai_message (microsoft#47)
* fix append_oai_message * add testcase for groupchat * add test_oai to openai workflow * code formate * update * formate * update
1 parent 46db75e commit a3030db

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

.github/workflows/openai.yml

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ jobs:
6969
OAI_CONFIG_LIST: ${{ secrets.OAI_CONFIG_LIST }}
7070
run: |
7171
pip install nbconvert nbformat ipykernel
72+
coverage run -a -m pytest test/test_with_openai.py
7273
coverage run -a -m pytest test/test_notebook.py
7374
coverage xml
7475
cat "$(pwd)/test/executed_openai_notebook_output.txt"

autogen/agentchat/conversable_agent.py

+12-6
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,7 @@ def _append_oai_message(self, message: Union[Dict, str], role, conversation_id:
259259
If the message received is a string, it will be put in the "content" field of the new dictionary.
260260
If the message received is a dictionary but does not have any of the two fields "content" or "function_call",
261261
this message is not a valid ChatCompletion message.
262+
If only "function_call" is provided, "content" will be set to None if not provided, and the role of the message will be forced "assistant".
262263
263264
Args:
264265
message (dict or str): message to be appended to the ChatCompletion conversation.
@@ -271,10 +272,15 @@ def _append_oai_message(self, message: Union[Dict, str], role, conversation_id:
271272
message = self._message_to_dict(message)
272273
# create oai message to be appended to the oai conversation that can be passed to oai directly.
273274
oai_message = {k: message[k] for k in ("content", "function_call", "name", "context") if k in message}
274-
if "content" not in oai_message and "function_call" not in oai_message:
275-
return False
275+
if "content" not in oai_message:
276+
if "function_call" in oai_message:
277+
oai_message["content"] = None # if only function_call is provided, content will be set to None.
278+
else:
279+
return False
276280

277281
oai_message["role"] = "function" if message.get("role") == "function" else role
282+
if "function_call" in oai_message:
283+
oai_message["role"] = "assistant" # only messages with role 'assistant' can have a function call.
278284
self._oai_messages[conversation_id].append(oai_message)
279285
return True
280286

@@ -289,8 +295,8 @@ def send(
289295
290296
Args:
291297
message (dict or str): message to be sent.
292-
The message could contain the following fields (either content or function_call must be provided):
293-
- content (str): the content of the message.
298+
The message could contain the following fields:
299+
- content (str): Required, the content of the message. (Can be None)
294300
- function_call (str): the name of the function to be called.
295301
- name (str): the name of the function to be called.
296302
- role (str): the role of the message, any role that is not "function"
@@ -338,8 +344,8 @@ async def a_send(
338344
339345
Args:
340346
message (dict or str): message to be sent.
341-
The message could contain the following fields (either content or function_call must be provided):
342-
- content (str): the content of the message.
347+
The message could contain the following fields:
348+
- content (str): Required, the content of the message. (Can be None)
343349
- function_call (str): the name of the function to be called.
344350
- name (str): the name of the function to be called.
345351
- role (str): the role of the message, any role that is not "function"

test/test_with_openai.py

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import autogen
2+
import pytest
3+
import sys
4+
5+
try:
6+
import openai
7+
8+
skip = False
9+
except ImportError:
10+
skip = True
11+
12+
13+
@pytest.mark.skipif(
14+
skip or not sys.version.startswith("3.10"),
15+
reason="do not run if openai is not installed or py!=3.10",
16+
)
17+
def test_function_call_groupchat():
18+
import random
19+
20+
def get_random_number():
21+
return random.randint(0, 100)
22+
23+
config_list_gpt4 = autogen.config_list_from_json(
24+
"OAI_CONFIG_LIST",
25+
filter_dict={
26+
"model": ["gpt-4", "gpt-4-0314", "gpt4", "gpt-4-32k", "gpt-4-32k-0314", "gpt-4-32k-v0314"],
27+
},
28+
)
29+
llm_config = {
30+
"config_list": config_list_gpt4,
31+
"seed": 42,
32+
"functions": [
33+
{
34+
"name": "get_random_number",
35+
"description": "Get a random number between 0 and 100",
36+
"parameters": {
37+
"type": "object",
38+
"properties": {},
39+
},
40+
},
41+
],
42+
}
43+
user_proxy = autogen.UserProxyAgent(
44+
name="User_proxy",
45+
system_message="A human admin that will execute function_calls.",
46+
function_map={"get_random_number": get_random_number},
47+
human_input_mode="NEVER",
48+
)
49+
coder = autogen.AssistantAgent(
50+
name="Player",
51+
system_message="You will can function `get_random_number` to get a random number. Stop only when you get at least 1 even number and 1 odd number. Reply TERMINATE to stop.",
52+
llm_config=llm_config,
53+
)
54+
groupchat = autogen.GroupChat(agents=[user_proxy, coder], messages=[], max_round=7)
55+
manager = autogen.GroupChatManager(groupchat=groupchat, llm_config=llm_config)
56+
57+
user_proxy.initiate_chat(manager, message="Let's start the game!")
58+
59+
60+
if __name__ == "__main__":
61+
test_function_call_groupchat()

0 commit comments

Comments
 (0)