Skip to content

Commit bb8965e

Browse files
committed
updates
1 parent cf0dc9b commit bb8965e

File tree

5 files changed

+147
-71
lines changed

5 files changed

+147
-71
lines changed

app.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,10 @@ def question_checker():
3838
data = request.json
3939
user_query = data.get("query", "")
4040
validation_result = kgqa.question_checker(user_query)
41-
completeness = feedback = ""
42-
if 'completeness' in validation_result:
43-
completeness = validation_result['completeness']
44-
if 'feedback' in completeness:
45-
feedback = validation_result['feedback']
41+
completeness = validation_result['completeness']
42+
feedback = validation_result['feedback']
4643
if completeness =='complete':
47-
return jsonify({'completeness': True})
44+
return jsonify({'completeness': True, 'feedback': feedback})
4845
else:
4946
return jsonify({'completeness': False, 'feedback': feedback})
5047
except Exception as e:

dblp-nli-app/app/page.tsx

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
"use client";
22
import {useEffect, useState} from "react";
33
import { Card, CardContent } from "@/components/ui/card";
4-
import { Textarea } from "@/components/ui/textarea";
54
import { Button } from "@/components/ui/button";
65
import { Input } from "@/components/ui/input";
76
import {toast, Toaster} from "sonner";
87
import { Loader2 } from "lucide-react";
98
import {MdOutlineThumbDown, MdOutlineThumbUp} from 'react-icons/md';
9+
import Image from "next/image";
10+
import CodeMirror from "@uiw/react-codemirror";
11+
import { StreamLanguage } from "@codemirror/language";
12+
import { sparql } from "@codemirror/legacy-modes/mode/sparql";
13+
import { EditorView } from "@codemirror/view";
1014

