label
Browse files- app.py +126 -0
- classify.py +24 -16
- judge.py +1 -2
app.py
CHANGED
@@ -478,6 +478,132 @@ Once created, knowledge graphs can be repurposed across multiple use cases (e.g.
|
|
478 |
btn_recommend = gr.Button("Classify & Evaluation")
|
479 |
btn_recommend.click(fn=judge, inputs=in_verbatim, outputs=out_product)
|
480 |
gr.Markdown("""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
481 |
Benefits of Multi Class Classification
|
482 |
==================
|
483 |
- Precision Decision-Making
|
|
|
478 |
btn_recommend = gr.Button("Classify & Evaluation")
|
479 |
btn_recommend.click(fn=judge, inputs=in_verbatim, outputs=out_product)
|
480 |
gr.Markdown("""
|
481 |
+
Example Output
|
482 |
+
===========
|
483 |
+
```
|
484 |
+
{
|
485 |
+
"texts": [
|
486 |
+
"\"The online portal makes managing my mortgage payments so convenient.\"",
|
487 |
+
"\"RBC offer great mortgage for my home with competitive rate thank you\"",
|
488 |
+
"\"Low interest rate compared to other cards I’ve used. Highly recommend for responsible spenders.\"",
|
489 |
+
"\"The mobile check deposit feature saves me so much time. Banking made easy!\"",
|
490 |
+
"\"Affordable premiums with great coverage. Switched from my old provider and saved!\""
|
491 |
+
],
|
492 |
+
"predictions": [
|
493 |
+
[
|
494 |
+
{
|
495 |
+
"chain_of_thought": [
|
496 |
+
"The customer mentions managing mortgage payments online, which directly relates to the 'online' tag.",
|
497 |
+
"There is no mention or implication of card, cars, insurance, or any other tags in the text."
|
498 |
+
],
|
499 |
+
"name": "online",
|
500 |
+
"id": 0,
|
501 |
+
"confidence": 1.0
|
502 |
+
}
|
503 |
+
],
|
504 |
+
[
|
505 |
+
{
|
506 |
+
"chain_of_thought": [
|
507 |
+
"The customer explicitly mentions 'mortgage for my home', which directly corresponds to the tag name 'mortgage'.",
|
508 |
+
"There is no mention of online, card, cars, or insurance in the text.",
|
509 |
+
"Therefore, we can confidently apply the mortgage tag."
|
510 |
+
],
|
511 |
+
"name": "mortgage",
|
512 |
+
"id": 3,
|
513 |
+
"confidence": 1.0
|
514 |
+
}
|
515 |
+
],
|
516 |
+
[
|
517 |
+
{
|
518 |
+
"chain_of_thought": [
|
519 |
+
"The customer mentions a low interest rate and compares it to other cards they have used. This indicates the text is related to a card product.",
|
520 |
+
"There is no mention of online services, cars, mortgage, or insurance in the text."
|
521 |
+
],
|
522 |
+
"name": "card",
|
523 |
+
"id": 1,
|
524 |
+
"confidence": 0.9
|
525 |
+
}
|
526 |
+
],
|
527 |
+
[
|
528 |
+
{
|
529 |
+
"chain_of_thought": [
|
530 |
+
"The customer explicitly mentions the mobile check deposit feature which is related to online banking services.",
|
531 |
+
"There is a Tag with id 0 named 'online' that matches the content of the text."
|
532 |
+
],
|
533 |
+
"name": "online",
|
534 |
+
"id": 0,
|
535 |
+
"confidence": 1.0
|
536 |
+
}
|
537 |
+
],
|
538 |
+
[
|
539 |
+
{
|
540 |
+
"chain_of_thought": [
|
541 |
+
"The customer mentions 'premiums' and 'coverage', which are related to insurance products. There is a tag named 'insurance' with id 4, so we can
|
542 |
+
tag this text with 'insurance'.",
|
543 |
+
"There's no mention of online services, cards, cars, or mortgages in the text."
|
544 |
+
],
|
545 |
+
"name": "insurance",
|
546 |
+
"id": 4,
|
547 |
+
"confidence": 0.9
|
548 |
+
}
|
549 |
+
]
|
550 |
+
],
|
551 |
+
"judgment": [
|
552 |
+
[
|
553 |
+
{
|
554 |
+
"thought": "The reasoning states that the customer mentioned managing mortgage payments online. The answer provided is 'online'. Since the context
|
555 |
+
explicitly stated that the topic was about online management, it logically follows that 'online' would be the correct and relevant response.",
|
556 |
+
"justification": "The reasoning directly connects the mention of 'managing mortgage payments online' to the answer 'online', making the logic sound
|
557 |
+
. There are no other tags or concepts mentioned that could have influenced this answer, so the connection is clear and valid.",
|
558 |
+
"logical": true
|
559 |
+
}
|
560 |
+
],
|
561 |
+
[
|
562 |
+
{
|
563 |
+
"thought": "<thought>Given that the reasoning explicitly states 'mortgage for my home' and directly corresponds to the tag name 'mortgage', and the
|
564 |
+
re's no mention of other financial products like online, card, cars, or insurance, it is logical to conclude that the answer 'mortgage' is correct. The con
|
565 |
+
text provided supports this by not contradicting the reasoning.</thought>",
|
566 |
+
"justification": "<justification>The reasoning clearly states a direct match between the customer's statement and the tag name 'mortgage'. There ar
|
567 |
+
e no conflicting elements in the text, making the connection sound and valid. Therefore, it is logical that the answer 'mortgage' is relevant to the given
|
568 |
+
context.</justification>",
|
569 |
+
"logical": true
|
570 |
+
}
|
571 |
+
],
|
572 |
+
[
|
573 |
+
{
|
574 |
+
"thought": "<thought>Given that the reasoning states there's a low interest rate mentioned and comparison to other cards, it logically follows that
|
575 |
+
'card' would be an appropriate answer. The context, although incomplete, aligns with the reasoning as it pertains to card products.</thought>",
|
576 |
+
"justification": "<justification>The reasoning correctly identifies the topic of discussion (cards) based on key phrases like 'low interest rate' a
|
577 |
+
nd 'comparison to other cards'. Since the answer provided is 'card', which directly corresponds to this context, the logical connection between the reasoni
|
578 |
+
ng and the answer is valid.</justification>",
|
579 |
+
"logical": true
|
580 |
+
}
|
581 |
+
],
|
582 |
+
[
|
583 |
+
{
|
584 |
+
"thought": "The reasoning states that the customer mentioned the mobile check deposit feature, which is related to online banking services. The con
|
585 |
+
text provided a tag with id '0' named 'online', and the answer given is 'online'. This directly matches the content of the text, making it relevant.",
|
586 |
+
"justification": "Since the context provides a clear connection between the customer's mention of mobile check deposit (related to online banking)
|
587 |
+
and the tag 'online', the answer 'online' is logically derived from this reasoning. The direct match in terms of content makes the logical link valid and s
|
588 |
+
ound.",
|
589 |
+
"logical": true
|
590 |
+
}
|
591 |
+
],
|
592 |
+
[
|
593 |
+
{
|
594 |
+
"thought": "<thought> The reasoning states that the context mentions 'premiums' and 'coverage', which are related to insurance. It also notes the p
|
595 |
+
resence of an 'insurance' tag with id 4, suggesting this should be tagged as such. The answer provided is 'insurance', directly matching the reasoning's co
|
596 |
+
nclusion. There is no mention in the text or reasoning that contradicts this.</thought>",
|
597 |
+
"justification": "<justification> The reasoning and the answer are logically consistent because they both point to the same key term, 'insurance'.
|
598 |
+
The presence of relevant terms like 'premiums' and 'coverage', along with the explicit tag reference, support a logical connection between the context and
|
599 |
+
the answer. There is no indication that any other services or products mentioned in the reasoning (like online services, cards, cars, or mortgages) are pre
|
600 |
+
sent in the text.</justification>",
|
601 |
+
"logical": true
|
602 |
+
}
|
603 |
+
]
|
604 |
+
]
|
605 |
+
}
|
606 |
+
```
|
607 |
Benefits of Multi Class Classification
|
608 |
==================
|
609 |
- Precision Decision-Making
|
classify.py
CHANGED
@@ -8,12 +8,11 @@ import os
|
|
8 |
|
9 |
|
10 |
from groq import AsyncGroq
|
11 |
-
# Initialize with API key
|
12 |
-
client = AsyncGroq(api_key=os.getenv("GROQ_API_KEY"))
|
13 |
|
14 |
# Enable instructor patches for Groq client
|
15 |
-
client = instructor.from_groq(
|
16 |
-
|
|
|
17 |
import openai
|
18 |
client = instructor.from_openai(
|
19 |
openai.AsyncOpenAI(
|
@@ -22,7 +21,7 @@ client = instructor.from_openai(
|
|
22 |
),
|
23 |
mode=instructor.Mode.JSON,
|
24 |
)
|
25 |
-
|
26 |
llm = 'llama-3.1-8b-instant' if os.getenv("GROQ_API_KEY") else "qwen2.5" #"gemma3:12b" #"llama3.2" #"deepseek-r1"
|
27 |
|
28 |
|
@@ -35,9 +34,10 @@ class Tag(BaseModel):
|
|
35 |
default=0.5,
|
36 |
ge=0,
|
37 |
le=1,
|
38 |
-
description="The confidence of the prediction(id, name) for the text, 0 is low, 1 is high"
|
39 |
)
|
40 |
|
|
|
41 |
@field_validator('confidence', mode="after")
|
42 |
@classmethod
|
43 |
def high_confidence(cls, c:float):
|
@@ -45,6 +45,7 @@ class Tag(BaseModel):
|
|
45 |
if c < 0.6:
|
46 |
raise ValueError(f"low confidence `{c}` ")
|
47 |
return c
|
|
|
48 |
|
49 |
@model_validator(mode="after")
|
50 |
def validate_ids(self, info: ValidationInfo):
|
@@ -109,16 +110,20 @@ async def tag_single_request(text: str, tags: List[Tag]) -> Iterable[Tag]:
|
|
109 |
messages=[
|
110 |
{
|
111 |
"role": "system",
|
112 |
-
"content": """You are a world-class text tagging system for customer feedback in the banking industry to classify banking product/services.
|
113 |
-
"""
|
114 |
},
|
115 |
-
{"role": "user", "content": f"""Create minimum multiple Tag according to instruction most appropriate for the following text:
|
116 |
-
|
|
|
|
|
|
|
|
|
117 |
Here are the allowed Tag(id, name), do not use any other Tag than these: {allowed_tags_str}
|
118 |
Tag the name based on fact stated and directly mention in the text. Do not guess the name, Do not tag if tag not mention in the text. Do not use implication.
|
119 |
Calculate the newly created Tag's confidence that Tag fit to the text
|
120 |
|
121 |
For each question, show your step-by-step thinking under 'chain_of_thought' in list of string, then clearly state your final answer under 'name'.
|
|
|
122 |
""" },
|
123 |
|
124 |
],
|
@@ -134,19 +139,24 @@ async def tag_request(request: TagRequest) -> TagResponse:
|
|
134 |
predictions = await asyncio.gather(
|
135 |
*[tag_single_request(text, request.tags) for text in request.texts]
|
136 |
)
|
|
|
137 |
pred_dedup=[]
|
138 |
for tags in predictions:
|
139 |
if tags is not None:
|
140 |
dedup=[]
|
141 |
-
#filter(lambda x: x
|
142 |
-
|
|
|
|
|
|
|
143 |
if len(tags_s)>0:
|
144 |
dedup.append(tags_s[0])
|
145 |
for j in range(1,len(tags_s)):
|
146 |
if tags_s[j-1].name!=tags_s[j].name:
|
147 |
dedup.append(tags_s[j])
|
148 |
|
149 |
-
|
|
|
150 |
else:
|
151 |
pred_dedup.append(None)
|
152 |
|
@@ -166,11 +176,9 @@ tags = [
|
|
166 |
|
167 |
|
168 |
texts = """
|
169 |
-
"The online portal makes managing my mortgage payments so convenient."
|
170 |
-
;"RBC offer great mortgage for my home with competitive rate thank you";
|
171 |
"Low interest rate compared to other cards I’ve used. Highly recommend for responsible spenders.";
|
172 |
"The mobile check deposit feature saves me so much time. Banking made easy!";
|
173 |
-
"Affordable premiums with great coverage. Switched from my old provider and saved!"
|
174 |
"""
|
175 |
|
176 |
def judge_response(response):
|
|
|
8 |
|
9 |
|
10 |
from groq import AsyncGroq
|
|
|
|
|
11 |
|
12 |
# Enable instructor patches for Groq client
|
13 |
+
#client = instructor.from_groq(AsyncGroq(api_key=os.getenv("GROQ_API_KEY")))
|
14 |
+
'''
|
15 |
+
|
16 |
import openai
|
17 |
client = instructor.from_openai(
|
18 |
openai.AsyncOpenAI(
|
|
|
21 |
),
|
22 |
mode=instructor.Mode.JSON,
|
23 |
)
|
24 |
+
'''
|
25 |
llm = 'llama-3.1-8b-instant' if os.getenv("GROQ_API_KEY") else "qwen2.5" #"gemma3:12b" #"llama3.2" #"deepseek-r1"
|
26 |
|
27 |
|
|
|
34 |
default=0.5,
|
35 |
ge=0,
|
36 |
le=1,
|
37 |
+
description="The confidence of the prediction(id, name) for the text, 0 is low, 1 is high"
|
38 |
)
|
39 |
|
40 |
+
"""
|
41 |
@field_validator('confidence', mode="after")
|
42 |
@classmethod
|
43 |
def high_confidence(cls, c:float):
|
|
|
45 |
if c < 0.6:
|
46 |
raise ValueError(f"low confidence `{c}` ")
|
47 |
return c
|
48 |
+
"""
|
49 |
|
50 |
@model_validator(mode="after")
|
51 |
def validate_ids(self, info: ValidationInfo):
|
|
|
110 |
messages=[
|
111 |
{
|
112 |
"role": "system",
|
113 |
+
"content": """You are a world-class text tagging system for customer feedback in the banking industry to classify banking product/services. """
|
|
|
114 |
},
|
115 |
+
{"role": "user", "content": f"""Create minimum multiple Tag according to instruction most appropriate for the following text:
|
116 |
+
< Text >
|
117 |
+
{text}
|
118 |
+
</ Text>
|
119 |
+
|
120 |
+
< Instruction >
|
121 |
Here are the allowed Tag(id, name), do not use any other Tag than these: {allowed_tags_str}
|
122 |
Tag the name based on fact stated and directly mention in the text. Do not guess the name, Do not tag if tag not mention in the text. Do not use implication.
|
123 |
Calculate the newly created Tag's confidence that Tag fit to the text
|
124 |
|
125 |
For each question, show your step-by-step thinking under 'chain_of_thought' in list of string, then clearly state your final answer under 'name'.
|
126 |
+
</ Instruction >
|
127 |
""" },
|
128 |
|
129 |
],
|
|
|
139 |
predictions = await asyncio.gather(
|
140 |
*[tag_single_request(text, request.tags) for text in request.texts]
|
141 |
)
|
142 |
+
|
143 |
pred_dedup=[]
|
144 |
for tags in predictions:
|
145 |
if tags is not None:
|
146 |
dedup=[]
|
147 |
+
#filter(lambda x: x>5, range(10))
|
148 |
+
t=list(filter(lambda x: x.confidence > 0.7, [tag async for tag in tags]))
|
149 |
+
#tags_s=set((n.name) for n in t) #sorted(t, key=lambda x: (x.name, x.confidence))
|
150 |
+
pred_dedup.append(t)
|
151 |
+
"""
|
152 |
if len(tags_s)>0:
|
153 |
dedup.append(tags_s[0])
|
154 |
for j in range(1,len(tags_s)):
|
155 |
if tags_s[j-1].name!=tags_s[j].name:
|
156 |
dedup.append(tags_s[j])
|
157 |
|
158 |
+
|
159 |
+
"""
|
160 |
else:
|
161 |
pred_dedup.append(None)
|
162 |
|
|
|
176 |
|
177 |
|
178 |
texts = """
|
179 |
+
"The online portal makes managing my mortgage payments so convenient.";
|
|
|
180 |
"Low interest rate compared to other cards I’ve used. Highly recommend for responsible spenders.";
|
181 |
"The mobile check deposit feature saves me so much time. Banking made easy!";
|
|
|
182 |
"""
|
183 |
|
184 |
def judge_response(response):
|
judge.py
CHANGED
@@ -8,10 +8,9 @@ import os
|
|
8 |
|
9 |
from groq import AsyncGroq
|
10 |
# Initialize with API key
|
11 |
-
client = AsyncGroq(api_key=os.getenv("GROQ_API_KEY"))
|
12 |
|
13 |
# Enable instructor patches for Groq client
|
14 |
-
client = instructor.from_groq(
|
15 |
|
16 |
"""
|
17 |
client = instructor.from_openai(
|
|
|
8 |
|
9 |
from groq import AsyncGroq
|
10 |
# Initialize with API key
|
|
|
11 |
|
12 |
# Enable instructor patches for Groq client
|
13 |
+
client = instructor.from_groq(AsyncGroq(api_key=os.getenv("GROQ_API_KEY")))
|
14 |
|
15 |
"""
|
16 |
client = instructor.from_openai(
|