markdown-flow 0.2.8__tar.gz → 0.2.10__tar.gz
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.
Potentially problematic release.
This version of markdown-flow might be problematic. Click here for more details.
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/PKG-INFO +1 -1
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/__init__.py +1 -1
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/core.py +23 -11
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow.egg-info/PKG-INFO +1 -1
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/tests/test_dynamic_interaction.py +151 -78
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/LICENSE +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/README.md +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/constants.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/enums.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/exceptions.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/llm.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/models.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow/utils.py +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow.egg-info/SOURCES.txt +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow.egg-info/dependency_links.txt +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/markdown_flow.egg-info/top_level.txt +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/pyproject.toml +0 -0
- {markdown_flow-0.2.8 → markdown_flow-0.2.10}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.10
|
|
4
4
|
Summary: An agent library designed to parse and process MarkdownFlow documents
|
|
5
5
|
Project-URL: Homepage, https://github.com/ai-shifu/markdown-flow-agent-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/ai-shifu/markdown-flow-agent-py/issues
|
|
@@ -478,7 +478,7 @@ class MarkdownFlow:
|
|
|
478
478
|
error_msg = f"Please select from: {', '.join(button_displays)}"
|
|
479
479
|
return self._render_error(error_msg, mode)
|
|
480
480
|
|
|
481
|
-
#
|
|
481
|
+
# First, check if user input matches available buttons
|
|
482
482
|
valid_values = []
|
|
483
483
|
invalid_values = []
|
|
484
484
|
|
|
@@ -491,19 +491,30 @@ class MarkdownFlow:
|
|
|
491
491
|
break
|
|
492
492
|
|
|
493
493
|
if not matched:
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
494
|
+
invalid_values.append(value)
|
|
495
|
+
|
|
496
|
+
# If there are invalid values and this interaction allows text input, use LLM validation
|
|
497
|
+
if invalid_values and allow_text_input:
|
|
498
|
+
# Use LLM validation for text input interactions
|
|
499
|
+
button_displays = [btn["display"] for btn in buttons]
|
|
500
|
+
question = parse_result.get("question", "")
|
|
501
|
+
|
|
502
|
+
return self._process_llm_validation_with_options(
|
|
503
|
+
block_index=0, # Not used in the method
|
|
504
|
+
user_input={target_variable: target_values},
|
|
505
|
+
target_variable=target_variable,
|
|
506
|
+
options=button_displays,
|
|
507
|
+
question=question,
|
|
508
|
+
mode=mode
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
# Check for validation errors in pure button mode or when text input not allowed
|
|
512
|
+
if invalid_values:
|
|
502
513
|
button_displays = [btn["display"] for btn in buttons]
|
|
503
514
|
error_msg = f"Invalid options: {', '.join(invalid_values)}. Please select from: {', '.join(button_displays)}"
|
|
504
515
|
return self._render_error(error_msg, mode)
|
|
505
516
|
|
|
506
|
-
# Success: return validated values
|
|
517
|
+
# Success: return validated button values
|
|
507
518
|
return LLMResult(
|
|
508
519
|
content="",
|
|
509
520
|
variables={target_variable: valid_values},
|
|
@@ -513,6 +524,7 @@ class MarkdownFlow:
|
|
|
513
524
|
"valid_values": valid_values,
|
|
514
525
|
"invalid_values": invalid_values,
|
|
515
526
|
"total_input_count": len(target_values),
|
|
527
|
+
"llm_validated": False,
|
|
516
528
|
},
|
|
517
529
|
)
|
|
518
530
|
|
|
@@ -1132,7 +1144,7 @@ Analyze the content and provide the structured interaction data.""")
|
|
|
1132
1144
|
)
|
|
1133
1145
|
|
|
1134
1146
|
# Merge with existing variables for dynamic interactions
|
|
1135
|
-
if hasattr(button_result, 'variables') and variables:
|
|
1147
|
+
if hasattr(button_result, 'variables') and button_result.variables is not None and variables:
|
|
1136
1148
|
merged_variables = dict(variables)
|
|
1137
1149
|
merged_variables.update(button_result.variables)
|
|
1138
1150
|
return LLMResult(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.10
|
|
4
4
|
Summary: An agent library designed to parse and process MarkdownFlow documents
|
|
5
5
|
Project-URL: Homepage, https://github.com/ai-shifu/markdown-flow-agent-py
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/ai-shifu/markdown-flow-agent-py/issues
|
|
@@ -77,36 +77,30 @@ def test_chinese_restaurant_scenario():
|
|
|
77
77
|
|
|
78
78
|
# 第三步:测试无效选择
|
|
79
79
|
print("\n--- 测试无效选择 ---")
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
print("⚠️ 可能允许了无效选择")
|
|
92
|
-
except Exception as e:
|
|
93
|
-
print(f"✅ 正确拒绝无效选择: {str(e)[:50]}...")
|
|
80
|
+
invalid_choices = ["意大利面", "汉堡包"] # 不在选项中的选择
|
|
81
|
+
result3 = mf.process(
|
|
82
|
+
block_index=0,
|
|
83
|
+
mode=ProcessMode.COMPLETE,
|
|
84
|
+
user_input={"菜品选择": invalid_choices},
|
|
85
|
+
dynamic_interaction_format=result1.content
|
|
86
|
+
)
|
|
87
|
+
print(f"无效选择输入: {invalid_choices}")
|
|
88
|
+
print(f"LLM完整响应: {result3.content}")
|
|
89
|
+
print(f"返回变量: {result3.variables}")
|
|
90
|
+
print(f"元数据: {result3.metadata}")
|
|
94
91
|
|
|
95
92
|
# 第四步:测试空输入
|
|
96
93
|
print("\n--- 测试空输入 ---")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
print("✅ 正确处理空输入")
|
|
108
|
-
except Exception as e:
|
|
109
|
-
print(f"✅ 正确处理空输入错误: {str(e)[:50]}...")
|
|
94
|
+
result4 = mf.process(
|
|
95
|
+
block_index=0,
|
|
96
|
+
mode=ProcessMode.COMPLETE,
|
|
97
|
+
user_input={"菜品选择": []},
|
|
98
|
+
dynamic_interaction_format=result1.content
|
|
99
|
+
)
|
|
100
|
+
print(f"空输入: []")
|
|
101
|
+
print(f"LLM完整响应: {result4.content}")
|
|
102
|
+
print(f"返回变量: {result4.variables}")
|
|
103
|
+
print(f"元数据: {result4.metadata}")
|
|
110
104
|
|
|
111
105
|
print("✅ 中文餐厅场景完整验证通过")
|
|
112
106
|
|
|
@@ -176,18 +170,17 @@ Format: Provide specific educational options"""
|
|
|
176
170
|
|
|
177
171
|
# 第三步:测试部分匹配选择
|
|
178
172
|
print("\n--- Test Partial Match ---")
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
print(f"Partial selection handling: {str(e)[:50]}...")
|
|
173
|
+
partial_choices = ["Computer"] # 只选择一个词
|
|
174
|
+
result3 = mf.process(
|
|
175
|
+
block_index=0,
|
|
176
|
+
mode=ProcessMode.COMPLETE,
|
|
177
|
+
user_input={"learning_choice": partial_choices},
|
|
178
|
+
dynamic_interaction_format=result1.content
|
|
179
|
+
)
|
|
180
|
+
print(f"部分匹配输入: {partial_choices}")
|
|
181
|
+
print(f"LLM完整响应: {result3.content}")
|
|
182
|
+
print(f"返回变量: {result3.variables}")
|
|
183
|
+
print(f"元数据: {result3.metadata}")
|
|
191
184
|
|
|
192
185
|
# 第四步:测试单个选择
|
|
193
186
|
print("\n--- Test Single Selection ---")
|
|
@@ -414,20 +407,18 @@ def test_complex_job_consultation_scenario():
|
|
|
414
407
|
|
|
415
408
|
# 测试无效职位选择
|
|
416
409
|
print("\n--- 测试无效职位选择 ---")
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
except Exception as e:
|
|
430
|
-
print(f"✅ 正确拒绝无效职位选择: {str(e)[:50]}...")
|
|
410
|
+
invalid_job = ["厨师", "司机"] # 不属于科技行业的职位
|
|
411
|
+
result_invalid = mf.process(
|
|
412
|
+
block_index=1,
|
|
413
|
+
mode=ProcessMode.COMPLETE,
|
|
414
|
+
variables=result1.variables,
|
|
415
|
+
user_input={"职位选择": invalid_job},
|
|
416
|
+
dynamic_interaction_format=result2.content
|
|
417
|
+
)
|
|
418
|
+
print(f"无效职位输入: {invalid_job}")
|
|
419
|
+
print(f"LLM完整响应: {result_invalid.content}")
|
|
420
|
+
print(f"返回变量: {result_invalid.variables}")
|
|
421
|
+
print(f"元数据: {result_invalid.metadata}")
|
|
431
422
|
|
|
432
423
|
# 第四步:生成薪资选项
|
|
433
424
|
print("\n--- 步骤4: 生成薪资选项 ---")
|
|
@@ -567,16 +558,16 @@ def test_text_input_scenario():
|
|
|
567
558
|
|
|
568
559
|
# 测试空输入(对于支持文本输入的交互,可能允许空输入)
|
|
569
560
|
print("\n--- 测试空输入处理 ---")
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
561
|
+
result5 = mf.process(
|
|
562
|
+
block_index=0,
|
|
563
|
+
mode=ProcessMode.COMPLETE,
|
|
564
|
+
user_input={"自定义需求": []},
|
|
565
|
+
dynamic_interaction_format=result1.content
|
|
566
|
+
)
|
|
567
|
+
print(f"空输入: []")
|
|
568
|
+
print(f"LLM完整响应: {result5.content}")
|
|
569
|
+
print(f"返回变量: {result5.variables}")
|
|
570
|
+
print(f"元数据: {result5.metadata}")
|
|
580
571
|
|
|
581
572
|
print("✅ 文本输入场景完整验证通过")
|
|
582
573
|
|
|
@@ -701,20 +692,18 @@ def test_variable_context_cuisine_scenario():
|
|
|
701
692
|
|
|
702
693
|
# 测试无效菜品选择
|
|
703
694
|
print("\n--- 测试无效菜品选择 ---")
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
except Exception as e:
|
|
717
|
-
print(f"✅ 正确拒绝无效菜品选择: {str(e)[:50]}...")
|
|
695
|
+
invalid_dishes = ["北京烤鸭", "小笼包"] # 非川菜选项
|
|
696
|
+
result_invalid = mf.process(
|
|
697
|
+
block_index=1,
|
|
698
|
+
mode=ProcessMode.COMPLETE,
|
|
699
|
+
variables=result1.variables,
|
|
700
|
+
user_input={"菜品": invalid_dishes},
|
|
701
|
+
dynamic_interaction_format=result2.content
|
|
702
|
+
)
|
|
703
|
+
print(f"无效菜品输入: {invalid_dishes}")
|
|
704
|
+
print(f"LLM完整响应: {result_invalid.content}")
|
|
705
|
+
print(f"返回变量: {result_invalid.variables}")
|
|
706
|
+
print(f"元数据: {result_invalid.metadata}")
|
|
718
707
|
|
|
719
708
|
print("✅ 变量上下文场景完整验证通过")
|
|
720
709
|
|
|
@@ -823,6 +812,89 @@ Format: Provide specific project options based on the selected programming langu
|
|
|
823
812
|
print(f"❌ Test failed: {e}")
|
|
824
813
|
|
|
825
814
|
|
|
815
|
+
def test_user_question_text_input():
|
|
816
|
+
"""测试用户疑问式文本输入场景"""
|
|
817
|
+
print("\n=== 用户疑问文本输入测试 ===")
|
|
818
|
+
|
|
819
|
+
document = """询问用户的故事风格偏好,并记录到变量{{风格选择}}"""
|
|
820
|
+
|
|
821
|
+
document_prompt = """你是故事创作助手。为用户提供故事风格选项:
|
|
822
|
+
- 常见风格:幽默、搞笑、悬疑、浪漫、文言文
|
|
823
|
+
- 同时允许用户输入其他风格偏好
|
|
824
|
+
|
|
825
|
+
语言:中文
|
|
826
|
+
格式:提供常见风格选项 + 允许自定义文本输入(使用...前缀)"""
|
|
827
|
+
|
|
828
|
+
try:
|
|
829
|
+
llm_provider = create_llm_provider()
|
|
830
|
+
mf = MarkdownFlow(
|
|
831
|
+
document=document,
|
|
832
|
+
llm_provider=llm_provider,
|
|
833
|
+
document_prompt=document_prompt
|
|
834
|
+
)
|
|
835
|
+
|
|
836
|
+
# 生成动态交互
|
|
837
|
+
print("--- 生成故事风格选项 ---")
|
|
838
|
+
result1 = mf.process(
|
|
839
|
+
block_index=0,
|
|
840
|
+
mode=ProcessMode.COMPLETE
|
|
841
|
+
)
|
|
842
|
+
|
|
843
|
+
print(f"转换为交互块: {result1.transformed_to_interaction}")
|
|
844
|
+
print(f"生成的交互: {result1.content}")
|
|
845
|
+
|
|
846
|
+
if result1.transformed_to_interaction:
|
|
847
|
+
# 验证是否包含文本输入选项
|
|
848
|
+
has_text_input = "..." in result1.content
|
|
849
|
+
if has_text_input:
|
|
850
|
+
print("✅ 包含文本输入选项")
|
|
851
|
+
|
|
852
|
+
# 测试用户疑问式输入
|
|
853
|
+
print("\n--- 测试疑问式文本输入 ---")
|
|
854
|
+
question_input = ["这里必须要选择么?"]
|
|
855
|
+
|
|
856
|
+
result2 = mf.process(
|
|
857
|
+
block_index=0,
|
|
858
|
+
mode=ProcessMode.COMPLETE,
|
|
859
|
+
user_input={"风格选择": question_input},
|
|
860
|
+
dynamic_interaction_format=result1.content
|
|
861
|
+
)
|
|
862
|
+
|
|
863
|
+
print(f"用户疑问输入: {question_input}")
|
|
864
|
+
print(f"验证结果: {result2.variables}")
|
|
865
|
+
|
|
866
|
+
# 显示疑问输入的完整处理结果
|
|
867
|
+
print(f"疑问输入: {question_input}")
|
|
868
|
+
print(f"LLM完整响应: {result2.content}")
|
|
869
|
+
print(f"返回变量: {result2.variables}")
|
|
870
|
+
print(f"元数据: {result2.metadata}")
|
|
871
|
+
|
|
872
|
+
# 测试其他类型的自定义输入
|
|
873
|
+
print("\n--- 测试其他自定义输入 ---")
|
|
874
|
+
custom_inputs = [
|
|
875
|
+
["我想要科幻加悬疑的混合风格"],
|
|
876
|
+
["可以不选择吗"],
|
|
877
|
+
["这些选项都不适合我"]
|
|
878
|
+
]
|
|
879
|
+
|
|
880
|
+
for custom_input in custom_inputs:
|
|
881
|
+
result_custom = mf.process(
|
|
882
|
+
block_index=0,
|
|
883
|
+
mode=ProcessMode.COMPLETE,
|
|
884
|
+
user_input={"风格选择": custom_input},
|
|
885
|
+
dynamic_interaction_format=result1.content
|
|
886
|
+
)
|
|
887
|
+
print(f"\n自定义输入: {custom_input}")
|
|
888
|
+
print(f"LLM完整响应: {result_custom.content}")
|
|
889
|
+
print(f"返回变量: {result_custom.variables}")
|
|
890
|
+
print(f"元数据: {result_custom.metadata}")
|
|
891
|
+
|
|
892
|
+
print("✅ 用户疑问文本输入场景测试完成")
|
|
893
|
+
|
|
894
|
+
except Exception as e:
|
|
895
|
+
print(f"❌ 测试失败: {e}")
|
|
896
|
+
|
|
897
|
+
|
|
826
898
|
def run_all_tests():
|
|
827
899
|
"""运行所有 document_prompt 测试"""
|
|
828
900
|
print("🧪 开始 document_prompt 动态交互测试")
|
|
@@ -836,7 +908,8 @@ def run_all_tests():
|
|
|
836
908
|
test_complex_job_consultation_scenario,
|
|
837
909
|
test_text_input_scenario,
|
|
838
910
|
test_variable_context_cuisine_scenario,
|
|
839
|
-
test_variable_context_skill_project_scenario
|
|
911
|
+
test_variable_context_skill_project_scenario,
|
|
912
|
+
test_user_question_text_input
|
|
840
913
|
]
|
|
841
914
|
|
|
842
915
|
for test_func in tests:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|