18
18
# pylint: disable=E1101
19
19
20
20
import os
21
- from typing import Tuple , Literal , Optional
21
+ from typing import AsyncGenerator , Tuple , Literal , Optional
22
22
23
23
import gradio as gr
24
24
import pandas as pd
25
25
from gradio .utils import NamedString
26
26
27
27
from hugegraph_llm .config import resource_path , prompt , huge_settings , llm_settings
28
28
from hugegraph_llm .operators .graph_rag_task import RAGPipeline
29
+ from hugegraph_llm .operators .llm_op .answer_synthesize import AnswerSynthesize
29
30
from hugegraph_llm .utils .log import log
30
31
31
32
@@ -56,25 +57,10 @@ def rag_answer(
56
57
4. Synthesize the final answer.
57
58
5. Run the pipeline and return the results.
58
59
"""
59
-
60
- gremlin_prompt = gremlin_prompt or prompt .gremlin_generate_prompt
61
- should_update_prompt = (
62
- prompt .default_question != text
63
- or prompt .answer_prompt != answer_prompt
64
- or prompt .keywords_extract_prompt != keywords_extract_prompt
65
- or prompt .gremlin_generate_prompt != gremlin_prompt
66
- or prompt .custom_rerank_info != custom_related_information
67
- )
68
- if should_update_prompt :
69
- prompt .custom_rerank_info = custom_related_information
70
- prompt .default_question = text
71
- prompt .answer_prompt = answer_prompt
72
- prompt .keywords_extract_prompt = keywords_extract_prompt
73
- prompt .gremlin_generate_prompt = gremlin_prompt
74
- prompt .update_yaml_file ()
75
-
76
- vector_search = vector_only_answer or graph_vector_answer
77
- graph_search = graph_only_answer or graph_vector_answer
60
+ graph_search , gremlin_prompt , vector_search = update_ui_configs (answer_prompt , custom_related_information ,
61
+ graph_only_answer , graph_vector_answer ,
62
+ gremlin_prompt , keywords_extract_prompt , text ,
63
+ vector_only_answer )
78
64
if raw_answer is False and not vector_search and not graph_search :
79
65
gr .Warning ("Please select at least one generate mode." )
80
66
return "" , "" , "" , ""
@@ -121,6 +107,106 @@ def rag_answer(
121
107
raise gr .Error (f"An unexpected error occurred: { str (e )} " )
122
108
123
109
110
+ def update_ui_configs (answer_prompt , custom_related_information , graph_only_answer , graph_vector_answer , gremlin_prompt ,
111
+ keywords_extract_prompt , text , vector_only_answer ):
112
+ gremlin_prompt = gremlin_prompt or prompt .gremlin_generate_prompt
113
+ should_update_prompt = (
114
+ prompt .default_question != text
115
+ or prompt .answer_prompt != answer_prompt
116
+ or prompt .keywords_extract_prompt != keywords_extract_prompt
117
+ or prompt .gremlin_generate_prompt != gremlin_prompt
118
+ or prompt .custom_rerank_info != custom_related_information
119
+ )
120
+ if should_update_prompt :
121
+ prompt .custom_rerank_info = custom_related_information
122
+ prompt .default_question = text
123
+ prompt .answer_prompt = answer_prompt
124
+ prompt .keywords_extract_prompt = keywords_extract_prompt
125
+ prompt .gremlin_generate_prompt = gremlin_prompt
126
+ prompt .update_yaml_file ()
127
+ vector_search = vector_only_answer or graph_vector_answer
128
+ graph_search = graph_only_answer or graph_vector_answer
129
+ return graph_search , gremlin_prompt , vector_search
130
+
131
+
132
+ async def rag_answer_streaming (
133
+ text : str ,
134
+ raw_answer : bool ,
135
+ vector_only_answer : bool ,
136
+ graph_only_answer : bool ,
137
+ graph_vector_answer : bool ,
138
+ graph_ratio : float ,
139
+ rerank_method : Literal ["bleu" , "reranker" ],
140
+ near_neighbor_first : bool ,
141
+ custom_related_information : str ,
142
+ answer_prompt : str ,
143
+ keywords_extract_prompt : str ,
144
+ gremlin_tmpl_num : Optional [int ] = 2 ,
145
+ gremlin_prompt : Optional [str ] = None ,
146
+ ) -> AsyncGenerator [Tuple [str , str , str , str ], None ]:
147
+ """
148
+ Generate an answer using the RAG (Retrieval-Augmented Generation) pipeline.
149
+ 1. Initialize the RAGPipeline.
150
+ 2. Select vector search or graph search based on parameters.
151
+ 3. Merge, deduplicate, and rerank the results.
152
+ 4. Synthesize the final answer.
153
+ 5. Run the pipeline and return the results.
154
+ """
155
+
156
+ graph_search , gremlin_prompt , vector_search = update_ui_configs (answer_prompt , custom_related_information ,
157
+ graph_only_answer , graph_vector_answer ,
158
+ gremlin_prompt , keywords_extract_prompt , text ,
159
+ vector_only_answer )
160
+ if raw_answer is False and not vector_search and not graph_search :
161
+ gr .Warning ("Please select at least one generate mode." )
162
+ yield "" , "" , "" , ""
163
+ return
164
+
165
+ rag = RAGPipeline ()
166
+ if vector_search :
167
+ rag .query_vector_index ()
168
+ if graph_search :
169
+ rag .extract_keywords (extract_template = keywords_extract_prompt ).keywords_to_vid ().import_schema (
170
+ huge_settings .graph_name
171
+ ).query_graphdb (
172
+ num_gremlin_generate_example = gremlin_tmpl_num ,
173
+ gremlin_prompt = gremlin_prompt ,
174
+ )
175
+ rag .merge_dedup_rerank (
176
+ graph_ratio ,
177
+ rerank_method ,
178
+ near_neighbor_first ,
179
+ )
180
+ # rag.synthesize_answer(raw_answer, vector_only_answer, graph_only_answer, graph_vector_answer, answer_prompt)
181
+
182
+ try :
183
+ context = rag .run (verbose = True , query = text , vector_search = vector_search , graph_search = graph_search )
184
+ if context .get ("switch_to_bleu" ):
185
+ gr .Warning ("Online reranker fails, automatically switches to local bleu rerank." )
186
+ answer_synthesize = AnswerSynthesize (
187
+ raw_answer = raw_answer ,
188
+ vector_only_answer = vector_only_answer ,
189
+ graph_only_answer = graph_only_answer ,
190
+ graph_vector_answer = graph_vector_answer ,
191
+ prompt_template = answer_prompt ,
192
+ )
193
+ async for context in answer_synthesize .run_streaming (context ):
194
+ if context .get ("switch_to_bleu" ):
195
+ gr .Warning ("Online reranker fails, automatically switches to local bleu rerank." )
196
+ yield (
197
+ context .get ("raw_answer" , "" ),
198
+ context .get ("vector_only_answer" , "" ),
199
+ context .get ("graph_only_answer" , "" ),
200
+ context .get ("graph_vector_answer" , "" ),
201
+ )
202
+ except ValueError as e :
203
+ log .critical (e )
204
+ raise gr .Error (str (e ))
205
+ except Exception as e :
206
+ log .critical (e )
207
+ raise gr .Error (f"An unexpected error occurred: { str (e )} " )
208
+
209
+
124
210
def create_rag_block ():
125
211
# pylint: disable=R0915 (too-many-statements),C0301
126
212
gr .Markdown ("""## 1. HugeGraph RAG Query""" )
@@ -130,13 +216,17 @@ def create_rag_block():
130
216
131
217
# TODO: Only support inline formula now. Should support block formula
132
218
gr .Markdown ("Basic LLM Answer" , elem_classes = "output-box-label" )
133
- raw_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True , latex_delimiters = [{"left" :"$" , "right" :"$" , "display" :False }])
219
+ raw_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True ,
220
+ latex_delimiters = [{"left" : "$" , "right" : "$" , "display" : False }])
134
221
gr .Markdown ("Vector-only Answer" , elem_classes = "output-box-label" )
135
- vector_only_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True , latex_delimiters = [{"left" :"$" , "right" :"$" , "display" :False }])
222
+ vector_only_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True ,
223
+ latex_delimiters = [{"left" : "$" , "right" : "$" , "display" : False }])
136
224
gr .Markdown ("Graph-only Answer" , elem_classes = "output-box-label" )
137
- graph_only_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True , latex_delimiters = [{"left" :"$" , "right" :"$" , "display" :False }])
225
+ graph_only_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True ,
226
+ latex_delimiters = [{"left" : "$" , "right" : "$" , "display" : False }])
138
227
gr .Markdown ("Graph-Vector Answer" , elem_classes = "output-box-label" )
139
- graph_vector_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True , latex_delimiters = [{"left" :"$" , "right" :"$" , "display" :False }])
228
+ graph_vector_out = gr .Markdown (elem_classes = "output-box" , show_copy_button = True ,
229
+ latex_delimiters = [{"left" : "$" , "right" : "$" , "display" : False }])
140
230
141
231
answer_prompt_input = gr .Textbox (
142
232
value = prompt .answer_prompt , label = "Query Prompt" , show_copy_button = True , lines = 7
@@ -184,7 +274,7 @@ def toggle_slider(enable):
184
274
btn = gr .Button ("Answer Question" , variant = "primary" )
185
275
186
276
btn .click ( # pylint: disable=no-member
187
- fn = rag_answer ,
277
+ fn = rag_answer_streaming ,
188
278
inputs = [
189
279
inp ,
190
280
raw_radio ,
@@ -254,13 +344,13 @@ def several_rag_answer(
254
344
is_vector_only_answer : bool ,
255
345
is_graph_only_answer : bool ,
256
346
is_graph_vector_answer : bool ,
257
- graph_ratio : float ,
258
- rerank_method : Literal ["bleu" , "reranker" ],
259
- near_neighbor_first : bool ,
260
- custom_related_information : str ,
347
+ graph_ratio_ui : float ,
348
+ rerank_method_ui : Literal ["bleu" , "reranker" ],
349
+ near_neighbor_first_ui : bool ,
350
+ custom_related_information_ui : str ,
261
351
answer_prompt : str ,
262
352
keywords_extract_prompt : str ,
263
- answer_max_line_count : int = 1 ,
353
+ answer_max_line_count_ui : int = 1 ,
264
354
progress = gr .Progress (track_tqdm = True ),
265
355
):
266
356
df = pd .read_excel (questions_path , dtype = str )
@@ -273,10 +363,10 @@ def several_rag_answer(
273
363
is_vector_only_answer ,
274
364
is_graph_only_answer ,
275
365
is_graph_vector_answer ,
276
- graph_ratio ,
277
- rerank_method ,
278
- near_neighbor_first ,
279
- custom_related_information ,
366
+ graph_ratio_ui ,
367
+ rerank_method_ui ,
368
+ near_neighbor_first_ui ,
369
+ custom_related_information_ui ,
280
370
answer_prompt ,
281
371
keywords_extract_prompt ,
282
372
)
@@ -285,9 +375,9 @@ def several_rag_answer(
285
375
df .at [index , "Graph-only Answer" ] = graph_only_answer
286
376
df .at [index , "Graph-Vector Answer" ] = graph_vector_answer
287
377
progress ((index + 1 , total_rows ))
288
- answers_path = os .path .join (resource_path , "demo" , "questions_answers.xlsx" )
289
- df .to_excel (answers_path , index = False )
290
- return df .head (answer_max_line_count ), answers_path
378
+ answers_path_ui = os .path .join (resource_path , "demo" , "questions_answers.xlsx" )
379
+ df .to_excel (answers_path_ui , index = False )
380
+ return df .head (answer_max_line_count_ui ), answers_path_ui
291
381
292
382
with gr .Row ():
293
383
with gr .Column ():
0 commit comments