Upload app.py
Browse files
app.py
CHANGED
@@ -17,27 +17,6 @@ from typing import Any, Dict, List, Optional
|
|
17 |
import threading
|
18 |
import time
|
19 |
|
20 |
-
# CRITICAL: FORCE OVERRIDE ALL ENVIRONMENT VARIABLES THAT COULD INTERFERE
|
21 |
-
print("π§ FORCING ENVIRONMENT VARIABLE OVERRIDES...")
|
22 |
-
|
23 |
-
# Remove any HF environment variables that could cause URL concatenation
|
24 |
-
problematic_env_vars = [
|
25 |
-
'HF_API_URL',
|
26 |
-
'HF_INFERENCE_URL',
|
27 |
-
'HF_ENDPOINT_URL',
|
28 |
-
'HF_MODEL',
|
29 |
-
'HUGGINGFACE_API_URL',
|
30 |
-
'HUGGINGFACE_INFERENCE_URL'
|
31 |
-
]
|
32 |
-
|
33 |
-
for var in problematic_env_vars:
|
34 |
-
if var in os.environ:
|
35 |
-
old_value = os.environ[var]
|
36 |
-
del os.environ[var]
|
37 |
-
print(f"ποΈ Removed environment variable: {var} = {old_value}")
|
38 |
-
|
39 |
-
print("β
Environment variables cleaned")
|
40 |
-
|
41 |
# Add current directory to path
|
42 |
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
43 |
|
@@ -68,22 +47,14 @@ except ImportError:
|
|
68 |
logging.basicConfig(level=logging.INFO)
|
69 |
logger = logging.getLogger(__name__)
|
70 |
|
71 |
-
# Configuration -
|
72 |
-
HF_API_KEY = os.getenv('HF_API_KEY', '') #
|
73 |
-
# FORCE HARDCODED VALUES - IGNORE ALL OTHER ENVIRONMENT VARIABLES
|
74 |
HF_ENDPOINT_URL = "https://evxgv66ksxjlfrts.us-east-1.aws.endpoints.huggingface.cloud/v1/"
|
75 |
HF_MODEL = "lmstudio-community/Llama-3.3-70B-Instruct-GGUF" # Correct model name for your endpoint
|
76 |
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
# EXTRA PROTECTION: Override any modules that might have cached env vars
|
82 |
-
import sys
|
83 |
-
if 'requests' in sys.modules:
|
84 |
-
print("π Requests module detected - ensuring no cached env vars")
|
85 |
-
if 'httpx' in sys.modules:
|
86 |
-
print("π HTTPX module detected - ensuring no cached env vars")
|
87 |
|
88 |
# OpenAI client configuration for the endpoint
|
89 |
def get_openai_client():
|
@@ -106,92 +77,53 @@ def get_openai_client():
|
|
106 |
SAMPLE_VALID_RDF = '''<?xml version="1.0" encoding="UTF-8"?>
|
107 |
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
108 |
xmlns:bf="http://id.loc.gov/ontologies/bibframe/"
|
109 |
-
xmlns:bflc="http://id.loc.gov/ontologies/bflc/"
|
110 |
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
|
111 |
|
112 |
<bf:Work rdf:about="http://example.org/work/1">
|
113 |
<rdf:type rdf:resource="http://id.loc.gov/ontologies/bibframe/Text"/>
|
114 |
<bf:title>
|
115 |
<bf:Title>
|
116 |
-
<bf:mainTitle>
|
117 |
-
<bf:subtitle>A Comprehensive Example for SHACL Validation</bf:subtitle>
|
118 |
-
</bf:Title>
|
119 |
-
</bf:title>
|
120 |
-
<bf:creator>
|
121 |
-
<bf:Agent>
|
122 |
-
<rdf:type rdf:resource="http://id.loc.gov/ontologies/bibframe/Person"/>
|
123 |
-
<rdfs:label>Valid Author Name</rdfs:label>
|
124 |
-
</bf:Agent>
|
125 |
-
</bf:creator>
|
126 |
-
<bf:subject>
|
127 |
-
<bf:Topic>
|
128 |
-
<rdfs:label>Library Science</rdfs:label>
|
129 |
-
</bf:Topic>
|
130 |
-
</bf:subject>
|
131 |
-
<bf:language>
|
132 |
-
<bf:Language rdf:about="http://id.loc.gov/vocabulary/languages/eng"/>
|
133 |
-
</bf:language>
|
134 |
-
<bf:hasInstance rdf:resource="http://example.org/instance/1"/>
|
135 |
-
</bf:Work>
|
136 |
-
|
137 |
-
<bf:Instance rdf:about="http://example.org/instance/1">
|
138 |
-
<rdf:type rdf:resource="http://id.loc.gov/ontologies/bibframe/Print"/>
|
139 |
-
<bf:instanceOf rdf:resource="http://example.org/work/1"/>
|
140 |
-
<bf:title>
|
141 |
-
<bf:Title>
|
142 |
-
<bf:mainTitle>Complete Valid Monograph Title</bf:mainTitle>
|
143 |
</bf:Title>
|
144 |
</bf:title>
|
145 |
-
<bf:
|
146 |
-
<bf:
|
147 |
-
<bf:date>2024</bf:date>
|
148 |
-
<bf:place>
|
149 |
-
<bf:Place>
|
150 |
-
<rdfs:label>Washington, DC</rdfs:label>
|
151 |
-
</bf:Place>
|
152 |
-
</bf:place>
|
153 |
<bf:agent>
|
154 |
<bf:Agent>
|
155 |
-
<rdfs:label>Sample
|
156 |
</bf:Agent>
|
157 |
</bf:agent>
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
</bf:
|
164 |
-
</bf:
|
165 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
166 |
|
167 |
</rdf:RDF>'''
|
168 |
|
169 |
SAMPLE_INVALID_RDF = '''<?xml version="1.0" encoding="UTF-8"?>
|
170 |
-
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
<bf:Work rdf:about="http://example.org/work/1">
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
<bf:mainTitle>Invalid Monograph Title Structure</bf:mainTitle>
|
179 |
-
</bf:title>
|
180 |
-
<!-- Missing required bf:creator property -->
|
181 |
-
<!-- Missing other required properties like bf:language -->
|
182 |
</bf:Work>
|
183 |
-
|
184 |
-
<bf:Instance rdf:about="http://example.org/instance/1">
|
185 |
-
<rdf:type rdf:resource="http://id.loc.gov/ontologies/bibframe/Print"/>
|
186 |
-
<!-- Missing bf:instanceOf property - should link to Work -->
|
187 |
-
<bf:title>
|
188 |
-
<bf:Title>
|
189 |
-
<bf:mainTitle>Invalid Instance Title</bf:mainTitle>
|
190 |
-
</bf:Title>
|
191 |
-
</bf:title>
|
192 |
-
<!-- Missing required bf:provisionActivity -->
|
193 |
-
</bf:Instance>
|
194 |
-
|
195 |
</rdf:RDF>'''
|
196 |
|
197 |
# MCP Server Tools (can be used independently)
|
@@ -265,16 +197,13 @@ def get_ai_suggestions(validation_results: str, rdf_content: str) -> str:
|
|
265 |
|
266 |
try:
|
267 |
# Use OpenAI client with your Hugging Face Inference Endpoint
|
268 |
-
print("π Attempting to get OpenAI client for suggestions...")
|
269 |
client = get_openai_client()
|
270 |
if not client:
|
271 |
-
print("β OpenAI client is None for suggestions.")
|
272 |
return f"""
|
273 |
-
π **AI suggestions disabled**: HF_API_KEY not configured
|
274 |
|
275 |
{generate_manual_suggestions(validation_results)}
|
276 |
"""
|
277 |
-
print(f"β
OpenAI client obtained for suggestions. Client timeout: {client.timeout}")
|
278 |
|
279 |
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.
|
280 |
|
@@ -293,9 +222,9 @@ Please provide:
|
|
293 |
Format your response in a helpful, structured way using markdown."""
|
294 |
|
295 |
# Make API call using OpenAI client
|
296 |
-
print(f"π Making
|
|
|
297 |
print(f"π Client base_url: {client.base_url}")
|
298 |
-
print("β³ Attempting client.chat.completions.create() for suggestions...")
|
299 |
|
300 |
chat_completion = client.chat.completions.create(
|
301 |
model=HF_MODEL,
|
@@ -310,34 +239,73 @@ Format your response in a helpful, structured way using markdown."""
|
|
310 |
top_p=0.9
|
311 |
)
|
312 |
|
313 |
-
print(
|
314 |
generated_text = chat_completion.choices[0].message.content
|
315 |
-
print("β
Suggestion API call successful, content extracted.")
|
316 |
return f"π€ **AI-Powered Suggestions:**\n\n{generated_text}"
|
317 |
|
318 |
except Exception as e:
|
319 |
-
logger.error(f"OpenAI/HF Inference Endpoint error
|
320 |
return f"""
|
321 |
β **AI suggestions error**: {str(e)}
|
322 |
|
323 |
{generate_manual_suggestions(validation_results)}
|
324 |
"""
|
325 |
|
326 |
-
def
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
327 |
"""
|
328 |
Generate AI-powered corrected RDF/XML based on validation errors.
|
329 |
|
330 |
This tool takes invalid RDF/XML and validation results, then generates
|
331 |
a corrected version that addresses all identified validation issues.
|
|
|
332 |
|
333 |
Args:
|
334 |
validation_results (str): The validation error messages
|
335 |
rdf_content (str): The original invalid RDF/XML content
|
|
|
|
|
336 |
|
337 |
Returns:
|
338 |
str: Corrected RDF/XML that should pass validation
|
339 |
"""
|
340 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
341 |
if not OPENAI_AVAILABLE:
|
342 |
return generate_manual_correction_hints(validation_results, rdf_content)
|
343 |
|
@@ -349,17 +317,15 @@ def get_ai_correction(validation_results: str, rdf_content: str) -> str:
|
|
349 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
350 |
|
351 |
try:
|
352 |
-
# Use OpenAI client with your Hugging Face Inference Endpoint
|
353 |
-
print("π Attempting to get OpenAI client for correction...")
|
354 |
client = get_openai_client()
|
355 |
if not client:
|
356 |
-
|
357 |
-
return f"""<!-- AI correction disabled: HF_API_KEY not configured or client creation failed. -->
|
358 |
|
359 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
360 |
-
print(f"β
OpenAI client obtained for correction. Client timeout: {client.timeout}")
|
361 |
|
362 |
-
|
|
|
|
|
363 |
|
364 |
Validation Errors:
|
365 |
{validation_results}
|
@@ -367,39 +333,69 @@ Validation Errors:
|
|
367 |
Original RDF/XML:
|
368 |
{rdf_content}
|
369 |
|
|
|
|
|
370 |
Please provide the corrected RDF/XML that addresses all validation issues.
|
371 |
- Return only the corrected XML without additional explanation
|
372 |
- Maintain the original structure as much as possible while fixing errors
|
373 |
- Ensure all namespace declarations are present
|
374 |
- Add any missing required properties
|
375 |
- Fix any syntax or structural issues"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
376 |
|
377 |
-
#
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
model=HF_MODEL,
|
384 |
-
messages=[
|
385 |
-
{
|
386 |
-
"role": "user",
|
387 |
-
"content": prompt
|
388 |
-
}
|
389 |
-
],
|
390 |
-
max_tokens=2000,
|
391 |
-
temperature=0.3,
|
392 |
-
top_p=0.9
|
393 |
-
)
|
394 |
-
|
395 |
-
print(f"β
client.chat.completions.create() returned for correction. Type: {type(chat_completion)}")
|
396 |
-
corrected_text = chat_completion.choices[0].message.content
|
397 |
-
print("β
Correction API call successful, content extracted.")
|
398 |
-
return corrected_text
|
399 |
|
400 |
except Exception as e:
|
401 |
-
logger.error(f"
|
402 |
-
return f"""<!-- AI correction
|
403 |
|
404 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
405 |
|
@@ -485,7 +481,7 @@ def validate_rdf_interface(rdf_content: str, template: str, use_ai: bool = True)
|
|
485 |
else:
|
486 |
if use_ai:
|
487 |
suggestions = get_ai_suggestions(results_text, rdf_content)
|
488 |
-
corrected_rdf = get_ai_correction(results_text, rdf_content)
|
489 |
else:
|
490 |
suggestions = generate_manual_suggestions(results_text)
|
491 |
corrected_rdf = generate_manual_correction_hints(results_text, rdf_content)
|
@@ -575,7 +571,7 @@ def create_interface():
|
|
575 |
|
576 |
gr.HTML(f"""
|
577 |
<div class="header-text">
|
578 |
-
<h1
|
579 |
<p>Validate RDF/XML against SHACL schemas with AI-powered suggestions and corrections</p>
|
580 |
<p><strong>Status:</strong> {api_status}</p>
|
581 |
<details><summary>Debug Info</summary><pre>{debug_info}</pre></details>
|
@@ -609,15 +605,6 @@ def create_interface():
|
|
609 |
)
|
610 |
|
611 |
validate_btn = gr.Button("π Validate RDF", variant="primary", size="lg")
|
612 |
-
|
613 |
-
# Examples and controls
|
614 |
-
gr.Markdown("### π Examples & Tools")
|
615 |
-
|
616 |
-
with gr.Row():
|
617 |
-
example1_btn = gr.Button("β
Valid RDF Example", variant="secondary")
|
618 |
-
example2_btn = gr.Button("β Invalid RDF Example", variant="secondary")
|
619 |
-
example3_btn = gr.Button("π BibFrame Example", variant="secondary")
|
620 |
-
clear_btn = gr.Button("ποΈ Clear All", variant="stop")
|
621 |
|
622 |
# Results section
|
623 |
with gr.Row():
|
@@ -658,6 +645,16 @@ def create_interface():
|
|
658 |
placeholder="Corrected RDF will appear here after validation..."
|
659 |
)
|
660 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
# Event handlers
|
662 |
validate_btn.click(
|
663 |
fn=validate_rdf_interface,
|
@@ -736,16 +733,6 @@ def create_interface():
|
|
736 |
|
737 |
# Launch configuration
|
738 |
if __name__ == "__main__":
|
739 |
-
# Force verify environment is clean
|
740 |
-
print("π FINAL CHECK: Verifying problematic environment variables are removed...")
|
741 |
-
for var in problematic_env_vars:
|
742 |
-
if var in os.environ:
|
743 |
-
print(f"β οΈ WARNING: {var} still exists! Value: {os.environ[var]}")
|
744 |
-
del os.environ[var]
|
745 |
-
print(f"ποΈ FORCE REMOVED: {var}")
|
746 |
-
else:
|
747 |
-
print(f"β
{var} confirmed not in environment")
|
748 |
-
|
749 |
demo = create_interface()
|
750 |
|
751 |
# Configuration for different environments
|
@@ -757,5 +744,6 @@ if __name__ == "__main__":
|
|
757 |
share=False, # Don't create gradio.live links in production
|
758 |
show_error=True, # Show errors in the interface
|
759 |
show_api=True, # Enable API endpoints
|
760 |
-
allowed_paths=["."]
|
|
|
761 |
)
|
|
|
17 |
import threading
|
18 |
import time
|
19 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20 |
# Add current directory to path
|
21 |
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
|
22 |
|
|
|
47 |
logging.basicConfig(level=logging.INFO)
|
48 |
logger = logging.getLogger(__name__)
|
49 |
|
50 |
+
# Configuration - Your specific Hugging Face Inference Endpoint (hardcoded)
|
51 |
+
HF_API_KEY = os.getenv('HF_API_KEY', '') # Hugging Face API key from Secret
|
|
|
52 |
HF_ENDPOINT_URL = "https://evxgv66ksxjlfrts.us-east-1.aws.endpoints.huggingface.cloud/v1/"
|
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():
|
|
|
77 |
SAMPLE_VALID_RDF = '''<?xml version="1.0" encoding="UTF-8"?>
|
78 |
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
79 |
xmlns:bf="http://id.loc.gov/ontologies/bibframe/"
|
|
|
80 |
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
|
81 |
|
82 |
<bf:Work rdf:about="http://example.org/work/1">
|
83 |
<rdf:type rdf:resource="http://id.loc.gov/ontologies/bibframe/Text"/>
|
84 |
<bf:title>
|
85 |
<bf:Title>
|
86 |
+
<bf:mainTitle>Sample Monograph Title</bf:mainTitle>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
87 |
</bf:Title>
|
88 |
</bf:title>
|
89 |
+
<bf:contribution>
|
90 |
+
<bf:Contribution>
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
<bf:agent>
|
92 |
<bf:Agent>
|
93 |
+
<rdfs:label>Sample Author</rdfs:label>
|
94 |
</bf:Agent>
|
95 |
</bf:agent>
|
96 |
+
<bf:role>
|
97 |
+
<bf:Role>
|
98 |
+
<rdfs:label>Author</rdfs:label>
|
99 |
+
</bf:Role>
|
100 |
+
</bf:role>
|
101 |
+
</bf:Contribution>
|
102 |
+
</bf:contribution>
|
103 |
+
<bf:language rdf:resource="http://id.loc.gov/vocabulary/languages/eng"/>
|
104 |
+
<bf:content rdf:resource="http://id.loc.gov/vocabulary/contentTypes/txt"/>
|
105 |
+
<bf:adminMetadata>
|
106 |
+
<bf:AdminMetadata>
|
107 |
+
<bf:assigner>
|
108 |
+
<bf:Organization>
|
109 |
+
<rdfs:label>Example Library</rdfs:label>
|
110 |
+
</bf:Organization>
|
111 |
+
</bf:assigner>
|
112 |
+
</bf:AdminMetadata>
|
113 |
+
</bf:adminMetadata>
|
114 |
+
</bf:Work>
|
115 |
|
116 |
</rdf:RDF>'''
|
117 |
|
118 |
SAMPLE_INVALID_RDF = '''<?xml version="1.0" encoding="UTF-8"?>
|
119 |
+
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
|
120 |
+
<!-- Missing namespace declarations -->
|
121 |
+
<!-- Missing required properties -->
|
|
|
122 |
<bf:Work rdf:about="http://example.org/work/1">
|
123 |
+
<bf:title>Incomplete Title</bf:title>
|
124 |
+
<!-- Missing rdf:type -->
|
125 |
+
<!-- Missing proper title structure -->
|
|
|
|
|
|
|
|
|
126 |
</bf:Work>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
</rdf:RDF>'''
|
128 |
|
129 |
# MCP Server Tools (can be used independently)
|
|
|
197 |
|
198 |
try:
|
199 |
# Use OpenAI client with your Hugging Face Inference Endpoint
|
|
|
200 |
client = get_openai_client()
|
201 |
if not client:
|
|
|
202 |
return f"""
|
203 |
+
π **AI suggestions disabled**: HF_API_KEY not configured.
|
204 |
|
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 |
|
|
|
222 |
Format your response in a helpful, structured way using markdown."""
|
223 |
|
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,
|
|
|
239 |
top_p=0.9
|
240 |
)
|
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)}")
|
248 |
return f"""
|
249 |
β **AI suggestions error**: {str(e)}
|
250 |
|
251 |
{generate_manual_suggestions(validation_results)}
|
252 |
"""
|
253 |
|
254 |
+
def extract_rdf_from_response(response: str) -> str:
|
255 |
+
"""
|
256 |
+
Extract RDF/XML content from AI response, handling code blocks.
|
257 |
+
|
258 |
+
Args:
|
259 |
+
response (str): AI response that may contain RDF wrapped in code blocks
|
260 |
+
|
261 |
+
Returns:
|
262 |
+
str: Extracted RDF/XML content
|
263 |
+
"""
|
264 |
+
response = response.strip()
|
265 |
+
|
266 |
+
# Handle ```xml code blocks
|
267 |
+
if "```xml" in response:
|
268 |
+
try:
|
269 |
+
return response.split("```xml")[1].split("```")[0].strip()
|
270 |
+
except IndexError:
|
271 |
+
pass
|
272 |
+
|
273 |
+
# Handle generic ``` code blocks
|
274 |
+
if "```" in response and response.count("```") >= 2:
|
275 |
+
try:
|
276 |
+
return response.split("```")[1].split("```")[0].strip()
|
277 |
+
except IndexError:
|
278 |
+
pass
|
279 |
+
|
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 |
|
287 |
This tool takes invalid RDF/XML and validation results, then generates
|
288 |
a corrected version that addresses all identified validation issues.
|
289 |
+
The generated correction is validated before being returned to the user.
|
290 |
|
291 |
Args:
|
292 |
validation_results (str): The validation error messages
|
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
|
299 |
"""
|
300 |
|
301 |
+
# Use configuration default if not specified
|
302 |
+
if max_attempts is None:
|
303 |
+
max_attempts = MAX_CORRECTION_ATTEMPTS
|
304 |
+
|
305 |
+
# Check if validation loop is enabled
|
306 |
+
if not ENABLE_VALIDATION_LOOP:
|
307 |
+
max_attempts = 1 # Fall back to single attempt if validation loop disabled
|
308 |
+
|
309 |
if not OPENAI_AVAILABLE:
|
310 |
return generate_manual_correction_hints(validation_results, rdf_content)
|
311 |
|
|
|
317 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
318 |
|
319 |
try:
|
|
|
|
|
320 |
client = get_openai_client()
|
321 |
if not client:
|
322 |
+
return f"""<!-- AI correction disabled: HF_API_KEY not configured -->
|
|
|
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}
|
|
|
333 |
Original RDF/XML:
|
334 |
{rdf_content}
|
335 |
|
336 |
+
{f"Previous attempt {attempt} still had validation errors. Please fix ALL issues this time." if attempt > 0 else ""}
|
337 |
+
|
338 |
Please provide the corrected RDF/XML that addresses all validation issues.
|
339 |
- Return only the corrected XML without additional explanation
|
340 |
- Maintain the original structure as much as possible while fixing errors
|
341 |
- Ensure all namespace declarations are present
|
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)}"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
395 |
|
396 |
except Exception as e:
|
397 |
+
logger.error(f"LLM API error: {str(e)}")
|
398 |
+
return f"""<!-- Error generating AI correction: {str(e)} -->
|
399 |
|
400 |
{generate_manual_correction_hints(validation_results, rdf_content)}"""
|
401 |
|
|
|
481 |
else:
|
482 |
if use_ai:
|
483 |
suggestions = get_ai_suggestions(results_text, rdf_content)
|
484 |
+
corrected_rdf = get_ai_correction(results_text, rdf_content, template)
|
485 |
else:
|
486 |
suggestions = generate_manual_suggestions(results_text)
|
487 |
corrected_rdf = generate_manual_correction_hints(results_text, rdf_content)
|
|
|
571 |
|
572 |
gr.HTML(f"""
|
573 |
<div class="header-text">
|
574 |
+
<h1>π RDF Validation Server with AI</h1>
|
575 |
<p>Validate RDF/XML against SHACL schemas with AI-powered suggestions and corrections</p>
|
576 |
<p><strong>Status:</strong> {api_status}</p>
|
577 |
<details><summary>Debug Info</summary><pre>{debug_info}</pre></details>
|
|
|
605 |
)
|
606 |
|
607 |
validate_btn = gr.Button("π Validate RDF", variant="primary", size="lg")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
608 |
|
609 |
# Results section
|
610 |
with gr.Row():
|
|
|
645 |
placeholder="Corrected RDF will appear here after validation..."
|
646 |
)
|
647 |
|
648 |
+
# Examples and controls
|
649 |
+
with gr.Row():
|
650 |
+
gr.Markdown("### π Examples & Tools")
|
651 |
+
|
652 |
+
with gr.Row():
|
653 |
+
example1_btn = gr.Button("β
Valid RDF Example", variant="secondary")
|
654 |
+
example2_btn = gr.Button("β Invalid RDF Example", variant="secondary")
|
655 |
+
example3_btn = gr.Button("π BibFrame Example", variant="secondary")
|
656 |
+
clear_btn = gr.Button("ποΈ Clear All", variant="stop")
|
657 |
+
|
658 |
# Event handlers
|
659 |
validate_btn.click(
|
660 |
fn=validate_rdf_interface,
|
|
|
733 |
|
734 |
# Launch configuration
|
735 |
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
736 |
demo = create_interface()
|
737 |
|
738 |
# Configuration for different environments
|
|
|
744 |
share=False, # Don't create gradio.live links in production
|
745 |
show_error=True, # Show errors in the interface
|
746 |
show_api=True, # Enable API endpoints
|
747 |
+
allowed_paths=["."], # Allow serving files from current directory
|
748 |
+
mcp_server=True # Enable MCP server functionality (Gradio 5.28+)
|
749 |
)
|