bfh-studadmin-assist / src /ui /formatters.py
awellis's picture
Refactor Gradio UI components and add configuration class for improved maintainability
ceb7cfa
"""HTML formatters for displaying retrieved chunks in Gradio UI."""
class ChunkFormatter:
"""Formats retrieved chunks as HTML for display."""
@staticmethod
def format_markdown_to_html(text: str) -> str:
"""Convert markdown formatting to HTML.
Args:
text: Text with markdown formatting
Returns:
HTML formatted text
"""
return text.replace('**', '<strong>').replace('**', '</strong>').replace('\n', '<br>')
@staticmethod
def format_chunk_card(chunk: dict) -> str:
"""Format a single chunk as an HTML card with preview and explanation.
Args:
chunk: Dictionary containing chunk data with keys:
- rank: Chunk ranking number
- source: Source file name
- section: Section within document
- score: Relevance score
- preview: Preview text (truncated)
- content: Full chunk content
- explanation: Relevance explanation
Returns:
HTML string for the chunk card
"""
explanation_html = ChunkFormatter.format_markdown_to_html(chunk['explanation'])
return f"""
<div style="border: 1px solid var(--border-color-primary); border-radius: 8px; padding: 16px; margin-bottom: 16px; background: var(--background-fill-secondary); box-shadow: var(--shadow-sm);">
<div style="margin-bottom: 12px;">
<strong style="color: var(--color-accent);">#{chunk['rank']}</strong> |
<span style="color: var(--color-accent);">📄 {chunk['source']}</span> |
<span>Section: {chunk['section']}</span> |
<span style="color: var(--color-accent-soft);">Score: {chunk['score']:.3f}</span>
</div>
<details style="margin-top: 8px;">
<summary style="cursor: pointer; padding: 10px; background: var(--background-fill-primary); border-radius: 4px; margin-bottom: 8px; font-weight: 500; border: 1px solid var(--border-color-primary);">
<strong>Preview:</strong> {chunk['preview']}
</summary>
<div style="padding: 12px; background: var(--background-fill-primary); border-radius: 4px; margin-top: 8px; white-space: pre-wrap; word-wrap: break-word; line-height: 1.6; border: 1px solid var(--border-color-primary);">
{chunk['content']}
</div>
</details>
<div style="margin-top: 12px; padding: 10px; background: var(--color-accent-soft); border-left: 3px solid var(--color-accent); border-radius: 4px; font-size: 0.9em; opacity: 0.9;">
{explanation_html}
</div>
</div>
"""
@staticmethod
def format_chunks_html(chunks_info: list) -> str:
"""Format all chunks as HTML.
Args:
chunks_info: List of chunk dictionaries
Returns:
Complete HTML string for all chunks
"""
if not chunks_info:
return "<p>No documents retrieved.</p>"
return "".join(ChunkFormatter.format_chunk_card(chunk) for chunk in chunks_info)