@@ -44,13 +44,16 @@ def extract_chunks(search_response: SearchResponse) -> List[Chunk]:
44
44
45
45
46
46
def replace_keywords (
47
- text : Union [str , List [str ]],
48
- keyword_replacements : Dict [ str , str ],
49
- conditional_replacements : List [tuple [ List [ str ], str ]] = [],
50
- ) -> tuple [ Union [ str , List [ str ]], Dict [ str , Union [ str , List [ str ]]]]:
47
+ text : Union [str , List [str ]], keyword_replacements : Dict [ str , str ]
48
+ ) -> tuple [
49
+ Union [ str , List [str ]], Dict [ str , Union [ str , List [ str ]]]
50
+ ]: # Changed return type
51
51
"""Replace keywords in text and return both the modified text and transformation details."""
52
- if not text or (not keyword_replacements and not conditional_replacements ):
53
- return text , {"original" : text , "resolved" : text }
52
+ if not text or not keyword_replacements :
53
+ return text , {
54
+ "original" : text ,
55
+ "resolved" : text ,
56
+ } # Return dict instead of TransformationDict
54
57
55
58
# Handle list of strings
56
59
if isinstance (text , list ):
@@ -59,12 +62,13 @@ def replace_keywords(
59
62
modified = False
60
63
61
64
# Create a single regex pattern for all keywords
62
- # pattern = "|".join(map(re.escape, keyword_replacements.keys()))
63
- # regex = re.compile(f"\\b({pattern})\\b")
65
+ pattern = "|" .join (map (re .escape , keyword_replacements .keys ()))
66
+ regex = re .compile (f"\\ b({ pattern } )\\ b" )
64
67
65
68
for item in text :
66
- new_item , _ = replace_keywords_in_string (
67
- item , keyword_replacements , conditional_replacements
69
+ # Single pass replacement for all keywords
70
+ new_item = regex .sub (
71
+ lambda m : keyword_replacements [m .group ()], item
68
72
)
69
73
result .append (new_item )
70
74
if new_item != item :
@@ -75,46 +79,24 @@ def replace_keywords(
75
79
return result , {"original" : original_text , "resolved" : result }
76
80
77
81
# Handle single string
78
- return replace_keywords_in_string (
79
- text , keyword_replacements , conditional_replacements
80
- )
81
-
82
-
83
- def parse_conditional_replacement (option : str ) -> tuple [List [str ], str ]:
84
- """Parse a conditional replacement rule like 'word a + word b : word c'."""
85
- conditions , replacement = option .split (":" )
86
- required_words = [word .strip () for word in conditions .split ("+" )]
87
- return required_words , replacement .strip ()
82
+ return replace_keywords_in_string (text , keyword_replacements )
88
83
89
84
90
85
def replace_keywords_in_string (
91
- text : str ,
92
- keyword_replacements : Dict [str , str ],
93
- conditional_replacements : List [tuple [List [str ], str ]] = [],
94
- ) -> tuple [str , Dict [str , Union [str , List [str ]]]]:
86
+ text : str , keyword_replacements : Dict [str , str ]
87
+ ) -> tuple [str , Dict [str , Union [str , List [str ]]]]: # Changed return type
95
88
"""Keywords for single string."""
96
- if not text or ( not keyword_replacements and not conditional_replacements ) :
89
+ if not text :
97
90
return text , {"original" : text , "resolved" : text }
98
91
99
- result = text
100
-
101
- # First check conditional replacements
102
- for required_words , replacement in conditional_replacements :
103
- # Check if all required words are present
104
- if all (word .lower () in text .lower () for word in required_words ):
105
- # Create a pattern that matches any of the required words
106
- pattern = "|" .join (map (re .escape , required_words ))
107
- # Replace all occurrences of the required words with the replacement
108
- result = re .sub (
109
- f"\\ b({ pattern } )\\ b" , replacement , result , flags = re .IGNORECASE
110
- )
92
+ # Create a single regex pattern for all keywords
93
+ pattern = "|" .join (map (re .escape , keyword_replacements .keys ()))
94
+ regex = re .compile (f"\\ b({ pattern } )\\ b" )
111
95
112
- # Then do normal replacements
113
- if keyword_replacements :
114
- pattern = "|" .join (map (re .escape , keyword_replacements .keys ()))
115
- regex = re .compile (f"\\ b({ pattern } )\\ b" )
116
- result = regex .sub (lambda m : keyword_replacements [m .group ()], result )
96
+ # Single pass replacement
97
+ result = regex .sub (lambda m : keyword_replacements [m .group ()], text )
117
98
99
+ # Only return transformation if something changed
118
100
if result != text :
119
101
return result , {"original" : text , "resolved" : result }
120
102
return text , {"original" : text , "resolved" : text }
@@ -149,13 +131,11 @@ async def process_query(
149
131
result_chunks = []
150
132
151
133
if format in ["str" , "str_array" ]:
152
- # Extract rules by type
134
+
135
+ # Extract and apply keyword replacements from all resolve_entity rules
153
136
resolve_entity_rules = [
154
137
rule for rule in rules if rule .type == "resolve_entity"
155
138
]
156
- conditional_rules = [
157
- rule for rule in rules if rule .type == "resolve_conditional"
158
- ]
159
139
160
140
result_chunks = (
161
141
[]
@@ -164,43 +144,28 @@ async def process_query(
164
144
else chunks
165
145
)
166
146
167
- # Process both types of replacements if we have an answer
168
- if answer_value and (resolve_entity_rules or conditional_rules ):
169
- # Build regular replacements dictionary
170
- replacements : Dict [str , str ] = {}
171
- if resolve_entity_rules :
172
- for rule in resolve_entity_rules :
173
- if rule .options :
174
- rule_replacements = dict (
175
- option .split (":" ) for option in rule .options
176
- )
177
- replacements .update (rule_replacements )
178
-
179
- # Build conditional replacements list
180
- conditional_replacements : List [tuple [List [str ], str ]] = []
181
- if conditional_rules :
182
- for rule in conditional_rules :
183
- if rule .options :
184
- for option in rule .options :
185
- required_words , replacement = (
186
- parse_conditional_replacement (option )
187
- )
188
- conditional_replacements .append (
189
- (required_words , replacement )
190
- )
191
-
192
- # Apply replacements if we have any
193
- if replacements or conditional_replacements :
147
+ # First populate the replacements dictionary
148
+ replacements : Dict [str , str ] = {}
149
+ if resolve_entity_rules and answer_value :
150
+ for rule in resolve_entity_rules :
151
+ if rule .options :
152
+ rule_replacements = dict (
153
+ option .split (":" ) for option in rule .options
154
+ )
155
+ replacements .update (rule_replacements )
156
+
157
+ # Then apply the replacements if we have any
158
+ if replacements :
194
159
print (f"Resolving entities in answer: { answer_value } " )
195
160
if isinstance (answer_value , list ):
196
161
transformed_list , transform_dict = replace_keywords (
197
- answer_value , replacements , conditional_replacements
162
+ answer_value , replacements
198
163
)
199
164
transformations = transform_dict
200
165
answer_value = transformed_list
201
166
else :
202
167
transformed_value , transform_dict = replace_keywords (
203
- answer_value , replacements , conditional_replacements
168
+ answer_value , replacements
204
169
)
205
170
transformations = transform_dict
206
171
answer_value = transformed_value
@@ -291,47 +256,31 @@ async def inference_query(
291
256
llm_service : CompletionService ,
292
257
) -> QueryResult :
293
258
"""Generate a response, no need for vector retrieval."""
259
+ # Since we are just answering this query based on data provided in the query,
260
+ # ther is no need to retrieve any chunks from the vector database.
261
+
294
262
answer = await generate_inferred_response (
295
263
llm_service , query , rules , format
296
264
)
297
265
answer_value = answer ["answer" ]
298
266
299
- # Extract rules by type
267
+ # Extract and apply keyword replacements from all resolve_entity rules
300
268
resolve_entity_rules = [
301
269
rule for rule in rules if rule .type == "resolve_entity"
302
270
]
303
- conditional_rules = [
304
- rule for rule in rules if rule .type == "resolve_conditional"
305
- ]
306
271
307
- if answer_value and ( resolve_entity_rules or conditional_rules ) :
308
- # Build regular replacements
272
+ if resolve_entity_rules and answer_value :
273
+ # Combine all replacements from all resolve_entity rules
309
274
replacements = {}
310
- if resolve_entity_rules :
311
- for rule in resolve_entity_rules :
312
- if rule .options :
313
- rule_replacements = dict (
314
- option .split (":" ) for option in rule .options
315
- )
316
- replacements .update (rule_replacements )
275
+ for rule in resolve_entity_rules :
276
+ if rule .options :
277
+ rule_replacements = dict (
278
+ option .split (":" ) for option in rule .options
279
+ )
280
+ replacements .update (rule_replacements )
317
281
318
- # Build conditional replacements
319
- conditional_replacements = []
320
- if conditional_rules :
321
- for rule in conditional_rules :
322
- if rule .options :
323
- for option in rule .options :
324
- required_words , replacement = (
325
- parse_conditional_replacement (option )
326
- )
327
- conditional_replacements .append (
328
- (required_words , replacement )
329
- )
330
-
331
- if replacements or conditional_replacements :
282
+ if replacements :
332
283
print (f"Resolving entities in answer: { answer_value } " )
333
- answer_value , _ = replace_keywords (
334
- answer_value , replacements , conditional_replacements
335
- )
284
+ answer_value = replace_keywords (answer_value , replacements )
336
285
337
286
return QueryResult (answer = answer_value , chunks = [])
0 commit comments