You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

test_logging.py 9.4 kB

Logging (#1146) * WIP:logging * serialize request, response and client * Fixed code formatting. * Updated to use a global package, and added some test cases. Still very-much a draft. * Update work in progress. * adding cost * log new agent * update log_completion test in test_agent_telemetry * tests * fix formatting * Added additional telemetry for wrappers and clients. * WIP: add test for oai client and oai wrapper table * update test_telemetry * fix format * More tests, update doc and clean up * small fix for session id - moved to start_logging and return from start_logging * update start_logging type to return str, add notebook to demonstrate use of telemetry * add ability to get log dataframe * precommit formatting fixes * formatting fix * Remove pandas dependency from telemetry and only use in notebook * formatting fixes * log query exceptions * fix formatting * fix ci * fix comment - add notebook link in doc and fix groupchat serialization * small fix * do not serialize Agent * formatting * wip * fix test * serialization bug fix for soc moderator * fix test and clean up * wip: add version table * fix test * fix test * fix test * make the logging interface more general and fix client model logging * fix format * fix formatting and tests * fix * fix comment * Renaming telemetry to logging * update notebook * update doc * formatting * formatting and clean up * fix doc * fix link and title * fix notebook format and fix comment * format * try fixing agent test and update migration guide * fix link * debug print * debug * format * add back tests * fix tests --------- Co-authored-by: Adam Fourney <adamfo@microsoft.com> Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Chi Wang <wang.chi@microsoft.com>
2 years ago
Logging (#1146) * WIP:logging * serialize request, response and client * Fixed code formatting. * Updated to use a global package, and added some test cases. Still very-much a draft. * Update work in progress. * adding cost * log new agent * update log_completion test in test_agent_telemetry * tests * fix formatting * Added additional telemetry for wrappers and clients. * WIP: add test for oai client and oai wrapper table * update test_telemetry * fix format * More tests, update doc and clean up * small fix for session id - moved to start_logging and return from start_logging * update start_logging type to return str, add notebook to demonstrate use of telemetry * add ability to get log dataframe * precommit formatting fixes * formatting fix * Remove pandas dependency from telemetry and only use in notebook * formatting fixes * log query exceptions * fix formatting * fix ci * fix comment - add notebook link in doc and fix groupchat serialization * small fix * do not serialize Agent * formatting * wip * fix test * serialization bug fix for soc moderator * fix test and clean up * wip: add version table * fix test * fix test * fix test * make the logging interface more general and fix client model logging * fix format * fix formatting and tests * fix * fix comment * Renaming telemetry to logging * update notebook * update doc * formatting * formatting and clean up * fix doc * fix link and title * fix notebook format and fix comment * format * try fixing agent test and update migration guide * fix link * debug print * debug * format * add back tests * fix tests --------- Co-authored-by: Adam Fourney <adamfo@microsoft.com> Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Chi Wang <wang.chi@microsoft.com>
2 years ago
Logging (#1146) * WIP:logging * serialize request, response and client * Fixed code formatting. * Updated to use a global package, and added some test cases. Still very-much a draft. * Update work in progress. * adding cost * log new agent * update log_completion test in test_agent_telemetry * tests * fix formatting * Added additional telemetry for wrappers and clients. * WIP: add test for oai client and oai wrapper table * update test_telemetry * fix format * More tests, update doc and clean up * small fix for session id - moved to start_logging and return from start_logging * update start_logging type to return str, add notebook to demonstrate use of telemetry * add ability to get log dataframe * precommit formatting fixes * formatting fix * Remove pandas dependency from telemetry and only use in notebook * formatting fixes * log query exceptions * fix formatting * fix ci * fix comment - add notebook link in doc and fix groupchat serialization * small fix * do not serialize Agent * formatting * wip * fix test * serialization bug fix for soc moderator * fix test and clean up * wip: add version table * fix test * fix test * fix test * make the logging interface more general and fix client model logging * fix format * fix formatting and tests * fix * fix comment * Renaming telemetry to logging * update notebook * update doc * formatting * formatting and clean up * fix doc * fix link and title * fix notebook format and fix comment * format * try fixing agent test and update migration guide * fix link * debug print * debug * format * add back tests * fix tests --------- Co-authored-by: Adam Fourney <adamfo@microsoft.com> Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Chi Wang <wang.chi@microsoft.com>
2 years ago
Logging (#1146) * WIP:logging * serialize request, response and client * Fixed code formatting. * Updated to use a global package, and added some test cases. Still very-much a draft. * Update work in progress. * adding cost * log new agent * update log_completion test in test_agent_telemetry * tests * fix formatting * Added additional telemetry for wrappers and clients. * WIP: add test for oai client and oai wrapper table * update test_telemetry * fix format * More tests, update doc and clean up * small fix for session id - moved to start_logging and return from start_logging * update start_logging type to return str, add notebook to demonstrate use of telemetry * add ability to get log dataframe * precommit formatting fixes * formatting fix * Remove pandas dependency from telemetry and only use in notebook * formatting fixes * log query exceptions * fix formatting * fix ci * fix comment - add notebook link in doc and fix groupchat serialization * small fix * do not serialize Agent * formatting * wip * fix test * serialization bug fix for soc moderator * fix test and clean up * wip: add version table * fix test * fix test * fix test * make the logging interface more general and fix client model logging * fix format * fix formatting and tests * fix * fix comment * Renaming telemetry to logging * update notebook * update doc * formatting * formatting and clean up * fix doc * fix link and title * fix notebook format and fix comment * format * try fixing agent test and update migration guide * fix link * debug print * debug * format * add back tests * fix tests --------- Co-authored-by: Adam Fourney <adamfo@microsoft.com> Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Chi Wang <wang.chi@microsoft.com>
2 years ago
Logging (#1146) * WIP:logging * serialize request, response and client * Fixed code formatting. * Updated to use a global package, and added some test cases. Still very-much a draft. * Update work in progress. * adding cost * log new agent * update log_completion test in test_agent_telemetry * tests * fix formatting * Added additional telemetry for wrappers and clients. * WIP: add test for oai client and oai wrapper table * update test_telemetry * fix format * More tests, update doc and clean up * small fix for session id - moved to start_logging and return from start_logging * update start_logging type to return str, add notebook to demonstrate use of telemetry * add ability to get log dataframe * precommit formatting fixes * formatting fix * Remove pandas dependency from telemetry and only use in notebook * formatting fixes * log query exceptions * fix formatting * fix ci * fix comment - add notebook link in doc and fix groupchat serialization * small fix * do not serialize Agent * formatting * wip * fix test * serialization bug fix for soc moderator * fix test and clean up * wip: add version table * fix test * fix test * fix test * make the logging interface more general and fix client model logging * fix format * fix formatting and tests * fix * fix comment * Renaming telemetry to logging * update notebook * update doc * formatting * formatting and clean up * fix doc * fix link and title * fix notebook format and fix comment * format * try fixing agent test and update migration guide * fix link * debug print * debug * format * add back tests * fix tests --------- Co-authored-by: Adam Fourney <adamfo@microsoft.com> Co-authored-by: Victor Dibia <victordibia@microsoft.com> Co-authored-by: Chi Wang <wang.chi@microsoft.com>
2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. import json
  2. import sqlite3
  3. import uuid
  4. from unittest.mock import Mock, patch
  5. import pytest
  6. from openai import AzureOpenAI
  7. import autogen.runtime_logging
  8. from autogen.logger.logger_utils import get_current_ts, to_dict
  9. SAMPLE_CHAT_REQUEST = json.loads(
  10. """
  11. {
  12. "messages": [
  13. {
  14. "content": "You are roleplaying a high school student strugling with linear algebra. Regardless how well the teacher explains things to you, you just don't quite get it. Keep your questions short.",
  15. "role": "system"
  16. },
  17. {
  18. "content": "Can you explain the difference between eigenvalues and singular values again?",
  19. "role": "assistant"
  20. },
  21. {
  22. "content": "Certainly!\\n\\nEigenvalues are associated with square matrices. They are the scalars, \\u03bb, that satisfy the equation\\n\\nA*x = \\u03bb*x\\n\\nwhere A is a square matrix, x is a nonzero vector (the eigenvector), and \\u03bb is the eigenvalue. The eigenvalue equation shows how the vector x is stretched or shrunk by the matrix A.\\n\\nSingular values, on the other hand, are associated with any m x n matrix, whether square or rectangular. They come from the matrix's singular value decomposition (SVD) and are the square roots of the non-negative eigenvalues of the matrix A*A^T or A^T*A (where A^T is the transpose of A). Singular values, denoted often by \\u03c3, represent the magnitude of the principal axes of the data's distribution and are always non-negative.\\n\\nTo sum up, eigenvalues relate to how a matrix scales vectors (specific to square matrices), while singular values give a measure of how a matrix stretches space (applicable to all matrices).",
  23. "role": "user"
  24. }
  25. ],
  26. "model": "gpt-4"
  27. }
  28. """
  29. )
  30. SAMPLE_CHAT_RESPONSE = json.loads(
  31. """
  32. {
  33. "id": "chatcmpl-8k57oSg1fz2JwpMcEOWMqUvwjf0cb",
  34. "choices": [
  35. {
  36. "finish_reason": "stop",
  37. "index": 0,
  38. "logprobs": null,
  39. "message": {
  40. "content": "Oh, wait, I don't think I completely understand the concept of matrix multiplication. Could you break down how you multiply two matrices together?",
  41. "role": "assistant",
  42. "function_call": null,
  43. "tool_calls": null
  44. }
  45. }
  46. ],
  47. "created": 1705993480,
  48. "model": "gpt-4",
  49. "object": "chat.completion",
  50. "system_fingerprint": "fp_6d044fb900",
  51. "usage": {
  52. "completion_tokens": 28,
  53. "prompt_tokens": 274,
  54. "total_tokens": 302
  55. }
  56. }
  57. """
  58. )
  59. ###############################################################
  60. @pytest.fixture(scope="function")
  61. def db_connection():
  62. autogen.runtime_logging.start(config={"dbname": ":memory:"})
  63. con = autogen.runtime_logging.get_connection()
  64. con.row_factory = sqlite3.Row
  65. yield con
  66. autogen.runtime_logging.stop()
  67. def get_sample_chat_completion(response):
  68. return {
  69. "invocation_id": str(uuid.uuid4()),
  70. "client_id": 140609438577184,
  71. "wrapper_id": 140610167717744,
  72. "request": SAMPLE_CHAT_REQUEST,
  73. "response": response,
  74. "is_cached": 0,
  75. "cost": 0.347,
  76. "start_time": get_current_ts(),
  77. }
  78. @pytest.mark.parametrize(
  79. "response, expected_logged_response",
  80. [
  81. (SAMPLE_CHAT_RESPONSE, SAMPLE_CHAT_RESPONSE),
  82. (None, {"response": None}),
  83. ("error in response", {"response": "error in response"}),
  84. ],
  85. )
  86. def test_log_completion(response, expected_logged_response, db_connection):
  87. cur = db_connection.cursor()
  88. sample_completion = get_sample_chat_completion(response)
  89. autogen.runtime_logging.log_chat_completion(**sample_completion)
  90. query = """
  91. SELECT invocation_id, client_id, wrapper_id, request, response, is_cached,
  92. cost, start_time FROM chat_completions
  93. """
  94. for row in cur.execute(query):
  95. assert row["invocation_id"] == sample_completion["invocation_id"]
  96. assert row["client_id"] == sample_completion["client_id"]
  97. assert row["wrapper_id"] == sample_completion["wrapper_id"]
  98. assert json.loads(row["request"]) == sample_completion["request"]
  99. assert json.loads(row["response"]) == expected_logged_response
  100. assert row["is_cached"] == sample_completion["is_cached"]
  101. assert row["cost"] == sample_completion["cost"]
  102. assert row["start_time"] == sample_completion["start_time"]
  103. def test_log_new_agent(db_connection):
  104. from autogen import AssistantAgent
  105. cur = db_connection.cursor()
  106. agent_name = "some_assistant"
  107. config_list = [{"model": "gpt-4", "api_key": "some_key"}]
  108. agent = AssistantAgent(agent_name, llm_config={"config_list": config_list})
  109. init_args = {"foo": "bar", "baz": {"other_key": "other_val"}, "a": None}
  110. autogen.runtime_logging.log_new_agent(agent, init_args)
  111. query = """
  112. SELECT session_id, name, class, init_args FROM agents
  113. """
  114. for row in cur.execute(query):
  115. assert (
  116. row["session_id"] and str(uuid.UUID(row["session_id"], version=4)) == row["session_id"]
  117. ), "session id is not valid uuid"
  118. assert row["name"] == agent_name
  119. assert row["class"] == "AssistantAgent"
  120. assert row["init_args"] == json.dumps(init_args)
  121. def test_log_oai_wrapper(db_connection):
  122. from autogen import OpenAIWrapper
  123. cur = db_connection.cursor()
  124. llm_config = {"config_list": [{"model": "gpt-4", "api_key": "some_key", "base_url": "some url"}]}
  125. init_args = {"llm_config": llm_config, "base_config": {}}
  126. wrapper = OpenAIWrapper(**llm_config)
  127. autogen.runtime_logging.log_new_wrapper(wrapper, init_args)
  128. query = """
  129. SELECT session_id, init_args FROM oai_wrappers
  130. """
  131. for row in cur.execute(query):
  132. assert (
  133. row["session_id"] and str(uuid.UUID(row["session_id"], version=4)) == row["session_id"]
  134. ), "session id is not valid uuid"
  135. saved_init_args = json.loads(row["init_args"])
  136. assert "config_list" in saved_init_args
  137. assert "api_key" not in saved_init_args["config_list"][0]
  138. assert "base_url" not in saved_init_args["config_list"][0]
  139. assert "base_config" in saved_init_args
  140. def test_log_oai_client(db_connection):
  141. cur = db_connection.cursor()
  142. openai_config = {
  143. "api_key": "some_key",
  144. "api_version": "2024-02-15-preview",
  145. "azure_deployment": "gpt-4",
  146. "azure_endpoint": "https://foobar.openai.azure.com/",
  147. }
  148. client = AzureOpenAI(**openai_config)
  149. autogen.runtime_logging.log_new_client(client, Mock(), openai_config)
  150. query = """
  151. SELECT session_id, init_args, class FROM oai_clients
  152. """
  153. for row in cur.execute(query):
  154. assert (
  155. row["session_id"] and str(uuid.UUID(row["session_id"], version=4)) == row["session_id"]
  156. ), "session id is not valid uuid"
  157. assert row["class"] == "AzureOpenAI"
  158. saved_init_args = json.loads(row["init_args"])
  159. assert "api_version" in saved_init_args
  160. assert "api_key" not in saved_init_args
  161. def test_to_dict():
  162. from autogen import Agent
  163. agent1 = autogen.ConversableAgent(
  164. "alice",
  165. human_input_mode="NEVER",
  166. llm_config=False,
  167. default_auto_reply="This is alice speaking.",
  168. )
  169. agent2 = autogen.ConversableAgent(
  170. "bob",
  171. human_input_mode="NEVER",
  172. llm_config=False,
  173. default_auto_reply="This is bob speaking.",
  174. function_map={"test_func": lambda x: x},
  175. )
  176. class Foo:
  177. def __init__(self):
  178. self.a = 1.234
  179. self.b = "some string"
  180. self.c = {"some_key": [7, 8, 9]}
  181. self.d = None
  182. self.test_function = lambda x, y: x + y
  183. self.extra_key = "remove this key"
  184. class Bar(object):
  185. def init(self):
  186. pass
  187. def build(self):
  188. self.foo_val = [Foo()]
  189. self.o = {"key_1": None, "key_2": [{"nested_key_1": ["nested_val_1", "nested_val_2"]}]}
  190. self.agents = [agent1, agent2]
  191. self.first_agent = agent1
  192. bar = Bar()
  193. bar.build()
  194. expected_foo_val_field = [
  195. {
  196. "a": 1.234,
  197. "b": "some string",
  198. "c": {"some_key": [7, 8, 9]},
  199. "d": None,
  200. "test_function": "self.test_function = lambda x, y: x + y",
  201. }
  202. ]
  203. expected_o_field = {"key_2": [{"nested_key_1": ["nested_val_1", "nested_val_2"]}]}
  204. result = to_dict(bar, exclude=("key_1", "extra_key"), no_recursive=(Agent))
  205. assert result["foo_val"] == expected_foo_val_field
  206. assert result["o"] == expected_o_field
  207. assert len(result["agents"]) == 2
  208. for agent in result["agents"]:
  209. assert "autogen.agentchat.conversable_agent.ConversableAgent" in agent
  210. assert "autogen.agentchat.conversable_agent.ConversableAgent" in result["first_agent"]
  211. @patch("logging.Logger.error")
  212. def test_logging_exception_will_not_crash_only_print_error(mock_logger_error, db_connection):
  213. sample_completion = get_sample_chat_completion(SAMPLE_CHAT_REQUEST)
  214. sample_completion["is_cached"] = {"foo": "bar"}
  215. autogen.runtime_logging.log_chat_completion(**sample_completion)
  216. args, _ = mock_logger_error.call_args
  217. error_message = args[0]
  218. assert error_message.startswith("[sqlite logger]Error running query with query")