Skip to content

Commit 7fb0077

Browse files
committed
Revert "Updating to add conditional rules"
This reverts commit d37b05f.
1 parent d37b05f commit 7fb0077

File tree

7 files changed

+67
-170
lines changed

7 files changed

+67
-170
lines changed

backend/src/app/models/query_core.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,7 @@ class TransformationDict(BaseModel):
3131
class Rule(BaseModel):
3232
"""Rule model."""
3333

34-
type: Literal[
35-
"must_return",
36-
"may_return",
37-
"max_length",
38-
"resolve_entity",
39-
"resolve_conditional",
40-
]
34+
type: Literal["must_return", "may_return", "max_length", "resolve_entity"]
4135
options: Optional[List[str]] = None
4236
length: Optional[int] = None
4337

backend/src/app/services/query_service.py

Lines changed: 54 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ def extract_chunks(search_response: SearchResponse) -> List[Chunk]:
4444

4545

4646
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
5151
"""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
5457

5558
# Handle list of strings
5659
if isinstance(text, list):
@@ -59,12 +62,13 @@ def replace_keywords(
5962
modified = False
6063

6164
# 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")
6467

6568
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
6872
)
6973
result.append(new_item)
7074
if new_item != item:
@@ -75,46 +79,24 @@ def replace_keywords(
7579
return result, {"original": original_text, "resolved": result}
7680

7781
# 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)
8883

8984

9085
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
9588
"""Keywords for single string."""
96-
if not text or (not keyword_replacements and not conditional_replacements):
89+
if not text:
9790
return text, {"original": text, "resolved": text}
9891

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")
11195

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)
11798

99+
# Only return transformation if something changed
118100
if result != text:
119101
return result, {"original": text, "resolved": result}
120102
return text, {"original": text, "resolved": text}
@@ -149,13 +131,11 @@ async def process_query(
149131
result_chunks = []
150132

151133
if format in ["str", "str_array"]:
152-
# Extract rules by type
134+
135+
# Extract and apply keyword replacements from all resolve_entity rules
153136
resolve_entity_rules = [
154137
rule for rule in rules if rule.type == "resolve_entity"
155138
]
156-
conditional_rules = [
157-
rule for rule in rules if rule.type == "resolve_conditional"
158-
]
159139

160140
result_chunks = (
161141
[]
@@ -164,43 +144,28 @@ async def process_query(
164144
else chunks
165145
)
166146

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:
194159
print(f"Resolving entities in answer: {answer_value}")
195160
if isinstance(answer_value, list):
196161
transformed_list, transform_dict = replace_keywords(
197-
answer_value, replacements, conditional_replacements
162+
answer_value, replacements
198163
)
199164
transformations = transform_dict
200165
answer_value = transformed_list
201166
else:
202167
transformed_value, transform_dict = replace_keywords(
203-
answer_value, replacements, conditional_replacements
168+
answer_value, replacements
204169
)
205170
transformations = transform_dict
206171
answer_value = transformed_value
@@ -291,47 +256,31 @@ async def inference_query(
291256
llm_service: CompletionService,
292257
) -> QueryResult:
293258
"""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+
294262
answer = await generate_inferred_response(
295263
llm_service, query, rules, format
296264
)
297265
answer_value = answer["answer"]
298266

299-
# Extract rules by type
267+
# Extract and apply keyword replacements from all resolve_entity rules
300268
resolve_entity_rules = [
301269
rule for rule in rules if rule.type == "resolve_entity"
302270
]
303-
conditional_rules = [
304-
rule for rule in rules if rule.type == "resolve_conditional"
305-
]
306271

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
309274
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)
317281

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:
332283
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)
336285

337286
return QueryResult(answer=answer_value, chunks=[])

