File size: 7,419 Bytes
f40f080
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
import gradio as gr
import os
from huggingface_hub import InferenceClient
from utils.retriever import KnowledgeRetriever
import json

class AccessibilityChatbot:
    def __init__(self):
        # Initialize DeepSeek-R1 client
        self.client = InferenceClient(
            model="deepseek-ai/DeepSeek-R1",
            token=os.getenv("HF_TOKEN")
        )
        
        # Initialize knowledge retriever
        self.retriever = KnowledgeRetriever()
        
        # System prompt for accessibility education
        self.system_prompt = """You are an expert web accessibility instructor helping university students learn about web accessibility. 

Your knowledge comes from WebAIM resources, which are authoritative sources for web accessibility information.

Guidelines for responses:
1. Provide clear, student-friendly explanations
2. Use the provided WebAIM context to answer questions accurately
3. Always cite your sources by mentioning the WebAIM document and page number
4. Include practical examples and code snippets when relevant
5. Break down complex concepts into digestible parts
6. Encourage best practices and standards compliance
7. If asked about assignments, provide actionable guidance

Remember: You're teaching students, so be encouraging and educational while maintaining accuracy."""

    def generate_response(self, message, history):
        """Generate response using DeepSeek-R1 with WebAIM context"""
        
        # Retrieve relevant content from WebAIM PDFs
        relevant_content = self.retriever.retrieve_relevant_content(message)
        context = self.retriever.format_context_for_llm(relevant_content)
        
        # Prepare messages for the LLM
        messages = [
            {"role": "system", "content": f"{self.system_prompt}\n\nContext from WebAIM resources:\n{context}"}
        ]
        
        # Add conversation history
        for human, assistant in history:
            messages.append({"role": "user", "content": human})
            messages.append({"role": "assistant", "content": assistant})
        
        # Add current message
        messages.append({"role": "user", "content": message})
        
        try:
            response = self.client.chat_completion(
                messages=messages,
                max_tokens=1500,
                temperature=0.7,
                top_p=0.9
            )
            
            assistant_response = response.choices[0].message.content
            
            # Add source information
            if relevant_content:
                sources = self.format_sources(relevant_content)
                assistant_response += f"\n\n**Sources:**\n{sources}"
            
            return assistant_response
            
        except Exception as e:
            return f"I apologize, but I'm experiencing technical difficulties. Please try again. Error: {str(e)}"
    
    def format_sources(self, content_list):
        """Format source citations for display"""
        sources = []
        seen_sources = set()
        
        for item in content_list:
            source_key = f"{item['source_file']}_{item['page_number']}"
            if source_key not in seen_sources:
                sources.append(f"β€’ {item['source_file']} (Page {item['page_number']})")
                seen_sources.add(source_key)
        
        return "\n".join(sources)

# Initialize chatbot
chatbot = AccessibilityChatbot()

# Create Gradio interface
def create_interface():
    with gr.Blocks(
        title="Web Accessibility Learning Assistant",
        theme=gr.themes.Soft(),
        css="""
        .gradio-container {
            max-width: 1000px !important;
        }
        """
    ) as demo:
        
        gr.Markdown("""
        # 🌐 Web Accessibility Learning Assistant
        
        Welcome to your personal web accessibility tutor! I'm here to help you learn about web accessibility using **WebAIM resources** - the gold standard for accessibility guidance.
        
        ## What I can help you with:
        - **WCAG Guidelines**: Understanding success criteria and implementation
        - **Screen Reader Testing**: How to test with assistive technologies  
        - **Code Examples**: Accessible HTML, CSS, and JavaScript patterns
        - **Best Practices**: Real-world accessibility solutions
        - **Assignment Help**: Guidance for your accessibility projects
        
        *All answers are based on authoritative WebAIM documentation with proper citations.*
        """)
        
        # Main chat interface
        chatbot_interface = gr.Chatbot(
            height=500,
            placeholder="πŸ‘‹ Ask me anything about web accessibility!",
            show_label=False,
            container=True,
            bubble_full_width=False
        )
        
        msg = gr.Textbox(
            placeholder="Type your question here... (e.g., 'How do I write good alt text?')",
            label="Your Question",
            lines=2,
            max_lines=4
        )
        
        # Quick start examples
        gr.Markdown("### πŸš€ Quick Start Examples:")
        gr.Examples(
            examples=[
                "What are the WCAG 2.1 AA requirements for color contrast?",
                "How do I make forms accessible to screen readers?",
                "What's the difference between aria-label and aria-labelledby?",
                "How can I test my website with a screen reader?",
                "What are the most common accessibility mistakes students make?",
                "How do I write effective alt text for complex images?",
                "What ARIA roles should I use for a navigation menu?",
                "How do I make data tables accessible?",
                "What are the keyboard navigation requirements?",
                "How do I ensure my site works without JavaScript?"
            ],
            inputs=msg,
            examples_per_page=5
        )
        
        # Additional resources
        with gr.Accordion("πŸ“š Additional Learning Resources", open=False):
            gr.Markdown("""
            ### Recommended Tools:
            - **WAVE**: Web accessibility evaluation tool
            - **axe DevTools**: Browser extension for accessibility testing
            - **Lighthouse**: Built-in accessibility audit in Chrome
            - **NVDA/JAWS**: Screen readers for testing
            
            ### Key Standards:
            - **WCAG 2.1**: Current web accessibility guidelines
            - **Section 508**: US federal accessibility requirements
            - **ADA**: Americans with Disabilities Act considerations
            """)
        
        # Handle message submission
        def respond(message, history):
            if not message.strip():
                return history, ""
            
            response = chatbot.generate_response(message, history)
            history.append((message, response))
            return history, ""
        
        msg.submit(respond, [msg, chatbot_interface], [chatbot_interface, msg])
        
        # Footer
        gr.Markdown("""
        ---
        *This chatbot uses WebAIM resources and is powered by DeepSeek-R1. 
        For the most up-to-date information, always refer to the original WebAIM documentation.*
        """)
    
    return demo

# Launch the app
if __name__ == "__main__":
    demo = create_interface()
    demo.launch()