Upload app.py
Browse files
app.py
CHANGED
|
@@ -53,8 +53,8 @@ HF_ENDPOINT_URL = "https://evxgv66ksxjlfrts.us-east-1.aws.endpoints.huggingface.
|
|
| 53 |
HF_MODEL = "lmstudio-community/Llama-3.3-70B-Instruct-GGUF" # Correct model name for your endpoint
|
| 54 |
|
| 55 |
# AI Correction Configuration
|
| 56 |
-
MAX_CORRECTION_ATTEMPTS =
|
| 57 |
-
ENABLE_VALIDATION_LOOP =
|
| 58 |
|
| 59 |
# OpenAI client configuration for the endpoint
|
| 60 |
def get_openai_client():
|
|
@@ -168,7 +168,7 @@ def validate_rdf_tool(rdf_content: str, template: str = "monograph") -> dict:
|
|
| 168 |
"conforms": False
|
| 169 |
}
|
| 170 |
|
| 171 |
-
def get_ai_suggestions(validation_results: str, rdf_content: str) -> str:
|
| 172 |
"""
|
| 173 |
Generate AI-powered fix suggestions for invalid RDF/XML.
|
| 174 |
|
|
@@ -178,6 +178,7 @@ def get_ai_suggestions(validation_results: str, rdf_content: str) -> str:
|
|
| 178 |
Args:
|
| 179 |
validation_results (str): The validation error messages
|
| 180 |
rdf_content (str): The original RDF/XML content that failed validation
|
|
|
|
| 181 |
|
| 182 |
Returns:
|
| 183 |
str: Detailed suggestions for fixing the RDF validation issues
|
|
@@ -205,8 +206,12 @@ def get_ai_suggestions(validation_results: str, rdf_content: str) -> str:
|
|
| 205 |
{generate_manual_suggestions(validation_results)}
|
| 206 |
"""
|
| 207 |
|
|
|
|
|
|
|
| 208 |
prompt = f"""You are an expert in RDF/XML and SHACL validation. Analyze the following validation results and provide clear, actionable suggestions for fixing the RDF issues.
|
| 209 |
|
|
|
|
|
|
|
| 210 |
Validation Results:
|
| 211 |
{validation_results}
|
| 212 |
|
|
@@ -224,7 +229,7 @@ Format your response in a helpful, structured way using markdown."""
|
|
| 224 |
# Make API call using OpenAI client
|
| 225 |
print(f"π Making API call to: {HF_ENDPOINT_URL}")
|
| 226 |
print(f"π Using model: {HF_MODEL}")
|
| 227 |
-
print(f"π
|
| 228 |
|
| 229 |
chat_completion = client.chat.completions.create(
|
| 230 |
model=HF_MODEL,
|
|
@@ -241,7 +246,7 @@ Format your response in a helpful, structured way using markdown."""
|
|
| 241 |
|
| 242 |
print("β
API call successful")
|
| 243 |
generated_text = chat_completion.choices[0].message.content
|
| 244 |
-
return f"π€ **AI-Powered Suggestions:**\n\n{generated_text}"
|
| 245 |
|
| 246 |
except Exception as e:
|
| 247 |
logger.error(f"OpenAI/HF Inference Endpoint error: {str(e)}")
|
|
@@ -280,7 +285,7 @@ def extract_rdf_from_response(response: str) -> str:
|
|
| 280 |
# If no code blocks found, return the response as-is
|
| 281 |
return response
|
| 282 |
|
| 283 |
-
def get_ai_correction(validation_results: str, rdf_content: str, template: str = 'monograph', max_attempts: int = None) -> str:
|
| 284 |
"""
|
| 285 |
Generate AI-powered corrected RDF/XML based on validation errors.
|
| 286 |
|
|
@@ -293,6 +298,7 @@ def get_ai_correction(validation_results: str, rdf_content: str, template: str =
|
|
| 293 |
rdf_content (str): The original invalid RDF/XML content
|
| 294 |
template (str): The validation template to use
|
| 295 |
max_attempts (int): Maximum number of attempts to generate valid RDF (uses MAX_CORRECTION_ATTEMPTS if None)
|
|
|
|
| 296 |
|
| 297 |
Returns:
|
| 298 |
str: Corrected RDF/XML that should pass validation
|
|
@@ -323,10 +329,26 @@ def get_ai_correction(validation_results: str, rdf_content: str, template: str =
|
|
| 323 |
|
| 324 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
| 325 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 326 |
# Try multiple attempts to generate valid RDF
|
| 327 |
for attempt in range(max_attempts):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 328 |
prompt = f"""You are an expert in RDF/XML. Fix the following RDF/XML based on the validation errors provided.
|
| 329 |
|
|
|
|
|
|
|
| 330 |
Validation Errors:
|
| 331 |
{validation_results}
|
| 332 |
|
|
@@ -342,53 +364,59 @@ Please provide the corrected RDF/XML that addresses all validation issues.
|
|
| 342 |
- Add any missing required properties
|
| 343 |
- Fix any syntax or structural issues"""
|
| 344 |
|
| 345 |
-
|
| 346 |
-
|
| 347 |
-
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
# Validate the corrected RDF using the same template
|
| 370 |
-
conforms, new_results = validate_rdf(corrected_rdf.encode('utf-8'), template)
|
| 371 |
-
|
| 372 |
-
if conforms:
|
| 373 |
-
print(f"β
Correction validated successfully on attempt {attempt + 1}")
|
| 374 |
-
return f"""<!-- AI-generated correction validated successfully -->
|
| 375 |
-
{corrected_rdf}"""
|
| 376 |
-
else:
|
| 377 |
-
print(f"β Correction attempt {attempt + 1} still has validation errors")
|
| 378 |
-
# Update validation_results for next attempt
|
| 379 |
-
validation_results = new_results
|
| 380 |
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
|
| 390 |
-
|
| 391 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 392 |
<!-- Please correct manually using the validation results as a guide -->
|
| 393 |
|
| 394 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
|
@@ -461,7 +489,7 @@ MANUAL CORRECTION STEPS:
|
|
| 461 |
5. Validate data types
|
| 462 |
-->"""
|
| 463 |
|
| 464 |
-
def validate_rdf_interface(rdf_content: str, template: str, use_ai: bool = True):
|
| 465 |
"""
|
| 466 |
Main validation function for Gradio interface and MCP server.
|
| 467 |
|
|
@@ -473,6 +501,7 @@ def validate_rdf_interface(rdf_content: str, template: str, use_ai: bool = True)
|
|
| 473 |
rdf_content (str): The RDF/XML content to validate
|
| 474 |
template (str): Validation template to use ('monograph' or 'custom')
|
| 475 |
use_ai (bool): Whether to enable AI-powered suggestions and corrections
|
|
|
|
| 476 |
|
| 477 |
Returns:
|
| 478 |
tuple: (status, results_text, suggestions, corrected_rdf) containing:
|
|
@@ -493,16 +522,36 @@ def validate_rdf_interface(rdf_content: str, template: str, use_ai: bool = True)
|
|
| 493 |
status = result["status"]
|
| 494 |
results_text = result["results"]
|
| 495 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 496 |
if result["conforms"]:
|
| 497 |
suggestions = "β
No issues found! Your RDF/XML is valid according to the selected template."
|
| 498 |
corrected_rdf = "β
Your RDF/XML is already valid - no corrections needed!"
|
| 499 |
else:
|
| 500 |
if use_ai:
|
| 501 |
-
|
| 502 |
-
|
|
|
|
| 503 |
else:
|
| 504 |
-
suggestions = generate_manual_suggestions(
|
| 505 |
-
corrected_rdf = generate_manual_correction_hints(
|
| 506 |
|
| 507 |
return status, results_text, suggestions, corrected_rdf
|
| 508 |
|
|
@@ -626,6 +675,12 @@ def create_interface():
|
|
| 626 |
value=True,
|
| 627 |
info="Enable AI-powered suggestions and corrections"
|
| 628 |
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
|
| 630 |
validate_btn = gr.Button("π Validate RDF", variant="primary", size="lg")
|
| 631 |
|
|
@@ -679,16 +734,16 @@ def create_interface():
|
|
| 679 |
# Event handlers
|
| 680 |
validate_btn.click(
|
| 681 |
fn=validate_rdf_interface,
|
| 682 |
-
inputs=[rdf_input, template_dropdown, use_ai_checkbox],
|
| 683 |
outputs=[status_output, results_output, suggestions_output, corrected_output]
|
| 684 |
)
|
| 685 |
|
| 686 |
-
#
|
| 687 |
-
rdf_input.change(
|
| 688 |
-
|
| 689 |
-
|
| 690 |
-
|
| 691 |
-
)
|
| 692 |
|
| 693 |
# Example buttons
|
| 694 |
example1_btn.click(
|
|
@@ -758,7 +813,7 @@ def create_interface():
|
|
| 758 |
- β
Real-time RDF/XML validation against SHACL schemas
|
| 759 |
- π€ AI-powered error suggestions and corrections (with HF Inference Endpoint)
|
| 760 |
- π Built-in examples and templates
|
| 761 |
-
-
|
| 762 |
- π Copy results with one click
|
| 763 |
|
| 764 |
**Note:** AI features require a valid Hugging Face API key (HF_API_KEY) set as a Secret. Manual suggestions are provided as fallback.
|
|
|
|
| 53 |
HF_MODEL = "lmstudio-community/Llama-3.3-70B-Instruct-GGUF" # Correct model name for your endpoint
|
| 54 |
|
| 55 |
# AI Correction Configuration
|
| 56 |
+
MAX_CORRECTION_ATTEMPTS = 2 # Reduced from 3 to speed up processing
|
| 57 |
+
ENABLE_VALIDATION_LOOP = False # Disable validation loop to prevent hanging
|
| 58 |
|
| 59 |
# OpenAI client configuration for the endpoint
|
| 60 |
def get_openai_client():
|
|
|
|
| 168 |
"conforms": False
|
| 169 |
}
|
| 170 |
|
| 171 |
+
def get_ai_suggestions(validation_results: str, rdf_content: str, include_warnings: bool = False) -> str:
|
| 172 |
"""
|
| 173 |
Generate AI-powered fix suggestions for invalid RDF/XML.
|
| 174 |
|
|
|
|
| 178 |
Args:
|
| 179 |
validation_results (str): The validation error messages
|
| 180 |
rdf_content (str): The original RDF/XML content that failed validation
|
| 181 |
+
include_warnings (bool): Whether to include warnings in suggestions
|
| 182 |
|
| 183 |
Returns:
|
| 184 |
str: Detailed suggestions for fixing the RDF validation issues
|
|
|
|
| 206 |
{generate_manual_suggestions(validation_results)}
|
| 207 |
"""
|
| 208 |
|
| 209 |
+
severity_instruction = "Focus only on violations (errors) and ignore any warnings." if not include_warnings else "Address both violations and warnings."
|
| 210 |
+
|
| 211 |
prompt = f"""You are an expert in RDF/XML and SHACL validation. Analyze the following validation results and provide clear, actionable suggestions for fixing the RDF issues.
|
| 212 |
|
| 213 |
+
{severity_instruction}
|
| 214 |
+
|
| 215 |
Validation Results:
|
| 216 |
{validation_results}
|
| 217 |
|
|
|
|
| 229 |
# Make API call using OpenAI client
|
| 230 |
print(f"π Making API call to: {HF_ENDPOINT_URL}")
|
| 231 |
print(f"π Using model: {HF_MODEL}")
|
| 232 |
+
print(f"π Include warnings: {include_warnings}")
|
| 233 |
|
| 234 |
chat_completion = client.chat.completions.create(
|
| 235 |
model=HF_MODEL,
|
|
|
|
| 246 |
|
| 247 |
print("β
API call successful")
|
| 248 |
generated_text = chat_completion.choices[0].message.content
|
| 249 |
+
return f"π€ **AI-Powered Suggestions ({('Violations + Warnings' if include_warnings else 'Violations Only')}):**\n\n{generated_text}"
|
| 250 |
|
| 251 |
except Exception as e:
|
| 252 |
logger.error(f"OpenAI/HF Inference Endpoint error: {str(e)}")
|
|
|
|
| 285 |
# If no code blocks found, return the response as-is
|
| 286 |
return response
|
| 287 |
|
| 288 |
+
def get_ai_correction(validation_results: str, rdf_content: str, template: str = 'monograph', max_attempts: int = None, include_warnings: bool = False) -> str:
|
| 289 |
"""
|
| 290 |
Generate AI-powered corrected RDF/XML based on validation errors.
|
| 291 |
|
|
|
|
| 298 |
rdf_content (str): The original invalid RDF/XML content
|
| 299 |
template (str): The validation template to use
|
| 300 |
max_attempts (int): Maximum number of attempts to generate valid RDF (uses MAX_CORRECTION_ATTEMPTS if None)
|
| 301 |
+
include_warnings (bool): Whether to fix warnings in addition to violations
|
| 302 |
|
| 303 |
Returns:
|
| 304 |
str: Corrected RDF/XML that should pass validation
|
|
|
|
| 329 |
|
| 330 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
| 331 |
|
| 332 |
+
# Add timeout protection
|
| 333 |
+
import time
|
| 334 |
+
start_time = time.time()
|
| 335 |
+
timeout = 60 # 60 second timeout
|
| 336 |
+
|
| 337 |
+
severity_instruction = "Fix only the violations (errors) and ignore any warnings." if not include_warnings else "Fix both violations and warnings."
|
| 338 |
+
|
| 339 |
# Try multiple attempts to generate valid RDF
|
| 340 |
for attempt in range(max_attempts):
|
| 341 |
+
# Check timeout
|
| 342 |
+
if time.time() - start_time > timeout:
|
| 343 |
+
print(f"β° Timeout reached after {timeout} seconds")
|
| 344 |
+
break
|
| 345 |
+
|
| 346 |
+
print(f"π Correction attempt {attempt + 1}/{max_attempts}")
|
| 347 |
+
|
| 348 |
prompt = f"""You are an expert in RDF/XML. Fix the following RDF/XML based on the validation errors provided.
|
| 349 |
|
| 350 |
+
{severity_instruction}
|
| 351 |
+
|
| 352 |
Validation Errors:
|
| 353 |
{validation_results}
|
| 354 |
|
|
|
|
| 364 |
- Add any missing required properties
|
| 365 |
- Fix any syntax or structural issues"""
|
| 366 |
|
| 367 |
+
try:
|
| 368 |
+
chat_completion = client.chat.completions.create(
|
| 369 |
+
model=HF_MODEL,
|
| 370 |
+
messages=[
|
| 371 |
+
{
|
| 372 |
+
"role": "user",
|
| 373 |
+
"content": prompt
|
| 374 |
+
}
|
| 375 |
+
],
|
| 376 |
+
max_tokens=2000,
|
| 377 |
+
temperature=0.3,
|
| 378 |
+
timeout=30 # 30 second timeout per API call
|
| 379 |
+
)
|
| 380 |
+
|
| 381 |
+
corrected_rdf = chat_completion.choices[0].message.content.strip()
|
| 382 |
+
|
| 383 |
+
# Extract RDF content if it's wrapped in code blocks
|
| 384 |
+
corrected_rdf = extract_rdf_from_response(corrected_rdf)
|
| 385 |
+
|
| 386 |
+
# Only validate if we have the validator and haven't hit timeout
|
| 387 |
+
if VALIDATOR_AVAILABLE and (time.time() - start_time < timeout - 10):
|
| 388 |
+
try:
|
| 389 |
+
# Quick validation check
|
| 390 |
+
conforms, new_results = validate_rdf(corrected_rdf.encode('utf-8'), template)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 391 |
|
| 392 |
+
if conforms:
|
| 393 |
+
print(f"β
Correction validated successfully on attempt {attempt + 1}")
|
| 394 |
+
return f"""<!-- AI-generated correction validated successfully -->
|
| 395 |
+
{corrected_rdf}"""
|
| 396 |
+
else:
|
| 397 |
+
print(f"β Correction attempt {attempt + 1} still has validation errors")
|
| 398 |
+
# Update validation_results for next attempt
|
| 399 |
+
validation_results = new_results
|
| 400 |
+
|
| 401 |
+
except Exception as e:
|
| 402 |
+
print(f"β οΈ Error validating correction attempt {attempt + 1}: {str(e)}")
|
| 403 |
+
# If validation fails, return the correction anyway
|
| 404 |
+
return f"""<!-- AI-generated correction (validation check failed) -->
|
| 405 |
+
{corrected_rdf}"""
|
| 406 |
+
else:
|
| 407 |
+
# If validator not available or timeout approaching, return the correction
|
| 408 |
+
print("β οΈ Returning correction without validation")
|
| 409 |
+
return f"""<!-- AI-generated correction (validation skipped) -->
|
| 410 |
+
{corrected_rdf}"""
|
| 411 |
+
|
| 412 |
+
except Exception as api_error:
|
| 413 |
+
print(f"β API error on attempt {attempt + 1}: {str(api_error)}")
|
| 414 |
+
if attempt == max_attempts - 1: # Last attempt
|
| 415 |
+
raise api_error
|
| 416 |
+
continue
|
| 417 |
+
|
| 418 |
+
# All attempts failed or timed out
|
| 419 |
+
return f"""<!-- AI correction failed after {max_attempts} attempts or timeout -->
|
| 420 |
<!-- Please correct manually using the validation results as a guide -->
|
| 421 |
|
| 422 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
|
|
|
| 489 |
5. Validate data types
|
| 490 |
-->"""
|
| 491 |
|
| 492 |
+
def validate_rdf_interface(rdf_content: str, template: str, use_ai: bool = True, include_warnings: bool = False):
|
| 493 |
"""
|
| 494 |
Main validation function for Gradio interface and MCP server.
|
| 495 |
|
|
|
|
| 501 |
rdf_content (str): The RDF/XML content to validate
|
| 502 |
template (str): Validation template to use ('monograph' or 'custom')
|
| 503 |
use_ai (bool): Whether to enable AI-powered suggestions and corrections
|
| 504 |
+
include_warnings (bool): Whether to include warnings in AI corrections (violations only by default)
|
| 505 |
|
| 506 |
Returns:
|
| 507 |
tuple: (status, results_text, suggestions, corrected_rdf) containing:
|
|
|
|
| 522 |
status = result["status"]
|
| 523 |
results_text = result["results"]
|
| 524 |
|
| 525 |
+
# Filter results if warnings should be excluded
|
| 526 |
+
filtered_results = results_text
|
| 527 |
+
if not include_warnings and "Warning" in results_text:
|
| 528 |
+
# Split results into lines and filter out warnings
|
| 529 |
+
lines = results_text.split('\n')
|
| 530 |
+
filtered_lines = []
|
| 531 |
+
skip_until_next_section = False
|
| 532 |
+
|
| 533 |
+
for line in lines:
|
| 534 |
+
if "Warning" in line and ("Constraint Violation" in line or "sh:Warning" in line):
|
| 535 |
+
skip_until_next_section = True
|
| 536 |
+
elif "Constraint Violation" in line and "Warning" not in line:
|
| 537 |
+
skip_until_next_section = False
|
| 538 |
+
filtered_lines.append(line)
|
| 539 |
+
elif not skip_until_next_section:
|
| 540 |
+
filtered_lines.append(line)
|
| 541 |
+
|
| 542 |
+
filtered_results = '\n'.join(filtered_lines)
|
| 543 |
+
|
| 544 |
if result["conforms"]:
|
| 545 |
suggestions = "β
No issues found! Your RDF/XML is valid according to the selected template."
|
| 546 |
corrected_rdf = "β
Your RDF/XML is already valid - no corrections needed!"
|
| 547 |
else:
|
| 548 |
if use_ai:
|
| 549 |
+
# Pass filtered results to AI functions
|
| 550 |
+
suggestions = get_ai_suggestions(filtered_results, rdf_content, include_warnings)
|
| 551 |
+
corrected_rdf = get_ai_correction(filtered_results, rdf_content, template, include_warnings=include_warnings)
|
| 552 |
else:
|
| 553 |
+
suggestions = generate_manual_suggestions(filtered_results)
|
| 554 |
+
corrected_rdf = generate_manual_correction_hints(filtered_results, rdf_content)
|
| 555 |
|
| 556 |
return status, results_text, suggestions, corrected_rdf
|
| 557 |
|
|
|
|
| 675 |
value=True,
|
| 676 |
info="Enable AI-powered suggestions and corrections"
|
| 677 |
)
|
| 678 |
+
|
| 679 |
+
include_warnings_checkbox = gr.Checkbox(
|
| 680 |
+
label="Include Warnings",
|
| 681 |
+
value=False,
|
| 682 |
+
info="Include warnings in AI corrections (violations only by default)"
|
| 683 |
+
)
|
| 684 |
|
| 685 |
validate_btn = gr.Button("π Validate RDF", variant="primary", size="lg")
|
| 686 |
|
|
|
|
| 734 |
# Event handlers
|
| 735 |
validate_btn.click(
|
| 736 |
fn=validate_rdf_interface,
|
| 737 |
+
inputs=[rdf_input, template_dropdown, use_ai_checkbox, include_warnings_checkbox],
|
| 738 |
outputs=[status_output, results_output, suggestions_output, corrected_output]
|
| 739 |
)
|
| 740 |
|
| 741 |
+
# Remove auto-validation to prevent processing loops
|
| 742 |
+
# rdf_input.change(
|
| 743 |
+
# fn=validate_rdf_interface,
|
| 744 |
+
# inputs=[rdf_input, template_dropdown, use_ai_checkbox],
|
| 745 |
+
# outputs=[status_output, results_output, suggestions_output, corrected_output]
|
| 746 |
+
# )
|
| 747 |
|
| 748 |
# Example buttons
|
| 749 |
example1_btn.click(
|
|
|
|
| 813 |
- β
Real-time RDF/XML validation against SHACL schemas
|
| 814 |
- π€ AI-powered error suggestions and corrections (with HF Inference Endpoint)
|
| 815 |
- π Built-in examples and templates
|
| 816 |
+
- οΏ½ Manual validation on-demand (click to validate)
|
| 817 |
- π Copy results with one click
|
| 818 |
|
| 819 |
**Note:** AI features require a valid Hugging Face API key (HF_API_KEY) set as a Secret. Manual suggestions are provided as fallback.
|