jimfhahn commited on
Commit
62f2727
Β·
verified Β·
1 Parent(s): eb168f6

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -65
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 = 3 # Maximum number of attempts to generate valid RDF
57
- ENABLE_VALIDATION_LOOP = True # Set to False to disable validation loop for debugging
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"πŸ”„ Client base_url: {client.base_url}")
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
- print(f"πŸ”„ Correction attempt {attempt + 1}/{max_attempts}")
346
- print(f"πŸ”„ Using endpoint: {HF_ENDPOINT_URL}")
347
- print(f"πŸ”„ Using model: {HF_MODEL}")
348
-
349
- chat_completion = client.chat.completions.create(
350
- model=HF_MODEL,
351
- messages=[
352
- {
353
- "role": "user",
354
- "content": prompt
355
- }
356
- ],
357
- max_tokens=2000,
358
- temperature=0.3 # Lower temperature for more consistent output
359
- )
360
-
361
- corrected_rdf = chat_completion.choices[0].message.content.strip()
362
-
363
- # Extract RDF content if it's wrapped in code blocks
364
- corrected_rdf = extract_rdf_from_response(corrected_rdf)
365
-
366
- # Validate the corrected RDF
367
- if VALIDATOR_AVAILABLE:
368
- try:
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
- except Exception as e:
382
- print(f"⚠️ Error validating correction attempt {attempt + 1}: {str(e)}")
383
- # Continue to next attempt
384
- else:
385
- # If validator not available, return the first attempt
386
- print("⚠️ Validator not available, returning unvalidated correction")
387
- return corrected_rdf
388
-
389
- # All attempts failed
390
- return f"""<!-- AI correction failed after {max_attempts} attempts to generate valid RDF -->
391
- <!-- The AI-generated corrections still contained validation errors -->
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
- suggestions = get_ai_suggestions(results_text, rdf_content)
502
- corrected_rdf = get_ai_correction(results_text, rdf_content, template)
 
503
  else:
504
- suggestions = generate_manual_suggestions(results_text)
505
- corrected_rdf = generate_manual_correction_hints(results_text, rdf_content)
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
- # Auto-validate on input change (debounced)
687
- rdf_input.change(
688
- fn=validate_rdf_interface,
689
- inputs=[rdf_input, template_dropdown, use_ai_checkbox],
690
- outputs=[status_output, results_output, suggestions_output, corrected_output]
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
- - πŸ”„ Auto-validation as you type
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.