0shin0/GraphDB_GraphRAG_Workshop
0
1from dotenv import load_dotenv2import os3 4from neo4j import GraphDatabase, basic_auth5import openai6 7from neo4j_graphrag.retrievers import Text2CypherRetriever8from neo4j_graphrag.llm import OpenAILLM9 10from neo4j import GraphDatabase11 12from neo4j_graphrag.generation import GraphRAG13 14import gradio as gr15 16from make_schema import get_schema, format_schema17from content import graphdb_lecture, graphrag_lecture, structure, cypher1, cypher2, cypher3, cypher418 19def ready_gpt(user_api_key):20 try:21 driver = GraphDatabase.driver(22 "bolt://54.205.151.177:7687",23 auth=basic_auth("neo4j", "library-evaluation-twigs"))24 25 llm = OpenAILLM(model_name="gpt-4o", model_params={"temperature": 0}, api_key = user_api_key)26 test_prompt = "Hello! How are you?"27 response = llm.invoke(test_prompt).content28 if response: # LLM 연결 성공29 print(response)30 31 # Neo4j Schema 가져오기 및 포맷32 schema = get_schema("bolt://54.205.151.177:7687", "neo4j", "library-evaluation-twigs")33 neo4j_schema = format_schema(schema)34 35 # LLM INPUT / QUERY 예시36 examples = [37 """USER INPUT: 'Tell me the problem code and question that Olivia solved.'38 QUERY: MATCH (p:Person {name:'Olivia'})-[r:SOLVED]->(q:Question)39 RETURN q.code, q.question LIMIT 10""",40 41 """USER INPUT: 'Can I check the problem codes and questions that Olivia has not solved yet?'42 QUERY: MATCH (p:Person {name:'Olivia'})-[r:UNSOLVED]->(q:Question)43 RETURN q.code, q.question""",44 45 """USER INPUT: 'What is the average score of the questions 4th grade students solved?'46 QUERY: MATCH (g:Grade {grade:'4'})<-[:belongs_to]-(p:Person)-[r:SOLVED]->(q:Question)47 RETURN AVG(r.score) AS avgScore""",48 49 """USER INPUT: 'I want to know which question 4th grade students solved the most.'50 QUERY: MATCH (g:Grade {grade:'4'})<-[:belongs_to]-(p:Person)-[r:SOLVED]->(q:Question)51 RETURN q.code, q.question, COUNT(r) AS solveCount52 ORDER BY solveCount DESC LIMIT 1""",53 54 """USER INPUT: 'What is the question that 4th grade students took the longest time to answer?'55 QUERY: MATCH (g:Grade {grade:'4'})<-[:belongs_to]-(p:Person)-[s:SOLVED]->(q:Question)56 RETURN q.code, q.question, AVG(s.time_taken) AS avgTime57 ORDER BY avgTime DESC LIMIT 1""",58 59 """USER INPUT: 'I would like to know 5 questions related to the major topic of 'Addition and Subtraction of Fractions.'60 QUERY: MATCH (m:MainTopic {name:'Addition and Substraction of Fractions'})-[r:has_question]->(q:Question)61 RETURN q.code, q.question LIMIT 5""",62 63 """USER INPUT: 'Show me the questions of the problems that Olivia has solved, which include feedback?'64 QUERY: MATCH (p:Person {name: 'Olivia'})-[r:SOLVED]->(q:Question)65 WHERE r.feedback IS NOT NULL66 RETURN p, r, q""",67 68 """USER INPUT: '"Can you check how many questions students in 5th grade have solved under the major topic of Divisors and Multiples?'69 QUERY: MATCH (g:Grade {grade:'5'})<-[:belongs_to]-(p:Person)-[s:SOLVED]->(q:Question)<-[:has_question]-(m:MainTopic {name:'Divisors and Multiples'})70 RETURN COUNT(s) AS solveCount"""71 72 """USER INPUT: 'Which major topic should a student who struggles with Division of Fractions?'73 QUERY: MATCH (relatedTopic:MainTopic)-[:precedes*]->(t:MainTopic {name: 'Division of Fractions'})74 RETURN relatedTopic.name;75 """76 77 # """USER INPUT: 'Please recommend questions for Erick's weakest main topic.'78 # QUERY: MATCH (p:Person {name: 'Erick'})-[:SOLVED]->(q:Question)<-[:has_question]-(mt:MainTopic)79 # MATCH (p)-[s:SOLVED]->(q)80 # WITH mt, AVG(s.score) AS avg_score81 # ORDER BY avg_score ASC82 # LIMIT 183 # WITH mt AS LowestAvgMainTopic, avg_score84 # MATCH (p:Person {name: 'Erick'})-[:UNSOLVED]->(q:Question)<-[:has_question]-(LowestAvgMainTopic)85 # RETURN LowestAvgMainTopic.name AS LowestAvgMainTopic, avg_score, q.question AS UnsolvedQuestions86 # """87 ]88 89 # Text2CypherRetriever 초기화90 retriever = Text2CypherRetriever(91 driver=driver,92 llm=llm,93 neo4j_schema=neo4j_schema,94 examples=examples,95 )96 97 # GraphRAG 초기화98 rag = GraphRAG(retriever=retriever, llm=llm)99 100 return {"llm": llm, "retriever": retriever, "rag": rag}, "You have successfully connected!"101 else:102 raise Exception("LLM Connection Failed")103 except Exception as e:104 print(f"Error: {e}")105 return {"llm": None, "retriever": None, "rag": None}, "Please check your API Key!"106 107def generate_query(browser_state, text_input):108 retriever = browser_state["retriever"]109 110 search_result = retriever.search(query_text=text_input)111 return search_result.metadata['cypher']112 113def default_llm(browser_state, message):114 llm = browser_state["llm"]115 116 prompt_text = f"""117 You are an elementary school assistant teacher chatbot. 118 Answer user_input, but if the question is about information in GraphDB, answer the question with detailed information.119 Also, recommend that you state the grade, student name, main topic name, and filtering criteria accurately.120 user_input : {message}121 """122 return llm.invoke(prompt_text).content123 124def intent_detection(browser_state, message):125 llm = browser_state["llm"]126 127 prompt_text = f"""128 Please return True if the given query_text appears to be a question 129 requesting an answer about the grade, student, main topic, or problem. 130 Otherwise, return False.131 query_text : {message}132 """133 return llm.invoke(prompt_text).content == 'True'134 135def response(browser_state, message, chat_history):136 llm = browser_state["llm"]137 138 if(intent_detection(browser_state, message)):139 rag = browser_state["rag"]140 141 rag_result = rag.search(query_text=message142 + "(Please also provide evidence for how you used context in your answer.)"143 , return_context = True)144 chat_history.append((message, rag_result.answer))145 return chat_history, rag_result.retriever_result.metadata['cypher'], rag_result.retriever_result.items146 else:147 llm_result = default_llm(browser_state, message)148 chat_history.append((message, llm_result))149 return chat_history, "Questions were related to grade, student, main topic, question.", llm_result150 151with gr.Blocks(theme=gr.themes.Soft(font=[gr.themes.GoogleFont("Noto Sans Korean")], text_size=gr.themes.sizes.text_lg)) as demo:152 gr.HTML("""153 <div style="text-align: center; max-width: 1000px; margin: 20px auto;">154 <h1>🔗 GraphRAG Hands-on Workshop</h1>155 </div>156 """)157 browser_state = gr.State({"llm": None, "retriever": None, "rag": None})158 159 with gr.Tabs():160 with gr.Tab("API Key"):161 with gr.Row():162 user_api_key = gr.Textbox(label="API Key", placeholder="Please put an API Key.", lines=1)163 api_btn = gr.Button("Upload", variant="primary")164 output_text = gr.Textbox(label="API Key Result", interactive=False)165 api_btn.click(ready_gpt, inputs=user_api_key, outputs = [browser_state, output_text])166 167 with gr.Tab("Note"):168 gr.HTML(169 graphdb_lecture170 )171 172 gr.Markdown(cypher1)173 gr.Markdown(cypher2)174 gr.Markdown(cypher3)175 gr.Markdown(cypher4)176 177 gr.HTML(178 graphrag_lecture179 )180 181 with gr.Tab("DB Structure"):182 gr.HTML(183 structure184 )185 186 # gr.Button(value='Go to GraphDB', link='http://54.205.151.177:7687/', variant='primary')187 188 # with gr.Tab("Example Generator"):189 # with gr.Row():190 # text_input = gr.Textbox(label="Question", placeholder="Please enter your question.", lines=2)191 192 # with gr.Column(scale=0):193 # btn = gr.Button("Generate Cypher Query", variant="primary")194 # clear = gr.Button("Clear")195 196 # output = gr.Textbox(label="Generated Cypher Query", placeholder="Your query will appear here.", lines=6)197 198 # btn.click(generate_query, inputs=[browser_state,text_input], outputs=output)199 # clear.click(lambda: None, None, queue=False)200 201 with gr.Tab("Chatbot"):202 with gr.Row():203 with gr.Column(scale=0):204 generated_query = gr.Textbox(label="Generated Cypher Query")205 query_result = gr.Textbox(label="Search Result")206 207 chatbot = gr.Chatbot()208 209 with gr.Row():210 with gr.Column():211 msg = gr.Textbox(212 placeholder="Please enter your question.",213 label="input",214 )215 with gr.Column(scale=0):216 btn = gr.Button("Submit", variant="primary")217 clear = gr.Button("Clear")218 219 with gr.Row():220 examples = gr.Examples(221 examples=[222 "What's the main topic that third grade students solved questions the most.",223 "Which major topic should a student who struggles with Division of Fractions?",224 ],225 inputs=[msg]226 )227 228 btn.click(fn=response, inputs=[browser_state, msg, chatbot], outputs=[chatbot, generated_query, query_result])229 msg.submit(response, [browser_state, msg, chatbot], [chatbot, generated_query, query_result])230 clear.click(lambda: None, None, msg, queue=False)231 232demo.launch(debug=True, share=True)