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_requests_markdown_browser.py 8.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python3 -m pytest
  2. import pytest
  3. import os
  4. import sys
  5. import requests
  6. import hashlib
  7. import re
  8. import math
  9. import pathlib
  10. BLOG_POST_URL = "https://microsoft.github.io/autogen/blog/2023/04/21/LLM-tuning-math"
  11. BLOG_POST_TITLE = "Does Model and Inference Parameter Matter in LLM Applications? - A Case Study for MATH | AutoGen"
  12. BLOG_POST_STRING = "Large language models (LLMs) are powerful tools that can generate natural language texts for various applications, such as chatbots, summarization, translation, and more. GPT-4 is currently the state of the art LLM in the world. Is model selection irrelevant? What about inference parameters?"
  13. BLOG_POST_FIND_ON_PAGE_QUERY = "an example where high * complex"
  14. BLOG_POST_FIND_ON_PAGE_MATCH = "an example where high cost can easily prevent a generic complex"
  15. WIKIPEDIA_URL = "https://en.wikipedia.org/wiki/Microsoft"
  16. WIKIPEDIA_TITLE = "Microsoft"
  17. WIKIPEDIA_STRING = "Redmond"
  18. PLAIN_TEXT_URL = "https://raw.githubusercontent.com/microsoft/autogen/main/README.md"
  19. DOWNLOAD_URL = "https://arxiv.org/src/2308.08155"
  20. PDF_URL = "https://arxiv.org/pdf/2308.08155.pdf"
  21. PDF_STRING = "Figure 1: AutoGen enables diverse LLM-based applications using multi-agent conversations."
  22. DIR_TEST_STRINGS = [
  23. "# Index of ",
  24. "[.. (parent directory)]",
  25. "/test/browser_utils/test_requests_markdown_browser.py",
  26. ]
  27. LOCAL_FILE_TEST_STRINGS = [
  28. BLOG_POST_STRING,
  29. BLOG_POST_FIND_ON_PAGE_MATCH,
  30. ]
  31. try:
  32. from autogen.browser_utils import RequestsMarkdownBrowser, BingMarkdownSearch
  33. except ImportError:
  34. skip_all = True
  35. else:
  36. skip_all = False
  37. def _rm_folder(path):
  38. """Remove all the regular files in a folder, then deletes the folder. Assumes a flat file structure, with no subdirectories."""
  39. for fname in os.listdir(path):
  40. fpath = os.path.join(path, fname)
  41. if os.path.isfile(fpath):
  42. os.unlink(fpath)
  43. os.rmdir(path)
  44. @pytest.mark.skipif(
  45. skip_all,
  46. reason="do not run if dependency is not installed",
  47. )
  48. def test_requests_markdown_browser():
  49. # Create a downloads folder (removing any leftover ones from prior tests)
  50. downloads_folder = os.path.join(os.getcwd(), "downloads")
  51. if os.path.isdir(downloads_folder):
  52. _rm_folder(downloads_folder)
  53. os.mkdir(downloads_folder)
  54. # Instantiate the browser
  55. viewport_size = 1024
  56. browser = RequestsMarkdownBrowser(
  57. viewport_size=viewport_size,
  58. downloads_folder=downloads_folder,
  59. search_engine=BingMarkdownSearch(),
  60. )
  61. # Test that we can visit a page and find what we expect there
  62. top_viewport = browser.visit_page(BLOG_POST_URL)
  63. assert browser.viewport == top_viewport
  64. assert browser.page_title.strip() == BLOG_POST_TITLE.strip()
  65. assert BLOG_POST_STRING in browser.page_content
  66. # Check if page splitting works
  67. approx_pages = math.ceil(len(browser.page_content) / viewport_size) # May be fewer, since it aligns to word breaks
  68. assert len(browser.viewport_pages) <= approx_pages
  69. assert abs(len(browser.viewport_pages) - approx_pages) <= 1 # allow only a small deviation
  70. assert browser.viewport_pages[0][0] == 0
  71. assert browser.viewport_pages[-1][1] == len(browser.page_content)
  72. # Make sure we can reconstruct the full contents from the split pages
  73. buffer = ""
  74. for bounds in browser.viewport_pages:
  75. buffer += browser.page_content[bounds[0] : bounds[1]]
  76. assert buffer == browser.page_content
  77. # Test scrolling (scroll all the way to the bottom)
  78. for i in range(1, len(browser.viewport_pages)):
  79. browser.page_down()
  80. assert browser.viewport_current_page == i
  81. # Test scrolloing beyond the limits
  82. for i in range(0, 5):
  83. browser.page_down()
  84. assert browser.viewport_current_page == len(browser.viewport_pages) - 1
  85. # Test scrolling (scroll all the way to the bottom)
  86. for i in range(len(browser.viewport_pages) - 2, 0, -1):
  87. browser.page_up()
  88. assert browser.viewport_current_page == i
  89. # Test scrolloing beyond the limits
  90. for i in range(0, 5):
  91. browser.page_up()
  92. assert browser.viewport_current_page == 0
  93. # Test Wikipedia handling
  94. assert WIKIPEDIA_STRING in browser.visit_page(WIKIPEDIA_URL)
  95. assert WIKIPEDIA_TITLE.strip() == browser.page_title.strip()
  96. # Visit a plain-text file
  97. response = requests.get(PLAIN_TEXT_URL)
  98. response.raise_for_status()
  99. expected_results = re.sub(r"\s+", " ", response.text, re.DOTALL).strip()
  100. browser.visit_page(PLAIN_TEXT_URL)
  101. assert re.sub(r"\s+", " ", browser.page_content, re.DOTALL).strip() == expected_results
  102. # Disrectly download a ZIP file and compute its md5
  103. response = requests.get(DOWNLOAD_URL, stream=True)
  104. response.raise_for_status()
  105. expected_md5 = hashlib.md5(response.raw.read()).hexdigest()
  106. # Download it with the browser and check for a match
  107. viewport = browser.visit_page(DOWNLOAD_URL)
  108. m = re.search(r"Saved file to '(.*?)'", viewport)
  109. download_loc = m.group(1)
  110. with open(download_loc, "rb") as fh:
  111. downloaded_md5 = hashlib.md5(fh.read()).hexdigest()
  112. # MD%s should match
  113. assert expected_md5 == downloaded_md5
  114. # Fetch a PDF
  115. viewport = browser.visit_page(PDF_URL)
  116. assert PDF_STRING in viewport
  117. # Test find in page
  118. browser.visit_page(BLOG_POST_URL)
  119. find_viewport = browser.find_on_page(BLOG_POST_FIND_ON_PAGE_QUERY)
  120. assert BLOG_POST_FIND_ON_PAGE_MATCH in find_viewport
  121. assert find_viewport is not None
  122. loc = browser.viewport_current_page
  123. find_viewport = browser.find_on_page("LLM app*")
  124. assert find_viewport is not None
  125. # Find next using the same query
  126. for i in range(0, 10):
  127. find_viewport = browser.find_on_page("LLM app*")
  128. assert find_viewport is not None
  129. new_loc = browser.viewport_current_page
  130. assert new_loc != loc
  131. loc = new_loc
  132. # Find next using find_next
  133. for i in range(0, 10):
  134. find_viewport = browser.find_next()
  135. assert find_viewport is not None
  136. new_loc = browser.viewport_current_page
  137. assert new_loc != loc
  138. loc = new_loc
  139. # Bounce around
  140. browser.viewport_current_page = 0
  141. find_viewport = browser.find_on_page("For Further Reading")
  142. assert find_viewport is not None
  143. loc = browser.viewport_current_page
  144. browser.page_up()
  145. assert browser.viewport_current_page != loc
  146. find_viewport = browser.find_on_page("For Further Reading")
  147. assert find_viewport is not None
  148. assert loc == browser.viewport_current_page
  149. # Find something that doesn't exist
  150. find_viewport = browser.find_on_page("7c748f9a-8dce-461f-a092-4e8d29913f2d")
  151. assert find_viewport is None
  152. assert loc == browser.viewport_current_page # We didn't move
  153. # Clean up
  154. _rm_folder(downloads_folder)
  155. @pytest.mark.skipif(
  156. skip_all,
  157. reason="do not run if dependency is not installed",
  158. )
  159. def test_local_file_browsing():
  160. directory = os.path.dirname(__file__)
  161. test_file = os.path.join(directory, "test_files", "test_blog.html")
  162. browser = RequestsMarkdownBrowser()
  163. # Directory listing via open_local_file
  164. viewport = browser.open_local_file(directory)
  165. for target_string in DIR_TEST_STRINGS:
  166. assert target_string in viewport
  167. # Directory listing via file URI
  168. viewport = browser.visit_page(pathlib.Path(os.path.abspath(directory)).as_uri())
  169. for target_string in DIR_TEST_STRINGS:
  170. assert target_string in viewport
  171. # File access via file open_local_file
  172. browser.open_local_file(test_file)
  173. for target_string in LOCAL_FILE_TEST_STRINGS:
  174. assert target_string in browser.page_content
  175. # File access via file URI
  176. browser.visit_page(pathlib.Path(os.path.abspath(test_file)).as_uri())
  177. for target_string in LOCAL_FILE_TEST_STRINGS:
  178. assert target_string in browser.page_content
  179. if __name__ == "__main__":
  180. """Runs this file's tests from the command line."""
  181. test_requests_markdown_browser()
  182. test_local_file_browsing()