frontend/src/components/kt/kt-controls/kt-global-rules.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,6 @@ export function KTGlobalRules(props: BoxProps) {
127127
max_length,3,
128128
<br />
129129
resolve_entity,"blue:ultramarine,red:crimson",Color
130-
<br />
131-
resolve_conditional,"word a + word b:word c",Words
132130
</Code>
133131
</Box>
134132
</Group>
@@ -249,7 +247,7 @@ export function KTGlobalRules(props: BoxProps) {
249247

250248
const csvJsonSchema = z.array(
251249
z.object({
252-
rule_type: z.enum(["must_return", "may_return", "max_length", "resolve_entity", "resolve_conditional"]),
250+
rule_type: z.enum(["must_return", "may_return", "max_length", "resolve_entity"]),
253251
value: z.string(),
254252
entity_type: z.string().optional()
255253
})

frontend/src/components/kt/kt-table/kt-cells/kt-column-settings/kt-column-settings.tsx

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -157,31 +157,6 @@ const rulesMenu = (
157157
}}
158158
/>
159159
</Group>
160-
) : rule.type === "resolve_conditional" ? (
161-
<Group gap="xs" wrap="nowrap">
162-
<TextInput
163-
w={150}
164-
placeholder="word a + word b"
165-
value={rule.options?.[0]?.split(":")[0] ?? ""}
166-
onChange={e => {
167-
const after = rule.options?.[0]?.split(":")[1] ?? "";
168-
handleRuleChange(rule, {
169-
options: [`${e.target.value}:${after}`]
170-
});
171-
}}
172-
/>
173-
<TextInput
174-
w={100}
175-
placeholder="word c"
176-
value={rule.options?.[0]?.split(":")[1] ?? ""}
177-
onChange={e => {
178-
const before = rule.options?.[0]?.split(":")[0] ?? "";
179-
handleRuleChange(rule, {
180-
options: [`${before}:${e.target.value}`]
181-
});
182-
}}
183-
/>
184-
</Group>
185160
) : (
186161
<TagsInput
187162
w={210}

frontend/src/config/store/store.ts

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -420,27 +420,12 @@ export const useStore = create<Store>()(
420420
? entity.original.join(' ')
421421
: entity.original;
422422

423-
return globalRules.some(rule => {
424-
// Handle regular resolve_entity rules
425-
if (rule.type === 'resolve_entity') {
426-
return rule.options?.some(pattern =>
427-
originalText.toLowerCase().includes(pattern.split(':')[0].toLowerCase())
428-
);
429-
}
430-
431-
// Handle conditional resolve rules
432-
if (rule.type === 'resolve_conditional') {
433-
return rule.options?.some(pattern => {
434-
const [conditions] = pattern.split(':');
435-
const requiredWords = conditions.split('+').map(word => word.trim());
436-
return requiredWords.every(word =>
437-
originalText.toLowerCase().includes(word.toLowerCase())
438-
);
439-
});
440-
}
441-
442-
return false;
443-
});
423+
return globalRules.some(rule =>
424+
rule.type === 'resolve_entity' &&
425+
rule.options?.some(pattern =>
426+
originalText.toLowerCase().includes(pattern.toLowerCase())
427+
)
428+
);
444429
};
445430

446431
editTable(activeTableId, {
@@ -466,7 +451,7 @@ export const useStore = create<Store>()(
466451
})),
467452
globalRules: currentTable.globalRules.map(rule => ({
468453
...rule,
469-
resolvedEntities: (rule.type === 'resolve_entity' || rule.type === 'resolve_conditional')
454+
resolvedEntities: rule.type === 'resolve_entity'
470455
? [
471456
...(rule.resolvedEntities || []),
472457
...(resolvedEntities || [])

frontend/src/config/store/store.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export interface AnswerTableGlobalRule extends AnswerTableRule {
111111
}
112112

113113
export interface AnswerTableRule {
114-
type: "must_return" | "may_return" | "max_length" | "resolve_entity" | "resolve_conditional";
114+
type: "must_return" | "may_return" | "max_length" | "resolve_entity";
115115
options?: string[];
116116
length?: number;
117117
}

frontend/src/config/store/store.utils.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ export const defaultRules: Record<AnswerTableRule["type"], AnswerTableRule> = {
8080
must_return: { type: "must_return", options: [] },
8181
may_return: { type: "may_return", options: [] },
8282
max_length: { type: "max_length", length: 1 },
83-
resolve_entity: { type: "resolve_entity", options: [] },
84-
resolve_conditional: { type: "resolve_conditional", options: [] }
83+
resolve_entity: { type: "resolve_entity", options: [] }
8584
};
8685

8786
export const ruleOptions: {
@@ -91,18 +90,15 @@ export const ruleOptions: {
9190
{ value: "must_return", label: "Must return" },
9291
{ value: "may_return", label: "May return" },
9392
{ value: "max_length", label: "Allowed # of responses" },
94-
{ value: "resolve_entity", label: "Resolve entity" },
95-
{ value: "resolve_conditional", label: "Resolve conditional" }
93+
{ value: "resolve_entity", label: "Resolve entity" }
9694
];
9795

9896
export const ruleInfo: Record<AnswerTableRule["type"], string> = {
9997
must_return: "The column must return the specified values",
10098
may_return: "The column may return the specified values",
10199
max_length: "The column must return at most N values",
102100
resolve_entity:
103-
"Replace all specified values with the first one from the list (i.e. 'turquioise:blue')",
104-
resolve_conditional:
105-
"Replace all specified values with the first one from the list (i.e. 'word a + word b:word c')"
101+
"Replace all specified values with the first one from the list (i.e. 'turquioise:blue')"
106102
};
107103

108104
// Casting

0 commit comments

Comments
 (0)