botrun-flow-lang 5.12.263__py3-none-any.whl → 5.12.264__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- botrun_flow_lang/api/auth_api.py +39 -39
- botrun_flow_lang/api/auth_utils.py +183 -183
- botrun_flow_lang/api/botrun_back_api.py +65 -65
- botrun_flow_lang/api/flow_api.py +3 -3
- botrun_flow_lang/api/hatch_api.py +508 -508
- botrun_flow_lang/api/langgraph_api.py +811 -811
- botrun_flow_lang/api/line_bot_api.py +1484 -1484
- botrun_flow_lang/api/model_api.py +300 -300
- botrun_flow_lang/api/rate_limit_api.py +32 -32
- botrun_flow_lang/api/routes.py +79 -79
- botrun_flow_lang/api/search_api.py +53 -53
- botrun_flow_lang/api/storage_api.py +395 -395
- botrun_flow_lang/api/subsidy_api.py +290 -290
- botrun_flow_lang/api/subsidy_api_system_prompt.txt +109 -109
- botrun_flow_lang/api/user_setting_api.py +70 -70
- botrun_flow_lang/api/version_api.py +31 -31
- botrun_flow_lang/api/youtube_api.py +26 -26
- botrun_flow_lang/constants.py +13 -13
- botrun_flow_lang/langgraph_agents/agents/agent_runner.py +178 -178
- botrun_flow_lang/langgraph_agents/agents/agent_tools/step_planner.py +77 -77
- botrun_flow_lang/langgraph_agents/agents/checkpointer/firestore_checkpointer.py +666 -666
- botrun_flow_lang/langgraph_agents/agents/gov_researcher/GOV_RESEARCHER_PRD.md +192 -192
- botrun_flow_lang/langgraph_agents/agents/gov_researcher/gemini_subsidy_graph.py +460 -460
- botrun_flow_lang/langgraph_agents/agents/gov_researcher/gov_researcher_2_graph.py +1002 -1002
- botrun_flow_lang/langgraph_agents/agents/gov_researcher/gov_researcher_graph.py +822 -822
- botrun_flow_lang/langgraph_agents/agents/langgraph_react_agent.py +723 -723
- botrun_flow_lang/langgraph_agents/agents/search_agent_graph.py +864 -864
- botrun_flow_lang/langgraph_agents/agents/tools/__init__.py +4 -4
- botrun_flow_lang/langgraph_agents/agents/tools/gemini_code_execution.py +376 -376
- botrun_flow_lang/langgraph_agents/agents/util/gemini_grounding.py +66 -66
- botrun_flow_lang/langgraph_agents/agents/util/html_util.py +316 -316
- botrun_flow_lang/langgraph_agents/agents/util/img_util.py +294 -294
- botrun_flow_lang/langgraph_agents/agents/util/local_files.py +419 -419
- botrun_flow_lang/langgraph_agents/agents/util/mermaid_util.py +86 -86
- botrun_flow_lang/langgraph_agents/agents/util/model_utils.py +143 -143
- botrun_flow_lang/langgraph_agents/agents/util/pdf_analyzer.py +486 -486
- botrun_flow_lang/langgraph_agents/agents/util/pdf_cache.py +250 -250
- botrun_flow_lang/langgraph_agents/agents/util/pdf_processor.py +204 -204
- botrun_flow_lang/langgraph_agents/agents/util/perplexity_search.py +464 -464
- botrun_flow_lang/langgraph_agents/agents/util/plotly_util.py +59 -59
- botrun_flow_lang/langgraph_agents/agents/util/tavily_search.py +199 -199
- botrun_flow_lang/langgraph_agents/agents/util/youtube_util.py +90 -90
- botrun_flow_lang/langgraph_agents/cache/langgraph_botrun_cache.py +197 -197
- botrun_flow_lang/llm_agent/llm_agent.py +19 -19
- botrun_flow_lang/llm_agent/llm_agent_util.py +83 -83
- botrun_flow_lang/log/.gitignore +2 -2
- botrun_flow_lang/main.py +61 -61
- botrun_flow_lang/main_fast.py +51 -51
- botrun_flow_lang/mcp_server/__init__.py +10 -10
- botrun_flow_lang/mcp_server/default_mcp.py +744 -744
- botrun_flow_lang/models/nodes/utils.py +205 -205
- botrun_flow_lang/models/token_usage.py +34 -34
- botrun_flow_lang/requirements.txt +21 -21
- botrun_flow_lang/services/base/firestore_base.py +30 -30
- botrun_flow_lang/services/hatch/hatch_factory.py +11 -11
- botrun_flow_lang/services/hatch/hatch_fs_store.py +419 -419
- botrun_flow_lang/services/storage/storage_cs_store.py +206 -206
- botrun_flow_lang/services/storage/storage_factory.py +12 -12
- botrun_flow_lang/services/storage/storage_store.py +65 -65
- botrun_flow_lang/services/user_setting/user_setting_factory.py +9 -9
- botrun_flow_lang/services/user_setting/user_setting_fs_store.py +66 -66
- botrun_flow_lang/static/docs/tools/index.html +926 -926
- botrun_flow_lang/tests/api_functional_tests.py +1525 -1525
- botrun_flow_lang/tests/api_stress_test.py +357 -357
- botrun_flow_lang/tests/shared_hatch_tests.py +333 -333
- botrun_flow_lang/tests/test_botrun_app.py +46 -46
- botrun_flow_lang/tests/test_html_util.py +31 -31
- botrun_flow_lang/tests/test_img_analyzer.py +190 -190
- botrun_flow_lang/tests/test_img_util.py +39 -39
- botrun_flow_lang/tests/test_local_files.py +114 -114
- botrun_flow_lang/tests/test_mermaid_util.py +103 -103
- botrun_flow_lang/tests/test_pdf_analyzer.py +104 -104
- botrun_flow_lang/tests/test_plotly_util.py +151 -151
- botrun_flow_lang/tests/test_run_workflow_engine.py +65 -65
- botrun_flow_lang/tools/generate_docs.py +133 -133
- botrun_flow_lang/tools/templates/tools.html +153 -153
- botrun_flow_lang/utils/__init__.py +7 -7
- botrun_flow_lang/utils/botrun_logger.py +344 -344
- botrun_flow_lang/utils/clients/rate_limit_client.py +209 -209
- botrun_flow_lang/utils/clients/token_verify_client.py +153 -153
- botrun_flow_lang/utils/google_drive_utils.py +654 -654
- botrun_flow_lang/utils/langchain_utils.py +324 -324
- botrun_flow_lang/utils/yaml_utils.py +9 -9
- {botrun_flow_lang-5.12.263.dist-info → botrun_flow_lang-5.12.264.dist-info}/METADATA +1 -1
- botrun_flow_lang-5.12.264.dist-info/RECORD +102 -0
- botrun_flow_lang-5.12.263.dist-info/RECORD +0 -102
- {botrun_flow_lang-5.12.263.dist-info → botrun_flow_lang-5.12.264.dist-info}/WHEEL +0 -0
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from botrun_flow_lang.models.botrun_app import BotrunApp, BotrunAppMode
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class TestBotrunApp(unittest.TestCase):
|
|
6
|
-
def test_to_yaml(self):
|
|
7
|
-
app = BotrunApp(
|
|
8
|
-
name="Test App",
|
|
9
|
-
description="A test application",
|
|
10
|
-
mode=BotrunAppMode.CHATBOT,
|
|
11
|
-
)
|
|
12
|
-
yaml_str = app.to_yaml()
|
|
13
|
-
self.assertIn("name: Test App", yaml_str)
|
|
14
|
-
self.assertIn("description: A test application", yaml_str)
|
|
15
|
-
self.assertIn("mode: chatbot", yaml_str)
|
|
16
|
-
|
|
17
|
-
def test_from_yaml(self):
|
|
18
|
-
yaml_str = """
|
|
19
|
-
name: Test App
|
|
20
|
-
description: A test application
|
|
21
|
-
mode: workflow
|
|
22
|
-
"""
|
|
23
|
-
app = BotrunApp.from_yaml(yaml_str)
|
|
24
|
-
self.assertEqual(app.name, "Test App")
|
|
25
|
-
self.assertEqual(app.description, "A test application")
|
|
26
|
-
self.assertEqual(app.mode, BotrunAppMode.WORKFLOW)
|
|
27
|
-
|
|
28
|
-
def test_roundtrip(self):
|
|
29
|
-
original_app = BotrunApp(
|
|
30
|
-
name="Test App",
|
|
31
|
-
description="A test application",
|
|
32
|
-
mode=BotrunAppMode.CHATBOT,
|
|
33
|
-
)
|
|
34
|
-
yaml_str = original_app.to_yaml()
|
|
35
|
-
reconstructed_app = BotrunApp.from_yaml(yaml_str)
|
|
36
|
-
self.assertEqual(original_app, reconstructed_app)
|
|
37
|
-
|
|
38
|
-
def test_invalid_mode(self):
|
|
39
|
-
with self.assertRaises(ValueError):
|
|
40
|
-
BotrunApp(
|
|
41
|
-
name="Test App", description="A test application", mode="invalid_mode"
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if __name__ == "__main__":
|
|
46
|
-
unittest.main()
|
|
1
|
+
import unittest
|
|
2
|
+
from botrun_flow_lang.models.botrun_app import BotrunApp, BotrunAppMode
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class TestBotrunApp(unittest.TestCase):
|
|
6
|
+
def test_to_yaml(self):
|
|
7
|
+
app = BotrunApp(
|
|
8
|
+
name="Test App",
|
|
9
|
+
description="A test application",
|
|
10
|
+
mode=BotrunAppMode.CHATBOT,
|
|
11
|
+
)
|
|
12
|
+
yaml_str = app.to_yaml()
|
|
13
|
+
self.assertIn("name: Test App", yaml_str)
|
|
14
|
+
self.assertIn("description: A test application", yaml_str)
|
|
15
|
+
self.assertIn("mode: chatbot", yaml_str)
|
|
16
|
+
|
|
17
|
+
def test_from_yaml(self):
|
|
18
|
+
yaml_str = """
|
|
19
|
+
name: Test App
|
|
20
|
+
description: A test application
|
|
21
|
+
mode: workflow
|
|
22
|
+
"""
|
|
23
|
+
app = BotrunApp.from_yaml(yaml_str)
|
|
24
|
+
self.assertEqual(app.name, "Test App")
|
|
25
|
+
self.assertEqual(app.description, "A test application")
|
|
26
|
+
self.assertEqual(app.mode, BotrunAppMode.WORKFLOW)
|
|
27
|
+
|
|
28
|
+
def test_roundtrip(self):
|
|
29
|
+
original_app = BotrunApp(
|
|
30
|
+
name="Test App",
|
|
31
|
+
description="A test application",
|
|
32
|
+
mode=BotrunAppMode.CHATBOT,
|
|
33
|
+
)
|
|
34
|
+
yaml_str = original_app.to_yaml()
|
|
35
|
+
reconstructed_app = BotrunApp.from_yaml(yaml_str)
|
|
36
|
+
self.assertEqual(original_app, reconstructed_app)
|
|
37
|
+
|
|
38
|
+
def test_invalid_mode(self):
|
|
39
|
+
with self.assertRaises(ValueError):
|
|
40
|
+
BotrunApp(
|
|
41
|
+
name="Test App", description="A test application", mode="invalid_mode"
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
if __name__ == "__main__":
|
|
46
|
+
unittest.main()
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
import asyncio
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
import os
|
|
5
|
-
from botrun_flow_lang.langgraph_agents.agents.util.html_util import modify_gcs_html
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TestHtmlUtil(unittest.TestCase):
|
|
9
|
-
def setUp(self):
|
|
10
|
-
"""Set up test fixtures"""
|
|
11
|
-
self.gcs_url = "https://storage.googleapis.com/hatch-botrun-hatch-dev/html/sebastian.hsu%40gmail.com/tmp_euvrg5j.html"
|
|
12
|
-
self.modification_instruction = (
|
|
13
|
-
"Increase the number at the top of the page by 1"
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
def test_modify_gcs_html(self):
|
|
17
|
-
"""Test modify_gcs_html function with real parameters"""
|
|
18
|
-
# Run the async function with real parameters
|
|
19
|
-
result = asyncio.run(
|
|
20
|
-
modify_gcs_html(self.gcs_url, self.modification_instruction)
|
|
21
|
-
)
|
|
22
|
-
|
|
23
|
-
# Print the result for manual verification
|
|
24
|
-
print("\nTest Result:")
|
|
25
|
-
print(f"Success: {result[0]}")
|
|
26
|
-
print(f"URL: {result[1]}")
|
|
27
|
-
print(f"Error (if any): {result[2]}")
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if __name__ == "__main__":
|
|
31
|
-
unittest.main()
|
|
1
|
+
import unittest
|
|
2
|
+
import asyncio
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
import os
|
|
5
|
+
from botrun_flow_lang.langgraph_agents.agents.util.html_util import modify_gcs_html
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestHtmlUtil(unittest.TestCase):
|
|
9
|
+
def setUp(self):
|
|
10
|
+
"""Set up test fixtures"""
|
|
11
|
+
self.gcs_url = "https://storage.googleapis.com/hatch-botrun-hatch-dev/html/sebastian.hsu%40gmail.com/tmp_euvrg5j.html"
|
|
12
|
+
self.modification_instruction = (
|
|
13
|
+
"Increase the number at the top of the page by 1"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
def test_modify_gcs_html(self):
|
|
17
|
+
"""Test modify_gcs_html function with real parameters"""
|
|
18
|
+
# Run the async function with real parameters
|
|
19
|
+
result = asyncio.run(
|
|
20
|
+
modify_gcs_html(self.gcs_url, self.modification_instruction)
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Print the result for manual verification
|
|
24
|
+
print("\nTest Result:")
|
|
25
|
+
print(f"Success: {result[0]}")
|
|
26
|
+
print(f"URL: {result[1]}")
|
|
27
|
+
print(f"Error (if any): {result[2]}")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
unittest.main()
|
|
@@ -1,190 +1,190 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
import os
|
|
3
|
-
from pathlib import Path
|
|
4
|
-
from botrun_flow_lang.langgraph_agents.agents.util.local_files import (
|
|
5
|
-
upload_and_get_tmp_public_url,
|
|
6
|
-
)
|
|
7
|
-
from botrun_flow_lang.langgraph_agents.agents.util.img_util import analyze_imgs
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class TestImgAnalyzer(unittest.TestCase):
|
|
11
|
-
def setUp(self):
|
|
12
|
-
# Get the path to the test image file
|
|
13
|
-
self.current_dir = Path(__file__).parent
|
|
14
|
-
self.img_path = self.current_dir / "test_files" / "d5712343.jpg"
|
|
15
|
-
|
|
16
|
-
# Ensure the test file exists
|
|
17
|
-
self.assertTrue(
|
|
18
|
-
os.path.exists(self.img_path), f"Test file not found at {self.img_path}"
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
def test_img_exists(self):
|
|
22
|
-
"""Test if the image file exists"""
|
|
23
|
-
self.assertEqual(True, os.path.exists(self.img_path))
|
|
24
|
-
|
|
25
|
-
def test_img_readable(self):
|
|
26
|
-
"""Test if the image file is readable"""
|
|
27
|
-
self.assertEqual(True, os.access(self.img_path, os.R_OK))
|
|
28
|
-
|
|
29
|
-
def test_img_not_empty(self):
|
|
30
|
-
"""Test if the image file is not empty"""
|
|
31
|
-
self.assertEqual(True, os.path.getsize(self.img_path) > 0)
|
|
32
|
-
|
|
33
|
-
def test_img_extension(self):
|
|
34
|
-
"""Test if the file has a JPG extension"""
|
|
35
|
-
self.assertEqual(True, self.img_path.suffix.lower() in [".jpg", ".jpeg"])
|
|
36
|
-
|
|
37
|
-
def test_analyze_1_image_content(self):
|
|
38
|
-
"""Test analyzing the content of the image"""
|
|
39
|
-
query = "請描述這張圖片的內容,並列出主要可見的物件或人物,請使用繁體中文,臺灣用語進行回答。"
|
|
40
|
-
img_url = upload_and_get_tmp_public_url(
|
|
41
|
-
self.img_path,
|
|
42
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
43
|
-
"sebastian.hsu@gmail.com",
|
|
44
|
-
)
|
|
45
|
-
result = analyze_imgs([img_url], query) # Pass URL in a list
|
|
46
|
-
|
|
47
|
-
# Print the result for inspection
|
|
48
|
-
print("\ntest_analyze_1_image_content:")
|
|
49
|
-
print("-" * 50)
|
|
50
|
-
print(result)
|
|
51
|
-
print("-" * 50)
|
|
52
|
-
|
|
53
|
-
# 確保結果不為空
|
|
54
|
-
self.assertIsNotNone(result)
|
|
55
|
-
self.assertNotEqual("", result)
|
|
56
|
-
|
|
57
|
-
# 確保結果不是錯誤訊息
|
|
58
|
-
self.assertFalse(result.startswith("Error:"))
|
|
59
|
-
|
|
60
|
-
# 確保回應內容包含描述性文字
|
|
61
|
-
self.assertTrue(len(result) > 50) # 確保回應有足夠的長度
|
|
62
|
-
self.assertIn("佛教", result, "找不到回應中包含佛教,回應內容:" + result)
|
|
63
|
-
|
|
64
|
-
def test_analyze_2_images_content(self):
|
|
65
|
-
"""Test analyzing the content of the image"""
|
|
66
|
-
img1_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
67
|
-
img2_path = self.current_dir / "test_files" / "spot_difference_2.png"
|
|
68
|
-
query = "幫我分析這兩張圖片裡的時鐘時間是否一樣?一樣回答「一樣」,不一樣回答「不一樣」"
|
|
69
|
-
img_url1 = upload_and_get_tmp_public_url(
|
|
70
|
-
img1_path,
|
|
71
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
72
|
-
"sebastian.hsu@gmail.com",
|
|
73
|
-
)
|
|
74
|
-
img_url2 = upload_and_get_tmp_public_url(
|
|
75
|
-
img2_path,
|
|
76
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
77
|
-
"sebastian.hsu@gmail.com",
|
|
78
|
-
)
|
|
79
|
-
result = analyze_imgs([img_url1, img_url2], query) # Pass URL in a list
|
|
80
|
-
|
|
81
|
-
# Print the result for inspection
|
|
82
|
-
print("\ntest_analyze_2_images_content_case_1:")
|
|
83
|
-
print("-" * 50)
|
|
84
|
-
print(result)
|
|
85
|
-
print("-" * 50)
|
|
86
|
-
|
|
87
|
-
# 確保結果不為空
|
|
88
|
-
self.assertIsNotNone(result)
|
|
89
|
-
self.assertNotEqual("", result)
|
|
90
|
-
|
|
91
|
-
# 確保結果不是錯誤訊息
|
|
92
|
-
self.assertFalse(result.startswith("Error:"))
|
|
93
|
-
|
|
94
|
-
# 確保回應內容包含描述性文字
|
|
95
|
-
self.assertIn("不一樣", result)
|
|
96
|
-
|
|
97
|
-
img1_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
98
|
-
img2_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
99
|
-
query = "幫我分析這兩張圖片裡的時鐘時間是否一樣?一樣回答「一樣」,不一樣回答「不一樣」"
|
|
100
|
-
img_url1 = upload_and_get_tmp_public_url(
|
|
101
|
-
img1_path,
|
|
102
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
103
|
-
"sebastian.hsu@gmail.com",
|
|
104
|
-
)
|
|
105
|
-
img_url2 = upload_and_get_tmp_public_url(
|
|
106
|
-
img2_path,
|
|
107
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
108
|
-
"sebastian.hsu@gmail.com",
|
|
109
|
-
)
|
|
110
|
-
result = analyze_imgs([img_url1, img_url2], query) # Pass URL in a list
|
|
111
|
-
|
|
112
|
-
# Print the result for inspection
|
|
113
|
-
print("\ntest_analyze_2_images_content_case_2:")
|
|
114
|
-
print("-" * 50)
|
|
115
|
-
print(result)
|
|
116
|
-
print("-" * 50)
|
|
117
|
-
|
|
118
|
-
# 確保結果不為空
|
|
119
|
-
self.assertIsNotNone(result)
|
|
120
|
-
self.assertNotEqual("", result)
|
|
121
|
-
|
|
122
|
-
# 確保結果不是錯誤訊息
|
|
123
|
-
self.assertFalse(result.startswith("Error:"))
|
|
124
|
-
|
|
125
|
-
# 確保回應內容包含描述性文字
|
|
126
|
-
self.assertIn("一樣", result)
|
|
127
|
-
|
|
128
|
-
def test_analyze_images_media_type_jpeg(self):
|
|
129
|
-
"""Test analyzing the content of the image"""
|
|
130
|
-
img1_path = (
|
|
131
|
-
self.current_dir / "test_files" / "ImportedPhoto.760363950.029251.jpeg"
|
|
132
|
-
)
|
|
133
|
-
img2_path = (
|
|
134
|
-
self.current_dir / "test_files" / "ImportedPhoto.760363950.030446.jpeg"
|
|
135
|
-
)
|
|
136
|
-
img3_path = (
|
|
137
|
-
self.current_dir / "test_files" / "ImportedPhoto.760363950.031127.jpeg"
|
|
138
|
-
)
|
|
139
|
-
query = "我該去哪個月台,為什麼?回答時要包含列車車號以及月台號。"
|
|
140
|
-
img_url1 = upload_and_get_tmp_public_url(
|
|
141
|
-
img1_path,
|
|
142
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
143
|
-
"sebastian.hsu@gmail.com",
|
|
144
|
-
)
|
|
145
|
-
img_url2 = upload_and_get_tmp_public_url(
|
|
146
|
-
img2_path,
|
|
147
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
148
|
-
"sebastian.hsu@gmail.com",
|
|
149
|
-
)
|
|
150
|
-
img_url3 = upload_and_get_tmp_public_url(
|
|
151
|
-
img3_path,
|
|
152
|
-
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
153
|
-
"sebastian.hsu@gmail.com",
|
|
154
|
-
)
|
|
155
|
-
result = analyze_imgs(
|
|
156
|
-
[img_url1, img_url2, img_url3], query
|
|
157
|
-
) # Pass URL in a list
|
|
158
|
-
|
|
159
|
-
# Print the result for inspection
|
|
160
|
-
print("\ntest_analyze_images_media_type_jpeg:")
|
|
161
|
-
print("-" * 50)
|
|
162
|
-
print(result)
|
|
163
|
-
print("-" * 50)
|
|
164
|
-
|
|
165
|
-
# 確保結果不為空
|
|
166
|
-
self.assertIsNotNone(result)
|
|
167
|
-
self.assertNotEqual("", result)
|
|
168
|
-
|
|
169
|
-
# 確保結果不是錯誤訊息
|
|
170
|
-
self.assertFalse(result.startswith("Error:"))
|
|
171
|
-
|
|
172
|
-
# 確保回應內容包含描述性文字
|
|
173
|
-
self.assertTrue(
|
|
174
|
-
any(
|
|
175
|
-
platform in result
|
|
176
|
-
for platform in [
|
|
177
|
-
"5 A-C",
|
|
178
|
-
"5 D-F",
|
|
179
|
-
"5-A-C",
|
|
180
|
-
"5-A/C",
|
|
181
|
-
"5-D-F",
|
|
182
|
-
"5-D/F",
|
|
183
|
-
]
|
|
184
|
-
),
|
|
185
|
-
"Result should contain either '5 A-C' or '5 D-F'",
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if __name__ == "__main__":
|
|
190
|
-
unittest.main()
|
|
1
|
+
import unittest
|
|
2
|
+
import os
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from botrun_flow_lang.langgraph_agents.agents.util.local_files import (
|
|
5
|
+
upload_and_get_tmp_public_url,
|
|
6
|
+
)
|
|
7
|
+
from botrun_flow_lang.langgraph_agents.agents.util.img_util import analyze_imgs
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestImgAnalyzer(unittest.TestCase):
|
|
11
|
+
def setUp(self):
|
|
12
|
+
# Get the path to the test image file
|
|
13
|
+
self.current_dir = Path(__file__).parent
|
|
14
|
+
self.img_path = self.current_dir / "test_files" / "d5712343.jpg"
|
|
15
|
+
|
|
16
|
+
# Ensure the test file exists
|
|
17
|
+
self.assertTrue(
|
|
18
|
+
os.path.exists(self.img_path), f"Test file not found at {self.img_path}"
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
def test_img_exists(self):
|
|
22
|
+
"""Test if the image file exists"""
|
|
23
|
+
self.assertEqual(True, os.path.exists(self.img_path))
|
|
24
|
+
|
|
25
|
+
def test_img_readable(self):
|
|
26
|
+
"""Test if the image file is readable"""
|
|
27
|
+
self.assertEqual(True, os.access(self.img_path, os.R_OK))
|
|
28
|
+
|
|
29
|
+
def test_img_not_empty(self):
|
|
30
|
+
"""Test if the image file is not empty"""
|
|
31
|
+
self.assertEqual(True, os.path.getsize(self.img_path) > 0)
|
|
32
|
+
|
|
33
|
+
def test_img_extension(self):
|
|
34
|
+
"""Test if the file has a JPG extension"""
|
|
35
|
+
self.assertEqual(True, self.img_path.suffix.lower() in [".jpg", ".jpeg"])
|
|
36
|
+
|
|
37
|
+
def test_analyze_1_image_content(self):
|
|
38
|
+
"""Test analyzing the content of the image"""
|
|
39
|
+
query = "請描述這張圖片的內容,並列出主要可見的物件或人物,請使用繁體中文,臺灣用語進行回答。"
|
|
40
|
+
img_url = upload_and_get_tmp_public_url(
|
|
41
|
+
self.img_path,
|
|
42
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
43
|
+
"sebastian.hsu@gmail.com",
|
|
44
|
+
)
|
|
45
|
+
result = analyze_imgs([img_url], query) # Pass URL in a list
|
|
46
|
+
|
|
47
|
+
# Print the result for inspection
|
|
48
|
+
print("\ntest_analyze_1_image_content:")
|
|
49
|
+
print("-" * 50)
|
|
50
|
+
print(result)
|
|
51
|
+
print("-" * 50)
|
|
52
|
+
|
|
53
|
+
# 確保結果不為空
|
|
54
|
+
self.assertIsNotNone(result)
|
|
55
|
+
self.assertNotEqual("", result)
|
|
56
|
+
|
|
57
|
+
# 確保結果不是錯誤訊息
|
|
58
|
+
self.assertFalse(result.startswith("Error:"))
|
|
59
|
+
|
|
60
|
+
# 確保回應內容包含描述性文字
|
|
61
|
+
self.assertTrue(len(result) > 50) # 確保回應有足夠的長度
|
|
62
|
+
self.assertIn("佛教", result, "找不到回應中包含佛教,回應內容:" + result)
|
|
63
|
+
|
|
64
|
+
def test_analyze_2_images_content(self):
|
|
65
|
+
"""Test analyzing the content of the image"""
|
|
66
|
+
img1_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
67
|
+
img2_path = self.current_dir / "test_files" / "spot_difference_2.png"
|
|
68
|
+
query = "幫我分析這兩張圖片裡的時鐘時間是否一樣?一樣回答「一樣」,不一樣回答「不一樣」"
|
|
69
|
+
img_url1 = upload_and_get_tmp_public_url(
|
|
70
|
+
img1_path,
|
|
71
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
72
|
+
"sebastian.hsu@gmail.com",
|
|
73
|
+
)
|
|
74
|
+
img_url2 = upload_and_get_tmp_public_url(
|
|
75
|
+
img2_path,
|
|
76
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
77
|
+
"sebastian.hsu@gmail.com",
|
|
78
|
+
)
|
|
79
|
+
result = analyze_imgs([img_url1, img_url2], query) # Pass URL in a list
|
|
80
|
+
|
|
81
|
+
# Print the result for inspection
|
|
82
|
+
print("\ntest_analyze_2_images_content_case_1:")
|
|
83
|
+
print("-" * 50)
|
|
84
|
+
print(result)
|
|
85
|
+
print("-" * 50)
|
|
86
|
+
|
|
87
|
+
# 確保結果不為空
|
|
88
|
+
self.assertIsNotNone(result)
|
|
89
|
+
self.assertNotEqual("", result)
|
|
90
|
+
|
|
91
|
+
# 確保結果不是錯誤訊息
|
|
92
|
+
self.assertFalse(result.startswith("Error:"))
|
|
93
|
+
|
|
94
|
+
# 確保回應內容包含描述性文字
|
|
95
|
+
self.assertIn("不一樣", result)
|
|
96
|
+
|
|
97
|
+
img1_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
98
|
+
img2_path = self.current_dir / "test_files" / "spot_difference_1.png"
|
|
99
|
+
query = "幫我分析這兩張圖片裡的時鐘時間是否一樣?一樣回答「一樣」,不一樣回答「不一樣」"
|
|
100
|
+
img_url1 = upload_and_get_tmp_public_url(
|
|
101
|
+
img1_path,
|
|
102
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
103
|
+
"sebastian.hsu@gmail.com",
|
|
104
|
+
)
|
|
105
|
+
img_url2 = upload_and_get_tmp_public_url(
|
|
106
|
+
img2_path,
|
|
107
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
108
|
+
"sebastian.hsu@gmail.com",
|
|
109
|
+
)
|
|
110
|
+
result = analyze_imgs([img_url1, img_url2], query) # Pass URL in a list
|
|
111
|
+
|
|
112
|
+
# Print the result for inspection
|
|
113
|
+
print("\ntest_analyze_2_images_content_case_2:")
|
|
114
|
+
print("-" * 50)
|
|
115
|
+
print(result)
|
|
116
|
+
print("-" * 50)
|
|
117
|
+
|
|
118
|
+
# 確保結果不為空
|
|
119
|
+
self.assertIsNotNone(result)
|
|
120
|
+
self.assertNotEqual("", result)
|
|
121
|
+
|
|
122
|
+
# 確保結果不是錯誤訊息
|
|
123
|
+
self.assertFalse(result.startswith("Error:"))
|
|
124
|
+
|
|
125
|
+
# 確保回應內容包含描述性文字
|
|
126
|
+
self.assertIn("一樣", result)
|
|
127
|
+
|
|
128
|
+
def test_analyze_images_media_type_jpeg(self):
|
|
129
|
+
"""Test analyzing the content of the image"""
|
|
130
|
+
img1_path = (
|
|
131
|
+
self.current_dir / "test_files" / "ImportedPhoto.760363950.029251.jpeg"
|
|
132
|
+
)
|
|
133
|
+
img2_path = (
|
|
134
|
+
self.current_dir / "test_files" / "ImportedPhoto.760363950.030446.jpeg"
|
|
135
|
+
)
|
|
136
|
+
img3_path = (
|
|
137
|
+
self.current_dir / "test_files" / "ImportedPhoto.760363950.031127.jpeg"
|
|
138
|
+
)
|
|
139
|
+
query = "我該去哪個月台,為什麼?回答時要包含列車車號以及月台號。"
|
|
140
|
+
img_url1 = upload_and_get_tmp_public_url(
|
|
141
|
+
img1_path,
|
|
142
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
143
|
+
"sebastian.hsu@gmail.com",
|
|
144
|
+
)
|
|
145
|
+
img_url2 = upload_and_get_tmp_public_url(
|
|
146
|
+
img2_path,
|
|
147
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
148
|
+
"sebastian.hsu@gmail.com",
|
|
149
|
+
)
|
|
150
|
+
img_url3 = upload_and_get_tmp_public_url(
|
|
151
|
+
img3_path,
|
|
152
|
+
"https://botrun-flow-lang-fastapi-dev-36186877499.asia-east1.run.app",
|
|
153
|
+
"sebastian.hsu@gmail.com",
|
|
154
|
+
)
|
|
155
|
+
result = analyze_imgs(
|
|
156
|
+
[img_url1, img_url2, img_url3], query
|
|
157
|
+
) # Pass URL in a list
|
|
158
|
+
|
|
159
|
+
# Print the result for inspection
|
|
160
|
+
print("\ntest_analyze_images_media_type_jpeg:")
|
|
161
|
+
print("-" * 50)
|
|
162
|
+
print(result)
|
|
163
|
+
print("-" * 50)
|
|
164
|
+
|
|
165
|
+
# 確保結果不為空
|
|
166
|
+
self.assertIsNotNone(result)
|
|
167
|
+
self.assertNotEqual("", result)
|
|
168
|
+
|
|
169
|
+
# 確保結果不是錯誤訊息
|
|
170
|
+
self.assertFalse(result.startswith("Error:"))
|
|
171
|
+
|
|
172
|
+
# 確保回應內容包含描述性文字
|
|
173
|
+
self.assertTrue(
|
|
174
|
+
any(
|
|
175
|
+
platform in result
|
|
176
|
+
for platform in [
|
|
177
|
+
"5 A-C",
|
|
178
|
+
"5 D-F",
|
|
179
|
+
"5-A-C",
|
|
180
|
+
"5-A/C",
|
|
181
|
+
"5-D-F",
|
|
182
|
+
"5-D/F",
|
|
183
|
+
]
|
|
184
|
+
),
|
|
185
|
+
"Result should contain either '5 A-C' or '5 D-F'",
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
if __name__ == "__main__":
|
|
190
|
+
unittest.main()
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from pathlib import Path
|
|
3
|
-
import os
|
|
4
|
-
from botrun_flow_lang.langgraph_agents.agents.util.img_util import get_img_content_type
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class TestImgUtil(unittest.TestCase):
|
|
8
|
-
def setUp(self):
|
|
9
|
-
"""Set up test fixtures"""
|
|
10
|
-
self.current_dir = Path(__file__).parent
|
|
11
|
-
self.test_files_dir = self.current_dir / "test_files"
|
|
12
|
-
|
|
13
|
-
def test_get_content_type_png_1(self):
|
|
14
|
-
"""Test get_content_type with PNG file"""
|
|
15
|
-
img_path = self.test_files_dir / "ImportedPhoto.760363950.029251.jpeg"
|
|
16
|
-
content_type = get_img_content_type(img_path)
|
|
17
|
-
self.assertEqual(content_type, "image/png")
|
|
18
|
-
|
|
19
|
-
def test_get_content_type_png_2(self):
|
|
20
|
-
"""Test get_content_type with PNG file"""
|
|
21
|
-
img_path = self.test_files_dir / "spot_difference_1.png"
|
|
22
|
-
content_type = get_img_content_type(img_path)
|
|
23
|
-
self.assertEqual(content_type, "image/png")
|
|
24
|
-
|
|
25
|
-
def test_get_content_type_jpeg_1(self):
|
|
26
|
-
"""Test get_content_type with PNG file"""
|
|
27
|
-
img_path = self.test_files_dir / "ImportedPhoto.760363950.030446.jpeg"
|
|
28
|
-
content_type = get_img_content_type(img_path)
|
|
29
|
-
self.assertEqual(content_type, "image/jpeg")
|
|
30
|
-
|
|
31
|
-
def test_get_content_type_jpeg_2(self):
|
|
32
|
-
"""Test get_content_type with PNG file"""
|
|
33
|
-
img_path = self.test_files_dir / "d5712343.jpg"
|
|
34
|
-
content_type = get_img_content_type(img_path)
|
|
35
|
-
self.assertEqual(content_type, "image/jpeg")
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
if __name__ == "__main__":
|
|
39
|
-
unittest.main()
|
|
1
|
+
import unittest
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
import os
|
|
4
|
+
from botrun_flow_lang.langgraph_agents.agents.util.img_util import get_img_content_type
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestImgUtil(unittest.TestCase):
|
|
8
|
+
def setUp(self):
|
|
9
|
+
"""Set up test fixtures"""
|
|
10
|
+
self.current_dir = Path(__file__).parent
|
|
11
|
+
self.test_files_dir = self.current_dir / "test_files"
|
|
12
|
+
|
|
13
|
+
def test_get_content_type_png_1(self):
|
|
14
|
+
"""Test get_content_type with PNG file"""
|
|
15
|
+
img_path = self.test_files_dir / "ImportedPhoto.760363950.029251.jpeg"
|
|
16
|
+
content_type = get_img_content_type(img_path)
|
|
17
|
+
self.assertEqual(content_type, "image/png")
|
|
18
|
+
|
|
19
|
+
def test_get_content_type_png_2(self):
|
|
20
|
+
"""Test get_content_type with PNG file"""
|
|
21
|
+
img_path = self.test_files_dir / "spot_difference_1.png"
|
|
22
|
+
content_type = get_img_content_type(img_path)
|
|
23
|
+
self.assertEqual(content_type, "image/png")
|
|
24
|
+
|
|
25
|
+
def test_get_content_type_jpeg_1(self):
|
|
26
|
+
"""Test get_content_type with PNG file"""
|
|
27
|
+
img_path = self.test_files_dir / "ImportedPhoto.760363950.030446.jpeg"
|
|
28
|
+
content_type = get_img_content_type(img_path)
|
|
29
|
+
self.assertEqual(content_type, "image/jpeg")
|
|
30
|
+
|
|
31
|
+
def test_get_content_type_jpeg_2(self):
|
|
32
|
+
"""Test get_content_type with PNG file"""
|
|
33
|
+
img_path = self.test_files_dir / "d5712343.jpg"
|
|
34
|
+
content_type = get_img_content_type(img_path)
|
|
35
|
+
self.assertEqual(content_type, "image/jpeg")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
if __name__ == "__main__":
|
|
39
|
+
unittest.main()
|