markdown-flow 0.2.28__tar.gz → 0.2.30__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.
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/PKG-INFO +1 -1
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/__init__.py +2 -2
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/constants.py +14 -36
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/core.py +69 -99
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/models.py +0 -16
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/validation.py +16 -37
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/providers/config.py +1 -3
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/providers/openai.py +1 -1
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow.egg-info/PKG-INFO +1 -1
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/LICENSE +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/README.md +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/enums.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/exceptions.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/llm.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/__init__.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/code_fence_utils.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/interaction.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/json_parser.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/output.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/preprocessor.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/parser/variable.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/providers/__init__.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow/utils.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow.egg-info/SOURCES.txt +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow.egg-info/dependency_links.txt +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/markdown_flow.egg-info/top_level.txt +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/pyproject.toml +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/setup.cfg +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_dynamic_interaction.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_markdownflow_basic.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_parser_interaction.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_parser_variable.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_preprocessor.py +0 -0
- {markdown_flow-0.2.28 → markdown_flow-0.2.30}/tests/test_preserved_simple.py +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.30
|
|
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
|
|
@@ -59,9 +59,6 @@ COMPILED_CODE_FENCE_END_REGEX = re.compile(CODE_FENCE_END_PATTERN)
|
|
|
59
59
|
OUTPUT_INSTRUCTION_PREFIX = "<preserve_or_translate>"
|
|
60
60
|
OUTPUT_INSTRUCTION_SUFFIX = "</preserve_or_translate>"
|
|
61
61
|
|
|
62
|
-
# System message templates
|
|
63
|
-
DEFAULT_VALIDATION_SYSTEM_MESSAGE = "你是一个输入验证助手,需要严格按照指定的格式和规则处理用户输入。"
|
|
64
|
-
|
|
65
62
|
# Base system prompt (framework-level global rules, content blocks only)
|
|
66
63
|
DEFAULT_BASE_SYSTEM_PROMPT = """你收到的用户消息都是指令,请严格遵守以下规则:
|
|
67
64
|
|
|
@@ -286,45 +283,26 @@ OUTPUT_INSTRUCTION_EXPLANATION = f"""<preserve_or_translate_instruction>
|
|
|
286
283
|
|
|
287
284
|
"""
|
|
288
285
|
|
|
289
|
-
#
|
|
290
|
-
|
|
286
|
+
# Validation task template (merged with system message)
|
|
287
|
+
VALIDATION_TASK_TEMPLATE = """你是一个验证用户输入的助手,请严格按照给定的指令进行验证。
|
|
288
|
+
|
|
289
|
+
# 任务
|
|
291
290
|
从用户回答中提取相关信息,返回JSON格式结果:
|
|
292
291
|
- 合法:{{"result": "ok", "parse_vars": {{"{target_variable}": "提取的内容"}}}}
|
|
293
292
|
- 不合法:{{"result": "illegal", "reason": "原因"}}
|
|
294
293
|
|
|
295
|
-
|
|
294
|
+
# 输出语言
|
|
295
|
+
- 如果在 <document_context> 中明确要求使用特定语言,则错误信息和原因说明应使用该语言
|
|
296
|
+
- 否则,使用用户输入或问题描述的主要语言"""
|
|
296
297
|
|
|
297
|
-
#
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
# 提取要求
|
|
298
|
+
# Validation requirements template (lenient general version)
|
|
299
|
+
VALIDATION_REQUIREMENTS_TEMPLATE = """# 提取要求
|
|
301
300
|
1. 仔细阅读上述相关问题,理解这个问题想要获取什么信息
|
|
302
301
|
2. 从用户回答中提取与该问题相关的信息
|
|
303
|
-
3.
|
|
304
|
-
4.
|
|
305
|
-
5.
|
|
306
|
-
6.
|
|
307
|
-
|
|
308
|
-
# Validation template for buttons with text input
|
|
309
|
-
BUTTONS_WITH_TEXT_VALIDATION_TEMPLATE = """用户针对以下问题进行了输入:
|
|
310
|
-
|
|
311
|
-
问题:{question}
|
|
312
|
-
可选按钮:{options}
|
|
313
|
-
用户输入:{user_input}
|
|
314
|
-
|
|
315
|
-
用户的输入不在预定义的按钮选项中,这意味着用户选择了自定义输入。
|
|
316
|
-
根据问题的性质,请判断用户的输入是否合理:
|
|
317
|
-
|
|
318
|
-
1. 如果用户输入能够表达与按钮选项类似的概念(比如按钮有"幽默、大气、二次元",用户输入了"搞笑"),请接受。
|
|
319
|
-
2. 如果用户输入是对问题的合理回答(比如问题要求描述风格,用户输入了任何有效的风格描述),请接受。
|
|
320
|
-
3. 只有当用户输入完全不相关、包含不当内容、或明显不合理时,才拒绝。
|
|
321
|
-
|
|
322
|
-
请按以下 JSON 格式回复:
|
|
323
|
-
{{
|
|
324
|
-
"result": "ok|illegal",
|
|
325
|
-
"parse_vars": {{"{target_variable}": "提取的值"}},
|
|
326
|
-
"reason": "接受或拒绝的原因"
|
|
327
|
-
}}"""
|
|
302
|
+
3. 如果提供了预定义选项,用户选择这些选项时都应该接受;自定义输入只要是对问题的合理回答即可接受
|
|
303
|
+
4. 对于昵称、姓名、标签等自由文本输入,任何非空的合理表达都应该接受(包括数字、字母、符号、emoji等创意性表达)
|
|
304
|
+
5. 只有当用户回答完全无关、包含不当内容或明显违背常识时才标记为不合法
|
|
305
|
+
6. 宽松验证原则:理解用户意图,接受多样化的合理表达形式"""
|
|
328
306
|
|
|
329
307
|
# ========== Error Message Constants ==========
|
|
330
308
|
|
|
@@ -355,5 +333,5 @@ CONTEXT_BUTTON_OPTIONS_MARKER = "## 预定义选项"
|
|
|
355
333
|
CONTEXT_QUESTION_TEMPLATE = f"{CONTEXT_QUESTION_MARKER}\n{{question}}"
|
|
356
334
|
CONTEXT_CONVERSATION_TEMPLATE = f"{CONTEXT_CONVERSATION_MARKER}\n{{content}}"
|
|
357
335
|
CONTEXT_BUTTON_OPTIONS_TEMPLATE = (
|
|
358
|
-
f"{CONTEXT_BUTTON_OPTIONS_MARKER}\n可选的预定义选项包括:{{button_options}}\n
|
|
336
|
+
f"{CONTEXT_BUTTON_OPTIONS_MARKER}\n可选的预定义选项包括:{{button_options}}\n注意:用户如果选择了这些选项,都应该接受;如果输入了自定义内容,只要是对问题的合理回答即可接受。"
|
|
359
337
|
)
|
|
@@ -13,11 +13,11 @@ from typing import Any
|
|
|
13
13
|
from .constants import (
|
|
14
14
|
BLOCK_INDEX_OUT_OF_RANGE_ERROR,
|
|
15
15
|
BLOCK_SEPARATOR,
|
|
16
|
-
|
|
16
|
+
CONTEXT_BUTTON_OPTIONS_TEMPLATE,
|
|
17
|
+
CONTEXT_QUESTION_TEMPLATE,
|
|
17
18
|
DEFAULT_BASE_SYSTEM_PROMPT,
|
|
18
19
|
DEFAULT_INTERACTION_ERROR_PROMPT,
|
|
19
20
|
DEFAULT_INTERACTION_PROMPT,
|
|
20
|
-
DEFAULT_VALIDATION_SYSTEM_MESSAGE,
|
|
21
21
|
INPUT_EMPTY_ERROR,
|
|
22
22
|
INTERACTION_ERROR_RENDER_INSTRUCTIONS,
|
|
23
23
|
INTERACTION_PARSE_ERROR,
|
|
@@ -26,16 +26,17 @@ from .constants import (
|
|
|
26
26
|
LLM_PROVIDER_REQUIRED_ERROR,
|
|
27
27
|
OUTPUT_INSTRUCTION_EXPLANATION,
|
|
28
28
|
UNSUPPORTED_PROMPT_TYPE_ERROR,
|
|
29
|
+
VALIDATION_REQUIREMENTS_TEMPLATE,
|
|
30
|
+
VALIDATION_TASK_TEMPLATE,
|
|
29
31
|
)
|
|
30
32
|
from .enums import BlockType
|
|
31
33
|
from .exceptions import BlockIndexError
|
|
32
34
|
from .llm import LLMProvider, LLMResult, ProcessMode
|
|
33
|
-
from .models import Block
|
|
35
|
+
from .models import Block
|
|
34
36
|
from .parser import (
|
|
35
37
|
CodeBlockPreprocessor,
|
|
36
38
|
InteractionParser,
|
|
37
39
|
InteractionType,
|
|
38
|
-
extract_interaction_question,
|
|
39
40
|
extract_preserved_content,
|
|
40
41
|
extract_variables_from_text,
|
|
41
42
|
is_preserved_content_block,
|
|
@@ -60,7 +61,6 @@ class MarkdownFlow:
|
|
|
60
61
|
_interaction_error_prompt: str | None
|
|
61
62
|
_max_context_length: int
|
|
62
63
|
_blocks: list[Block] | None
|
|
63
|
-
_interaction_configs: dict[int, InteractionValidationConfig]
|
|
64
64
|
_model: str | None
|
|
65
65
|
_temperature: float | None
|
|
66
66
|
_preprocessor: CodeBlockPreprocessor
|
|
@@ -95,7 +95,6 @@ class MarkdownFlow:
|
|
|
95
95
|
self._interaction_error_prompt = interaction_error_prompt or DEFAULT_INTERACTION_ERROR_PROMPT
|
|
96
96
|
self._max_context_length = max_context_length
|
|
97
97
|
self._blocks = None
|
|
98
|
-
self._interaction_configs: dict[int, InteractionValidationConfig] = {}
|
|
99
98
|
self._model: str | None = None
|
|
100
99
|
self._temperature: float | None = None
|
|
101
100
|
|
|
@@ -310,14 +309,6 @@ class MarkdownFlow:
|
|
|
310
309
|
"""Extract all variable names from the document."""
|
|
311
310
|
return extract_variables_from_text(self._document)
|
|
312
311
|
|
|
313
|
-
def set_interaction_validation_config(self, block_index: int, config: InteractionValidationConfig) -> None:
|
|
314
|
-
"""Set validation config for specified interaction block."""
|
|
315
|
-
self._interaction_configs[block_index] = config
|
|
316
|
-
|
|
317
|
-
def get_interaction_validation_config(self, block_index: int) -> InteractionValidationConfig | None:
|
|
318
|
-
"""Get validation config for specified interaction block."""
|
|
319
|
-
return self._interaction_configs.get(block_index)
|
|
320
|
-
|
|
321
312
|
# Core unified interface
|
|
322
313
|
|
|
323
314
|
def process(
|
|
@@ -472,9 +463,7 @@ class MarkdownFlow:
|
|
|
472
463
|
translated_json = self._llm_provider.complete(messages, model=self._model, temperature=self._temperature)
|
|
473
464
|
|
|
474
465
|
# 使用翻译结果重构交互内容
|
|
475
|
-
translated_content = self._reconstruct_with_translation(
|
|
476
|
-
processed_block.content, translatable_json, translated_json, interaction_info
|
|
477
|
-
)
|
|
466
|
+
translated_content = self._reconstruct_with_translation(processed_block.content, translatable_json, translated_json, interaction_info)
|
|
478
467
|
|
|
479
468
|
return LLMResult(
|
|
480
469
|
content=translated_content,
|
|
@@ -509,9 +498,7 @@ class MarkdownFlow:
|
|
|
509
498
|
full_response += chunk
|
|
510
499
|
|
|
511
500
|
# 使用翻译结果重构交互内容
|
|
512
|
-
translated_content = self._reconstruct_with_translation(
|
|
513
|
-
processed_block.content, translatable_json, full_response, interaction_info
|
|
514
|
-
)
|
|
501
|
+
translated_content = self._reconstruct_with_translation(processed_block.content, translatable_json, full_response, interaction_info)
|
|
515
502
|
|
|
516
503
|
# 一次性返回完整内容(不是增量)
|
|
517
504
|
yield LLMResult(
|
|
@@ -847,8 +834,8 @@ class MarkdownFlow:
|
|
|
847
834
|
mode: ProcessMode,
|
|
848
835
|
) -> LLMResult | Generator[LLMResult, None, None]:
|
|
849
836
|
"""Process LLM validation with button options (third case)."""
|
|
850
|
-
#
|
|
851
|
-
messages = self.
|
|
837
|
+
# Use unified validation message builder (button context will be included automatically)
|
|
838
|
+
messages = self._build_validation_messages(block_index, user_input, target_variable, context=None)
|
|
852
839
|
|
|
853
840
|
if mode == ProcessMode.COMPLETE:
|
|
854
841
|
if not self._llm_provider:
|
|
@@ -977,9 +964,7 @@ class MarkdownFlow:
|
|
|
977
964
|
|
|
978
965
|
return messages
|
|
979
966
|
|
|
980
|
-
def _extract_translatable_content(
|
|
981
|
-
self, interaction_content: str
|
|
982
|
-
) -> tuple[str, dict[str, Any] | None]:
|
|
967
|
+
def _extract_translatable_content(self, interaction_content: str) -> tuple[str, dict[str, Any] | None]:
|
|
983
968
|
"""提取交互内容中需要翻译的部分为 JSON 格式
|
|
984
969
|
|
|
985
970
|
Args:
|
|
@@ -1007,13 +992,12 @@ class MarkdownFlow:
|
|
|
1007
992
|
|
|
1008
993
|
# 转换为 JSON
|
|
1009
994
|
import json
|
|
995
|
+
|
|
1010
996
|
json_str = json.dumps(translatable, ensure_ascii=False)
|
|
1011
997
|
|
|
1012
998
|
return json_str, interaction_info
|
|
1013
999
|
|
|
1014
|
-
def _build_translation_messages(
|
|
1015
|
-
self, translatable_json: str
|
|
1016
|
-
) -> list[dict[str, str]]:
|
|
1000
|
+
def _build_translation_messages(self, translatable_json: str) -> list[dict[str, str]]:
|
|
1017
1001
|
"""构建翻译用的消息列表
|
|
1018
1002
|
|
|
1019
1003
|
Args:
|
|
@@ -1118,87 +1102,73 @@ class MarkdownFlow:
|
|
|
1118
1102
|
target_variable: str,
|
|
1119
1103
|
context: list[dict[str, str]] | None = None,
|
|
1120
1104
|
) -> list[dict[str, str]]:
|
|
1121
|
-
"""
|
|
1122
|
-
|
|
1123
|
-
config = self.get_interaction_validation_config(block_index)
|
|
1124
|
-
|
|
1125
|
-
# Truncate context to configured maximum length
|
|
1126
|
-
truncated_context = self._truncate_context(context)
|
|
1127
|
-
|
|
1128
|
-
if config and config.validation_template:
|
|
1129
|
-
# Use custom validation template
|
|
1130
|
-
validation_prompt = config.validation_template
|
|
1131
|
-
user_input_str = json.dumps(user_input, ensure_ascii=False)
|
|
1132
|
-
validation_prompt = validation_prompt.replace("{sys_user_input}", user_input_str)
|
|
1133
|
-
validation_prompt = validation_prompt.replace("{block_content}", block.content)
|
|
1134
|
-
validation_prompt = validation_prompt.replace("{target_variable}", target_variable)
|
|
1135
|
-
system_message = DEFAULT_VALIDATION_SYSTEM_MESSAGE
|
|
1136
|
-
else:
|
|
1137
|
-
# Use smart default validation template
|
|
1138
|
-
from .parser import (
|
|
1139
|
-
InteractionParser,
|
|
1140
|
-
extract_interaction_question,
|
|
1141
|
-
generate_smart_validation_template,
|
|
1142
|
-
)
|
|
1143
|
-
|
|
1144
|
-
# Extract interaction question
|
|
1145
|
-
interaction_question = extract_interaction_question(block.content)
|
|
1146
|
-
|
|
1147
|
-
# Parse interaction to extract button information
|
|
1148
|
-
parser = InteractionParser()
|
|
1149
|
-
parse_result = parser.parse(block.content)
|
|
1150
|
-
buttons = parse_result.get("buttons") if "buttons" in parse_result else None
|
|
1151
|
-
|
|
1152
|
-
# Generate smart validation template with context and buttons
|
|
1153
|
-
validation_template = generate_smart_validation_template(
|
|
1154
|
-
target_variable,
|
|
1155
|
-
context=truncated_context,
|
|
1156
|
-
interaction_question=interaction_question,
|
|
1157
|
-
buttons=buttons,
|
|
1158
|
-
)
|
|
1105
|
+
"""
|
|
1106
|
+
Build validation messages with new structure.
|
|
1159
1107
|
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1108
|
+
System message contains:
|
|
1109
|
+
- VALIDATION_TASK_TEMPLATE (includes task description and output language rules)
|
|
1110
|
+
- Question context (if exists)
|
|
1111
|
+
- Button options context (if exists)
|
|
1112
|
+
- VALIDATION_REQUIREMENTS_TEMPLATE
|
|
1113
|
+
- document_prompt wrapped in <document_context> tags (if exists)
|
|
1166
1114
|
|
|
1167
|
-
|
|
1115
|
+
User message contains:
|
|
1116
|
+
- User input only
|
|
1117
|
+
"""
|
|
1118
|
+
from .parser import InteractionParser, extract_interaction_question
|
|
1168
1119
|
|
|
1169
|
-
|
|
1120
|
+
block = self.get_block(block_index)
|
|
1170
1121
|
|
|
1171
|
-
#
|
|
1172
|
-
|
|
1173
|
-
|
|
1122
|
+
# Extract user input values for target variable
|
|
1123
|
+
target_values = user_input.get(target_variable, [])
|
|
1124
|
+
user_input_str = ", ".join(target_values) if target_values else ""
|
|
1174
1125
|
|
|
1175
|
-
|
|
1126
|
+
# Build System Message (contains all validation rules and context)
|
|
1127
|
+
# VALIDATION_TASK_TEMPLATE already includes system message, directly replace variables
|
|
1128
|
+
task_template = VALIDATION_TASK_TEMPLATE.replace("{target_variable}", target_variable)
|
|
1129
|
+
system_parts = [task_template]
|
|
1176
1130
|
|
|
1177
|
-
|
|
1131
|
+
# Extract interaction question
|
|
1132
|
+
interaction_question = extract_interaction_question(block.content)
|
|
1178
1133
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
question: str,
|
|
1185
|
-
) -> list[dict[str, str]]:
|
|
1186
|
-
"""Build validation messages with button options (third case)."""
|
|
1187
|
-
# Use validation template from constants
|
|
1188
|
-
user_input_str = json.dumps(user_input, ensure_ascii=False)
|
|
1189
|
-
validation_prompt = BUTTONS_WITH_TEXT_VALIDATION_TEMPLATE.format(
|
|
1190
|
-
question=question,
|
|
1191
|
-
options=", ".join(options),
|
|
1192
|
-
user_input=user_input_str,
|
|
1193
|
-
target_variable=target_variable,
|
|
1194
|
-
)
|
|
1134
|
+
# Add question context (if exists)
|
|
1135
|
+
if interaction_question:
|
|
1136
|
+
question_context = CONTEXT_QUESTION_TEMPLATE.format(question=interaction_question)
|
|
1137
|
+
system_parts.append("")
|
|
1138
|
+
system_parts.append(question_context)
|
|
1195
1139
|
|
|
1196
|
-
|
|
1140
|
+
# Parse interaction to extract button information
|
|
1141
|
+
parser = InteractionParser()
|
|
1142
|
+
parse_result = parser.parse(block.content)
|
|
1143
|
+
buttons = parse_result.get("buttons") if "buttons" in parse_result else None
|
|
1144
|
+
|
|
1145
|
+
# Add button options context (if exists)
|
|
1146
|
+
if buttons:
|
|
1147
|
+
button_displays = [btn.get("display", "") for btn in buttons if btn.get("display")]
|
|
1148
|
+
if button_displays:
|
|
1149
|
+
button_options = "、".join(button_displays)
|
|
1150
|
+
button_context = CONTEXT_BUTTON_OPTIONS_TEMPLATE.format(button_options=button_options)
|
|
1151
|
+
system_parts.append("")
|
|
1152
|
+
system_parts.append(button_context)
|
|
1153
|
+
|
|
1154
|
+
# Add extraction requirements (using template)
|
|
1155
|
+
system_parts.append("")
|
|
1156
|
+
system_parts.append(VALIDATION_REQUIREMENTS_TEMPLATE)
|
|
1157
|
+
|
|
1158
|
+
# Add document_prompt (if exists)
|
|
1197
1159
|
if self._document_prompt:
|
|
1198
|
-
|
|
1160
|
+
system_parts.append("")
|
|
1161
|
+
system_parts.append("<document_context>")
|
|
1162
|
+
system_parts.append(self._document_prompt)
|
|
1163
|
+
system_parts.append("</document_context>")
|
|
1199
1164
|
|
|
1200
|
-
|
|
1201
|
-
|
|
1165
|
+
system_content = "\n".join(system_parts)
|
|
1166
|
+
|
|
1167
|
+
# Build message list
|
|
1168
|
+
messages = [
|
|
1169
|
+
{"role": "system", "content": system_content},
|
|
1170
|
+
{"role": "user", "content": user_input_str}, # Only user input
|
|
1171
|
+
]
|
|
1202
1172
|
|
|
1203
1173
|
return messages
|
|
1204
1174
|
|
|
@@ -26,22 +26,6 @@ class UserInput:
|
|
|
26
26
|
is_multi_select: bool = False
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
@dataclass
|
|
30
|
-
class InteractionValidationConfig:
|
|
31
|
-
"""
|
|
32
|
-
Simplified interaction validation configuration.
|
|
33
|
-
|
|
34
|
-
Attributes:
|
|
35
|
-
validation_template (Optional[str]): Validation prompt template
|
|
36
|
-
target_variable (Optional[str]): Target variable name
|
|
37
|
-
enable_custom_validation (bool): Enable custom validation, defaults to True
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
validation_template: str | None = None
|
|
41
|
-
target_variable: str | None = None
|
|
42
|
-
enable_custom_validation: bool = True
|
|
43
|
-
|
|
44
|
-
|
|
45
29
|
@dataclass
|
|
46
30
|
class Block:
|
|
47
31
|
"""
|
|
@@ -12,10 +12,10 @@ from ..constants import (
|
|
|
12
12
|
CONTEXT_CONVERSATION_TEMPLATE,
|
|
13
13
|
CONTEXT_QUESTION_MARKER,
|
|
14
14
|
CONTEXT_QUESTION_TEMPLATE,
|
|
15
|
-
SMART_VALIDATION_TEMPLATE,
|
|
16
15
|
VALIDATION_ILLEGAL_DEFAULT_REASON,
|
|
17
16
|
VALIDATION_RESPONSE_ILLEGAL,
|
|
18
17
|
VALIDATION_RESPONSE_OK,
|
|
18
|
+
VALIDATION_TASK_TEMPLATE,
|
|
19
19
|
)
|
|
20
20
|
from .json_parser import parse_json_response
|
|
21
21
|
|
|
@@ -29,6 +29,9 @@ def generate_smart_validation_template(
|
|
|
29
29
|
"""
|
|
30
30
|
Generate smart validation template based on context and question.
|
|
31
31
|
|
|
32
|
+
DEPRECATED: This function is no longer used internally.
|
|
33
|
+
Use _build_validation_messages() in MarkdownFlow class instead.
|
|
34
|
+
|
|
32
35
|
Args:
|
|
33
36
|
target_variable: Target variable name
|
|
34
37
|
context: Context message list with role and content fields
|
|
@@ -36,42 +39,13 @@ def generate_smart_validation_template(
|
|
|
36
39
|
buttons: Button options list with display and value fields
|
|
37
40
|
|
|
38
41
|
Returns:
|
|
39
|
-
Generated validation template
|
|
42
|
+
Generated validation template (for backward compatibility)
|
|
40
43
|
"""
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
# Add question information (most important, put first)
|
|
47
|
-
if interaction_question:
|
|
48
|
-
context_parts.append(CONTEXT_QUESTION_TEMPLATE.format(question=interaction_question))
|
|
49
|
-
|
|
50
|
-
# Add button options information
|
|
51
|
-
if buttons:
|
|
52
|
-
button_displays = [btn.get("display", "") for btn in buttons if btn.get("display")]
|
|
53
|
-
if button_displays:
|
|
54
|
-
button_options_str = ", ".join(button_displays)
|
|
55
|
-
button_info = CONTEXT_BUTTON_OPTIONS_TEMPLATE.format(button_options=button_options_str)
|
|
56
|
-
context_parts.append(button_info)
|
|
57
|
-
|
|
58
|
-
# Add conversation context
|
|
59
|
-
if context:
|
|
60
|
-
for msg in context:
|
|
61
|
-
if msg.get("role") == "assistant" and CONTEXT_QUESTION_MARKER not in msg.get("content", ""):
|
|
62
|
-
# Other assistant messages as context (exclude extracted questions)
|
|
63
|
-
context_parts.append(CONTEXT_CONVERSATION_TEMPLATE.format(content=msg.get("content", "")))
|
|
64
|
-
|
|
65
|
-
if context_parts:
|
|
66
|
-
context_info = "\n\n".join(context_parts)
|
|
67
|
-
|
|
68
|
-
# Use template from constants
|
|
69
|
-
# Note: {sys_user_input} will be replaced later in _build_validation_messages
|
|
70
|
-
return SMART_VALIDATION_TEMPLATE.format(
|
|
71
|
-
target_variable=target_variable,
|
|
72
|
-
context_info=context_info,
|
|
73
|
-
sys_user_input="{sys_user_input}", # Keep placeholder for later replacement
|
|
74
|
-
).strip()
|
|
44
|
+
# For backward compatibility, return a simple template
|
|
45
|
+
# This function is no longer used in the core validation flow
|
|
46
|
+
template = VALIDATION_TASK_TEMPLATE.replace("{target_variable}", target_variable)
|
|
47
|
+
template += "\n\n# 用户回答\n{sys_user_input}"
|
|
48
|
+
return template.strip()
|
|
75
49
|
|
|
76
50
|
|
|
77
51
|
def parse_validation_response(llm_response: str, original_input: str, target_variable: str) -> dict[str, Any]:
|
|
@@ -101,6 +75,10 @@ def parse_validation_response(llm_response: str, original_input: str, target_var
|
|
|
101
75
|
if target_variable not in parse_vars:
|
|
102
76
|
parse_vars[target_variable] = original_input.strip()
|
|
103
77
|
|
|
78
|
+
# Ensure the variable value is in list format (user_input format)
|
|
79
|
+
if target_variable in parse_vars and not isinstance(parse_vars[target_variable], list):
|
|
80
|
+
parse_vars[target_variable] = [parse_vars[target_variable]]
|
|
81
|
+
|
|
104
82
|
return {"content": "", "variables": parse_vars}
|
|
105
83
|
|
|
106
84
|
if result == VALIDATION_RESPONSE_ILLEGAL:
|
|
@@ -117,5 +95,6 @@ def parse_validation_response(llm_response: str, original_input: str, target_var
|
|
|
117
95
|
|
|
118
96
|
# Check against standard response format
|
|
119
97
|
if "ok" in response_lower or "valid" in response_lower:
|
|
120
|
-
|
|
98
|
+
# Return in list format to match user_input format
|
|
99
|
+
return {"content": "", "variables": {target_variable: [original_input.strip()]}}
|
|
121
100
|
return {"content": llm_response, "variables": None}
|
|
@@ -31,9 +31,7 @@ class ProviderConfig:
|
|
|
31
31
|
debug: bool = field(default_factory=lambda: os.getenv("LLM_DEBUG", "false").lower() in ("true", "1", "yes"))
|
|
32
32
|
"""Enable debug mode (colorized console output). Default: LLM_DEBUG environment variable or False."""
|
|
33
33
|
|
|
34
|
-
timeout: float | None = field(
|
|
35
|
-
default_factory=lambda: float(os.getenv("LLM_TIMEOUT")) if os.getenv("LLM_TIMEOUT") else None
|
|
36
|
-
)
|
|
34
|
+
timeout: float | None = field(default_factory=lambda: float(os.getenv("LLM_TIMEOUT")) if os.getenv("LLM_TIMEOUT") else None)
|
|
37
35
|
"""Request timeout in seconds. None means no timeout. Default: LLM_TIMEOUT environment variable or None."""
|
|
38
36
|
|
|
39
37
|
def __post_init__(self):
|
|
@@ -281,7 +281,7 @@ class OpenAIProvider(LLMProvider):
|
|
|
281
281
|
role = message.get("role", "user")
|
|
282
282
|
content = message.get("content", "")
|
|
283
283
|
# Truncate long content for readability
|
|
284
|
-
display_content = content
|
|
284
|
+
display_content = content
|
|
285
285
|
print(f"\033[30m\033[43m{role}\033[0m: {display_content}")
|
|
286
286
|
|
|
287
287
|
print("\033[97m\033[44m[ ====== LLM Request End ====== ]\033[0m")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: markdown-flow
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.30
|
|
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
|
|
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
|
|
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
|