1115
interface SPARQLResult {
1216
head: {
@@ -54,11 +58,9 @@ export default function SPARQLQueryApp() {
5458
const [prevUsedEntities, setPrevUsedEntities] = useState<EntityWithType[]>([]);
5559

5660
const exampleQuestions = [
57-
"Top 10 most frequent authors from Germany who have published at the International Semantic Web Conference (ISWC).",
58-
"Which publications from the International Semantic Web Conference are the highly cited?",
61+
"Top 10 most frequent authors who have published at the International Semantic Web Conference (ISWC).",
5962
"Database papers published in the Semantic Web Journal.",
6063
"Who are the highly cited coauthors of Hannah Bast?"
61-
6264
];
6365
const validateQuestion = async (question: string): Promise<{ valid: boolean; feedback?: string }> => {
6466
try {
@@ -164,9 +166,9 @@ export default function SPARQLQueryApp() {
164166
toast.error(`Error generating SPARQL. (${data.error})`);
165167
return;
166168
}
167-
const confidence_string = `# Confidence_score: ${data.confidence_score}`;
169+
// const confidence_string = `# Confidence_score: ${data.confidence_score}`;
168170
const ask_dblp_string = `# ASK-DBLP: ${userQuery}`;
169-
updateSparqlQuery(`${confidence_string}\n${ask_dblp_string} \n${data.sparql}`);
171+
updateSparqlQuery(`${ask_dblp_string} \n${data.sparql}`);
170172
const allEntities: EntityGroup[] = data.linked_entities || [];
171173
const entitiesInSparql = data.entities_used_in_sparql || [];
172174

@@ -289,19 +291,27 @@ export default function SPARQLQueryApp() {
289291
return (
290292
//<div className="max-w-2xl mx-auto p-6 space-y-4">
291293
<div className="max-w-6xl mx-auto overflow-x-auto">
294+
<header className="flex items-center space-x-4 p-4 border-b">
295+
<Image
296+
src="/ask-dblp-logo.png"
297+
alt="ASK DBLP Logo"
298+
width={300}
299+
height={100}
300+
priority
301+
/>
302+
</header>
292303
<Card className="mb-4">
293304
<CardContent className="p-4 space-y-2">
294-
<p className="text-justify text-sm text-gray-600">
305+
<p className="text-justify text-sm text-gray-600 font-bold">
295306
Welcome to ASK-DBLP! <br/> <br/>
296307
ASK-DBLP offers a natural language interface (NLI) that allows users to question the DBLP Knowledge Graph.
297308
The system generates a corresponding SPARQL query, which you can review and edit. Once ready, it executes the query against the DBLP SPARQL endpoint and displays the results. <br/>
298-
299309
</p>
300-
<p className="text-sm text-gray-600">
301-
Type your question or choose from the sample questions below.
310+
<p className="text-sm text-gray-600 font-bold">
311+
302312
</p>
303313
<Input
304-
placeholder="Enter your query"
314+
placeholder="Type your question or select from the sample questions below."
305315
value={userQuery}
306316
onChange={(e) => {
307317
setUserQuery(e.target.value);
@@ -310,11 +320,12 @@ export default function SPARQLQueryApp() {
310320
setEntityLinkingGroups([]);
311321
}}
312322
/>
313-
<div className="flex flex-wrap gap-2">
323+
<div className="overflow-x-auto flex flex-col items-start gap-2 mt-2 py-2 px-1">
314324
{exampleQuestions.map((question, index) => (
315325
<Button
316326
key={index}
317327
variant="outline"
328+
className="text-left w-auto"
318329
onClick={() => handleExampleClick(question)}
319330
>
320331
{question}
@@ -374,11 +385,20 @@ export default function SPARQLQueryApp() {
374385
{sparqlQuery && (
375386
<Card className="mb-4">
376387
<CardContent className="p-4 space-y-2">
377-
<Textarea
378-
className="w-full"
379-
rows={10}
388+
<CodeMirror
380389
value={sparqlQuery}
381-
onChange={(e) => updateSparqlQuery(e.target.value)}
390+
height="300px"
391+
basicSetup={{
392+
lineNumbers: true,
393+
highlightActiveLineGutter: true,
394+
highlightActiveLine: true,
395+
}}
396+
extensions={[
397+
StreamLanguage.define(sparql),
398+
EditorView.lineWrapping,
399+
]}
400+
onChange={(value) => updateSparqlQuery(value)}
401+
theme="light"
382402
/>
383403

384404
<div className="row flex">
@@ -439,13 +459,25 @@ export default function SPARQLQueryApp() {
439459
</thead>
440460
<tbody>
441461
{queryResult.results.bindings.map((binding, rowIndex) => (
442-
<tr key={rowIndex} className="hover:bg-gray-50">
443-
<td className="border border-gray-300 px-4 py-2">{rowIndex + 1}</td>
444-
{queryResult.head.vars.map((varName, colIndex) => (
445-
<td key={colIndex} className="border border-gray-300 px-4 py-2">
446-
{binding[varName]?.value || ""}
447-
</td>
448-
))}
462+
<tr key={rowIndex} className="border-t">
463+
<td className="p-2 text-sm text-gray-600 font-mono">{rowIndex + 1}.</td>
464+
{queryResult.head.vars.map((varName, colIndex) => {
465+
const valueObj = binding[varName];
466+
const value = valueObj?.value || "";
467+
const isUri = valueObj?.type === "uri";
468+
469+
return (
470+
<td key={colIndex} className="p-2 text-sm text-gray-800">
471+
{isUri ? (
472+
<a href={value} target="_blank" rel="noopener noreferrer" className="text-blue-600 underline">
473+
{value}
474+
</a>
475+
) : (
476+
value
477+
)}
478+
</td>
479+
);
480+
})}
449481
</tr>
450482
))}
451483
</tbody>
90.1 KB
Loading

kgqa.py

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,56 @@
99
import utils
1010
import re
1111

12+
def parse_completness_check_result(raw_content):
13+
result = {"completeness": None, "feedback": None}
14+
try:
15+
parsed = json.loads(raw_content)
16+
if isinstance(parsed, dict):
17+
result["completeness"] = parsed.get("completeness")
18+
result["feedback"] = parsed.get("feedback")
19+
return result
20+
except json.JSONDecodeError:
21+
pass
22+
23+
# Step 2: Regex fallback for malformed or escaped JSON-like strings
24+
completeness_match = re.search(r'"completeness"\s*:\s*"([^"]+)"', raw_content)
25+
feedback_match = re.search(r'"feedback"\s*:\s*"([^"]+)"', raw_content)
26+
27+
if completeness_match:
28+
result["completeness"] = completeness_match.group(1).encode().decode("unicode_escape").strip()
29+
30+
if feedback_match:
31+
result["feedback"] = feedback_match.group(1).encode().decode("unicode_escape").strip()
32+
33+
return result
34+
35+
36+
def extract_sparql(response_content):
37+
"""
38+
Extracts a SPARQL query string from LLM output.
39+
Attempts JSON parsing first, then falls back to regex-based extraction.
40+
Args:
41+
response_content (str): Raw LLM output string.
42+
Returns:
43+
str | None: The SPARQL query if found, else None.
44+
"""
45+
try:
46+
data = json.loads(response_content)
47+
sparql = data.get("sparql")
48+
if isinstance(sparql, str) and sparql.strip():
49+
return sparql.strip()
50+
except json.JSONDecodeError:
51+
pass
52+
53+
# Regex fallback (extract string value of "sparql": "...")
54+
match = re.search(r'"sparql"\s*:\s*"((?:[^"\\]|\\.)*)"', response_content)
55+
if match:
56+
sparql_raw = match.group(1)
57+
return bytes(sparql_raw, "utf-8").decode("unicode_escape").strip()
58+
59+
return ""
60+
61+
1262
def clean_label(label, entity_type):
1363
if "Publication" in entity_type:
1464
# Remove everything before and including "et al.: "
@@ -110,15 +160,9 @@ def question_to_sparql(question, llm='chatai'):
110160
all_entities = []
111161
selected_entities = []
112162
prompt = get_question_to_sparql_prompt(question, selected_entities)
113-
# if llm == 'chatgpt':
114-
# sparql = llms.chatgpt(prompt)
115-
# return sparql['sparql']
116-
# sparql_result = llama(prompt)
117163
chatai_llm_model = 'qwen2.5-coder-32b-instruct'
118164
sparql_result, confidence = llms.chatai_models(prompt=prompt, model=chatai_llm_model)
119-
sparql = ''
120-
if 'sparql' in sparql_result:
121-
sparql = sparql_result['sparql']
165+
sparql = extract_sparql(sparql_result)
122166
return sparql, confidence, all_entities, selected_entities
123167
except Exception as e:
124168
logging.error(f"An error occurred during SPARQL Generation: {e}", exc_info=e)
@@ -129,10 +173,9 @@ def question_checker(question):
129173
question_checker_prompt_template = question_checker_prompt.QUESTION_VALIDATION_PROMPT
130174
qc_prompt = question_checker_prompt_template.format(question=question)
131175
chatai_llm_model = 'qwen2.5-coder-32b-instruct'
132-
validation_result = llms.chatai_models(prompt=qc_prompt, model=chatai_llm_model, function_call_flag=2)
133-
# print(validation_result)
134-
# validation_result = llms.chatgpt(qc_prompt, 2)
135-
return validation_result
176+
validation_result, confidence_score = llms.chatai_models(prompt=qc_prompt, model=chatai_llm_model, function_call_flag=2)
177+
parse_validation_result = parse_completness_check_result(validation_result)
178+
return parse_validation_result
136179

137180

138181
if __name__ == '__main__':

llms.py

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -130,46 +130,50 @@ def llama(user_prompt, sys_prompt_string="You are an experienced knowledge graph
130130

131131

132132
def chatai_models(prompt, model, function_call_flag = 1):
133-
function_call = sparql_generation_function
134-
flag = True
135-
if function_call_flag == 2:
136-
function_call = question_completeness_checker
137-
flag = False
138-
elif function_call_flag == 3:
139-
function_call = question_generation_function
140-
flag = False
133+
# function_call = sparql_generation_function
134+
# flag = True
135+
# if function_call_flag == 2:
136+
# function_call = question_completeness_checker
137+
# flag = False
138+
# elif function_call_flag == 3:
139+
# function_call = question_generation_function
140+
# flag = False
141141
api_key = Config.LLMS['chatai']['chatai_api_key']
142142
base_url = Config.LLMS['chatai']['url']
143-
model = model # Config.LLMS['chatai']['model']
143+
model = Config.LLMS['chatai']['model']
144144
client = OpenAI(
145-
api_key=api_key,
146-
base_url=base_url
145+
base_url=base_url,
146+
api_key=api_key
147147
)
148-
# messages = [{"role": "user", "content": prompt}]
149148
messages = [ {"role": "system", "content": "You are an experienced knowledge graph expert."},
150149
{"role": "user", "content": prompt}
151150
]
152-
chat_completion = client.chat.completions.create(
151+
# chat_completion = client.chat.completions.create(
152+
# model=model,
153+
# messages=messages,
154+
# functions=function_call,
155+
# function_call='auto',
156+
# temperature=0,
157+
# logprobs=True
158+
# )
159+
# try:
160+
# if hasattr(chat_completion.choices[0].message, 'function_call') and \
161+
# hasattr(chat_completion.choices[0].message.function_call, 'arguments'):
162+
# args = chat_completion.choices[0].message.function_call.arguments
163+
# else:
164+
# args = chat_completion.choices[0].message.content
165+
# result = json.loads(args)
166+
# logprobs = chat_completion.choices[0].logprobs.content
167+
# confidence_score = compute_confidence_score(logprobs)
168+
# return result, confidence_score
169+
# except Exception as e:
170+
# print(f"An error occurred while generating response: {e}")
171+
# return "", 0.0
172+
response = client.chat.completions.create(
153173
model=model,
154-
messages=messages,
155-
functions=function_call,
156-
function_call='auto',
157-
temperature=0,
158-
logprobs=True
174+
messages=messages
159175
)
160-
try:
161-
if hasattr(chat_completion.choices[0].message, 'function_call') and \
162-
hasattr(chat_completion.choices[0].message.function_call, 'arguments'):
163-
args = chat_completion.choices[0].message.function_call.arguments
164-
else:
165-
args = chat_completion.choices[0].message.content
166-
result = json.loads(args)
167-
logprobs = chat_completion.choices[0].logprobs.content
168-
confidence_score = compute_confidence_score(logprobs)
169-
return result, confidence_score
170-
except Exception as e:
171-
print(f"An error occurred while generating response: {e}")
172-
return "", 0.0
176+
return response.choices[0].message.content, 0.0
173177

174178

175179
def chatgpt(prompt, function_call_flag = 1):

0 commit comments

Comments
 (0)