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_filesurfer_agent.py 5.3 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import asyncio
  2. import json
  3. import logging
  4. import os
  5. from datetime import datetime
  6. from typing import Any, AsyncGenerator, List
  7. import aiofiles
  8. import pytest
  9. from autogen_agentchat import EVENT_LOGGER_NAME
  10. from autogen_ext.agents.file_surfer import FileSurfer
  11. from autogen_ext.models.openai import OpenAIChatCompletionClient
  12. from openai.resources.chat.completions import AsyncCompletions
  13. from openai.types.chat.chat_completion import ChatCompletion, Choice
  14. from openai.types.chat.chat_completion_chunk import ChatCompletionChunk
  15. from openai.types.chat.chat_completion_message import ChatCompletionMessage
  16. from openai.types.chat.chat_completion_message_tool_call import ChatCompletionMessageToolCall, Function
  17. from openai.types.completion_usage import CompletionUsage
  18. from pydantic import BaseModel
  19. class FileLogHandler(logging.Handler):
  20. def __init__(self, filename: str) -> None:
  21. super().__init__()
  22. self.filename = filename
  23. self.file_handler = logging.FileHandler(filename)
  24. def emit(self, record: logging.LogRecord) -> None:
  25. ts = datetime.fromtimestamp(record.created).isoformat()
  26. if isinstance(record.msg, BaseModel):
  27. record.msg = json.dumps(
  28. {
  29. "timestamp": ts,
  30. "message": record.msg.model_dump(),
  31. "type": record.msg.__class__.__name__,
  32. },
  33. )
  34. self.file_handler.emit(record)
  35. class _MockChatCompletion:
  36. def __init__(self, chat_completions: List[ChatCompletion]) -> None:
  37. self._saved_chat_completions = chat_completions
  38. self._curr_index = 0
  39. async def mock_create(
  40. self, *args: Any, **kwargs: Any
  41. ) -> ChatCompletion | AsyncGenerator[ChatCompletionChunk, None]:
  42. await asyncio.sleep(0.1)
  43. completion = self._saved_chat_completions[self._curr_index]
  44. self._curr_index += 1
  45. return completion
  46. logger = logging.getLogger(EVENT_LOGGER_NAME)
  47. logger.setLevel(logging.DEBUG)
  48. logger.addHandler(FileLogHandler("test_filesurfer_agent.log"))
  49. @pytest.mark.asyncio
  50. async def test_run_filesurfer(monkeypatch: pytest.MonkeyPatch) -> None:
  51. # Create a test file
  52. test_file = os.path.abspath("test_filesurfer_agent.html")
  53. async with aiofiles.open(test_file, "wt") as file:
  54. await file.write("""<html>
  55. <head>
  56. <title>FileSurfer test file</title>
  57. </head>
  58. <body>
  59. <h1>FileSurfer test H1</h1>
  60. <p>FileSurfer test body</p>
  61. </body>
  62. </html>""")
  63. # Mock the API calls
  64. model = "gpt-4o-2024-05-13"
  65. chat_completions = [
  66. ChatCompletion(
  67. id="id1",
  68. choices=[
  69. Choice(
  70. finish_reason="tool_calls",
  71. index=0,
  72. message=ChatCompletionMessage(
  73. content=None,
  74. tool_calls=[
  75. ChatCompletionMessageToolCall(
  76. id="1",
  77. type="function",
  78. function=Function(
  79. name="open_path",
  80. arguments=json.dumps({"path": test_file}),
  81. ),
  82. )
  83. ],
  84. role="assistant",
  85. ),
  86. )
  87. ],
  88. created=0,
  89. model=model,
  90. object="chat.completion",
  91. usage=CompletionUsage(prompt_tokens=10, completion_tokens=5, total_tokens=0),
  92. ),
  93. ChatCompletion(
  94. id="id2",
  95. choices=[
  96. Choice(
  97. finish_reason="tool_calls",
  98. index=0,
  99. message=ChatCompletionMessage(
  100. content=None,
  101. tool_calls=[
  102. ChatCompletionMessageToolCall(
  103. id="1",
  104. type="function",
  105. function=Function(
  106. name="open_path",
  107. arguments=json.dumps({"path": os.path.dirname(test_file)}),
  108. ),
  109. )
  110. ],
  111. role="assistant",
  112. ),
  113. )
  114. ],
  115. created=0,
  116. model=model,
  117. object="chat.completion",
  118. usage=CompletionUsage(prompt_tokens=10, completion_tokens=5, total_tokens=0),
  119. ),
  120. ]
  121. mock = _MockChatCompletion(chat_completions)
  122. monkeypatch.setattr(AsyncCompletions, "create", mock.mock_create)
  123. agent = FileSurfer(
  124. "FileSurfer",
  125. model_client=OpenAIChatCompletionClient(model=model, api_key=""),
  126. )
  127. # Get the FileSurfer to read the file, and the directory
  128. assert agent._name == "FileSurfer" # pyright: ignore[reportPrivateUsage]
  129. result = await agent.run(task="Please read the test file")
  130. assert "# FileSurfer test H1" in result.messages[1].content
  131. result = await agent.run(task="Please read the test directory")
  132. assert "# Index of " in result.messages[1].content
  133. assert "test_filesurfer_agent.html" in result.messages[1].content