بناء فريق من وكلاء الذكاء الاصطناعي لموقعك مجانًا باستخدام Agno و Groq
وكلاء الذكاء الاصطناعي (AI Agents) هم برامج ذكية تتفاعل مع زوار موقعك تلقائيًا. باستخدام مكتبة Agno كطبقة تنسيق وخدمة Groq Cloud كمحرك استدلال فائق السرعة مع نموذج LLaMA 3.3 70B، يمكنك بناء خمسة وكلاء متخصصين:
- 🎭 وكيل الترحيب — يستقبل الزوار ويوجههم
- 💼 وكيل المشاريع — يعرض أعمالك التقنية
- 📋 وكيل المسيرة المهنية — يلخص خبراتك ومهاراتك
- 🤝 وكيل العملاء — يقدم الخدمات والأسعار
- 🔬 وكيل الأبحاث — يبحث عن أحدث التقنيات
مع واجهة Python خلفية عبر Flask وواجهة React أمامية عبر Vite — مجانًا تمامًا.
🚀 المقدمة
يشهد عالم تطوير الويب تحولًا جذريًا بفضل الذكاء الاصطناعي، حيث أصبحت الشركات والمطورون يعتمدون بشكل متزايد على وكلاء ذكاء اصطناعي لتقديم تجارب تفاعلية لزوار مواقعهم.
تخيّل أن يكون لديك فريق كامل من المساعدين الأذكياء يعملون على موقعك على مدار الساعة:
- ✨ يرحبون بالزوار بشكل شخصي حسب نوعهم
- 💬 يجيبون عن أسئلتهم التقنية والعملية
- 🖥️ يعرضون مشاريعك بالتفصيل
- 💰 يقدمون استشارات وعروض أسعار للعملاء المحتملين
- 🔍 يبحثون عن أحدث التقنيات والاتجاهات
وكل ذلك مجانًا تمامًا!
في هذا الدليل الشامل، سأرشدك خطوة بخطوة لبناء هذا الفريق باستخدام أدوات مجانية ومفتوحة المصدر. سأعرض لك الكود الكامل لكل ملف في المشروع حتى تتمكن من تطبيقه مباشرة.
🤖 ما هم وكلاء الذكاء الاصطناعي (AI Agents)؟
وكلاء الذكاء الاصطناعي هم أنظمة برمجية ذكية مصممة لاستخدام تقنيات الذكاء الاصطناعي للتفاعل مع بيئتها وتحقيق أهداف محددة. يمكنهم إدراك محيطهم — من خلال مدخلات المستخدم أو البيانات — واتخاذ إجراءات لتحقيق الأهداف بدرجة معينة من الاستقلالية.
على عكس روبوتات الدردشة التقليدية التي تعتمد على ردود مبرمجة مسبقًا، يستطيع وكلاء الذكاء الاصطناعي:
- 🧠 فهم السياق — يدركون ما يقصده المستخدم حتى لو لم يكن واضحًا
- 🎯 تقديم إجابات مخصصة — يولّدون ردودًا فريدة لكل سؤال
- 📚 التعلم من التفاعلات — يتحسنون مع الوقت
- 🔗 التكامل مع أنظمة أخرى — يمكنهم البحث والتحليل واتخاذ إجراءات
🆚 الفرق بين روبوت الدردشة التقليدي ووكيل الذكاء الاصطناعي
-
📋 ردود محددة مسبقاً
يعتمد على سيناريوهات ثابتة -
🔄 تفاعل محدود
مسارات محادثة جامدة -
❌ فهم سطحي
يعتمد على الكلمات المفتاحية فقط -
⚙️ صيانة معقدة
يحتاج تحديث يدوي مستمر
-
🎓 تعلم مستمر
يتحسن تلقائياً مع كل تفاعل -
💡 ذكاء سياقي
يفهم النوايا والسياق -
✨ ردود ديناميكية
يولد إجابات فريدة ومخصصة -
🔗 تكامل متقدم
يتصل بأنظمة وأدوات متعددة
🛠️ ما هي Agno و Groq Cloud؟
قبل الغوص في التطبيق العملي، من الضروري فهم الأدوات الرئيسية التي سنستخدمها.
🔷 Agno: طبقة التنسيق الذكية
Agno هي مكتبة Python خفيفة الوزن تتيح لك بناء وكلاء ذكاء اصطناعي متعددي الوسائط (Multimodal Agents). تعمل كـطبقة تنسيق (Orchestration Layer) التي:
- تدير المحادثات بين الوكلاء المتعددين
- تفوّض المهام للوكيل المناسب
- تدير الذاكرة والسياق
- توفر واجهة موحدة للتعامل مع نماذج LLM مختلفة
⚡ Groq Cloud: محرك الاستدلال فائق السرعة
Groq Cloud هي منصة استدلال ذكاء اصطناعي سحابية تعتمد على شرائح Groq LPU (وحدة معالجة اللغة) المُحسّنة لأحمال العمل ذات زمن استجابة منخفض للغاية.
ملاحظة مهمة: Groq Cloud ليست نموذج لغة كبير بحد ذاتها، بل هي محرك استدلال عالي الأداء يستضيف ويخدم نماذج LLM من مزودين متعددين:
- 🦙 Meta LLaMA — النموذج الذي سنستخدمه:
llama-3.3-70b-versatile - 🔮 DeepSeek R1
- 💎 Google Gemma 2
- 🌬️ Mistral AI
- 🏮 Qwen
هذا النموذج يوفر توازنًا ممتازًا بين الأداء والسرعة، ويدعم اللغة العربية بشكل جيد، ومتاح مجانًا على Groq Cloud. يمكنك تغيير النموذج لاحقًا إذا أردت.
🏗️ ما الذي ستبنيه في هذا المشروع؟
ستبني موقع محفظة أعمال شخصية (Portfolio) يتضمن فريقًا من خمسة وكلاء ذكاء اصطناعي متخصصين. هؤلاء الوكلاء يعملون كممثلي خدمة عملاء ذكيين — يمكن لأي شخص سؤالهم عن مهاراتك ومشاريعك وخبراتك.
📄 صفحات الموقع:
الرئيسية
Home
المشاريع
Projects
المسيرة المهنية
Career
الخدمات
Services
الأبحاث
Research
التواصل
Contact
📦 المتطلبات الأساسية
قبل البدء، تأكد من توفر المتطلبات التالية على جهازك:
✅ المعرفة المطلوبة:
- معرفة أساسية بلغة Python
- معرفة أساسية بـ JavaScript و React
- فهم مبادئ REST APIs
- معرفة بأوامر Terminal/Command Line
💻 البرامج المطلوبة:
- Python 3.8+ — تحميل Python
- Node.js 18+ و npm — تحميل Node.js
- محرر أكواد — VS Code أو Cursor أو PyCharm
- Git (اختياري) — لإدارة الإصدارات
🔑 الحسابات المطلوبة:
- حساب على Groq Cloud (مجاني) — إنشاء حساب
🔐 إنشاء حساب على Groq Cloud والحصول على مفتاح API
الخطوة الأولى هي إنشاء حساب مجاني على Groq Cloud للحصول على مفتاح API الذي سيمكّن وكلاءنا من التواصل مع نماذج الذكاء الاصطناعي.
📝 خطوات إنشاء الحساب:
- توجه إلى صفحة تسجيل Groq Cloud
- سجّل الدخول باستخدام حساب Google أو GitHub أو أنشئ حسابًا جديدًا
- بعد تسجيل الدخول، انتقل إلى صفحة "API Keys" من القائمة الجانبية
- اضغط على "Create API Key"
-
أعطِ المفتاح اسمًا مميزًا (مثلاً:
ai-agents-portfolio) - مهم جداً: انسخ المفتاح واحفظه في مكان آمن — لن تتمكن من رؤيته مرة أخرى!
إنشاء مفتاح API على Groq Cloud
- ❌ لا تشارك مفتاح API مع أي شخص
- ❌ لا ترفعه إلى مستودعات عامة على GitHub
- ✅ استخدم دائمًا ملفات
.envلتخزين المفاتيح السرية - ✅ أضف
.envإلى ملف.gitignore
الخدمة مجانية لكن توجد حدود للاستخدام يمكنك مراجعتها في توثيق Rate Limits. الحد المجاني كافٍ جدًا للمشاريع الشخصية والتعليمية.
🐍 إعداد مشروع Python (الواجهة الخلفية)
سنبدأ الآن ببناء الواجهة الخلفية (Backend) باستخدام Python و Flask. سننشئ بيئة افتراضية نظيفة ونثبت جميع الحزم المطلوبة.
📁 الخطوة 1: إنشاء مجلد المشروع والبيئة الافتراضية
افتح Terminal أو Command Prompt ونفّذ الأوامر التالية:
# إنشاء مجلد المشروع الرئيسي
mkdir ai-agents-portfolio
cd ai-agents-portfolio
# إنشاء مجلد الواجهة الخلفية
mkdir backend
cd backend
# إنشاء بيئة Python الافتراضية
python -m venv venv
# تفعيل البيئة على Windows
venv\Scripts\activate
# تفعيل البيئة على macOS/Linux
# source venv/bin/activate
البيئة الافتراضية هي مساحة معزولة تحتوي على نسخة مستقلة من Python والحزم المثبتة. هذا يمنع التعارض بين المشاريع المختلفة ويضمن أن مشروعك يعمل بنفس الطريقة على أي جهاز.
📦 الخطوة 2: تثبيت الحزم المطلوبة
بعد تفعيل البيئة الافتراضية، ثبّت الحزم التالية:
# تثبيت جميع الحزم المطلوبة
pip install agno groq flask flask-cors requests python-dotenv
🗂️ الخطوة 3: إنشاء هيكل الملفات
سننشئ الآن هيكل المجلدات والملفات للمشروع:
# إنشاء مجلد الوكلاء
mkdir agents
# إنشاء الملفات (Windows - PowerShell)
New-Item -ItemType File -Name ".env"
New-Item -ItemType File -Name "main.py"
New-Item -ItemType File -Name "agents/__init__.py"
New-Item -ItemType File -Name "agents/base_agent.py"
New-Item -ItemType File -Name "agents/welcome_agent.py"
New-Item -ItemType File -Name "agents/project_agent.py"
New-Item -ItemType File -Name "agents/career_agent.py"
New-Item -ItemType File -Name "agents/client_agent.py"
New-Item -ItemType File -Name "agents/research_agent.py"
# على macOS/Linux استخدم touch بدلاً من New-Item
# touch .env main.py
# touch agents/__init__.py agents/base_agent.py ...
📂 هيكل مجلد backend/
backend/
├── 📄 .env # متغيرات البيئة (مفتاح API)
├── 📄 .gitignore # ملفات يتجاهلها Git
├── 📄 main.py # الملف الرئيسي (Flask Server)
├── 📄 requirements.txt # قائمة الحزم
└── 📁 agents/ # مجلد الوكلاء
├── 📄 __init__.py # ملف التصدير
├── 📄 base_agent.py # الوكيل الأساسي
├── 📄 welcome_agent.py # وكيل الترحيب
├── 📄 project_agent.py # وكيل المشاريع
├── 📄 career_agent.py # وكيل المسيرة المهنية
├── 📄 client_agent.py # وكيل العملاء
└── 📄 research_agent.py # وكيل الأبحاث
🔑 الخطوة 4: إعداد ملف المتغيرات البيئية (.env)
افتح ملف .env
وأضف مفتاح API الذي حصلت عليه من Groq Cloud:
📄 ملف: .env
# Groq Cloud API Key
GROQ_API_KEY=gsk_your_actual_api_key_here
# يمكنك إضافة متغيرات أخرى لاحقاً
# FLASK_ENV=development
# FLASK_DEBUG=1
استبدل gsk_your_actual_api_key_here بمفتاح API الحقيقي الذي نسخته من Groq Cloud.
المفتاح يبدأ عادةً بـ gsk_.
📄 الخطوة 5: إنشاء ملف .gitignore
إذا كنت ستستخدم Git، أنشئ ملف .gitignore لحماية ملفاتك الحساسة:
📄 ملف: .gitignore
# Environment variables
.env
.env.local
.env.*.local
# Python
venv/
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
dist/
*.egg-info/
# IDE
.vscode/
.idea/
*.swp
*.swo
# OS
.DS_Store
Thumbs.db
📋 الخطوة 6: إنشاء ملف requirements.txt
هذا الملف يسهّل تثبيت الحزم على أي جهاز آخر:
📄 ملف: requirements.txt
agno>=1.0.0
groq>=0.4.0
flask>=3.0.0
flask-cors>=4.0.0
requests>=2.31.0
python-dotenv>=1.0.0
🤖 ملفات الوكلاء (الكود الكامل)
الآن ننتقل إلى كتابة الكود الفعلي للوكلاء. سنبدأ بالوكيل الأساسي الذي ترث منه جميع الوكلاء، ثم نُنشئ كل وكيل متخصص. سأشرح كل سطر في الكود.
1️⃣ الوكيل الأساسي — base_agent.py
هذا الملف يُعرّف الفئة الأساسية BaseAgent التي يرث منها جميع الوكلاء.
يحتوي على الإعدادات المشتركة والاتصال بـ Groq Cloud.
📄 ملف: agents/base_agent.py
# استيراد المكتبات المطلوبة
from agno.agent import Agent
from agno.models.groq import Groq
from dotenv import load_dotenv
import os
# تحميل متغيرات البيئة من ملف .env
load_dotenv()
class BaseAgent:
"""
الوكيل الأساسي الذي ترث منه جميع الوكلاء المتخصصين.
يوفر الإعدادات المشتركة والاتصال بنموذج LLaMA عبر Groq.
"""
def __init__(self, name, description, avatar="default_avatar.png"):
"""
تهيئة الوكيل الأساسي.
Args:
name: اسم الوكيل (للعرض)
description: وصف مختصر لوظيفة الوكيل
avatar: صورة الوكيل (اختياري)
"""
self.name = name
self.description = description
self.avatar = avatar
# إعداد نموذج LLaMA 3.3 70B عبر Groq
# هذا النموذج يوفر توازناً ممتازاً بين الجودة والسرعة
self.model = Groq(id="llama-3.3-70b-versatile")
# إنشاء وكيل Agno مع تفعيل دعم Markdown
self.agent = Agent(
model=self.model,
markdown=True # تفعيل تنسيق Markdown في الردود
)
def get_response(self, query, stream=False):
"""
الحصول على رد من الوكيل.
Args:
query: السؤال أو الطلب من المستخدم
stream: هل يتم البث المباشر للرد (افتراضي: False)
Returns:
رد الوكيل كنص أو كائن RunResponse
"""
try:
response = self.agent.run(query, stream=stream)
return response
except Exception as e:
return f"Error getting response: {str(e)}"
def print_response(self, query, stream=True):
"""
طباعة رد الوكيل مباشرة في الـ Console.
مفيد للاختبار والتطوير.
"""
return self.agent.print_response(query, stream=stream)
- load_dotenv() — يحمّل متغيرات البيئة من ملف .env (يشمل GROQ_API_KEY)
- Groq(id="llama-3.3-70b-versatile") — يُنشئ اتصالاً بنموذج LLaMA عبر Groq Cloud
- Agent(model, markdown=True) — يُنشئ وكيل Agno مع دعم Markdown
- agent.run(query) — يرسل الاستعلام للنموذج ويحصل على الرد
2️⃣ وكيل الترحيب — welcome_agent.py
هذا الوكيل هو نقطة الاتصال الأولى للزوار. يقدم تحيات مخصصة حسب نوع الزائر ويوجهه للأقسام المناسبة في الموقع.
📄 ملف: agents/welcome_agent.py
from agents.base_agent import BaseAgent
class WelcomeAgent(BaseAgent):
"""
وكيل الترحيب - يستقبل الزوار ويوجههم للأقسام المناسبة.
"""
def __init__(self):
# استدعاء constructor الوكيل الأساسي
super().__init__(
name="Greeter",
description="I'm the welcome agent for this portfolio. I help guide visitors to the right section.",
avatar="welcome_avatar.png"
)
def greet(self, visitor_type=None):
"""
توليد تحية مخصصة حسب نوع الزائر.
Args:
visitor_type: نوع الزائر (employer/client/fellow_programmer/None)
Returns:
تحية مخصصة من الوكيل
"""
if visitor_type == "employer":
prompt = """
Generate a friendly, professional greeting for a potential employer
visiting a programmer's portfolio website.
Guidelines:
- Be warm but professional
- Mention they can explore the Projects section for technical skills
- Mention the Career section for professional experience
- Keep it concise (2-3 sentences)
- Use a welcoming tone
"""
elif visitor_type == "client":
prompt = """
Generate a friendly, business-oriented greeting for a potential client
visiting a programmer's portfolio website.
Guidelines:
- Be warm and service-oriented
- Mention the Projects section for examples of past work
- Mention the Services section for available services and pricing
- Emphasize quality and reliability
- Keep it concise (2-3 sentences)
"""
elif visitor_type == "fellow_programmer":
prompt = """
Generate a friendly, casual greeting for a fellow programmer
visiting a portfolio website.
Guidelines:
- Be friendly and collegial
- Mention the Projects section for technical details and code samples
- Mention the Research section for tech insights
- Use a more casual, developer-to-developer tone
- Keep it concise (2-3 sentences)
"""
else:
# تحية عامة للزوار غير المحددين
prompt = """
Generate a friendly, general greeting for a visitor to a programmer's
portfolio website.
Guidelines:
- Be warm and welcoming
- Ask if they are an employer, client, or fellow programmer
- Offer to help them find what they're looking for
- Keep it concise (2-3 sentences)
"""
return self.get_response(prompt)
def suggest_section(self, interest):
"""
اقتراح قسم مناسب بناءً على اهتمام الزائر.
Args:
interest: اهتمام الزائر (مثل: "machine learning", "web development")
Returns:
اقتراح مع شرح مختصر
"""
prompt = f"""
A visitor expressed interest in '{interest}'.
Based on this interest, suggest which section of a programmer's portfolio
they should visit.
Available sections:
- Projects: Technical projects with code samples
- Career: Professional experience and skills
- Services: Available services for clients
- Research: Latest tech trends and insights
- Contact: Get in touch
Provide a brief recommendation (1-2 sentences) explaining why that section
would be most relevant for their interest.
"""
return self.get_response(prompt)
def answer_question(self, question):
"""
الإجابة على أسئلة عامة من الزوار.
Args:
question: سؤال الزائر
Returns:
إجابة مفيدة وموجهة
"""
prompt = f"""
A visitor to a programmer's portfolio website asked: "{question}"
Provide a helpful, friendly response. If the question is about:
- Technical skills → Suggest visiting the Projects or Career section
- Services/Pricing → Suggest visiting the Services section
- Getting in touch → Suggest visiting the Contact section
- Tech trends → Suggest visiting the Research section
Keep your response concise and helpful (2-4 sentences).
"""
return self.get_response(prompt)
3️⃣ وكيل المشاريع — project_agent.py
هذا الوكيل متخصص في عرض المشاريع التقنية والإجابة عن الأسئلة المتعلقة بتفاصيل التنفيذ والتقنيات المستخدمة.
📄 ملف: agents/project_agent.py
from agents.base_agent import BaseAgent
class ProjectAgent(BaseAgent):
"""
وكيل المشاريع - يعرض المشاريع التقنية ويجيب عن الأسئلة المتعلقة بها.
"""
def __init__(self):
super().__init__(
name="TechExpert",
description="I'm the project specialist. I provide detailed information about technical projects.",
avatar="project_avatar.png"
)
# قاعدة بيانات المشاريع (في مشروع حقيقي، ستأتي من قاعدة بيانات فعلية)
self.projects = {
"ecommerce": {
"name": "E-commerce Platform",
"tech_stack": ["React", "Node.js", "MongoDB", "Express", "Stripe"],
"description": "A full-stack e-commerce platform with user authentication, product catalog, shopping cart, and payment processing.",
"highlights": [
"Responsive design for all devices",
"RESTful API architecture",
"Stripe payment integration",
"JWT authentication",
"Admin dashboard"
],
"github_link": "https://github.com/username/ecommerce-platform",
"demo_link": "https://ecommerce-demo.example.com",
"status": "Completed",
"year": "2024"
},
"taskmanager": {
"name": "Task Management App",
"tech_stack": ["Vue.js", "Firebase", "Tailwind CSS", "Vuex"],
"description": "A real-time task management application with collaborative features, notifications, and progress tracking.",
"highlights": [
"Real-time synchronization",
"Team collaboration features",
"Drag-and-drop interface",
"Progressive Web App (PWA)",
"Push notifications"
],
"github_link": "https://github.com/username/task-manager",
"demo_link": "https://taskmanager-demo.example.com",
"status": "Completed",
"year": "2024"
},
"dashboard": {
"name": "Data Visualization Dashboard",
"tech_stack": ["Python", "Django", "D3.js", "PostgreSQL", "Redis"],
"description": "An interactive dashboard for visualizing complex datasets with filtering, sorting, and export capabilities.",
"highlights": [
"Interactive charts and graphs",
"Advanced data filtering",
"CSV/PDF export",
"Caching with Redis",
"Responsive design"
],
"github_link": "https://github.com/username/data-dashboard",
"demo_link": "https://dataviz-demo.example.com",
"status": "Completed",
"year": "2023"
},
"aiagents": {
"name": "AI Agents Portfolio",
"tech_stack": ["Python", "Flask", "React", "Agno", "Groq"],
"description": "This very portfolio website featuring a team of AI agents powered by LLaMA 3.3.",
"highlights": [
"5 specialized AI agents",
"Real-time chat interface",
"Web search capabilities",
"Markdown rendering",
"Responsive design"
],
"github_link": "https://github.com/username/ai-agents-portfolio",
"demo_link": "https://ai-portfolio.example.com",
"status": "In Progress",
"year": "2025"
}
}
def get_project_list(self):
"""
الحصول على قائمة بجميع المشاريع مع ملخص لكل منها.
"""
projects_summary = []
for project_id, project in self.projects.items():
projects_summary.append(
f"- **{project['name']}** ({project['year']}): {project['description'][:100]}..."
)
projects_text = "\n".join(projects_summary)
prompt = f"""
Present the following projects in an engaging way for a portfolio website:
{projects_text}
Format as a numbered list with brief descriptions.
Add emojis for visual appeal.
Mention that visitors can ask for more details about any specific project.
"""
return self.get_response(prompt)
def get_project_details(self, project_id):
"""
الحصول على تفاصيل مشروع معين.
Args:
project_id: معرّف المشروع (ecommerce, taskmanager, dashboard, aiagents)
"""
# البحث عن المشروع بالمعرّف أو بالاسم
project = self.projects.get(project_id.lower())
if not project:
# البحث بالاسم الجزئي
for pid, p in self.projects.items():
if project_id.lower() in p['name'].lower():
project = p
break
if not project:
return self.get_response(
f"I couldn't find a project matching '{project_id}'. "
f"Available projects are: {', '.join([p['name'] for p in self.projects.values()])}"
)
prompt = f"""
Generate a detailed, engaging description for this project:
**Project Name:** {project['name']}
**Tech Stack:** {', '.join(project['tech_stack'])}
**Description:** {project['description']}
**Key Features:** {', '.join(project['highlights'])}
**GitHub:** {project['github_link']}
**Live Demo:** {project['demo_link']}
**Status:** {project['status']}
**Year:** {project['year']}
Include:
1. A brief overview
2. Technical details about implementation
3. Key features and what makes it special
4. Links to GitHub and demo
Format the response in markdown with appropriate headers and bullet points.
"""
return self.get_response(prompt)
def answer_technical_question(self, project_id, question):
"""
الإجابة على سؤال تقني حول مشروع معين.
Args:
project_id: معرّف المشروع
question: السؤال التقني
"""
project = self.projects.get(project_id.lower())
if not project:
# البحث بالاسم الجزئي
for pid, p in self.projects.items():
if project_id.lower() in p['name'].lower():
project = p
break
if not project:
return self.get_response(
f"Project not found. Available projects: {', '.join([p['name'] for p in self.projects.values()])}"
)
prompt = f"""
Answer this technical question about the project:
**Project:** {project['name']}
**Tech Stack:** {', '.join(project['tech_stack'])}
**Description:** {project['description']}
**Features:** {', '.join(project['highlights'])}
**Question:** {question}
Provide a detailed technical answer. If relevant, include:
- Code examples or snippets
- Architecture decisions
- Best practices used
- Challenges faced and solutions
Format the response in markdown.
"""
return self.get_response(prompt)
def search_projects(self, technology):
"""
البحث عن مشاريع تستخدم تقنية معينة.
Args:
technology: اسم التقنية (مثل: React, Python, MongoDB)
"""
matching_projects = []
for project_id, project in self.projects.items():
for tech in project['tech_stack']:
if technology.lower() in tech.lower():
matching_projects.append(project)
break
if not matching_projects:
return self.get_response(
f"No projects found using '{technology}'. "
f"Technologies used in my projects include: React, Vue.js, Node.js, Python, Django, Flask, MongoDB, PostgreSQL, Firebase."
)
projects_text = "\n".join([
f"- {p['name']}: {p['description'][:80]}..."
for p in matching_projects
])
prompt = f"""
The visitor is looking for projects that use {technology}.
Here are the matching projects:
{projects_text}
Present these projects in an engaging way, highlighting how {technology}
is used in each one. Offer to provide more details about any specific project.
"""
return self.get_response(prompt)
4️⃣ وكيل المسيرة المهنية — career_agent.py
هذا الوكيل مصمم لمساعدة أصحاب العمل المحتملين في التعرف على المهارات والخبرات المهنية، وتقييم مدى ملاءمة المرشح للوظائف المختلفة.
📄 ملف: agents/career_agent.py (تكملة)
from agents.base_agent import BaseAgent
class CareerAgent(BaseAgent):
"""
وكيل المسيرة المهنية - يقدم معلومات عن المهارات والخبرات.
"""
def __init__(self):
super().__init__(
name="CareerGuide",
description="I'm the career specialist. I provide information about skills, experience, and job suitability.",
avatar="career_avatar.png"
)
# قاعدة بيانات المهارات
self.skills = {
"programming_languages": {
"expert": ["Python", "JavaScript", "TypeScript"],
"proficient": ["Java", "SQL", "PHP"],
"familiar": ["Go", "Rust", "C++"]
},
"frameworks": {
"frontend": ["React", "Vue.js", "Next.js", "Tailwind CSS"],
"backend": ["Node.js", "Express", "Django", "Flask", "FastAPI"],
"mobile": ["React Native", "Flutter"]
},
"databases": ["PostgreSQL", "MongoDB", "MySQL", "Redis", "Firebase"],
"cloud_devops": ["AWS", "Google Cloud", "Docker", "Kubernetes", "CI/CD", "GitHub Actions"],
"soft_skills": [
"Team Leadership",
"Project Management",
"Agile/Scrum",
"Technical Writing",
"Client Communication",
"Problem Solving"
]
}
# قاعدة بيانات الخبرات المهنية
self.experience = [
{
"title": "Senior Full Stack Developer",
"company": "Tech Innovations Inc.",
"period": "2022 - Present",
"type": "Full-time",
"responsibilities": [
"Led development of cloud-based SaaS platform serving 10,000+ users",
"Managed and mentored team of 5 developers",
"Implemented CI/CD pipeline reducing deployment time by 60%",
"Architected microservices infrastructure on AWS",
"Reduced server costs by 40% through optimization"
],
"technologies": ["React", "Node.js", "AWS", "PostgreSQL", "Docker"]
},
{
"title": "Full Stack Developer",
"company": "WebSolutions Co.",
"period": "2019 - 2022",
"type": "Full-time",
"responsibilities": [
"Developed responsive web applications using React and Vue.js",
"Built RESTful APIs with Node.js and Django",
"Collaborated with UX/UI designers on user-friendly interfaces",
"Conducted code reviews and mentored junior developers",
"Implemented automated testing achieving 85% code coverage"
],
"technologies": ["Vue.js", "Django", "MongoDB", "Redis"]
},
{
"title": "Junior Developer",
"company": "StartUp Labs",
"period": "2017 - 2019",
"type": "Full-time",
"responsibilities": [
"Built and maintained client websites and web applications",
"Developed custom WordPress plugins and themes",
"Implemented responsive designs with cross-browser compatibility",
"Assisted in database design and query optimization"
],
"technologies": ["PHP", "WordPress", "MySQL", "JavaScript"]
}
]
# التعليم والشهادات
self.education = {
"degree": "Bachelor's in Computer Science",
"university": "University of Technology",
"year": "2017",
"certifications": [
"AWS Certified Solutions Architect",
"Google Cloud Professional Developer",
"MongoDB Certified Developer"
]
}
def get_skills_summary(self):
"""
الحصول على ملخص شامل للمهارات التقنية.
"""
skills_text = f"""
**Programming Languages:**
- Expert: {', '.join(self.skills['programming_languages']['expert'])}
- Proficient: {', '.join(self.skills['programming_languages']['proficient'])}
- Familiar: {', '.join(self.skills['programming_languages']['familiar'])}
**Frameworks & Libraries:**
- Frontend: {', '.join(self.skills['frameworks']['frontend'])}
- Backend: {', '.join(self.skills['frameworks']['backend'])}
- Mobile: {', '.join(self.skills['frameworks']['mobile'])}
**Databases:** {', '.join(self.skills['databases'])}
**Cloud & DevOps:** {', '.join(self.skills['cloud_devops'])}
**Soft Skills:** {', '.join(self.skills['soft_skills'])}
"""
prompt = f"""
Generate a professional, engaging summary of these technical skills
for a portfolio website:
{skills_text}
Format the response with:
- Clear sections with emojis
- Skill levels clearly indicated
- A brief introduction about being a full-stack developer
- Use markdown formatting
"""
return self.get_response(prompt)
def get_experience_summary(self):
"""
الحصول على ملخص الخبرات المهنية.
"""
experience_text = ""
for job in self.experience:
experience_text += f"""
**{job['title']}** at {job['company']}
*{job['period']}* ({job['type']})
Responsibilities:
{chr(10).join(['- ' + r for r in job['responsibilities']])}
Technologies: {', '.join(job['technologies'])}
---
"""
prompt = f"""
Generate a professional career summary based on this work experience:
{experience_text}
Education: {self.education['degree']} from {self.education['university']} ({self.education['year']})
Certifications: {', '.join(self.education['certifications'])}
Include:
1. A compelling career narrative showing progression
2. Key achievements highlighted
3. Total years of experience
4. Education and certifications
Format in markdown with clear sections.
"""
return self.get_response(prompt)
def assess_job_fit(self, job_description):
"""
تقييم مدى ملاءمة المهارات لوظيفة معينة.
Args:
job_description: وصف الوظيفة المطلوبة
"""
# تجميع كل المهارات
all_skills = []
all_skills.extend(self.skills['programming_languages']['expert'])
all_skills.extend(self.skills['programming_languages']['proficient'])
all_skills.extend(self.skills['frameworks']['frontend'])
all_skills.extend(self.skills['frameworks']['backend'])
all_skills.extend(self.skills['databases'])
all_skills.extend(self.skills['cloud_devops'])
# تجميع الخبرات
experience_summary = []
for job in self.experience:
experience_summary.extend(job['responsibilities'])
prompt = f"""
Assess the fit for this job based on the candidate's profile:
**Job Description:**
{job_description}
**Candidate's Skills:**
{', '.join(all_skills)}
**Candidate's Experience:**
- 7+ years of professional experience
- {chr(10).join(['- ' + exp for exp in experience_summary[:8]])}
**Certifications:**
{', '.join(self.education['certifications'])}
Provide:
1. **Match Score**: X/10 with brief explanation
2. **Matching Skills**: Skills that align with the job
3. **Strengths**: Why this candidate is a good fit
4. **Potential Gaps**: Any missing requirements (if any)
5. **Recommendation**: Final assessment
Be honest but positive. Format in markdown.
"""
return self.get_response(prompt)
def answer_career_question(self, question):
"""
الإجابة على أسئلة عامة حول المسيرة المهنية.
"""
prompt = f"""
Answer this career-related question based on the following profile:
**Question:** {question}
**Profile Summary:**
- 7+ years of full-stack development experience
- Expert in Python, JavaScript, TypeScript
- Experienced with React, Vue.js, Node.js, Django
- Strong background in cloud services (AWS, GCP)
- Team leadership and project management experience
- Bachelor's in Computer Science
- AWS and GCP certified
Provide a helpful, professional answer. If the question is about
availability, mention that the candidate is open to opportunities.
"""
return self.get_response(prompt)
5️⃣ وكيل العملاء — client_agent.py
هذا الوكيل مصمم لمساعدة العملاء المحتملين في التعرف على الخدمات المتاحة، وشرح عملية التعاقد، وإنشاء عروض أسعار مخصصة.
📄 ملف: agents/client_agent.py
from agents.base_agent import BaseAgent
class ClientAgent(BaseAgent):
"""
وكيل العملاء - يقدم معلومات عن الخدمات ويُنشئ عروض الأسعار.
"""
def __init__(self):
super().__init__(
name="BusinessAdvisor",
description="I'm the client specialist. I provide information about services, pricing, and project proposals.",
avatar="client_avatar.png"
)
# قاعدة بيانات الخدمات
self.services = {
"web_development": {
"name": "Web Application Development",
"description": "Custom web application development using modern frameworks and best practices. From simple websites to complex SaaS platforms.",
"features": [
"Responsive design for all devices",
"Modern UI/UX implementation",
"SEO optimization",
"Performance optimization",
"Security best practices"
],
"pricing_model": "Project-based or hourly",
"price_range": {
"simple": "\$2,000 - \$5,000",
"medium": "\$5,000 - \$15,000",
"complex": "\$15,000 - \$50,000+"
},
"timeline": "4-16 weeks depending on complexity",
"technologies": ["React", "Vue.js", "Next.js", "Node.js", "Django"]
},
"mobile_development": {
"name": "Mobile App Development",
"description": "Native and cross-platform mobile application development for iOS and Android.",
"features": [
"Cross-platform development (iOS & Android)",
"Native performance",
"Push notifications",
"Offline functionality",
"App Store submission support"
],
"pricing_model": "Project-based",
"price_range": {
"simple": "\$8,000 - \$15,000",
"medium": "\$15,000 - \$35,000",
"complex": "\$35,000 - \$80,000+"
},
"timeline": "8-20 weeks depending on complexity",
"technologies": ["React Native", "Flutter", "Swift", "Kotlin"]
},
"api_development": {
"name": "API Development & Integration",
"description": "RESTful and GraphQL API development, third-party integrations, and backend services.",
"features": [
"RESTful API design",
"GraphQL implementation",
"Third-party integrations",
"API documentation",
"Authentication & security"
],
"pricing_model": "Project-based or hourly",
"price_range": {
"simple": "\$1,500 - \$4,000",
"medium": "\$4,000 - \$10,000",
"complex": "\$10,000 - \$25,000+"
},
"timeline": "2-8 weeks depending on scope",
"technologies": ["Node.js", "FastAPI", "Django REST", "GraphQL"]
},
"consulting": {
"name": "Technical Consulting",
"description": "Expert advice on architecture, technology stack selection, code review, and development best practices.",
"features": [
"Architecture review & design",
"Technology stack recommendations",
"Code review & audit",
"Performance optimization",
"Team training & mentoring"
],
"pricing_model": "Hourly",
"price_range": {
"hourly": "\$100 - \$200 per hour",
"daily": "\$700 - \$1,400 per day"
},
"timeline": "Flexible - ongoing or one-time",
"technologies": ["All major technologies"]
}
}
# عملية التعاقد
self.process_steps = [
{
"step": 1,
"name": "Discovery Call",
"description": "Free 30-minute consultation to understand your needs and goals.",
"duration": "30 minutes"
},
{
"step": 2,
"name": "Proposal & Quote",
"description": "Detailed proposal with scope, timeline, and pricing.",
"duration": "2-3 business days"
},
{
"step": 3,
"name": "Contract & Kickoff",
"description": "Sign agreement and begin project with kickoff meeting.",
"duration": "1-2 days"
},
{
"step": 4,
"name": "Design & Planning",
"description": "UI/UX design, technical architecture, and sprint planning.",
"duration": "1-2 weeks"
},
{
"step": 5,
"name": "Development Sprints",
"description": "Agile development with regular demos and feedback cycles.",
"duration": "Varies by project"
},
{
"step": 6,
"name": "Testing & QA",
"description": "Comprehensive testing, bug fixes, and quality assurance.",
"duration": "1-2 weeks"
},
{
"step": 7,
"name": "Launch & Deployment",
"description": "Production deployment with monitoring setup.",
"duration": "1-3 days"
},
{
"step": 8,
"name": "Support & Maintenance",
"description": "30 days free support, optional ongoing maintenance plans.",
"duration": "Ongoing"
}
]
def get_services_overview(self):
"""
الحصول على نظرة عامة على جميع الخدمات.
"""
services_text = ""
for service_id, service in self.services.items():
services_text += f"""
**{service['name']}**
{service['description']}
Timeline: {service['timeline']}
Technologies: {', '.join(service['technologies'])}
"""
prompt = f"""
Present these services in an engaging, professional way for potential clients:
{services_text}
Format with:
- Clear sections for each service
- Emojis for visual appeal
- Brief but compelling descriptions
- Mention that detailed pricing is available upon request
- Invite them to ask about any specific service
Use markdown formatting.
"""
return self.get_response(prompt)
def get_service_details(self, service_name):
"""
الحصول على تفاصيل خدمة معينة.
"""
# البحث عن الخدمة
service = None
for sid, s in self.services.items():
if service_name.lower() in s['name'].lower() or service_name.lower() in sid:
service = s
break
if not service:
available = ", ".join([s['name'] for s in self.services.values()])
return self.get_response(
f"I couldn't find a service matching '{service_name}'. "
f"Available services are: {available}"
)
prompt = f"""
Provide detailed information about this service for a potential client:
**Service:** {service['name']}
**Description:** {service['description']}
**Features:**
{chr(10).join(['- ' + f for f in service['features']])}
**Pricing:** {service['pricing_model']}
- Simple projects: {service['price_range'].get('simple', 'N/A')}
- Medium projects: {service['price_range'].get('medium', 'N/A')}
- Complex projects: {service['price_range'].get('complex', 'N/A')}
**Timeline:** {service['timeline']}
**Technologies:** {', '.join(service['technologies'])}
Format professionally with:
- Value proposition
- What's included
- Pricing breakdown
- Call to action (schedule a consultation)
Use markdown formatting.
"""
return self.get_response(prompt)
def explain_process(self):
"""
شرح عملية التعاقد والعمل.
"""
process_text = ""
for step in self.process_steps:
process_text += f"""
Step {step['step']}: {step['name']}
{step['description']}
Duration: {step['duration']}
"""
prompt = f"""
Explain the client engagement process in a friendly, professional way:
{process_text}
Format as a clear step-by-step guide with:
- Numbered steps with emojis
- Brief explanation of each phase
- What the client can expect
- Timeline indicators
Emphasize the collaborative nature and regular communication.
Use markdown formatting.
"""
return self.get_response(prompt)
def generate_proposal(self, project_description):
"""
إنشاء عرض سعر مبدئي بناءً على وصف المشروع.
"""
prompt = f"""
Generate a preliminary project proposal based on this description:
**Client's Project Description:**
{project_description}
**Available Services:**
- Web Development: \$2,000 - \$50,000+ (4-16 weeks)
- Mobile Development: \$8,000 - \$80,000+ (8-20 weeks)
- API Development: \$1,500 - \$25,000+ (2-8 weeks)
- Consulting: \$100-200/hour
Create a professional proposal with:
1. **Project Understanding** - Show you understand their needs
2. **Proposed Solution** - Recommend approach and technologies
3. **Scope of Work** - Break down the deliverables
4. **Estimated Timeline** - Realistic phases
5. **Budget Range** - Preliminary estimate with explanation
6. **Next Steps** - How to proceed (schedule a call)
Be professional but friendly. Include a disclaimer that this is
a preliminary estimate and final pricing requires a detailed discussion.
Use markdown formatting with clear sections.
"""
return self.get_response(prompt)
def answer_client_question(self, question):
"""
الإجابة على أسئلة العملاء العامة.
"""
prompt = f"""
Answer this client question professionally:
**Question:** {question}
**Context:**
- Services: Web Development, Mobile Apps, APIs, Consulting
- Experience: 7+ years, 50+ projects delivered
- Process: Agile methodology with regular updates
- Support: 30 days free post-launch support
- Payment: Typically 30% upfront, 70% on completion
Provide a helpful, sales-oriented (but not pushy) response.
If appropriate, suggest scheduling a consultation call.
"""
return self.get_response(prompt)
6️⃣ وكيل الأبحاث — research_agent.py
ما يُميّز هذا الوكيل عن الوكلاء الآخرين هو أنه يبحث في الويب للحصول على معلومات حديثة عن التقنيات والاتجاهات، بدلاً من الاعتماد فقط على بيانات مُعرّفة مسبقًا.
هذا الوكيل يستخدم ميزة البحث في الويب من Groq API (إذا كانت متاحة). إذا لم تكن هذه الميزة متاحة في حسابك، سيعتمد الوكيل على معرفة النموذج المدمجة.
📄 ملف: agents/research_agent.py (الكود الكامل)
from agents.base_agent import BaseAgent
import requests
import os
class ResearchAgent(BaseAgent):
"""
وكيل الأبحاث - يبحث عن أحدث التقنيات والاتجاهات.
"""
def __init__(self):
super().__init__(
name="ResearchAssistant",
description="I research latest technologies and industry trends.",
avatar="research_avatar.png"
)
self.api_key = os.getenv("GROQ_API_KEY")
self.api_url = "https://api.groq.com/openai/v1/chat/completions"
def _make_api_request(self, messages, use_search=False):
"""إرسال طلب إلى Groq API."""
headers = {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json"
}
payload = {
"model": "llama-3.3-70b-versatile",
"messages": messages,
"temperature": 0.7,
"max_tokens": 2048
}
if use_search:
payload["tools"] = [{"type": "web_search"}]
try:
response = requests.post(self.api_url, headers=headers, json=payload, timeout=60)
if response.status_code == 200:
return response.json()["choices"][0]["message"]["content"]
return None
except Exception as e:
print(f"API error: {e}")
return None
def research_technology(self, technology):
"""البحث عن تقنية معينة."""
prompt = f"""
Provide a comprehensive overview of **{technology}**:
## 1. What is {technology}?
Brief introduction and core concept.
## 2. Key Features
Main features and capabilities (bullet points).
## 3. Use Cases
Common applications and when to use it.
## 4. Pros and Cons
| Pros | Cons |
|------|------|
| ... | ... |
## 5. Getting Started
Basic steps to start using it.
## 6. Current State (2025)
Popularity, community support, latest developments.
## 7. Learning Resources
Top 3-5 recommended resources.
Format in clean markdown with emojis. Be accurate and practical.
"""
return self.get_response(prompt)
def compare_technologies(self, tech1, tech2):
"""مقارنة بين تقنيتين."""
prompt = f"""
Compare **{tech1}** vs **{tech2}** for developers:
## Overview
Brief intro to both technologies.
## Comparison Table
| Aspect | {tech1} | {tech2} |
|--------|---------|---------|
| Type | ... | ... |
| Learning Curve | ... | ... |
| Performance | ... | ... |
| Community Size | ... | ... |
| Job Market | ... | ... |
| Best For | ... | ... |
## When to Choose {tech1}
- Scenario 1
- Scenario 2
## When to Choose {tech2}
- Scenario 1
- Scenario 2
## Verdict
Final recommendation based on different use cases.
Be objective and practical. Use markdown formatting.
"""
return self.get_response(prompt)
def get_industry_trends(self):
"""الحصول على أحدث اتجاهات صناعة البرمجيات."""
prompt = """
Provide an overview of the latest software development trends for 2025:
## 🚀 Emerging Technologies
Top 5 emerging technologies developers should watch.
## 💼 In-Demand Skills
Most sought-after skills in the job market.
## 🔄 Industry Shifts
Major changes in how software is built and deployed.
## 🤖 AI & Automation
How AI is changing development workflows.
## ☁️ Cloud & Infrastructure
Latest trends in cloud services and DevOps.
## 📱 Frontend Trends
What's new in frontend development.
## 🔮 Predictions
What to expect in the next 1-2 years.
Be specific with examples. Format in markdown with emojis.
"""
return self.get_response(prompt)
def get_learning_path(self, goal):
"""إنشاء مسار تعلم مخصص."""
prompt = f"""
Create a learning roadmap for someone who wants to: **{goal}**
## 🎯 Goal Analysis
Break down what skills are needed.
## 📚 Learning Path
### Phase 1: Fundamentals (Weeks 1-4)
- Topic 1
- Topic 2
### Phase 2: Core Skills (Weeks 5-12)
- Topic 1
- Topic 2
### Phase 3: Advanced Topics (Weeks 13-20)
- Topic 1
- Topic 2
### Phase 4: Projects & Portfolio (Weeks 21-24)
- Project ideas
## 🛠️ Recommended Tools
Essential tools and software.
## 📖 Resources
- Free resources
- Paid courses (worth the investment)
## ⏱️ Time Estimate
Realistic timeline with daily commitment.
Be practical and specific. Format in markdown.
"""
return self.get_response(prompt)
def answer_research_question(self, question):
"""الإجابة على أسئلة بحثية عامة."""
prompt = f"""
Answer this technology/research question:
**Question:** {question}
Provide a well-researched, accurate answer with:
- Clear explanation
- Practical examples if applicable
- Links to concepts (not actual URLs)
- Your recommendation if relevant
Format in markdown. Be concise but comprehensive.
"""
return self.get_response(prompt)
7️⃣ ملف التصدير — __init__.py
هذا الملف يجمع جميع الوكلاء ويصدّرهم ليكونوا متاحين للاستخدام في الملف الرئيسي
main.py.
📄 ملف: agents/__init__.py
"""
AI Agents Package
================
This package contains all specialized AI agents for the portfolio website.
Available Agents:
- WelcomeAgent: Greets visitors and guides them
- ProjectAgent: Showcases technical projects
- CareerAgent: Provides career and skills information
- ClientAgent: Handles service inquiries and proposals
- ResearchAgent: Researches technologies and trends
"""
# استيراد جميع الوكلاء
from agents.base_agent import BaseAgent
from agents.welcome_agent import WelcomeAgent
from agents.project_agent import ProjectAgent
from agents.career_agent import CareerAgent
from agents.client_agent import ClientAgent
from agents.research_agent import ResearchAgent
# تحديد ما يتم تصديره عند استخدام from agents import *
__all__ = [
'BaseAgent',
'WelcomeAgent',
'ProjectAgent',
'CareerAgent',
'ClientAgent',
'ResearchAgent'
]
# معلومات الإصدار
__version__ = "1.0.0"
__author__ = "Your Name"
هذا الملف يحوّل مجلد agents إلى حزمة Python (Package)، مما يتيح لنا:
- استيراد الوكلاء بسهولة:
from agents import WelcomeAgent - استيراد جميع الوكلاء دفعة واحدة:
from agents import * - تنظيم الكود وجعله أكثر قابلية للصيانة
🚀 الملف الرئيسي — main.py
هذا هو قلب الواجهة الخلفية. يُنشئ خادم Flask ويربط جميع الوكلاء بنقاط نهاية API التي ستتصل بها الواجهة الأمامية.
📄 ملف: main.py (الكود الكامل)
"""
AI Agents Portfolio - Backend Server
====================================
Flask server that provides API endpoints for AI agents.
"""
from flask import Flask, request, jsonify
from flask_cors import CORS
from dotenv import load_dotenv
import os
# تحميل متغيرات البيئة
load_dotenv()
# استيراد الوكلاء
from agents import (
WelcomeAgent,
ProjectAgent,
CareerAgent,
ClientAgent,
ResearchAgent
)
# إنشاء تطبيق Flask
app = Flask(__name__)
# تفعيل CORS للسماح بالوصول من الواجهة الأمامية
CORS(app, resources={
r"/api/*": {
"origins": ["http://localhost:5173", "http://127.0.0.1:5173"],
"methods": ["GET", "POST", "OPTIONS"],
"allow_headers": ["Content-Type"]
}
})
# ═══════════════════════════════════════════════════════════
# تهيئة الوكلاء
# ═══════════════════════════════════════════════════════════
print("🤖 Initializing AI Agents...")
welcome_agent = WelcomeAgent()
project_agent = ProjectAgent()
career_agent = CareerAgent()
client_agent = ClientAgent()
research_agent = ResearchAgent()
print("✅ All agents initialized successfully!")
# ═══════════════════════════════════════════════════════════
# دوال مساعدة
# ═══════════════════════════════════════════════════════════
def extract_response_content(response):
"""
استخراج النص من رد الوكيل.
يتعامل مع أنواع مختلفة من الردود.
"""
if response is None:
return "I apologize, but I couldn't generate a response. Please try again."
# إذا كان الرد كائن RunResponse من Agno
if hasattr(response, 'content'):
return response.content
# إذا كان الرد له دالة run()
if hasattr(response, 'run'):
result = response.run()
if hasattr(result, 'content'):
return result.content
return str(result)
# إذا كان نصًا عاديًا
return str(response)
def create_error_response(message, status_code=500):
"""إنشاء رد خطأ موحد."""
return jsonify({
"error": True,
"message": message,
"response": f"I apologize, but an error occurred: {message}"
}), status_code
# ═══════════════════════════════════════════════════════════
# نقاط النهاية (API Endpoints)
# ═══════════════════════════════════════════════════════════
# --- نقطة فحص الحالة ---
@app.route('/api/status', methods=['GET'])
def status():
"""التحقق من حالة الخادم والوكلاء."""
return jsonify({
"status": "online",
"message": "AI Agents Team is Ready! 🤖",
"agents": {
"welcome": "✅ Active",
"project": "✅ Active",
"career": "✅ Active",
"client": "✅ Active",
"research": "✅ Active"
},
"version": "1.0.0"
})
# --- وكيل الترحيب ---
@app.route('/api/welcome', methods=['POST'])
def welcome_endpoint():
"""نقطة نهاية وكيل الترحيب."""
try:
data = request.get_json() or {}
message = data.get('message', '').lower()
visitor_type = data.get('visitor_type', None)
# تحديد نوع الزائر من الرسالة إذا لم يُحدد
if not visitor_type:
if any(word in message for word in ['employer', 'hiring', 'recruit', 'job']):
visitor_type = 'employer'
elif any(word in message for word in ['client', 'project', 'hire', 'service']):
visitor_type = 'client'
elif any(word in message for word in ['developer', 'programmer', 'coding', 'tech']):
visitor_type = 'fellow_programmer'
# اختيار الدالة المناسبة
if 'section' in message or 'where' in message or 'suggest' in message:
response = welcome_agent.suggest_section(message)
elif message and len(message) > 20:
response = welcome_agent.answer_question(message)
else:
response = welcome_agent.greet(visitor_type)
return jsonify({
"response": extract_response_content(response),
"agent": "welcome",
"visitor_type": visitor_type
})
except Exception as e:
print(f"Welcome endpoint error: {e}")
return create_error_response(str(e))
# --- وكيل المشاريع ---
@app.route('/api/project', methods=['POST'])
def project_endpoint():
"""نقطة نهاية وكيل المشاريع."""
try:
data = request.get_json() or {}
message = data.get('message', '').lower()
project_id = data.get('project_id', None)
# تحديد نوع الطلب
if project_id:
response = project_agent.get_project_details(project_id)
elif any(word in message for word in ['list', 'all', 'show', 'projects']):
response = project_agent.get_project_list()
elif any(word in message for word in ['ecommerce', 'e-commerce', 'shop']):
response = project_agent.get_project_details('ecommerce')
elif any(word in message for word in ['task', 'todo', 'management']):
response = project_agent.get_project_details('taskmanager')
elif any(word in message for word in ['dashboard', 'data', 'visualization']):
response = project_agent.get_project_details('dashboard')
elif any(word in message for word in ['ai', 'agent', 'portfolio']):
response = project_agent.get_project_details('aiagents')
elif any(tech in message for tech in ['react', 'vue', 'python', 'node', 'django']):
# استخراج اسم التقنية
for tech in ['react', 'vue', 'python', 'node', 'django', 'mongodb']:
if tech in message:
response = project_agent.search_projects(tech)
break
else:
response = project_agent.get_project_list()
else:
# سؤال تقني عام
response = project_agent.answer_technical_question('ecommerce', message)
return jsonify({
"response": extract_response_content(response),
"agent": "project"
})
except Exception as e:
print(f"Project endpoint error: {e}")
return create_error_response(str(e))
# --- وكيل المسيرة المهنية ---
@app.route('/api/career', methods=['POST'])
def career_endpoint():
"""نقطة نهاية وكيل المسيرة المهنية."""
try:
data = request.get_json() or {}
message = data.get('message', '').lower()
if any(word in message for word in ['skill', 'know', 'technology', 'tech']):
response = career_agent.get_skills_summary()
elif any(word in message for word in ['experience', 'work', 'history', 'career', 'job']):
response = career_agent.get_experience_summary()
elif any(word in message for word in ['fit', 'suitable', 'qualify', 'position']):
response = career_agent.assess_job_fit(message)
else:
response = career_agent.answer_career_question(message)
return jsonify({
"response": extract_response_content(response),
"agent": "career"
})
except Exception as e:
print(f"Career endpoint error: {e}")
return create_error_response(str(e))
# --- وكيل العملاء ---
@app.route('/api/client', methods=['POST'])
def client_endpoint():
"""نقطة نهاية وكيل العملاء."""
try:
data = request.get_json() or {}
message = data.get('message', '').lower()
if any(word in message for word in ['service', 'offer', 'provide', 'do you']):
response = client_agent.get_services_overview()
elif any(word in message for word in ['web', 'website', 'webapp']):
response = client_agent.get_service_details('web development')
elif any(word in message for word in ['mobile', 'app', 'ios', 'android']):
response = client_agent.get_service_details('mobile')
elif any(word in message for word in ['api', 'backend', 'integration']):
response = client_agent.get_service_details('api')
elif any(word in message for word in ['consult', 'advice', 'review']):
response = client_agent.get_service_details('consulting')
elif any(word in message for word in ['process', 'work with', 'how do', 'steps']):
response = client_agent.explain_process()
elif any(word in message for word in ['quote', 'proposal', 'estimate', 'price', 'cost', 'budget']):
response = client_agent.generate_proposal(message)
else:
response = client_agent.answer_client_question(message)
return jsonify({
"response": extract_response_content(response),
"agent": "client"
})
except Exception as e:
print(f"Client endpoint error: {e}")
return create_error_response(str(e))
# --- وكيل الأبحاث ---
@app.route('/api/research', methods=['POST'])
def research_endpoint():
"""نقطة نهاية وكيل الأبحاث."""
try:
data = request.get_json() or {}
message = data.get('message', '').lower()
if any(word in message for word in ['compare', 'vs', 'versus', 'or', 'difference']):
# محاولة استخراج التقنيتين للمقارنة
techs = ['react', 'vue', 'angular', 'svelte', 'python', 'javascript',
'typescript', 'node', 'django', 'flask', 'fastapi',
'mongodb', 'postgresql', 'mysql', 'docker', 'kubernetes']
found_techs = [t for t in techs if t in message]
if len(found_techs) >= 2:
response = research_agent.compare_technologies(found_techs[0], found_techs[1])
else:
response = research_agent.compare_technologies('React', 'Vue')
elif any(word in message for word in ['trend', 'latest', 'new', '2025', 'future']):
response = research_agent.get_industry_trends()
elif any(word in message for word in ['learn', 'roadmap', 'path', 'become']):
response = research_agent.get_learning_path(message)
else:
# بحث عن تقنية محددة أو سؤال عام
techs = ['react', 'vue', 'angular', 'python', 'javascript', 'docker',
'kubernetes', 'aws', 'node', 'django', 'graphql', 'ai']
found_tech = None
for tech in techs:
if tech in message:
found_tech = tech
break
if found_tech:
response = research_agent.research_technology(found_tech)
else:
response = research_agent.answer_research_question(message)
return jsonify({
"response": extract_response_content(response),
"agent": "research"
})
except Exception as e:
print(f"Research endpoint error: {e}")
return create_error_response(str(e))
# ═══════════════════════════════════════════════════════════
# تشغيل الخادم
# ═══════════════════════════════════════════════════════════
if __name__ == '__main__':
print("""
╔══════════════════════════════════════════════════════════╗
║ 🤖 AI Agents Portfolio - Backend Server ║
╠══════════════════════════════════════════════════════════╣
║ Server running at: http://127..0.0.1:5001 ║
║ ║
║ Available Endpoints: ║
║ ├── GET /api/status - Check server status ║
║ ├── POST /api/welcome - Welcome Agent ║
║ ├── POST /api/project - Project Agent ║
║ ├── POST /api/career - Career Agent ║
║ ├── POST /api/client - Client Agent ║
║ └── POST /api/research - Research Agent ║
║ ║
║ Press Ctrl+C to stop the server ║
╚══════════════════════════════════════════════════════════╝
""")
# تشغيل الخادم
app.run(
host='0.0.0.0', # السماح بالوصول من أي عنوان
port=5001, # المنفذ
debug=True # وضع التطوير (أعد التحميل التلقائي)
)
| النقطة | الطريقة | الوظيفة |
|---|---|---|
/api/status |
GET | فحص حالة الخادم |
/api/welcome |
POST | وكيل الترحيب |
/api/project |
POST | وكيل المشاريع |
/api/career |
POST | وكيل المسيرة المهنية |
/api/client |
POST | وكيل العملاء |
/api/research |
POST | وكيل الأبحاث |
🧪 تشغيل واختبار الواجهة الخلفية
الآن بعد إكمال جميع ملفات الواجهة الخلفية، حان وقت تشغيل الخادم واختباره للتأكد من أن كل شيء يعمل بشكل صحيح.
🚀 تشغيل الخادم
تأكد أنك داخل مجلد backend وأن البيئة الافتراضية مُفعّلة:
# تأكد أنك في المجلد الصحيح
cd ai-agents-portfolio/backend
# تفعيل البيئة الافتراضية (إذا لم تكن مفعّلة)
# Windows:
venv\Scripts\activate
# macOS/Linux:
# source venv/bin/activate
# تشغيل الخادم
python main.py
إذا سار كل شيء على ما يرام، سترى رسالة مثل هذه:
🤖 Initializing AI Agents...
✅ All agents initialized successfully!
╔══════════════════════════════════════════════════════════╗
║ 🤖 AI Agents Portfolio - Backend Server ║
╠══════════════════════════════════════════════════════════╣
║ Server running at: http://127.0.0.1:5001 ║
╚══════════════════════════════════════════════════════════╝
* Running on http://127.0.0.1:5001
* Debug mode: on
🔍 اختبار نقاط النهاية باستخدام curl
افتح نافذة Terminal جديدة (أبقِ الخادم يعمل) واختبر كل نقطة نهاية:
🧪 اختبار 1: فحص حالة الخادم
curl http://localhost:5001/api/status
النتيجة المتوقعة:
{
"status": "online",
"message": "AI Agents Team is Ready! 🤖",
"agents": {
"welcome": "✅ Active",
"project": "✅ Active",
"career": "✅ Active",
"client": "✅ Active",
"research": "✅ Active"
}
}
🧪 اختبار 2: وكيل الترحيب
curl -X POST http://localhost:5001/api/welcome \
-H "Content-Type: application/json" \
-d '{"message": "Hello, I am an employer looking for developers"}'
🧪 اختبار 3: وكيل المشاريع
curl -X POST http://localhost:5001/api/project \
-H "Content-Type: application/json" \
-d '{"message": "Show me all your projects"}'
🧪 اختبار 4: وكيل المسيرة المهنية
curl -X POST http://localhost:5001/api/career \
-H "Content-Type: application/json" \
-d '{"message": "What skills do you have?"}'
🧪 اختبار 5: وكيل العملاء
curl -X POST http://localhost:5001/api/client \
-H "Content-Type: application/json" \
-d '{"message": "What services do you offer and what are the prices?"}'
🧪 اختبار 6: وكيل الأبحاث
curl -X POST http://localhost:5001/api/research \
-H "Content-Type: application/json" \
-d '{"message": "Compare React vs Vue for frontend development"}'
- كل طلب POST يستهلك استدعاء API واحد من حصتك على Groq Cloud
- الردود قد تستغرق 2-5 ثوانٍ حسب طول الرد
- يمكنك مراقبة استخدامك في لوحة تحكم Groq
- إذا ظهرت أخطاء، تحقق من أن GROQ_API_KEY صحيح في ملف
.env
مبروك! 🎉 الواجهة الخلفية تعمل بشكل صحيح. أبقِ الخادم يعمل وانتقل إلى بناء الواجهة الأمامية.
⚛️ بناء الواجهة الأمامية بـ React و Vite
وصلنا إلى النصف الثاني من المشروع! 🎯 الآن سنبني واجهة أمامية جميلة وتفاعلية باستخدام React و Vite و Tailwind CSS.
📦 الخطوة 1: إنشاء مشروع React
افتح نافذة Terminal جديدة (أبقِ خادم Flask يعمل) وانتقل إلى المجلد الرئيسي:
# انتقل إلى المجلد الرئيسي للمشروع
cd ai-agents-portfolio
# إنشاء مشروع React مع Vite
npm create vite@latest frontend -- --template react
# الدخول إلى مجلد الواجهة الأمامية
cd frontend
# تثبيت الحزم الأساسية
npm install
# تثبيت الحزم الإضافية المطلوبة
npm install react-router-dom axios
# تثبيت Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
🗂️ الخطوة 2: إنشاء هيكل الملفات
# إنشاء المجلدات
mkdir -p src/components src/pages
# إنشاء ملفات المكونات
touch src/components/Chat.jsx
touch src/components/Layout.jsx
touch src/components/Navbar.jsx
touch src/components/Footer.jsx
# إنشاء ملفات الصفحات
touch src/pages/Home.jsx
touch src/pages/Projects.jsx
touch src/pages/Career.jsx
touch src/pages/Services.jsx
touch src/pages/Research.jsx
touch src/pages/Contact.jsx
📂 هيكل مجلد frontend/
frontend/
├── 📄 index.html
├── 📄 package.json
├── 📄 vite.config.js
├── 📄 tailwind.config.js
├── 📄 postcss.config.js
└── 📁 src/
├── 📄 main.jsx
├── 📄 App.jsx
├── 📄 App.css
├── 📄 index.css
├── 📁 components/
│ ├── 📄 Chat.jsx # مكون الدردشة الرئيسي
│ ├── 📄 Layout.jsx # تخطيط الصفحة
│ ├── 📄 Navbar.jsx # شريط التنقل
│ └── 📄 Footer.jsx # التذييل
└── 📁 pages/
├── 📄 Home.jsx # الصفحة الرئيسية
├── 📄 Projects.jsx # صفحة المشاريع
├── 📄 Career.jsx # صفحة المسيرة المهنية
├── 📄 Services.jsx # صفحة الخدمات
├── 📄 Research.jsx # صفحة الأبحاث
└── 📄 Contact.jsx # صفحة التواصل
⚙️ الخطوة 3: ملفات التكوين
📄 ملف: tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {
colors: {
// ألوان مخصصة للمشروع
primary: {
50: '#f0fdf4',
100: '#dcfce7',
500: '#22c55e',
600: '#16a34a',
700: '#15803d',
}
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
},
},
plugins: [],
}
📄 ملف: vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
server: {
port: 5173,
proxy: {
// توجيه طلبات API إلى خادم Flask
'/api': {
target: 'http://127.0.0.1:5001',
changeOrigin: true,
}
}
}
})
📄 ملف: src/index.css
/* Tailwind CSS Directives */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Google Fonts */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
/* Base Styles */
body {
font-family: 'Inter', sans-serif;
background-color: #f9fafb;
min-height: 100vh;
}
/* Custom Scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
::-webkit-scrollbar-thumb {
background: #22c55e;
border-radius: 10px;
}
::-webkit-scrollbar-thumb:hover {
background: #16a34a;
}
/* Chat Animation */
@keyframes bounce {
0%, 60%, 100% { transform: translateY(0); }
30% { transform: translateY(-8px); }
}
.typing-dot {
animation: bounce 1.4s infinite ease-in-out;
}
.typing-dot:nth-child(1) { animation-delay: 0s; }
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
/* Message Fade In */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.message-fade-in {
animation: fadeIn 0.3s ease-out;
}
📄 ملف: src/main.jsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.jsx'
import './index.css'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>
)
📄 ملف: src/App.jsx
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import Layout from './components/Layout'
import Home from './pages/Home'
import Projects from './pages/Projects'
import Career from './pages/Career'
import Services from './pages/Services'
import Research from './pages/Research'
import Contact from './pages/Contact'
function App() {
return (
<Router>
<Layout>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/projects" element={<Projects />} />
<Route path="/career" element={<Career />} />
<Route path="/services" element={<Services />} />
<Route path="/research" element={<Research />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</Layout>
</Router>
)
}
export default App
🧩 مكونات React (Components)
1️⃣ مكون التخطيط — Layout.jsx
📄 ملف: src/components/Layout.jsx
import Navbar from './Navbar'
import Footer from './Footer'
function Layout({ children }) {
return (
<div className="min-h-screen flex flex-col bg-gray-50">
<Navbar />
<main className="flex-1 container mx-auto px-4 py-8">
{children}
</main>
<Footer />
</div>
)
}
export default Layout
2️⃣ شريط التنقل — Navbar.jsx
📄 ملف: src/components/Navbar.jsx
import { Link, useLocation } from 'react-router-dom'
import { useState } from 'react'
function Navbar() {
const location = useLocation()
const [isMenuOpen, setIsMenuOpen] = useState(false)
const navLinks = [
{ path: '/', label: 'Home', icon: '🏠' },
{ path: '/projects', label: 'Projects', icon: '💻' },
{ path: '/career', label: 'Career', icon: '📋' },
{ path: '/services', label: 'Services', icon: '🛠️' },
{ path: '/research', label: 'Research', icon: '🔬' },
{ path: '/contact', label: 'Contact', icon: '📧' },
]
return (
<nav className="bg-gradient-to-r from-green-600 to-teal-600 text-white shadow-lg sticky top-0 z-50">
<div className="container mx-auto px-4">
<div className="flex items-center justify-between h-16">
{/* Logo */}
<Link to="/" className="flex items-center space-x-2 text-xl font-bold hover:opacity-90 transition-opacity">
<span className="text-2xl">🤖</span>
<span>AI Agents Portfolio</span>
</Link>
{/* Desktop Navigation */}
<div className="hidden md:flex items-center space-x-1">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
className={`px-4 py-2 rounded-lg transition-all duration-200 flex items-center space-x-1
${location.pathname === link.path
? 'bg-white/20 font-semibold'
: 'hover:bg-white/10'
}`}
>
<span>{link.icon}</span>
<span>{link.label}</span>
</Link>
))}
</div>
{/* Mobile Menu Button */}
<button
onClick={() => setIsMenuOpen(!isMenuOpen)}
className="md:hidden p-2 rounded-lg hover:bg-white/10 transition-colors"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{isMenuOpen ? (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
) : (
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
)}
</svg>
</button>
</div>
{/* Mobile Navigation */}
{isMenuOpen && (
<div className="md:hidden py-4 border-t border-white/20">
{navLinks.map((link) => (
<Link
key={link.path}
to={link.path}
onClick={() => setIsMenuOpen(false)}
className={`block px-4 py-3 rounded-lg transition-colors flex items-center space-x-2
${location.pathname === link.path
? 'bg-white/20 font-semibold'
: 'hover:bg-white/10'
}`}
>
<span>{link.icon}</span>
<span>{link.label}</span>
</Link>
))}
</div>
)}
</div>
</nav>
)
}
export default Navbar
3️⃣ التذييل — Footer.jsx
📄 ملف: src/components/Footer.jsx (الكود الكامل)
function Footer() {
const currentYear = new Date().getFullYear()
return (
<footer className="bg-gray-800 text-white">
<div className="container mx-auto px-4 py-8">
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
{/* About Section */}
<div>
<h3 className="text-lg font-semibold mb-4 flex items-center gap-2">
<span>🤖</span> AI Agents Portfolio
</h3>
<p className="text-gray-400 text-sm leading-relaxed">
A portfolio website powered by a team of AI agents.
Built with React, Flask, and Groq Cloud using LLaMA 3.3 70B.
</p>
</div>
{/* Quick Links */}
<div>
<h3 className="text-lg font-semibold mb-4">Quick Links</h3>
<ul className="space-y-2 text-sm">
<li>
<a href="/projects" className="text-gray-400 hover:text-green-400 transition-colors">
💻 Projects
</a>
</li>
<li>
<a href="/career" className="text-gray-400 hover:text-green-400 transition-colors">
📋 Career
</a>
</li>
<li>
<a href="/services" className="text-gray-400 hover:text-green-400 transition-colors">
🛠️ Services
</a>
</li>
<li>
<a href="/contact" className="text-gray-400 hover:text-green-400 transition-colors">
📧 Contact
</a>
</li>
</ul>
</div>
{/* Tech Stack */}
<div>
<h3 className="text-lg font-semibold mb-4">Built With</h3>
<div className="flex flex-wrap gap-2">
{['React', 'Flask', 'Agno', 'Groq', 'LLaMA', 'Tailwind'].map((tech) => (
<span
key={tech}
className="px-3 py-1 bg-gray-700 rounded-full text-xs text-gray-300"
>
{tech}
</span>
))}
</div>
</div>
</div>
{/* Copyright */}
<div className="border-t border-gray-700 mt-8 pt-6 text-center">
<p className="text-gray-400 text-sm">
© {currentYear} AI Agents Portfolio. Powered by
<span className="text-green-400"> Groq Cloud </span>
&
<span className="text-green-400"> LLaMA 3.3 70B</span>
</p>
</div>
</div>
</footer>
)
}
export default Footer
4️⃣ مكون الدردشة — Chat.jsx ⭐ (الأهم)
هذا هو أهم مكون في المشروع. يُدير إرسال الرسائل إلى الوكلاء وعرض ردودهم مع تحويل Markdown إلى HTML وعرض مؤشر الكتابة.
📄 ملف: src/components/Chat.jsx (الكود الكامل)
import { useState, useEffect, useRef, useCallback } from 'react'
import axios from 'axios'
function Chat({ agentType, initialMessage, agentName, agentIcon }) {
// حالات المكون
const [messages, setMessages] = useState([])
const [input, setInput] = useState('')
const [isLoading, setIsLoading] = useState(false)
const [isOnline, setIsOnline] = useState(true)
const messagesEndRef = useRef(null)
// عنوان API
const API_BASE_URL = 'http://127.0.0.1:5001'
// التمرير إلى آخر رسالة
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
}
// تحويل Markdown إلى HTML
const renderMarkdown = (text) => {
if (!text) return ''
let html = text
// Headers
.replace(/^### (.*$)/gim, '<h3 class="text-lg font-bold mt-4 mb-2 text-gray-800">\$1</h3>')
.replace(/^## (.*$)/gim, '<h2 class="text-xl font-bold mt-4 mb-2 text-gray-800">\$1</h2>')
.replace(/^# (.*$)/gim, '<h1 class="text-2xl font-bold mt-4 mb-2 text-gray-800">\$1</h1>')
// Bold & Italic
.replace(/\*\*\*(.*?)\*\*\*/g, '<strong><em>\$1</em></strong>')
.replace(/\*\*(.*?)\*\*/g, '<strong class="font-semibold">\$1</strong>')
.replace(/\*(.*?)\*/g, '<em>\$1</em>')
// Code blocks
.replace(/```(\w+)?\n([\s\S]*?)```/g, '<pre class="bg-gray-800 text-green-400 p-4 rounded-lg my-3 overflow-x-auto text-sm"><code>\$2</code></pre>')
.replace(/`(.*?)`/g, '<code class="bg-gray-200 text-red-600 px-1.5 py-0.5 rounded text-sm">\$1</code>')
// Lists
.replace(/^\s*[-*]\s+(.*$)/gim, '<li class="ml-4 mb-1">\$1</li>')
.replace(/^\s*(\d+)\.\s+(.*$)/gim, '<li class="ml-4 mb-1">\$2</li>')
// Links
.replace(/$$([^$$]+)\]\(([^)]+)\)/g, '<a href="\$2" class="text-green-600 hover:underline" target="_blank">\$1</a>')
// Tables (basic support)
.replace(/\|(.+)\|/g, '<div class="table-row">\$1</div>')
// Line breaks
.replace(/\n\n/g, '</p><p class="mb-3">')
.replace(/\n/g, '<br>')
return `<p class="mb-3">${html}</p>`
}
// إرسال رسالة
const sendMessage = useCallback(async (messageText = null) => {
const textToSend = messageText || input.trim()
if (!textToSend) return
// إضافة رسالة المستخدم
const userMessage = {
id: Date.now(),
content: textToSend,
isUser: true,
timestamp: new Date().toLocaleTimeString()
}
setMessages(prev => [...prev, userMessage])
setInput('')
setIsLoading(true)
try {
const response = await axios.post(
`${API_BASE_URL}/api/${agentType}`,
{ message: textToSend },
{
headers: { 'Content-Type': 'application/json' },
timeout: 60000 // 60 seconds timeout
}
)
if (response.data?.response) {
const botMessage = {
id: Date.now() + 1,
content: response.data.response,
isUser: false,
timestamp: new Date().toLocaleTimeString()
}
setMessages(prev => [...prev, botMessage])
setIsOnline(true)
}
} catch (error) {
console.error('Error sending message:', error)
setIsOnline(false)
const errorMessage = {
id: Date.now() + 1,
content: error.code === 'ECONNABORTED'
? '⏱️ Request timed out. The AI is taking longer than expected. Please try again.'
: '❌ Unable to connect to the AI agent. Please make sure the Flask server is running on http://127.0.0.1:5001',
isUser: false,
isError: true,
timestamp: new Date().toLocaleTimeString()
}
setMessages(prev => [...prev, errorMessage])
} finally {
setIsLoading(false)
}
}, [input, agentType, API_BASE_URL])
// معالجة ضغط Enter
const handleKeyPress = (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault()
sendMessage()
}
}
// إضافة الرسالة الأولى عند التحميل
useEffect(() => {
if (initialMessage) {
setMessages([{
id: 0,
content: initialMessage,
isUser: false,
timestamp: new Date().toLocaleTimeString()
}])
}
}, [initialMessage])
// التمرير عند إضافة رسائل جديدة
useEffect(() => {
scrollToBottom()
}, [messages])
// أسئلة سريعة مقترحة
const quickQuestions = {
welcome: ['I am an employer', 'I am a client', 'I am a developer'],
project: ['Show all projects', 'React projects', 'E-commerce details'],
career: ['What are your skills?', 'Work experience', 'Certifications'],
client: ['What services do you offer?', 'Pricing info', 'Get a quote'],
research: ['Latest tech trends', 'Compare React vs Vue', 'Learn Python path']
}
return (
<div className="flex flex-col h-[600px] bg-white rounded-2xl shadow-xl overflow-hidden border border-gray-200">
{/* Header */}
<div className="bg-gradient-to-r from-green-500 to-teal-500 text-white p-4">
<div className="flex items-center gap-3">
<div className="w-12 h-12 bg-white/20 rounded-full flex items-center justify-center text-2xl">
{agentIcon || '🤖'}
</div>
<div>
<h3 className="font-semibold text-lg">{agentName || 'AI Agent'}</h3>
<div className="flex items-center gap-2 text-sm">
<span className={`w-2 h-2 rounded-full ${isOnline ? 'bg-green-300' : 'bg-red-400'}`}></span>
<span className="opacity-90">{isOnline ? 'Online' : 'Offline'}</span>
</div>
</div>
</div>
</div>
{/* Messages Area */}
<div className="flex-1 overflow-y-auto p-4 space-y-4 bg-gray-50">
{messages.map((msg) => (
<div
key={msg.id}
className={`flex ${msg.isUser ? 'justify-end' : 'justify-start'} message-fade-in`}
>
<div
className={`max-w-[85%] rounded-2xl px-4 py-3 ${
msg.isUser
? 'bg-gradient-to-r from-green-500 to-teal-500 text-white rounded-br-md'
: msg.isError
? 'bg-red-50 text-red-700 border border-red-200 rounded-bl-md'
: 'bg-white text-gray-800 shadow-md rounded-bl-md'
}`}
>
{msg.isUser ? (
<p>{msg.content}</p>
) : (
<div
className="prose prose-sm max-w-none"
dangerouslySetInnerHTML={{ __html: renderMarkdown(msg.content) }}
/>
)}
<span className={`text-xs mt-2 block ${msg.isUser ? 'text-white/70' : 'text-gray-400'}`}>
{msg.timestamp}
</span>
</div>
</div>
))}
{/* Typing Indicator */}
{isLoading && (
<div className="flex justify-start">
<div className="bg-white rounded-2xl rounded-bl-md px-4 py-3 shadow-md">
<div className="flex items-center gap-1">
<span className="w-2 h-2 bg-gray-400 rounded-full typing-dot"></span>
<span className="w-2 h-2 bg-gray-400 rounded-full typing-dot"></span>
<span className="w-2 h-2 bg-gray-400 rounded-full typing-dot"></span>
<span className="text-sm text-gray-500 ml-2">AI is thinking...</span>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Quick Questions */}
{messages.length <= 1 && quickQuestions[agentType] && (
<div className="px-4 py-2 bg-gray-50 border-t border-gray-100">
<p className="text-xs text-gray-500 mb-2">Quick questions:</p>
<div className="flex flex-wrap gap-2">
{quickQuestions[agentType].map((q, i) => (
<button
key={i}
onClick={() => sendMessage(q)}
className="text-xs px-3 py-1.5 bg-white border border-gray-200 rounded-full hover:bg-green-50 hover:border-green-300 transition-colors"
>
{q}
</button>
))}
</div>
</div>
)}
{/* Input Area */}
<div className="p-4 bg-white border-t border-gray-200">
<div className="flex gap-3">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
disabled={isLoading}
className="flex-1 px-4 py-3 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent disabled:bg-gray-100 disabled:cursor-not-allowed transition-all"
/>
<button
onClick={() => sendMessage()}
disabled={isLoading || !input.trim()}
className="px-6 py-3 bg-gradient-to-r from-green-500 to-teal-500 text-white rounded-xl font-medium hover:opacity-90 disabled:opacity-50 disabled:cursor-not-allowed transition-all flex items-center gap-2"
>
{isLoading ? (
<>
<svg className="animate-spin h-5 w-5" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" fill="none" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" />
</svg>
</>
) : (
<>
Send
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 19l9 2-9-18-9 18 9-2zm0 0v-8" />
</svg>
</>
)}
</button>
</div>
</div>
</div>
)
}
export default Chat
📄 صفحات التطبيق (Pages)
1️⃣ الصفحة الرئيسية — Home.jsx
📄 ملف: src/pages/Home.jsx
import Chat from '../components/Chat'
function Home() {
return (
<div className="max-w-4xl mx-auto">
{/* Hero Section */}
<div className="text-center mb-10">
<div className="text-6xl mb-4">👋</div>
<h1 className="text-4xl md:text-5xl font-bold text-gray-800 mb-4">
Welcome to My Portfolio
</h1>
<p className="text-xl text-gray-600 max-w-2xl mx-auto leading-relaxed">
I'm a Full-Stack Developer with 7+ years of experience.
Meet my AI assistant team — they're here to help you explore my work
and answer any questions you might have!
</p>
</div>
{/* Features Grid */}
<div className="grid grid-cols-2 md:grid-cols-5 gap-4 mb-10">
{[
{ icon: '🎭', label: 'Welcome Agent', color: 'bg-yellow-100' },
{ icon: '💻', label: 'Projects Agent', color: 'bg-blue-100' },
{ icon: '📋', label: 'Career Agent', color: 'bg-pink-100' },
{ icon: '🤝', label: 'Client Agent', color: 'bg-purple-100' },
{ icon: '🔬', label: 'Research Agent', color: 'bg-red-100' },
].map((agent, i) => (
<div key={i} className={`${agent.color} rounded-xl p-4 text-center`}>
<div className="text-3xl mb-2">{agent.icon}</div>
<div className="text-sm font-medium text-gray-700">{agent.label}</div>
</div>
))}
</div>
{/* Chat Component */}
<Chat
agentType="welcome"
agentName="Welcome Agent"
agentIcon="🎭"
initialMessage="Hello! 👋 I'm the Welcome Agent for this portfolio. I can help guide you to the right section based on your interests. Are you an employer looking for talent, a potential client, or a fellow programmer? Let me know how I can help!"
/>
</div>
)
}
export default Home
2️⃣ صفحة المشاريع — Projects.jsx
📄 ملف: src/pages/Projects.jsx
import Chat from '../components/Chat'
function Projects() {
return (
<div className="max-w-4xl mx-auto">
<div className="text-center mb-10">
<div className="text-6xl mb-4">💻</div>
<h1 className="text-4xl font-bold text-gray-800 mb-4">My Projects</h1>
<p className="text-xl text-gray-600">
Explore my technical projects and ask about implementation details
</p>
</div>
{/* Project Cards Preview */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
{[
{ name: 'E-commerce Platform', tech: 'React, Node.js, MongoDB', icon: '🛒' },
{ name: 'Task Manager', tech: 'Vue.js, Firebase', icon: '✅' },
{ name: 'Data Dashboard', tech: 'Python, Django, D3.js', icon: '📊' },
{ name: 'AI Agents Portfolio', tech: 'React, Flask, Groq', icon: '🤖' },
].map((project, i) => (
<div key={i} className="bg-white p-4 rounded-xl shadow-md hover:shadow-lg transition-shadow">
<div className="flex items-center gap-3">
<span className="text-2xl">{project.icon}</span>
<div>
<h3 className="font-semibold text-gray-800">{project.name}</h3>
<p className="text-sm text-gray-500">{project.tech}</p>
</div>
</div>
</div>
))}
</div>
<Chat
agentType="project"
agentName="Project Agent"
agentIcon="💻"
initialMessage="Hi! 👋 I'm the Project Agent. I can tell you all about the technical projects in this portfolio. Would you like to see a list of all projects, or ask about a specific one? You can also ask technical questions about implementation details!"
/>
</div>
)
}
export default Projects
3️⃣ صفحة المسيرة المهنية — Career.jsx
📄 ملف: src/pages/Career.jsx (الكود الكامل)
import Chat from '../components/Chat'
function Career() {
return (
<div className="max-w-4xl mx-auto">
<div className="text-center mb-10">
<div className="text-6xl mb-4">📋</div>
<h1 className="text-4xl font-bold text-gray-800 mb-4">Career & Skills</h1>
<p className="text-xl text-gray-600">
Learn about my professional experience and technical expertise
</p>
</div>
{/* Stats Overview */}
<div className="bg-white rounded-xl shadow-md p-6 mb-8">
<h3 className="font-semibold text-lg mb-4 text-gray-800">🚀 Quick Overview</h3>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
<div className="text-center p-3 bg-green-50 rounded-lg">
<div className="text-2xl font-bold text-green-600">7+</div>
<div className="text-sm text-gray-600">Years Experience</div>
</div>
<div className="text-center p-3 bg-blue-50 rounded-lg">
<div className="text-2xl font-bold text-blue-600">50+</div>
<div className="text-sm text-gray-600">Projects</div>
</div>
<div className="text-center p-3 bg-purple-50 rounded-lg">
<div className="text-2xl font-bold text-purple-600">15+</div>
<div className="text-sm text-gray-600">Technologies</div>
</div>
<div className="text-center p-3 bg-yellow-50 rounded-lg">
<div className="text-2xl font-bold text-yellow-600">3</div>
<div className="text-sm text-gray-600">Certifications</div>
</div>
</div>
</div>
{/* Skills Tags */}
<div className="bg-white rounded-xl shadow-md p-6 mb-8">
<h3 className="font-semibold text-lg mb-4 text-gray-800">🛠️ Tech Stack</h3>
<div className="flex flex-wrap gap-2">
{['Python', 'JavaScript', 'TypeScript', 'React', 'Vue.js', 'Node.js',
'Django', 'Flask', 'PostgreSQL', 'MongoDB', 'AWS', 'Docker'].map((skill) => (
<span
key={skill}
className="px-3 py-1 bg-gradient-to-r from-green-100 to-teal-100 text-green-700 rounded-full text-sm font-medium"
>
{skill}
</span>
))}
</div>
</div>
<Chat
agentType="career"
agentName="Career Agent"
agentIcon="📋"
initialMessage="Hello! 👋 I'm the Career Agent. I can provide detailed information about skills, work experience, and professional background. I can also assess job fit if you share a job description. What would you like to know?"
/>
</div>
)
}
export default Career
4️⃣ صفحة الخدمات — Services.jsx
📄 ملف: src/pages/Services.jsx
import Chat from '../components/Chat'
function Services() {
const services = [
{
icon: '🌐',
title: 'Web Development',
desc: 'Custom web applications',
price: 'From \$2,000',
color: 'bg-blue-50 border-blue-200'
},
{
icon: '📱',
title: 'Mobile Apps',
desc: 'iOS & Android development',
price: 'From \$8,000',
color: 'bg-green-50 border-green-200'
},
{
icon: '🔗',
title: 'API Development',
desc: 'RESTful & GraphQL APIs',
price: 'From \$1,500',
color: 'bg-purple-50 border-purple-200'
},
{
icon: '💡',
title: 'Consulting',
desc: 'Technical advice & reviews',
price: '\$100-200/hr',
color: 'bg-yellow-50 border-yellow-200'
}
]
return (
<div className="max-w-4xl mx-auto">
<div className="text-center mb-10">
<div className="text-6xl mb-4">🛠️</div>
<h1 className="text-4xl font-bold text-gray-800 mb-4">Services</h1>
<p className="text-xl text-gray-600">
Professional development services tailored to your needs
</p>
</div>
{/* Services Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
{services.map((service, i) => (
<div
key={i}
className={`p-5 rounded-xl border-2 ${service.color} hover:shadow-md transition-shadow`}
>
<div className="flex items-start gap-4">
<span className="text-3xl">{service.icon}</span>
<div>
<h3 className="font-semibold text-gray-800 text-lg">{service.title}</h3>
<p className="text-gray-600 text-sm mb-2">{service.desc}</p>
<span className="text-green-600 font-semibold">{service.price}</span>
</div>
</div>
</div>
))}
</div>
{/* CTA */}
<div className="bg-gradient-to-r from-green-500 to-teal-500 text-white rounded-xl p-6 mb-8 text-center">
<h3 className="text-xl font-semibold mb-2">💬 Need a Custom Quote?</h3>
<p className="opacity-90">
Describe your project below and the AI agent will generate a preliminary proposal!
</p>
</div>
<Chat
agentType="client"
agentName="Business Advisor"
agentIcon="🤝"
initialMessage="Welcome! 👋 I'm the Business Advisor. I can help you understand our services, explain the engagement process, and even generate a preliminary proposal for your project. What would you like to know? Feel free to describe your project for a custom quote!"
/>
</div>
)
}
export default Services
5️⃣ صفحة الأبحاث — Research.jsx
📄 ملف: src/pages/Research.jsx
import Chat from '../components/Chat'
function Research() {
const topics = [
{ icon: '⚛️', name: 'React' },
{ icon: '💚', name: 'Vue.js' },
{ icon: '🐍', name: 'Python' },
{ icon: '🐳', name: 'Docker' },
{ icon: '☸️', name: 'Kubernetes' },
{ icon: '🤖', name: 'AI/ML' },
]
return (
<div className="max-w-4xl mx-auto">
<div className="text-center mb-10">
<div className="text-6xl mb-4">🔬</div>
<h1 className="text-4xl font-bold text-gray-800 mb-4">Tech Research</h1>
<p className="text-xl text-gray-600">
Explore latest technologies, compare tools, and discover industry trends
</p>
</div>
{/* Popular Topics */}
<div className="bg-white rounded-xl shadow-md p-6 mb-8">
<h3 className="font-semibold text-lg mb-4 text-gray-800">🔥 Popular Topics</h3>
<div className="flex flex-wrap gap-3">
{topics.map((topic, i) => (
<span
key={i}
className="px-4 py-2 bg-gray-100 rounded-lg text-gray-700 hover:bg-green-100 hover:text-green-700 cursor-pointer transition-colors flex items-center gap-2"
>
<span>{topic.icon}</span>
<span>{topic.name}</span>
</span>
))}
</div>
</div>
{/* Research Ideas */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
<div className="bg-blue-50 p-4 rounded-xl text-center">
<div className="text-2xl mb-2">📖</div>
<h4 className="font-medium text-gray-800">Learn a Technology</h4>
<p className="text-sm text-gray-600">Get comprehensive overviews</p>
</div>
<div className="bg-green-50 p-4 rounded-xl text-center">
<div className="text-2xl mb-2">⚖️</div>
<h4 className="font-medium text-gray-800">Compare Tools</h4>
<p className="text-sm text-gray-600">React vs Vue, etc.</p>
</div>
<div className="bg-purple-50 p-4 rounded-xl text-center">
<div className="text-2xl mb-2">🚀</div>
<h4 className="font-medium text-gray-800">Latest Trends</h4>
<p className="text-sm text-gray-600">2025 industry insights</p>
</div>
</div>
<Chat
agentType="research"
agentName="Research Assistant"
agentIcon="🔬"
initialMessage="Hi! 👋 I'm the Research Assistant. I can help you explore technologies, compare different tools and frameworks, or provide insights on industry trends. What would you like to research today? Try asking me to compare React vs Vue, or about the latest trends in AI!"
/>
</div>
)
}
export default Research
6️⃣ صفحة التواصل — Contact.jsx
📄 ملف: src/pages/Contact.jsx
import { useState } from 'react'
function Contact() {
const [formData, setFormData] = useState({
name: '',
email: '',
subject: '',
message: ''
})
const [isSubmitted, setIsSubmitted] = useState(false)
const handleChange = (e) => {
setFormData({ ...formData, [e.target.name]: e.target.value })
}
const handleSubmit = (e) => {
e.preventDefault()
// في مشروع حقيقي، سترسل البيانات إلى الخادم
console.log('Form submitted:', formData)
setIsSubmitted(true)
}
return (
<div className="max-w-4xl mx-auto">
<div className="text-center mb-10">
<div className="text-6xl mb-4">📧</div>
<h1 className="text-4xl font-bold text-gray-800 mb-4">Get In Touch</h1>
<p className="text-xl text-gray-600">
Have a project in mind? Let's discuss how we can work together!
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
{/* Contact Info */}
<div>
<div className="bg-white rounded-xl shadow-md p-6 mb-6">
<h3 className="font-semibold text-lg mb-4 text-gray-800">📍 Contact Information</h3>
<div className="space-y-4">
<div className="flex items-center gap-3">
<span className="text-xl">📧</span>
<span className="text-gray-600">[email protected]</span>
</div>
<div className="flex items-center gap-3">
<span className="text-xl">💼</span>
<span className="text-gray-600">LinkedIn Profile</span>
</div>
<div className="flex items-center gap-3">
<span className="text-xl">🐙</span>
<span className="text-gray-600">GitHub Profile</span>
</div>
<div className="flex items-center gap-3">
<span className="text-xl">🌍</span>
<span className="text-gray-600">Remote - Worldwide</span>
</div>
</div>
</div>
<div className="bg-gradient-to-r from-green-500 to-teal-500 text-white rounded-xl p-6">
<h3 className="font-semibold text-lg mb-2">⚡ Quick Response</h3>
<p className="opacity-90 text-sm">
I typically respond within 24 hours. For urgent inquiries,
please mention "URGENT" in the subject line.
</p>
</div>
</div>
{/* Contact Form */}
<div className="bg-white rounded-xl shadow-md p-6">
{isSubmitted ? (
<div className="text-center py-10">
<div className="text-5xl mb-4">✅</div>
<h3 className="text-xl font-semibold text-gray-800 mb-2">Message Sent!</h3>
<p className="text-gray-600">Thank you! I'll get back to you soon.</p>
<button
onClick={() => setIsSubmitted(false)}
className="mt-4 text-green-600 hover:underline"
>
Send another message
</button>
</div>
) : (
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Name</label>
<input
type="text"
name="name"
value={formData.name}
onChange={handleChange}
required
className="w-full px-4 py-2 border border-gray-200 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Your name"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Email</label>
<input
type="email"
name="email"
value={formData.email}
onChange={handleChange}
required
className="w-full px-4 py-2 border border-gray-200 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="[email protected]"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Subject</label>
<input
type="text"
name="subject"
value={formData.subject}
onChange={handleChange}
required
className="w-full px-4 py-2 border border-gray-200 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent"
placeholder="Project inquiry"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Message</label>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
required
rows={4}
className="w-full px-4 py-2 border border-gray-200 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-transparent resize-none"
placeholder="Tell me about your project..."
/>
</div>
<button
type="submit"
className="w-full py-3 bg-gradient-to-r from-green-500 to-teal-500 text-white rounded-lg font-medium hover:opacity-90 transition-opacity"
>
Send Message 📨
</button>
</form>
)}
</div>
</div>
</div>
)
}
export default Contact
🚀 تشغيل المشروع الكامل
الآن بعد إكمال جميع الملفات، حان وقت تشغيل المشروع بالكامل واختباره!
📋 ملخص الخطوات
- تأكد من حفظ جميع الملفات في مواقعها الصحيحة
- افتح نافذتين Terminal — واحدة للـ Backend وواحدة للـ Frontend
- شغّل الخادم الخلفي أولاً ثم الواجهة الأمامية
- افتح المتصفح وابدأ التفاعل مع الوكلاء!
🖥️ النافذة الأولى: تشغيل الواجهة الخلفية (Backend)
# انتقل إلى مجلد الواجهة الخلفية
cd ai-agents-portfolio/backend
# تفعيل البيئة الافتراضية
# Windows:
venv\Scripts\activate
# macOS/Linux:
# source venv/bin/activate
# تشغيل الخادم
python main.py
✅ يجب أن ترى:
🤖 Initializing AI Agents... ✅ All agents initialized successfully! * Running on http://127.0.0.1:5001
🌐 النافذة الثانية: تشغيل الواجهة الأمامية (Frontend)
# افتح نافذة Terminal جديدة
# انتقل إلى مجلد الواجهة الأمامية
cd ai-agents-portfolio/frontend
# تشغيل خادم التطوير
npm run dev
✅ يجب أن ترى:
VITE v5.x.x ready in xxx ms ➜ Local: http://localhost:5173/ ➜ Network: use --host to expose
🎉 فتح التطبيق
افتح متصفحك وانتقل إلى: http://localhost:5173
مبروك!
لديك الآن موقع محفظة أعمال مدعوم بفريق من 5 وكلاء ذكاء اصطناعي!
🔧 التحديات الشائعة وحلولها
عند بناء أنظمة الوكلاء الذكية، قد تواجه بعض التحديات التقنية. إليك أكثرها شيوعاً مع حلول عملية:
❌ المشكلة 1: خطأ "CORS" عند الاتصال بالـ API
Access to XMLHttpRequest has been blocked by CORS policy
✅ الحل:
تأكد من أن flask-cors مثبت ومُفعّل في main.py:
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # يجب أن يكون بعد إنشاء التطبيق مباشرة
❌ المشكلة 2: خطأ "API Key Invalid"
Invalid API Key أو Authentication failed
✅ الحل:
- تأكد من أن ملف
.envموجود في مجلدbackend - تأكد من صحة المفتاح (يبدأ بـ
gsk_) - تأكد من عدم وجود مسافات أو أحرف إضافية حول المفتاح
- تأكد من استدعاء
load_dotenv()في أعلىmain.py
❌ المشكلة 3: بطء الاستجابة أو Timeout
✅ الحل:
- الردود من LLM قد تستغرق 3-10 ثوانٍ — هذا طبيعي
- تأكد من أن الـ timeout في axios كافٍ (60 ثانية على الأقل)
- استخدم Groq Cloud لأنه أسرع بكثير من البدائل
- قلّل طول الـ prompts إذا كانت طويلة جداً
❌ المشكلة 4: خطأ "Module not found"
ModuleNotFoundError: No module named 'agents'
✅ الحل:
- تأكد من وجود ملف
__init__.pyفي مجلدagents - تأكد من أنك تشغّل
main.pyمن داخل مجلدbackend - تأكد من تفعيل البيئة الافتراضية قبل التشغيل
# تأكد من الهيكل الصحيح
backend/
├── main.py
└── agents/
├── __init__.py ← هذا الملف ضروري!
├── base_agent.py
└── ...
❌ المشكلة 5: الصفحة تظهر فارغة أو خطأ في React
✅ الحل:
- افتح Developer Console في المتصفح (F12) وتحقق من الأخطاء
- تأكد من تثبيت جميع الحزم:
npm install - تأكد من صحة مسارات الاستيراد في الملفات
- جرّب حذف
node_modulesوإعادة التثبيت:
rm -rf node_modules package-lock.json
npm install
npm run dev
❌ المشكلة 6: Rate Limit Exceeded (تجاوز حد الاستخدام)
Error 429: Too Many Requests
✅ الحل:
- انتظر بضع دقائق قبل إرسال طلبات جديدة
- راجع حدود الاستخدام في توثيق Groq
- قلّل عدد الطلبات المتزامنة
- استخدم التخزين المؤقت (Caching) للردود المتكررة
لا تمنح الوكلاء صلاحيات تنفيذية خطيرة (مثل حذف الملفات أو إجراء مدفوعات أو تعديل قواعد البيانات) دون وجود طبقة تأكيد بشري وسيطة. الوكلاء قد يُخطئون أو يُساء استخدامهم.
⭐ أفضل الممارسات والنصائح المتقدمة
بعد بناء النظام الأساسي، إليك نصائح لتحسين مشروعك وجعله أكثر احترافية:
1️⃣ إدارة الأخطاء الشاملة
أضف معالجة شاملة للأخطاء في كل نقطة نهاية API، بما في ذلك:
- أخطاء الاتصال بـ Groq API
- انتهاء المهلة (Timeout)
- البيانات غير الصالحة من المستخدم
- تجاوز حدود الاستخدام
2️⃣ التخزين المؤقت (Caching)
خزّن الردود المتكررة لتقليل استدعاءات API وتحسين السرعة:
from functools import lru_cache
@lru_cache(maxsize=100)
def get_cached_response(query_hash):
# تخزين مؤقت للردود المتكررة
return agent.get_response(query)
3️⃣ حدود المعدل (Rate Limiting)
أضف حدودًا لطلبات المستخدمين لحماية حصتك المجانية من Groq:
from flask_limiter import Limiter
limiter = Limiter(app, default_limits=["100 per hour"])
@app.route('/api/welcome', methods=['POST'])
@limiter.limit("10 per minute")
def welcome_endpoint():
# ...
4️⃣ تسجيل الأحداث (Logging)
سجّل التفاعلات لتحليل الأداء وتتبع الأخطاء:
import logging
logging.basicConfig(
filename='app.log',
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
# في كل endpoint
logging.info(f"Welcome request: {message[:50]}...")
5️⃣ تخصيص الأوامر (Prompt Engineering)
صمّم أوامر (Prompts) دقيقة لكل وكيل لضمان ردود متسقة وعالية الجودة:
- حدد شخصية الوكيل بوضوح
- اذكر القيود والحدود
- حدد تنسيق الرد المطلوب (Markdown, JSON, etc.)
- أعطِ أمثلة على الردود المثالية
يمكنك نشر مشروعك ليكون متاحًا للجميع على الإنترنت — مجانًا!
💡 أفكار لتوسيع فريقك مستقبلاً
لا تتوقف هنا! يمكنك إضافة وكلاء متخصصين لمهام أخرى:
وكيل SEO
تحليل الكلمات المفتاحية واقتراح العناوين
محلل البيانات
تحليل تفاعل الزوار وتقديم تقارير
مدقق لغوي
مراجعة النصوص وتصحيح الأخطاء
مستشار تصميم
اقتراحات UI/UX وتحسينات التصميم
📊 مقارنة بين الأدوات المتاحة
لمساعدتك في اختيار الأدوات المناسبة لمشاريعك المستقبلية، إليك مقارنة شاملة:
📝 الخلاصة
بناء فريق من وكلاء الذكاء الاصطناعي لموقعك باستخدام Agno و Groq Cloud هو طريقة فعّالة لتحسين تجربة المستخدم وتقديم خدمة متميزة — دون أي تكلفة.
🎯 ما تعلمته في هذا الدليل:
الجمع بين تنسيق Agno واستدلال Groq فائق السرعة يوفر مسارًا مجانيًا لاستكشاف تطبيقات الذكاء الاصطناعي العملية. مع التطورات المتسارعة في هذا المجال، فإن القدرة على تجربة هذه الحلول ستبقيك في المقدمة.
ابدأ اليوم وشاركنا تجربتك! إذا واجهت أي مشاكل أو لديك أسئلة، لا تتردد في ترك تعليق أدناه.
هل استفدت من هذا المقال؟
انضم إلى مئات المشتركين واحصل على أحدث المقالات والدروس مباشرة في بريدك الإلكتروني.
نعم، أريد الاشتراك! ✉️🔒 خصوصيتك مهمة لنا. لن نرسل رسائل مزعجة أبداً.
يسعدنا أن نسمع آراءكم! اتركوا تعليقاً أدناه وشاركوا تجاربكم أو أسئلتكم.