union-app-chat-stream 1.0.6 → 1.0.7

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.
@@ -14,6 +14,7 @@ import yaml
14
14
 
15
15
  PROJECT_ROOT = Path(__file__).resolve().parents[2]
16
16
  DEFAULT_TOOL_DEFINITIONS_PATH = PROJECT_ROOT / "tools" / "tool_definitions.yaml"
17
+ FIELD_DICTIONARY_PATH = PROJECT_ROOT / "tools" / "field_dictionary.yaml"
17
18
 
18
19
 
19
20
  @dataclass
@@ -47,6 +48,44 @@ def _load_yaml(path: Path) -> Dict[str, Any]:
47
48
  return data if isinstance(data, dict) else {}
48
49
 
49
50
 
51
+ def _normalize_field_name(name: str) -> str:
52
+ return re.sub(r"[\s_-]+", "", str(name)).lower()
53
+
54
+
55
+ @lru_cache(maxsize=1)
56
+ def _field_dictionary_index() -> Dict[str, Any]:
57
+ if not FIELD_DICTIONARY_PATH.exists():
58
+ return {"fallback_description": "", "exact": {}, "normalized": {}, "relations": []}
59
+
60
+ config = _load_yaml(FIELD_DICTIONARY_PATH)
61
+ if not isinstance(config, dict):
62
+ config = {}
63
+
64
+ exact: Dict[str, Dict[str, Any]] = {}
65
+ normalized: Dict[str, Dict[str, Any]] = {}
66
+ fields = config.get("fields") if isinstance(config.get("fields"), dict) else {}
67
+ for canonical, raw_info in fields.items():
68
+ if not isinstance(raw_info, dict):
69
+ continue
70
+ info = {key: value for key, value in raw_info.items() if key not in {"aliases", "patterns"}}
71
+ info["canonical"] = canonical
72
+ exact[canonical] = info
73
+ normalized[_normalize_field_name(canonical)] = info
74
+ aliases = raw_info.get("aliases") if isinstance(raw_info.get("aliases"), list) else []
75
+ for alias in aliases:
76
+ alias = str(alias)
77
+ exact[alias] = info
78
+ normalized[_normalize_field_name(alias)] = info
79
+
80
+ relations = config.get("relations") if isinstance(config.get("relations"), list) else []
81
+ return {
82
+ "fallback_description": str(config.get("fallback_description") or ""),
83
+ "exact": exact,
84
+ "normalized": normalized,
85
+ "relations": relations,
86
+ }
87
+
88
+
50
89
  @lru_cache(maxsize=1)
51
90
  def _tool_definition_config() -> Dict[str, Any]:
52
91
  path = Path(os.environ.get("TOOL_DEFINITIONS_PATH", DEFAULT_TOOL_DEFINITIONS_PATH))
@@ -55,6 +94,7 @@ def _tool_definition_config() -> Dict[str, Any]:
55
94
 
56
95
  def reload_tool_configs():
57
96
  _tool_definition_config.cache_clear()
97
+ _field_dictionary_index.cache_clear()
58
98
 
59
99
 
60
100
  def _raw_tool_definitions() -> List[Dict[str, Any]]:
@@ -178,6 +218,56 @@ def _render_value(value: Any, args: Dict[str, Any], *, allow_missing: bool = Fal
178
218
  return value
179
219
 
180
220
 
221
+ def _collect_data_fields(data: Any, sample_size: int = 5) -> List[str]:
222
+ if not isinstance(data, list):
223
+ return []
224
+ fields: List[str] = []
225
+ seen = set()
226
+ for item in data[:sample_size]:
227
+ if not isinstance(item, dict):
228
+ continue
229
+ for key in item:
230
+ key = str(key)
231
+ if key not in seen:
232
+ seen.add(key)
233
+ fields.append(key)
234
+ return fields
235
+
236
+
237
+ def _build_field_context(data: Any) -> Dict[str, Any]:
238
+ fields = _collect_data_fields(data)
239
+ if not fields:
240
+ return {}
241
+
242
+ index = _field_dictionary_index()
243
+ fallback = index["fallback_description"]
244
+ descriptions: Dict[str, Dict[str, Any]] = {}
245
+ canonical_fields = set()
246
+ for field in fields:
247
+ info = index["exact"].get(field) or index["normalized"].get(_normalize_field_name(field))
248
+ if info:
249
+ descriptions[field] = dict(info)
250
+ canonical_fields.add(str(info["canonical"]))
251
+ elif fallback:
252
+ descriptions[field] = {"description": fallback}
253
+
254
+ relations = []
255
+ for relation in index["relations"]:
256
+ if not isinstance(relation, dict):
257
+ continue
258
+ when_all = relation.get("when_all")
259
+ description = relation.get("description")
260
+ if isinstance(when_all, list) and description and all(str(field) in canonical_fields for field in when_all):
261
+ relations.append(str(description))
262
+
263
+ context: Dict[str, Any] = {}
264
+ if descriptions:
265
+ context["field_descriptions"] = descriptions
266
+ if relations:
267
+ context["field_relations"] = relations
268
+ return context
269
+
270
+
181
271
  def _base_result(spec: Dict[str, Any], args: Dict[str, Any]) -> Dict[str, Any]:
182
272
  result = {
183
273
  "tool_name": spec["name"],
@@ -242,6 +332,7 @@ def _run_backend_tool(
242
332
  })
243
333
  if path:
244
334
  result["backend"]["path"] = path
335
+ result.update(_build_field_context(data))
245
336
  return result
246
337
 
247
338
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "union-app-chat-stream",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Union operations chat stream Flask application package.",
5
5
  "license": "UNLICENSED",
6
6
  "files": [
@@ -0,0 +1,28 @@
1
+ fallback_description: 字段未命中全局字段字典。请结合字段名、字段值和上下文谨慎理解,不要编造枚举含义。
2
+ fields:
3
+ sysSuccessPercent:
4
+ meaning: 系统成功率,表示成功交易占总交易的比例,通常越高越好。
5
+ aliases:
6
+ - sysSuccessPercent
7
+ - avgSuccessPercent
8
+ - avg_success_percent
9
+ - successPer
10
+ failRate:
11
+ meaning: 失败率,通常表示失败交易笔数占总交易笔数的比例。
12
+ aliases:
13
+ - failRate
14
+ - fail_rate
15
+ faultLevel:
16
+ meaning: 故障等级,表示故障严重程度。
17
+ enum:
18
+ P1: 重大故障
19
+ P2: 较大故障
20
+ P3: 一般故障
21
+ aliases:
22
+ - faultLevel
23
+ - fault_level
24
+ relations:
25
+ - when_all:
26
+ - sysSuccessPercent
27
+ - failRate
28
+ description: 系统成功率和失败率通常反向相关。成功率下降时,应同时检查失败率是否上升。