بناء مساعد دردشة باستخدام الذكاء الاصطناعي
هل تتذكر في مسلسل "ستار تريك" عندما كان الطاقم يتحدث بشكل عادي مع كمبيوتر السفينة، يطرحون عليه أسئلة معقدة ويحصلون على إجابات مدروسة؟ ما كان يبدو كخيال علمي في الستينيات أصبح الآن شيئًا يمكنك بناؤه باستخدام تقنيات الويب التي تعرفها بالفعل. في هذه الدرس، سنقوم بإنشاء مساعد دردشة بالذكاء الاصطناعي باستخدام HTML، CSS، JavaScript وبعض التكامل الخلفي. ستكتشف كيف يمكن للمهارات التي تعلمتها أن تتصل بخدمات ذكاء اصطناعي قوية تفهم السياق وتولد ردودًا ذات معنى. فكر في الذكاء الاصطناعي كأنه مكتبة ضخمة يمكنها ليس فقط العثور على المعلومات، بل أيضًا صياغتها في إجابات متماسكة ومخصصة لأسئلتك المحددة. بدلاً من البحث عبر آلاف الصفحات، تحصل على ردود مباشرة وسياقية. يحدث التكامل من خلال تقنيات الويب المألوفة التي تعمل معًا. HTML ينشئ واجهة الدردشة، CSS يتولى التصميم البصري، JavaScript يدير التفاعلات مع المستخدم، وواجهة برمجة التطبيقات الخلفية تربط كل شيء بخدمات الذكاء الاصطناعي. يشبه ذلك كيف تعمل أقسام مختلفة من الأوركسترا معًا لتقديم سيمفونية. نحن نبني جسرًا بين التواصل البشري الطبيعي ومعالجة الآلة. ستتعلم التنفيذ الفني لتكامل خدمات الذكاء الاصطناعي وأنماط التصميم التي تجعل التفاعلات تبدو طبيعية. بنهاية هذا الدرس، سيصبح تكامل الذكاء الاصطناعي أقل غموضًا وأكثر كأنه واجهة برمجة تطبيقات أخرى يمكنك العمل معها. ستفهم الأنماط الأساسية التي تشغل تطبيقات مثل ChatGPT وClaude باستخدام نفس مبادئ تطوير الويب التي كنت تتعلمها. ## ⚡ ما يمكنك القيام به في الـ 5 دقائق القادمة مسار البداية السريعة للمطورين المشغولين - الدقيقة الأولى: قم بزيارة GitHub Models Playground وأنشئ رمز وصول شخصي - الدقيقة الثانية: اختبر التفاعلات مع الذكاء الاصطناعي مباشرة في واجهة الملعب - الدقيقة الثالثة: انقر على علامة التبويب "Code" ونسخ مقتطف Python - الدقيقة الرابعة: قم بتشغيل الكود محليًا باستخدام الرمز الخاص بك: GITHUB_TOKEN=your_token python test.py - الدقيقة الخامسة: شاهد أول استجابة من الذكاء الاصطناعي يتم إنشاؤها من الكود الخاص بك كود الاختبار السريع: لماذا هذا مهم: في 5 دقائق، ستختبر سحر التفاعل البرمجي مع الذكاء الاصطناعي. هذا يمثل حجر الأساس الذي يشغل كل تطبيقات الذكاء الاصطناعي التي تستخدمها. إليك كيف سيبدو مشروعك النهائي: ## 🗺️ رحلتك التعليمية عبر تطوير تطبيقات الذكاء الاصطناعي وجهة رحلتك: بنهاية هذا الدرس، ستكون قد أنشأت تطبيقًا كاملًا مدعومًا بالذكاء الاصطناعي باستخدام نفس التقنيات والأنماط التي تشغل مساعدي الذكاء الاصطناعي الحديثين مثل ChatGPT وClaude وGoogle Bard. ## فهم الذكاء الاصطناعي: من الغموض إلى الإتقان قبل الغوص في الكود، دعونا نفهم ما نعمل عليه. إذا كنت قد استخدمت واجهات برمجة التطبيقات من قبل، فأنت تعرف النمط الأساسي: إرسال طلب، تلقي استجابة. واجهات برمجة تطبيقات الذكاء الاصطناعي تتبع هيكلًا مشابهًا، ولكن بدلاً من استرجاع بيانات مخزنة مسبقًا من قاعدة بيانات، فإنها تولد ردودًا جديدة بناءً على أنماط تعلمتها من كميات هائلة من النصوص. فكر في الأمر كأنه الفرق بين نظام فهرسة مكتبة وأمين مكتبة ذو معرفة واسعة يمكنه صياغة المعلومات من مصادر متعددة. ### ما هو "الذكاء الاصطناعي التوليدي" حقًا؟ تأمل كيف سمحت حجر رشيد للعلماء بفهم الهيروغليفية المصرية من خلال العثور على أنماط بين اللغات المعروفة وغير المعروفة. نماذج الذكاء الاصطناعي تعمل بطريقة مشابهة – فهي تجد أنماطًا في كميات هائلة من النصوص لفهم كيفية عمل اللغة، ثم تستخدم تلك الأنماط لتوليد ردود مناسبة على الأسئلة الجديدة. دعني أوضح ذلك بمقارنة بسيطة: - قاعدة بيانات تقليدية: مثل طلب شهادة ميلادك – تحصل على نفس الوثيقة في كل مرة - محرك بحث: مثل طلب أمين مكتبة العثور على كتب عن القطط – يظهر لك ما هو متاح - الذكاء الاصطناعي التوليدي: مثل سؤال صديق ذو معرفة عن القطط – يخبرك بأشياء مثيرة للاهتمام بكلماته الخاصة، مخصصة لما تريد معرفته ### كيف تتعلم نماذج الذكاء الاصطناعي (النسخة المبسطة) تتعلم نماذج الذكاء الاصطناعي من خلال التعرض لمجموعات بيانات ضخمة تحتوي على نصوص من كتب، مقالات، ومحادثات. من خلال هذه العملية، تحدد الأنماط في: - كيفية هيكلة الأفكار في التواصل الكتابي - الكلمات التي تظهر عادةً معًا - كيفية تدفق المحادثات عادةً - الفروقات السياقية بين التواصل الرسمي وغير الرسمي يشبه ذلك كيف يفك علماء الآثار رموز اللغات القديمة: يحللون آلاف الأمثلة لفهم القواعد، المفردات، والسياق الثقافي، وفي النهاية يصبحون قادرين على تفسير نصوص جديدة باستخدام تلك الأنماط المكتسبة. ### لماذا GitHub Models؟ نستخدم GitHub Models لسبب عملي جدًا – فهو يمنحنا الوصول إلى ذكاء اصطناعي على مستوى المؤسسات دون الحاجة إلى إعداد بنية تحتية خاصة بالذكاء الاصطناعي (والتي، صدقني، لا تريد القيام بها الآن!). فكر في الأمر كأنه استخدام واجهة برمجة تطبيقات الطقس بدلاً من محاولة التنبؤ بالطقس بنفسك عن طريق إعداد محطات الطقس في كل مكان. إنه ببساطة "الذكاء الاصطناعي كخدمة"، وأفضل جزء؟ يمكنك البدء مجانًا، لذا يمكنك التجربة دون القلق بشأن تكاليف باهظة. سنستخدم GitHub Models لتكاملنا الخلفي، الذي يوفر الوصول إلى قدرات ذكاء اصطناعي على مستوى احترافي من خلال واجهة سهلة الاستخدام للمطورين. GitHub Models Playground يعمل كبيئة اختبار حيث يمكنك تجربة نماذج ذكاء اصطناعي مختلفة وفهم قدراتها قبل تنفيذها في الكود. ## 🧠 نظام تطوير تطبيقات الذكاء الاصطناعي المبدأ الأساسي: تطوير تطبيقات الذكاء الاصطناعي يجمع بين مهارات تطوير الويب التقليدية وتكامل خدمات الذكاء الاصطناعي، مما يخلق تطبيقات ذكية تبدو طبيعية وتفاعلية للمستخدمين. ما الذي يجعل الملعب مفيدًا جدًا: - جرب نماذج ذكاء اصطناعي مختلفة مثل GPT-4o-mini، Claude، وغيرها (كلها مجانية!) - اختبر أفكارك ومطالباتك قبل كتابة أي كود - احصل على مقتطفات كود جاهزة للاستخدام بلغتك البرمجية المفضلة - عدل الإعدادات مثل مستوى الإبداع وطول الاستجابة لترى كيف تؤثر على النتائج بمجرد أن تجرب قليلاً، فقط انقر على علامة التبويب "Code" واختر لغتك البرمجية للحصول على كود التنفيذ الذي تحتاجه. ## إعداد تكامل الخلفية باستخدام Python الآن دعونا ننفذ التكامل مع الذكاء الاصطناعي باستخدام Python. Python ممتازة لتطبيقات الذكاء الاصطناعي بسبب بساطة صياغتها ومكتباتها القوية. سنبدأ بالكود من ملعب GitHub Models ثم نعيد صياغته ليصبح وظيفة قابلة لإعادة الاستخدام وجاهزة للإنتاج. ### فهم التنفيذ الأساسي عندما تحصل على كود Python من الملعب، سيبدو كالتالي. لا تقلق إذا بدا كثيرًا في البداية – دعونا نمر عليه خطوة بخطوة: ما الذي يحدث في هذا الكود: - نستورد الأدوات التي نحتاجها: os لقراءة متغيرات البيئة وOpenAI للتواصل مع الذكاء الاصطناعي - نقوم بإعداد عميل OpenAI للإشارة إلى خوادم الذكاء الاصطناعي الخاصة بـ GitHub بدلاً من OpenAI مباشرة - نقوم بالمصادقة باستخدام رمز GitHub خاص (المزيد عن ذلك لاحقًا!) - نهيكل محادثتنا بأدوار مختلفة – فكر فيها كإعداد المشهد لمسرحية - نرسل طلبنا إلى الذكاء الاصطناعي مع بعض معلمات الضبط - نستخرج النص الفعلي للاستجابة من جميع البيانات التي تعود ### فهم أدوار الرسائل: إطار عمل المحادثة مع الذكاء الاصطناعي تستخدم محادثات الذكاء الاصطناعي هيكلًا محددًا بأدوار مختلفة تخدم أغراضًا متميزة: فكر فيها كإخراج مسرحية: - دور النظام: مثل تعليمات المسرح للممثل – يخبر الذكاء الاصطناعي كيف يتصرف، وما الشخصية التي يجب أن يتبناها، وكيف يرد - دور المستخدم: السؤال الفعلي أو الرسالة من الشخص الذي يستخدم التطبيق - دور المساعد: استجابة الذكاء الاصطناعي (لا ترسل هذا، لكنه يظهر في تاريخ المحادثة) تشبيه واقعي: تخيل أنك تقدم صديقًا لشخص ما في حفلة: - رسالة النظام: "هذا صديقي سارة، هي طبيبة رائعة في شرح المفاهيم الطبية بطريقة بسيطة" - رسالة المستخدم: "هل يمكنك شرح كيفية عمل اللقاحات؟" - استجابة المساعد: سارة ترد كطبيبة ودودة، وليس كمحامية أو طاهية ### فهم معلمات الذكاء الاصطناعي: ضبط سلوك الاستجابة تتحكم المعلمات الرقمية في استدعاءات واجهات برمجة تطبيقات الذكاء الاصطناعي في كيفية توليد النموذج للاستجابات. تتيح لك هذه الإعدادات ضبط سلوك الذكاء الاصطناعي لحالات الاستخدام المختلفة: #### درجة الحرارة (0.0 إلى 2.0): مؤشر الإبداع ما الذي تفعله: تتحكم في مدى إبداع أو توقع استجابات الذكاء الاصطناعي. فكر فيها كمستوى ارتجال عازف الجاز: - درجة الحرارة = 0.1: يعزف نفس اللحن تمامًا في كل مرة (متوقع للغاية) - درجة الحرارة = 0.7: يضيف بعض التغييرات اللطيفة مع الحفاظ على التعرف (إبداع متوازن) - درجة الحرارة = 1.5: ارتجال كامل مع تحولات غير متوقعة (غير متوقع للغاية) #### الحد الأقصى للرموز (1 إلى 4096+): التحكم في طول الاستجابة ما الذي تفعله: تحدد حدًا لطول استجابة الذكاء الاصطناعي. فكر في الرموز كأنها تعادل الكلمات تقريبًا (حوالي 1 رمز = 0.75 كلمة بالإنجليزية): - max_tokens=50: قصير ومباشر (مثل رسالة نصية) - max_tokens=500: فقرة أو اثنتين - max_tokens=2000: شرح مفصل مع أمثلة #### Top_p (0.0 إلى 1.0): مؤشر التركيز ما الذي تفعله: تتحكم في مدى تركيز الذكاء الاصطناعي على الاستجابات الأكثر احتمالًا. تخيل الذكاء الاصطناعي لديه مفردات ضخمة، مرتبة حسب مدى احتمال كل كلمة: - top_p=0.1: يأخذ في الاعتبار أعلى 10% من الكلمات الأكثر احتمالًا (مركّز جدًا) - top_p=0.9: يأخذ في الاعتبار 90% من الكلمات الممكنة (أكثر إبداعًا) - top_p=1.0: يأخذ في الاعتبار كل شيء (أقصى تنوع) على سبيل المثال: إذا سألت "السماء عادةً..." - top_p منخفض: سيقول "زرقاء" بالتأكيد - top_p مرتفع: قد يقول "زرقاء"، "غائمة"، "واسعة"، "متغيرة"، "جميلة"، إلخ. ### جمع كل شيء معًا: تركيبات المعلمات لحالات الاستخدام المختلفة فهم لماذا هذه المعلمات مهمة: التطبيقات المختلفة تحتاج إلى أنواع مختلفة من الاستجابات. يجب أن يكون روبوت خدمة العملاء متسقًا وواقعيًا (درجة حرارة منخفضة)، بينما يجب أن يكون مساعد الكتابة الإبداعي خياليًا ومتغيرًا (درجة حرارة عالية). فهم هذه المعلمات يمنحك التحكم في شخصية الذكاء الاصطناعي وأسلوب استجابته. import asyncio from openai import AsyncOpenAI # Use AsyncOpenAI for better performance client = AsyncOpenAI( base_url="https://models.github.ai/inference", api_key=os.environ["GITHUB_TOKEN"], async def call_llm_async(prompt: str, system_message: str = "You are a helpful assistant."): """ Sends a prompt to the AI model asynchronously and returns the response. Args: prompt: The user's question or message system_message: Instructions that define the AI's behavior and personality Returns: str: The AI's response to the prompt """ try: response = await client.chat.completions.create( messages=[ "role": "system", "content": system_message, "role": "user", "content": prompt, model="openai/gpt-4o-mini", temperature=1, max_tokens=4096, top_p=1 return response.choices[0].message.content except Exception as e: logger.error(f"AI API error: {str(e)}") return "I'm sorry, I'm having trouble processing your request right now." # Backward compatibility function for synchronous calls def call_llm(prompt: str, system_message: str = "You are a helpful assistant."): """Synchronous wrapper for async AI calls.""" return asyncio.run(call_llm_async(prompt, system_message)) # ❌ Vague system prompt "You are helpful." # ✅ Detailed, effective system prompt "You are Dr. Sarah Chen, a senior software engineer with 15 years of experience at major tech companies. You explain programming concepts using real-world analogies and always provide practical examples. You're patient with beginners and enthusiastic about helping them understand complex topics." # Example 1: The Patient Teacher teacher_prompt = """ You are an experienced programming instructor who has taught thousands of students. You break down complex concepts into simple steps, use analogies from everyday life, and always check if the student understands before moving on. You're encouraging and never make students feel bad for not knowing something. """ # Example 2: The Creative Collaborator creative_prompt = """ You are a creative writing partner who loves brainstorming wild ideas. You're enthusiastic, imaginative, and always build on the user's ideas rather than replacing them. You ask thought-provoking questions to spark creativity and offer unexpected perspectives that make stories more interesting. """ # Example 3: The Strategic Business Advisor business_prompt = """ You are a strategic business consultant with an MBA and 20 years of experience helping startups scale. You think in frameworks, provide structured advice, and always consider both short-term tactics and long-term strategy. You ask probing questions to understand the full business context before giving advice. """ # With teacher prompt: teacher_response = call_llm( "How do I handle user authentication in my web app?", teacher_prompt # Typical response: "Great question! Let's break authentication down into simple steps. # Think of it like a nightclub bouncer checking IDs..." # With business prompt: business_response = call_llm( "How do I handle user authentication in my web app?", business_prompt # Typical response: "From a strategic perspective, authentication is crucial for user # trust and regulatory compliance. Let me outline a framework considering security, # user experience, and scalability..." system_prompt = """ You are helping a junior developer who just started their first job at a startup. They know basic HTML/CSS/JavaScript but are new to backend development and databases. Be encouraging and explain things step-by-step without being condescending. """ system_prompt = """ You are a technical mentor. Always structure your responses as: 1. Quick Answer (1-2 sentences) 2. Detailed Explanation 3. Code Example 4. Common Pitfalls to Avoid 5. Next Steps for Learning """ system_prompt = """ You are a coding tutor focused on teaching best practices. Never write complete solutions for the user - instead, guide them with hints and questions so they learn by doing. Always explain the 'why' behind coding decisions. """ sequenceDiagram participant User as 👤 User participant Frontend as 🌐 Frontend participant API as 🔧 FastAPI Server participant AI as 🤖 AI Service User->>Frontend: Types "Hello AI!" Frontend->>API: POST /hello {"message": "Hello AI!"} Note over API: Validates requestAdds system prompt API->>AI: Sends formatted request AI->>API: Returns AI response Note over API: Processes responseLogs conversation API->>Frontend: {"response": "Hello! How can I help?"} Frontend->>User: Displays AI message sequenceDiagram participant Frontend participant FastAPI participant AI Function participant GitHub Models Frontend->>FastAPI: POST /hello {"message": "Hello AI!"} FastAPI->>AI Function: call_llm(message, system_prompt) AI Function->>GitHub Models: API request GitHub Models->>AI Function: AI response AI Function->>FastAPI: response text FastAPI->>Frontend: {"response": "Hello! How can I help?"} flowchart TD A[User Input] --> B[Frontend Validation] B --> C[HTTP POST Request] C --> D[FastAPI Router] D --> E[Pydantic Validation] E --> F[AI Function Call] F --> G[GitHub Models API] G --> H[Response Processing] H --> I[JSON Response] I --> J[Frontend Update] subgraph "Security Layer" K[CORS Middleware] L[Environment Variables] M[Error Handling] end D --> K F --> L H --> M # api.py from fastapi import FastAPI, HTTPException from fastapi.middleware.cors import CORSMiddleware from pydantic import BaseModel from llm import call_llm import logging # Configure logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name) # Create FastAPI application app = FastAPI( title="AI Chat API", description="A high-performance API for AI-powered chat applications", version="1.0.0" # Configure CORS app.add_middleware( CORSMiddleware, allow_origins=[""], # Configure appropriately for production allow_credentials=True, allow_methods=[""], allow_headers=["*"], # Pydantic models for request/response validation class ChatMessage(BaseModel): message: str class ChatResponse(BaseModel): response: str @app.get("/") async def root(): """Root endpoint providing API information.""" return { "message": "Welcome to the AI Chat API", "docs": "/docs", "health": "/health" @app.get("/health") async def health_check(): """Health check endpoint.""" return {"status": "healthy", "service": "ai-chat-api"} @app.post("/hello", response_model=ChatResponse) async def chat_endpoint(chat_message: ChatMessage): """Main chat endpoint that processes messages and returns AI responses.""" try: # Extract and validate message message = chat_message.message.strip() if not message: raise HTTPException(status_code=400, detail="Message cannot be empty") logger.info(f"Processing message: {message[:50]}...") # Call AI service (note: call_llm should be made async for better performance) ai_response = await call_llm_async(message, "You are a helpful and friendly assistant.") logger.info("AI response generated successfully") return ChatResponse(response=ai_response) except HTTPException: raise except Exception as e: logger.error(f"Error processing chat message: {str(e)}") raise HTTPException(status_code=500, detail="Internal server error") if name == "main": import uvicorn uvicorn.run(app, host="0.0.0.0", port=5000, reload=True) from fastapi.middleware.cors import CORSMiddleware app = FastAPI(name) CORS(app) # This tells browsers: "It's okay for other origins to make requests to this API" # 🚨 Development: Allows ALL origins (convenient but insecure) CORS(app) # ✅ Production: Only allow your specific frontend domain CORS(app, origins=["https://yourdomain.com", "https://www.yourdomain.com"]) # 🔒 Advanced: Different origins for different environments if app.debug: # Development mode CORS(app, origins=["http://localhost:3000", "http://127.0.0.1:3000"]) else: # Production mode CORS(app, origins=["https://yourdomain.com"]) # Validate that we received a message if not message: return jsonify({"error": "Message field is required"}), 400 # Navigate to your backend directory cd backend # Create a virtual environment (like creating a clean room for your project) python -m venv venv # Activate it (Linux/Mac) source ./venv/bin/activate # On Windows, use: # venv\Scripts\activate # Install the good stuff pip install openai fastapi uvicorn python-dotenv # 🚨 NEVER DO THIS - API key visible to everyone client = OpenAI( api_key="ghp_1234567890abcdef...", # Anyone can steal this! base_url="https://models.github.ai/inference" # ✅ DO THIS - API key stored securely client = OpenAI( api_key=os.environ["GITHUB_TOKEN"], # Only your app can access this base_url="https://models.github.ai/inference" # .env file - This should NEVER be committed to Git GITHUB_TOKEN=your_github_personal_access_token_here FASTAPI_DEBUG=True ENVIRONMENT=development # Example of what your token looks like (this is fake!) GITHUB_TOKEN=ghp_1A2B3C4D5E6F7G8H9I0J1K2L3M4N5O6P7Q8R import os from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Now you can access them securely api_key = os.environ.get("GITHUB_TOKEN") if not api_key: raise ValueError("GITHUB_TOKEN not found in environment variables!") client = OpenAI( api_key=api_key, base_url="https://models.github.ai/inference" # .gitignore - Add these lines .env *.env .env.local .env.production pycache/ venv/ .vscode/ # .env.development GITHUB_TOKEN=your_development_token DEBUG=True # .env.production GITHUB_TOKEN=your_production_token DEBUG=False # Method 1: Direct Python execution (includes auto-reload) python api.py # Method 2: Using Uvicorn directly (more control) uvicorn api:app --host 0.0.0.0 --port 5000 --reload $ python api.py INFO: Will watch for changes in these directories: ['/your/project/path'] INFO: Uvicorn running on http://0.0.0.0:5000 (Press CTRL+C to quit) INFO: Started reloader process [12345] using WatchFiles INFO: Started server process [12346] INFO: Waiting for application startup. INFO: Application startup complete. # Test with curl (if available) curl -X POST http://localhost:5000/hello \ -H "Content-Type: application/json" \ -d '{"message": "Hello AI!"}' # Expected response: # {"response": "Hello! I'm your AI assistant. How can I help you today?"} # test_api.py - Create this file to test your API import requests import json # Test the API endpoint url = "http://localhost:5000/hello" data = {"message": "Tell me a joke about programming"} response = requests.post(url, json=data) if response.status_code == 200: result = response.json() print("AI Response:", result['response']) else: print("Error:", response.status_code, response.text) # Enable hot reloading explicitly if name == "main": app.run(host="0.0.0.0", port=5000, debug=True) # debug=True enables hot reload import logging # Set up logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(name) @app.route("/hello", methods=["POST"]) def hello(): data = request.get_json() message = data.get("message", "") logger.info(f"Received message: {message}") if not message: logger.warning("Empty message received") return jsonify({"error": "Message field is required"}), 400 try: response = call_llm(message, "You are a helpful and friendly assistant.") logger.info(f"AI response generated successfully") return jsonify({"response": response}) except Exception as e: logger.error(f"AI API error: {str(e)}") return jsonify({"error": "AI service temporarily unavailable"}), 500 cd backend python api.py https://your-codespace-name-5000.app.github.dev // In your frontend app.js, update the BASE_URL: this.BASE_URL = "https://your-codespace-name-5000.app.github.dev"; https://[codespace-name]-[port].app.github.dev Welcome to the AI Chat API. Send POST requests to /hello with JSON payload containing 'message' field. // Open browser console and test your API fetch('https://your-codespace-name-5000.app.github.dev/hello', { method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify({message: 'Hello from Codespaces!'}) .then(response => response.json()) .then(data => console.log(data)); # Set environment variable for the current session export GITHUB_TOKEN="your_token_here" # Or add to your .bashrc for persistence echo 'export GITHUB_TOKEN="your_token_here"' >> ~/.bashrc graph TD A[User Types Message] --> B[JavaScript Captures Input] B --> C[Validate & Format Data] C --> D[Send to Backend API] D --> E[Display Loading State] E --> F[Receive AI Response] F --> G[Update Chat Interface] G --> H[Ready for Next Message] classDiagram class ChatApp { +messages: HTMLElement +form: HTMLElement +input: HTMLElement +sendButton: HTMLElement +BASE_URL: string +API_ENDPOINT: string +constructor() +initializeEventListeners() +handleSubmit(event) +callAPI(message) +appendMessage(text, role) +escapeHtml(text) +scrollToBottom() +setLoading(isLoading) ChatApp --> DOM : manipulates ChatApp --> FastAPI : sends requests frontend/ ├── index.html # Main HTML structure ├── app.js # JavaScript functionality └── styles.css # Visual styling AI Chat Assistant AI Chat Assistant Ask me anything! <input type="text" id="messageInput" placeholder="Type your message here..." required aria-label="Chat message input" Send // app.js - Modern chat application logic class ChatApp { constructor() { // Get references to DOM elements we'll need to manipulate this.messages = document.getElementById("messages"); this.form = document.getElementById("chatForm"); this.input = document.getElementById("messageInput"); this.sendButton = document.getElementById("sendBtn"); // Configure your backend URL here this.BASE_URL = "http://localhost:5000"; // Update this for your environment this.API_ENDPOINT = ${this.BASE_URL}/hello; // Set up event listeners when the chat app is created this.initializeEventListeners(); initializeEventListeners() { // Listen for form submission (when user clicks Send or presses Enter) this.form.addEventListener("submit", (e) => this.handleSubmit(e)); // Also listen for Enter key in the input field (better UX) this.input.addEventListener("keypress", (e) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); this.handleSubmit(e); }); async handleSubmit(event) { event.preventDefault(); // Prevent form from refreshing the page const messageText = this.input.value.trim(); if (!messageText) return; // Don't send empty messages // Provide user feedback that something is happening this.setLoading(true); // Add user message to chat immediately (optimistic UI) this.appendMessage(messageText, "user"); // Clear input field so user can type next message this.input.value = ''; try { // Call the AI API and wait for response const reply = await this.callAPI(messageText); // Add AI response to chat this.appendMessage(reply, "assistant"); } catch (error) { console.error('API Error:', error); this.appendMessage("Sorry, I'm having trouble connecting right now. Please try again.", "error"); } finally { // Re-enable the interface regardless of success or failure this.setLoading(false); async callAPI(message) { const response = await fetch(this.API_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json" body: JSON.stringify({ message }) }); if (!response.ok) { throw new Error(HTTP error! status: ${response.status}); const data = await response.json(); return data.response; appendMessage(text, role) { const messageElement = document.createElement("div"); messageElement.className = message ${role}; messageElement.innerHTML = ` ${this.escapeHtml(text)} ${new Date().toLocaleTimeString()} this.messages.appendChild(messageElement); this.scrollToBottom(); escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; return div.innerHTML; scrollToBottom() { this.messages.scrollTop = this.messages.scrollHeight; setLoading(isLoading) { this.sendButton.disabled = isLoading; this.input.disabled = isLoading; this.sendButton.textContent = isLoading ? "Sending..." : "Send"; // Initialize the chat application when the page loads document.addEventListener("DOMContentLoaded", () => { new ChatApp(); }); class ChatApp { constructor() { // This runs when you create a new ChatApp instance // It's like the "setup" function for your chat methodName() { // Methods are functions that belong to the class // They can access class properties using "this" // Old way (callback hell): fetch(url) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error)); // Modern way (async/await): try { const response = await fetch(url); const data = await response.json(); console.log(data); } catch (error) { console.error(error); // When form is submitted, run handleSubmit this.form.addEventListener("submit", (e) => this.handleSubmit(e)); // When Enter key is pressed, also run handleSubmit this.input.addEventListener("keypress", (e) => { / ... / }); // Create new elements const messageElement = document.createElement("div"); // Modify their properties messageElement.className = "message user"; messageElement.innerHTML = "Hello world!"; // Add to the page this.messages.appendChild(messageElement); escapeHtml(text) { const div = document.createElement('div'); div.textContent = text; // This automatically escapes HTML return div.innerHTML; try { const reply = await this.callAPI(messageText); this.appendMessage(reply, "assistant"); } catch (error) { // Show user-friendly error instead of breaking the app this.appendMessage("Sorry, I'm having trouble...", "error"); / styles.css - Modern chat interface styling / :root { --primary-color: #2563eb; --secondary-color: #f1f5f9; --user-color: #3b82f6; --assistant-color: #6b7280; --error-color: #ef4444; --text-primary: #1e293b; --text-secondary: #64748b; --border-radius: 12px; --shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); * { margin: 0; padding: 0; box-sizing: border-box; body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 20px; .chat-container { width: 100%; max-width: 800px; height: 600px; background: white; border-radius: var(--border-radius); box-shadow: var(--shadow); display: flex; flex-direction: column; overflow: hidden; .chat-header { background: var(--primary-color); color: white; padding: 20px; text-align: center; .chat-header h1 { font-size: 1.5rem; margin-bottom: 5px; .chat-header p { opacity: 0.9; font-size: 0.9rem; .chat-messages { flex: 1; padding: 20px; overflow-y: auto; display: flex; flex-direction: column; gap: 15px; background: var(--secondary-color); .message { display: flex; max-width: 80%; animation: slideIn 0.3s ease-out; .message.user { align-self: flex-end; .message.user .message-content { background: var(--user-color); color: white; border-radius: var(--border-radius) var(--border-radius) 4px var(--border-radius); .message.assistant { align-self: flex-start; .message.assistant .message-content { background: white; color: var(--text-primary); border-radius: var(--border-radius) var(--border-radius) var(--border-radius) 4px; border: 1px solid #e2e8f0; .message.error .message-content { background: var(--error-color); color: white; border-radius: var(--border-radius); .message-content { padding: 12px 16px; box-shadow: var(--shadow); position: relative; .message-text { display: block; line-height: 1.5; word-wrap: break-word; .message-time { display: block; font-size: 0.75rem; opacity: 0.7; margin-top: 5px; .chat-form { padding: 20px; border-top: 1px solid #e2e8f0; background: white; .input-group { display: flex; gap: 10px; align-items: center; #messageInput { flex: 1; padding: 12px 16px; border: 2px solid #e2e8f0; border-radius: var(--border-radius); font-size: 1rem; outline: none; transition: border-color 0.2s ease; #messageInput:focus { border-color: var(--primary-color); #messageInput:disabled { background: #f8fafc; opacity: 0.6; cursor: not-allowed; #sendBtn { padding: 12px 24px; background: var(--primary-color); color: white; border: none; border-radius: var(--border-radius); font-size: 1rem; font-weight: 600; cursor: pointer; transition: background-color 0.2s ease; min-width: 80px; #sendBtn:hover:not(:disabled) { background: #1d4ed8; #sendBtn:disabled { background: #94a3b8; cursor: not-allowed; @keyframes slideIn { from { opacity: 0; transform: translateY(10px); to { opacity: 1; transform: translateY(0); / Responsive design for mobile devices / @media (max-width: 768px) { body { padding: 10px; .chat-container { height: calc(100vh - 20px); border-radius: 8px; .message { max-width: 90%; .input-group { flex-direction: column; gap: 10px; #messageInput { width: 100%; #sendBtn { width: 100%; / Accessibility improvements / @media (prefers-reduced-motion: reduce) { .message { animation: none; * { transition: none !important; / Dark mode support / @media (prefers-color-scheme: dark) { .chat-container { background: #1e293b; color: #f1f5f9; .chat-messages { background: #0f172a; .message.assistant .message-content { background: #334155; color: #f1f5f9; border-color: #475569; .chat-form { background: #1e293b; border-color: #475569; #messageInput { background: #334155; color: #f1f5f9; border-color: #475569; // For local development this.BASE_URL = "http://localhost:5000"; // For GitHub Codespaces (replace with your actual URL) this.BASE_URL = "https://your-codespace-name-5000.app.github.dev"; graph TD A[Start Backend Server] --> B[Configure Environment Variables] B --> C[Test API Endpoints] C --> D[Open Frontend in Browser] D --> E[Test Chat Functionality] E --> F[Debug Any Issues] timeline title Complete AI Application Development Journey section AI Foundations Understanding Generative AI : Grasp pattern recognition concepts : Master AI parameter control : Learn prompt engineering techniques GitHub Models Integration : Navigate AI service platforms : Handle authentication securely : Optimize model parameters section Backend Development Python API Architecture : Build FastAPI applications : Implement async operations : Create secure endpoints AI Service Integration : Connect to external AI APIs : Handle rate limiting : Implement error boundaries section Frontend Mastery Modern JavaScript Patterns : Master ES6 class architecture : Implement async/await flows : Build responsive interfaces Real-time User Experience : Create dynamic chat interfaces : Handle loading states : Optimize user interactions section Production Readiness Security & Performance : Implement secure token management : Prevent XSS vulnerabilities : Optimize API performance Professional Deployment : Build scalable architectures : Create maintainable code : Document development processes my-ai-assistant/ ├── backend/ │ ├── api.py # Your FastAPI server │ ├── llm.py # AI integration functions │ ├── .env # Your secrets (keep this safe!) │ └── requirements.txt # Python dependencies ├── frontend/ │ ├── index.html # Your chat interface │ ├── app.js # The JavaScript magic │ └── styles.css # Make it look amazing └── README.md # Tell the world about your creation call_llm(message, "You are a professional business consultant with 20 years of experience. Provide structured, actionable advice with specific steps and considerations.") call_llm(message, "You are an enthusiastic creative writing coach. Help users develop their storytelling skills with imaginative prompts and constructive feedback.") call_llm(message, "You are a patient senior developer who explains complex programming concepts using simple analogies and practical examples.") mindmap root((AI Chat App Skills)) API Integration Authentication Error Handling Async Programming Web Development HTML5 Semantics Modern CSS ES6+ JavaScript User Experience Responsive Design Accessibility Real-time Interaction AI Understanding Prompt Engineering Model Parameters Conversation Flow
flowchart LR A[⚡ 5 minutes] --> B[Get GitHub token] B --> C[Test AI playground] C --> D[Copy Python code] D --> E[See AI responses]
Follow the lesson from Microsoft Web-Dev-For-Beginners course