stackConsult commited on
Commit
9989568
·
verified ·
1 Parent(s): 40a5e4c

Add query/search agent with advanced mapping, validation, error reporting, and JSON support

Browse files
Files changed (1) hide show
  1. query_search_agent.py +124 -0
query_search_agent.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Query/Search Agent Tool with Dynamic Column Mapping and JSON Support
2
+
3
+ This agent provides query and search capabilities over registered schemas,
4
+ performs dynamic mapping, validates target fields, and supports error handling
5
+ and JSON round-trip.
6
+ """
7
+
8
+ import json
9
+ from typing import Any, Dict, List, Tuple, Optional
10
+ from schema_registry import SchemaRegistry
11
+
12
+ class QuerySearchAgent:
13
+ """Query/search agent leveraging the SchemaRegistry's mapping and validation."""
14
+ def __init__(self, registry: Optional[SchemaRegistry] = None):
15
+ self.registry = registry or SchemaRegistry()
16
+
17
+ def search(self, schema_name: str, query: Dict[str, Any], data_source: List[Dict[str, Any]],
18
+ container_map: Optional[Dict[str, str]] = None) -> Tuple[List[Dict[str, Any]], List[str]]:
19
+ """Searches for items matching query constraints, supports dynamic container mapping."""
20
+ errors = []
21
+ results = []
22
+
23
+ # Validate schema
24
+ schema = self.registry.get_schema(schema_name)
25
+ if not schema:
26
+ errors.append(f"Schema '{schema_name}' not found")
27
+ return [], errors
28
+
29
+ # Validate query against schema
30
+ _, query_errors = self.registry.validate_data(schema_name, query)
31
+ if query_errors:
32
+ errors.extend(query_errors)
33
+ return [], errors
34
+
35
+ # Search logic
36
+ for item in data_source:
37
+ match = True
38
+ for qkey, qval in query.items():
39
+ if item.get(qkey) != qval:
40
+ match = False
41
+ break
42
+ if match:
43
+ results.append(item)
44
+
45
+ # Apply dynamic mapping if requested
46
+ if container_map:
47
+ mapped_results = []
48
+ for result in results:
49
+ mapped_item = {}
50
+ for orig_field, mapped_field in container_map.items():
51
+ mapped_item[mapped_field] = result.get(orig_field)
52
+ mapped_results.append(mapped_item)
53
+ results = mapped_results
54
+
55
+ return results, errors
56
+
57
+ def advanced_query(self, source_schema: str, target_schema: str, query: Dict[str, Any],
58
+ data_source: List[Dict[str, Any]]) -> Tuple[List[Dict[str, Any]], List[str]]:
59
+ """Search and transform data from source to target schema with validation/errors/JSON support."""
60
+ errors = []
61
+ transformed_results = []
62
+
63
+ for item in data_source:
64
+ # Validate source item
65
+ is_valid, validation_errors = self.registry.validate_data(source_schema, item)
66
+ if not is_valid:
67
+ errors.extend([f"Source error: {err}" for err in validation_errors])
68
+ continue
69
+ # Check query match
70
+ match = True
71
+ for qkey, qval in query.items():
72
+ if item.get(qkey) != qval:
73
+ match = False
74
+ break
75
+ if not match:
76
+ continue
77
+ # Transform to target schema
78
+ transformed, trans_errors = self.registry.transform_data(item, source_schema, target_schema)
79
+ if transformed:
80
+ transformed_results.append(transformed)
81
+ else:
82
+ errors.extend([f"Mapping error: {err}" for err in trans_errors])
83
+
84
+ return transformed_results, errors
85
+
86
+ def round_trip_json(self, obj: Any) -> Any:
87
+ """Verifies serialization and deserialization integrity (round-trip)."""
88
+ try:
89
+ dump = json.dumps(obj)
90
+ restore = json.loads(dump)
91
+ if dump == json.dumps(restore):
92
+ return restore
93
+ return None
94
+ except Exception as e:
95
+ return None
96
+
97
+
98
+ if __name__ == "__main__":
99
+ # Example usage/test
100
+ registry = SchemaRegistry()
101
+ agent = QuerySearchAgent(registry)
102
+ users = [
103
+ {'id': 1, 'username': 'alice', 'email': 'alice@example.com', 'age': 30},
104
+ {'id': 2, 'username': 'bob', 'email': 'bob@example.com', 'age': 24},
105
+ {'id': 3, 'username': 'carol', 'email': 'carol@test.com', 'age': 29},
106
+ ]
107
+ query = {'username': 'alice'}
108
+ results, errors = agent.search('user', query, users)
109
+ print("Basic results:", results, "Errors:", errors)
110
+
111
+ # Advanced query with transformation and error reporting
112
+ registry.register_schema('short_user', {
113
+ 'username': {'type': 'string', 'required': True},
114
+ 'age': {'type': 'int', 'required': False}
115
+ }, 'Short user schema')
116
+ registry.register_mapping('user', 'short_user', {
117
+ 'username': 'username',
118
+ 'age': 'age',
119
+ })
120
+ adv_results, adv_errors = agent.advanced_query('user', 'short_user', query, users)
121
+ print("Advanced results:", adv_results, "Errors:", adv_errors)
122
+
123
+ # Round-trip JSON test
124
+ print("Round-trip JSON:", agent.round_trip_json(results))