diff --git a/i18n/ar/code.json b/i18n/ar/code.json index 216281a..55f7400 100644 --- a/i18n/ar/code.json +++ b/i18n/ar/code.json @@ -901,5 +901,13 @@ "homepage.projects.meetingNotesSummarizer.summary": { "message": "حوّل نص اجتماع خام إلى قرارات وعناصر عمل وأسئلة مفتوحة مُهيكَلة، باستخدام نموذج لغوي من مستوى مجاني وprompt استخلاص JSON مصمَّم بعناية.", "description": "Homepage project card summary" + }, + "homepage.projects.multiAgentResearch.title": { + "message": "بناء مساعد بحث متعدد الوكلاء", + "description": "Homepage project card title" + }, + "homepage.projects.multiAgentResearch.summary": { + "message": "ابنِ نظامًا صغيرًا متعدد الوكلاء — مُخطِّطًا وباحثًا وكاتبًا — يقسّم سؤال بحث ويركّب تقريرًا نهائيًا، باستخدام وكلاء deepagents الفرعيين من LangChain ونموذجًا لغويًا من مستوى مجاني.", + "description": "Homepage project card summary" } } diff --git a/i18n/ar/docusaurus-plugin-content-docs/current/projects/index.mdx b/i18n/ar/docusaurus-plugin-content-docs/current/projects/index.mdx index c79b9cf..88e5a86 100644 --- a/i18n/ar/docusaurus-plugin-content-docs/current/projects/index.mdx +++ b/i18n/ar/docusaurus-plugin-content-docs/current/projects/index.mdx @@ -143,5 +143,11 @@ import {mergeProjectMeta} from '@site/src/data/projects'; summary: 'حوّل نص اجتماع خام إلى قرارات وعناصر عمل وأسئلة مفتوحة مُهيكَلة، باستخدام نموذج لغوي من مستوى مجاني وprompt استخلاص JSON مصمَّم بعناية.', }, + { + id: 'multi-agent-research', + title: 'بناء مساعد بحث متعدد الوكلاء', + summary: + 'ابنِ نظامًا صغيرًا متعدد الوكلاء — مُخطِّطًا وباحثًا وكاتبًا — يقسّم سؤال بحث ويركّب تقريرًا نهائيًا، باستخدام وكلاء deepagents الفرعيين من LangChain ونموذجًا لغويًا من مستوى مجاني.', + }, ])} /> diff --git a/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json b/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json new file mode 100644 index 0000000..d163f8c --- /dev/null +++ b/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "مساعد بحث متعدد الوكلاء", + "position": 7 +} diff --git a/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md b/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md new file mode 100644 index 0000000..74e5e48 --- /dev/null +++ b/i18n/ar/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md @@ -0,0 +1,278 @@ +--- +id: multi-agent-research +title: "بناء مساعد بحث متعدد الوكلاء" +sidebar_label: "بناء مساعد بحث متعدد الوكلاء" +slug: /projects/multi-agent-research +description: "تخرّج من بيئة اللعب داخل المتصفح إلى Python حقيقية: ابنِ نظامًا صغيرًا متعدد الوكلاء — مُخطِّطًا وباحثًا وكاتبًا — يقسّم سؤال بحث ويركّب تقريرًا حقيقيًا، باستخدام وكلاء deepagents الفرعيين من LangChain ونموذجًا لغويًا من المستوى المجاني." +--- + +import ProjectProgressCheckbox from '@site/src/components/ProjectProgressCheckbox'; +import ProjectPublishedDate from '@site/src/components/ProjectPublishedDate'; +import ProjectGreeting from '@site/src/components/ProjectGreeting'; +import {StepChecklist, StepChecklistItem} from '@site/src/components/StepChecklist'; + +# 🌍 بناء مساعد بحث متعدد الوكلاء + + + + + +وكيل واحد بمجموعة أدوات وتعليمات نظام واحدة طويلة يعمل جيدًا للمهام الصغيرة، لكنه يبدأ بالضغط بمجرد أن تكتسب مهمة *مراحل* مختلفة فعلًا تستدعي تعليمات مختلفة — تخطيط ما ستبحث عنه، ثم البحث الفعلي في كل جزء، ثم كتابة كل ذلك. يقسّم هذا المشروع ذلك العمل عبر ثلاثة وكلاء صغار ضيّقي التعليمات بدلًا من وكيل كبير واحد: **مُخطِّط** يحوّل سؤال بحث إلى حفنة من الأسئلة الفرعية، و**باحث** يجيب عن كل سؤال فرعي بمفرده، و**كاتب** يركّب كل شيء في تقرير نهائي واحد — منسّقين عبر خاصية الوكلاء الفرعيين `deepagents` من LangChain. + +يفترض هذا Python بمستوى 101، ويبني مباشرةً على [مشروع وكيل الذكاء الاصطناعي](/docs/projects/ai-agent) — نفس مكتبة `deepagents`، نفس إعداد API من المستوى المجاني، نفس فكرة نموذج يقرر ماذا يستدعي ومتى، فقط مطبّقة على تفويض مهام فرعية كاملة بدلًا من استدعاء أدوات فردية. إنجاز ذلك المشروع أولًا ليس شرطًا صارمًا، لكنه مسار دخول أكثر سلاسة بكثير من البدء هنا بلا مقدمات. + +هذا اختياري وغير مُقيَّم. راجع [مشاريع من العالم الحقيقي](/docs/projects) للاطلاع على القائمة الكاملة والنامية. + +## 🎯 ما ستفعله + +1. تثبيت `uv`، أداة حديثة وسريعة لإدارة Python نفسها واعتماديات مشروعك. +2. الحصول على مفتاح API مجاني لنموذج ذكاء اصطناعي — نفس خيار المزوّدين الستة من مشروع وكيل الذكاء الاصطناعي. +3. إعداد مشروع صغير وتثبيت `deepagents`. +4. تعريف ثلاثة وكلاء فرعيين — مُخطِّط وباحث وكاتب — لكل واحد تعليمات نظام ضيّقة خاصة به. +5. ربطهم معًا في وكيل واحد من المستوى الأعلى وتشغيله على سؤال بحث حقيقي، من البداية إلى النهاية. + +## أين تشغّل هذا + +**محليًا باستخدام `uv`** هو المسار الذي تتبعه خطوات هذا الدرس، والموصى به — إنه Python حقيقي يعمل على جهازك الخاص، نفس حركة "التخرّج إلى Python حقيقية" كما في كل مشروع آخر في هذا القسم. يشرح قسم الإعداد أدناه كيفية تثبيته. + +**GitHub Codespaces** بديل بلا أي إعداد إن كنت تفضّل عدم تثبيت أي شيء محليًا الآن: افتح [مستودع الدورة كاملاً في Codespace مجاني](https://codespaces.new/abderrahim-lectures/python-data-analysis-course) (Node وPython وuv مثبّتة مسبقًا، حسب ملف `.devcontainer/devcontainer.json` الخاص بالمستودع) وشغّل نفس أوامر `uv` تمامًا من طرفية في تبويب متصفحك. + +**Google Colab أو Kaggle Notebooks أو Binder** تعمل أيضًا، لأن لا شيء هنا يحتاج GPU — كل خطوة مجرد استدعاء API لنموذج لغوي من المستوى المجاني. نسخة دفتر ملاحظات حقيقية وقابلة للتشغيل من هذا المشروع موجودة في المستودع في [`examples/multi-agent-research/notebook.ipynb`](https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) — انقر على شارة أدناه لتشغيلها بلا أي إعداد محلي، وبلا حاجة لملف `.env` (يطلب مفتاح API الخاص بك تفاعليًا بـ`getpass` بدلًا من ذلك): + + +[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Open in Kaggle](https://kaggle.com/static/images/open-in-kaggle.svg)](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fmulti-agent-research%2Fnotebook.ipynb) + +إنها طريقة أقل دقة لتجربة المشروع مقارنة بمشروع `uv` محلي حقيقي، لكنها قابلة للتشغيل تمامًا لتجربة الفكرة بسرعة. + +## الإعداد + +كل ما يلي يجهّز بيئتك بالكامل قبل أن يبدأ أي بناء: تثبيت `uv`، والحصول على مفتاح API مجاني، وإعداد المشروع، وتهيئة ملف `.env` الخاص بك. + +### تثبيت `uv` + +`uv` أداة واحدة تحل محل سلسلة "ثبّت Python، ثم ثبّت pip، ثم ثبّت أداة بيئة افتراضية، ثم ثبّت الحزم" المعتادة — تستطيع تثبيت وإدارة إصدارات Python بنفسها، إلى جانب اعتماديات مشروعك. + +**macOS / Linux** (الطرفية): + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +**Windows** (PowerShell): + +```powershell +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +``` + +أغلق طرفيتك وأعد فتحها، ثم تأكد من التثبيت: + +```bash +uv --version +``` + +### الحصول على مفتاح API مجاني + +**اختر أي مزوّد تفضله** — لا يتطلب أيٌّ منها بطاقة ائتمان وقت كتابة هذا النص، وهذه الدورة لا تفضّل واحدًا على آخر. الوكيل المثال في مستودع الدورة ([`examples/multi-agent-research/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/multi-agent-research)) يدعم الستة جميعًا جاهزين للاستخدام، يُختار عبر إعداد واحد، بنفس نمط مشروع وكيل الذكاء الاصطناعي. + +| المزوّد | أين تحصل على مفتاح | لماذا قد تختاره | +|---|---|---| +| **GitHub Models** *(الافتراضي المقترح)* | [github.com/settings/tokens](https://github.com/settings/tokens) — رمز وصول شخصي بصلاحية `models: read` | لا تسجيل منفصل — لديك بالفعل حساب GitHub. حدود مستوى مجاني أكثر سخاءً من Gemini. | +| Gemini | [Google AI Studio](https://aistudio.google.com/) | الخيار الأكثر شيوعًا في المراجع. | +| Groq | [console.groq.com/keys](https://console.groq.com/keys) | استدلال سريع، مستوى مجاني سخي، بلا بطاقة. | +| Mistral | [console.mistral.ai/api-keys](https://console.mistral.ai/api-keys) | من أكثر الحصص المجانية الدائمة سخاءً. | +| Cerebras | [cloud.cerebras.ai](https://cloud.cerebras.ai/) | حجم رموز يومي مرتفع، بلا بطاقة. | +| OpenRouter | [openrouter.ai/keys](https://openrouter.ai/keys) | واجهة برمجة واحدة، نماذج مجانية عديدة — جيدة لمقارنة المزوّدين. | + +أيًّا كان اختيارك، العملية نفسها: + +1. سجّل الدخول وولّد مفتاح API على موقع ذلك المزوّد. +2. **لا تلصق هذا المفتاح مطلقًا مباشرة في الكود أو تُودعه في مستودع.** اضبطه كمتغيّر بيئة بدلاً من ذلك: + +```bash +# macOS / Linux (add to ~/.bashrc or ~/.zshrc to persist it) +export GITHUB_TOKEN="your-key-here" # or GOOGLE_API_KEY, GROQ_API_KEY, etc. -- match your provider + +# Windows (PowerShell) +$env:GITHUB_TOKEN = "your-key-here" +``` + +:::tip[ملف .env غالبًا أكثر ملاءمة من export] +بدلاً من استخدام `export` لمفتاح في كل جلسة طرفية جديدة، يمكنك وضعه في ملف `.env` داخل مجلد مشروعك (انظر `.env.example` في مثال المستودع) وتحميله تلقائيًا بحزمة `python-dotenv` — مشروحة أدناه. +::: + +### إعداد المشروع بـ `uv` + +```bash +uv init multi-agent-research +cd multi-agent-research +uv add deepagents langchain-openai python-dotenv +``` + +`deepagents` هو نفس إطار عمل LangChain المستخدم في مشروع وكيل الذكاء الاصطناعي، وهو ما يجعل هذا المشروع بأكمله صغيرًا: إلى جانب استخدام الأدوات، فيه خاصية **وكلاء فرعيين** مدمجة — طريقة لتسليم جزء من مهمة إلى وكيل مُعطى تعليمات منفصلة، بدلاً من صنع حلقتك الخاصة يدويًا التي تستدعي النموذج ثلاث مرات بثلاثة تعليمات مختلفة وتخيط النتائج معًا بنفسك. `langchain-openai` يتحدث إلى GitHub Models (واجهته البرمجية متوافقة مع OpenAI)؛ استبدله بـ `langchain-google-genai`، أو `langchain-groq`، أو `langchain-mistralai` إن اخترت مزوّدًا مختلفًا أعلاه — Cerebras وOpenRouter متوافقان أيضًا مع OpenAI، لذا يغطيهما `langchain-openai` أيضًا، فقط بـ `base_url` مختلف، تمامًا كما في مشروع وكيل الذكاء الاصطناعي. + +أنشئ ملف `.env` (لا تُودعه أبدًا) بمفتاح المزوّد الذي اخترته: + +```bash +# .env +GITHUB_TOKEN=your-key-here +``` + +**✅ قائمة التحقق** + + +اكتمل `uv add deepagents langchain-openai python-dotenv` دون أخطاء. +يوجد ملف `.env` في مجلد المشروع بمفتاح حقيقي، ولا يتتبعه git (`uv init` يمنحك `.gitignore` — تأكد أن `.env` فيه). + + +## الخطوة 1: عرّف الوكلاء الفرعيين: المُخطِّط والباحث والكاتب + +كل وكيل فرعي في `deepagents` مجرد قاموس بسيط: `name`، و`description` (يستخدمه الوكيل من المستوى الأعلى ليقرر متى يفوض إليه)، و`system_prompt` (تعليماته الضيّقة الخاصة)، وبشكل اختياري `tools` الخاص به. أنشئ `agent.py`: + +```python +import os + +from deepagents import create_deep_agent +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +load_dotenv() + +model = ChatOpenAI( + model="gpt-4o-mini", # confirm this still has a free tier before running + api_key=os.environ["GITHUB_TOKEN"], + base_url="https://models.github.ai/inference", +) + +planner_subagent = { + "name": "planner", + "description": "Breaks a research question down into 3-5 focused, independently-answerable sub-questions.", + "system_prompt": ( + "You are a research planner. Given a broad research question, break it " + "into 3 to 5 specific, independently-answerable sub-questions that together " + "cover the topic well. Output ONLY a numbered list of sub-questions -- no " + "preamble, no answers, just the questions themselves." + ), +} + +researcher_subagent = { + "name": "researcher", + "description": "Answers one specific sub-question at a time, concisely and factually.", + "system_prompt": ( + "You are a researcher. Answer the single sub-question you are given as " + "accurately and concisely as you can, using your own knowledge. You have " + "no web search tool in this version -- if you are not confident about a " + "fact, say so explicitly rather than guessing. Answer in 2-4 sentences." + ), +} + +writer_subagent = { + "name": "writer", + "description": "Synthesizes a set of sub-question answers into one coherent final report.", + "system_prompt": ( + "You are a writer. Given a research question and a set of sub-question/answer " + "pairs, synthesize them into one coherent, well-organized report of a few " + "paragraphs. Do not just concatenate the answers -- connect them into prose " + "that reads as a single piece of writing, and note plainly if the underlying " + "research flagged low confidence anywhere." + ), +} +``` + +:::tip[كن صادقًا بشأن ما تعنيه "البحث" هنا] +يجيب الوكيل الفرعي الباحث أعلاه من معرفة النموذج التدريبية الخاصة به — لا توجد أداة بحث ويب حقيقية موصولة. هذا تبسيط مقصود، لا اختصار خفي: يبقي هذا المشروع صغيرًا وصديقًا للمستوى المجاني، لكنه يعني أن الإجابات قد تكون قديمة أو خاطئة في أي شيء لم يُدرَّب النموذج عليه جيدًا، بلا طريقة للتحقق من مصدر حي. انظر "إلى أين من هنا" لمعرفة كيفية ربط أداة بحث حقيقية بمجرد ارتياحك لهذه النسخة. +::: + +**✅ قائمة التحقق** + + +يعرّف `agent.py` كلاً من `planner_subagent` و`researcher_subagent` و`writer_subagent`، كل واحد بـ `system_prompt` مميز. +يقول كل `system_prompt` بوضوح ما يفعله ذلك الدور وما *لا* يفعله — مثل أن تعليمات المُخطِّط تذكر عدم الإجابة عن الأسئلة الفرعية التي يولدها. + + +**🤔 سؤال (أسئلة) سقراطي(ة)** + +- تحظر تعليمات نظام المُخطِّط صراحةً إجابته عن أسئلته الفرعية الخاصة. ما رأيك بما سيحدث لبقية خط الأنابيب لو تجاهل تلك التعليمات وأجاب عنها على أي حال؟ +- لماذا قد يهم أن يكون `description` لكل وكيل فرعي مكتوبًا لكي يقرأه *الوكيل من المستوى الأعلى*، لا إنسان؟ ما الذي قد يكلّفك إياه وصف غامض (مثل "يعمل أشياء بحثية") هنا؟ + +## الخطوة 2: اربط الوكلاء الفرعيين معًا وشغّل الأمر + +لا يجري الوكيل من المستوى الأعلى أي بحث بنفسه — وظيفته كلها تفويض، بالترتيب: خطّط، ثم ابحث في كل سؤال فرعي، ثم اكتب. أضف هذا إلى أسفل `agent.py`: + +```python +agent = create_deep_agent( + model=model, + subagents=[planner_subagent, researcher_subagent, writer_subagent], + system_prompt=( + "You coordinate a research task using your sub-agents, strictly in this order: " + "1) delegate to the 'planner' sub-agent to get a numbered list of sub-questions. " + "2) delegate each sub-question, one at a time, to the 'researcher' sub-agent. " + "3) delegate to the 'writer' sub-agent, giving it the original question plus every " + "sub-question/answer pair, and have it produce the final report. " + "Return ONLY the writer's final report as your answer -- no intermediate steps." + ), +) + +if __name__ == "__main__": + question = "What makes a programming language good for beginners to learn first?" + result = agent.invoke({"messages": [{"role": "user", "content": question}]}) + print(result["messages"][-1].content) +``` + +شغّله: + +```bash +uv run python agent.py +``` + +`subagents=[...]` هو الآلية بأكملها: يرى الوكيل من المستوى الأعلى `name` و`description` لكل وكيل فرعي بنفس الطريقة التي يرى بها اسم الأداة وdocstring الخاصة بها، ويقرر متى يسلم إلى أي واحد، استنادًا إلى تعليمات `system_prompt` من المستوى الأعلى وحالة المحادثة حتى الآن. هذه هي الفكرة نفسها المُدرَّسة في قسم "إلى أين من هنا" في مشروع وكيل الذكاء الاصطناعي، مستخدمة فقط لكامل خط الأنابيب هنا بدلاً من متخصص إضافي واحد بجانب وكيل عام الغرض. + +### ما يجب أن تراه + +كتلة نص واحدة مطبوعة — تقرير الكاتب النهائي المركَّب، بضعة فقرات تغطي الأسئلة الفرعية التي ابتكرها المُخطِّط. إن طبعت قائمة `result["messages"]` كاملة بدلاً من ذلك (بنفس نمط مشروع وكيل الذكاء الاصطناعي)، سترى التتبع بالكامل: القائمة المرقّمة للمُخطِّط، وكل استدعاء للباحث وإجابته، ثم الجولة الأخيرة للكاتب — كلها كرسائل حقيقية تتناقل بين الوكيل من المستوى الأعلى وكل وكيل فرعي. + +إن رأيت بدلاً من ذلك تتبعًا لخطأ (traceback)، تحقق من نوعه — نفس الفئات الثلاث من مشروع وكيل الذكاء الاصطناعي: متغيّر بيئة مفقود/خاطئ (`KeyError`)، مفتاح خاطئ (401/403)، أو حد معدل (429، انظر المأزق أدناه). + +**✅ قائمة التحقق** + + +يطبع `uv run python agent.py` تقريرًا نهائيًا، لا traceback. +يُقرأ التقرير فعلًا كتوليف لعدة أسئلة فرعية، لا فقرة واحدة سطحية. +إظهار قائمة `result["messages"]` كاملة يُظهر أن الأدوار الثلاثة استُدعيت فعلًا — المُخطِّط، ثم الباحث (عدة مرات)، ثم الكاتب. + + +**🤔 سؤال (أسئلة) سقراطي(ة)** + +- جرّب سؤال بحث أضيق بكثير (شيئًا لديه سؤال فرعي واحد واضح أساسًا) وسؤالًا أوسع بكثير (شيئًا قد ينقسم إلى عشرة أسئلة فرعية). كيف يتغير سلوك المُخطِّط، وهل تتبع جودة التقرير النهائي مدى جودة تحلل السؤال فعلًا؟ +- يقول `system_prompt` من المستوى الأعلى "أعِد تقرير الكاتب النهائي فقط." ماذا تتوقع أن تراه في المخرجات لو أزلت تلك التعليمات؟ + +:::tip[تحقق من الوثائق الحالية قبل الاعتماد على هذا] +واجهة الوكلاء الفرعيين في `deepagents` أحدث وأقل اختبارًا من واجهة استدعاء الأدوات العادية، وقد غيّر كلاهما شكله مرة منذ مسودات سابقة لمشروع وكيل الذكاء الاصطناعي. قبل البناء على هذا أبعد من الدرس، تصفّح ملف README الخاص بـ `deepagents` نفسه لشكل `subagents=[...]` الحالي، بنفس النصيحة الواردة في مشروع وكيل الذكاء الاصطناعي لوسائط `create_deep_agent` الأخرى. +::: + +## ⚠️ مآزق شائعة + +- **تداخل الأدوار.** إن لم تكن تعليمات نظام وكيل فرعي ضيّقة بما يكفي، يبدأ بأداء عمل دور آخر — مُخطِّط يجيب أيضًا عن أسئلته الخاصة، أو كاتب يخترع أسئلة فرعية جديدة بدلاً من توليف المعطاة له. إن بدت المخرجات غريبة، فالحل دائمًا تقريبًا هو تضييق تعليمات الوكيل الفرعي المخالف، لا إضافة تعليمات أكثر إلى الوكيل من المستوى الأعلى. +- **حدود المعدل تتضاعف بسرعة.** يكلّف سؤال بحث واحد هنا استدعاءً واحدًا للمُخطِّط على الأقل، واستدعاءً للباحث *لكل سؤال فرعي* (عادةً 3-5)، واستدعاءً واحدًا للكاتب — ست إلى ثماني رحلات ذهاب وإياب كحد أدنى، مقابل الاستدعاءات ذات الرقم الواحد التي يجريها وكيل بسيط لاستدعاء الأدوات. توقّع الاصطدام بـ 429 أبكر مما في مشروع وكيل الذكاء الاصطناعي؛ نفس نمط إعادة المحاولة مع التأخير من دالة `ask()` في ذلك المشروع ينطبق هنا دون تغيير. +- **الهلوسة الواثقة عند الباحث.** بدون أداة بحث حقيقية، يمكن للوكيل الفرعي الباحث أن ينتج إجابة سلسة تبدو صحيحة لكنها خاطئة عن أي شيء غامض أو حديث. يطلب منه `system_prompt` الإشارة إلى انخفاض الثقة صراحةً، لكن ليس مضمونًا أن يتبع نموذج لغوي تلك التعليمات بإتقان في كل مرة — تحقق من الإجابات على أسئلة تعرف إجابتها مسبقًا. +- **الكاتب يفقد إجابات الأسئلة الفرعية بدلاً من الاستشهاد بها.** إن لم يخبر `system_prompt` من المستوى الأعلى الوكيل من المستوى الأعلى بوضوح بتمرير *كل* زوج سؤال فرعي/إجابة إلى الكاتب، فقد يلخّص بعضها فقط، أو يخترع روابط بين إجابات لم يرها فعلًا. اطبع التتبع الكامل (الخطوة 2) لتأكيد أن الكاتب استلم فعلًا كل ما أنتجه الباحث. + +## ما بنيته للتو + +خط أنابيب صغير حيث ينتج ثلاثة وكلاء ضيّقي التعليمات، لكل واحد تعليمات نظام محصورة في وظيفة واحدة بالضبط، نتيجةً لا يستطيع أيٌّ منهم إنتاجها جيدًا بمفرده — مُخطِّط جيد في التحليل، لا الإجابة؛ باحث جيد في الإجابة عن سؤال مركّز واحد، لا إدارة تقرير كامل؛ كاتب جيد في التوليف، لا البحث. هذه هي الفكرة نفسها وراء أنظمة متعددة الوكلاء أكبر في الإنتاج: لا تعليمات ضخمة واحدة تحاول فعل كل شيء، بل عدة تعليمات صغيرة، كل واحد سهل التفكير فيه وتصحيح أخطائه بمفرده، تُنسَّق بواسطة وكيل من المستوى الأعلى لا يقرر سوى *من* يليه. + +## إلى أين من هنا + +- **امنح الباحث أداة بحث حقيقية.** أكبر فجوة صدق في هذه النسخة هي أن "البحث" هنا يعني "معرفة النموذج التدريبية الخاصة به"، لا بحث ويب فعلي. عدة مزوّدين لديهم واجهات بحث من المستوى المجاني (Tavily وواجهة DuckDuckGo غير الرسمية من نقط البداية الشائعة) — اربط واحدة كأداة على `researcher_subagent["tools"]`، بنفس نمط `tools=[...]` من مشروع وكيل الذكاء الاصطناعي، وسيستطيع الباحث حينها الاستشهاد بمصادر حقيقية وحديثة بدلاً من الاسترجاع من بيانات التدريب. +- **أضف دورًا رابعًا**، مثل وكيل فرعي ناقد يراجع تقرير الكاتب مقابل الأسئلة الفرعية الأصلية ويعلّم الفجوات قبل المخرجات النهائية — نمط شائع بمجرد أن يمتلك خط الأنابيب أكثر من مرحلتين. +- **بثّ المخرجات الوسيطة** بدلاً من طباعة التقرير النهائي فقط، لكي تستطيع مشاهدة أسئلة المُخطِّط الفرعية وكل إجابة باحث وهي تصل في الوقت الفعلي بدلاً من انتظار انتهاء خط الأنابيب كله بصمت. +- أعد زيارة قسم مشروع وكيل الذكاء الاصطناعي عن التتبع الداخلي الكامل (`result["messages"]`) — التقنية نفسها لتحويل نتيجة خام مزعجة إلى حساب مقروء خطوة بخطوة تنطبق هنا، فقط مع رسائل ثلاثة أدوار متشابكة بدلاً من واحد. + +## شارك مشروعك مع الصف + +بنيت شيئًا تفتخر به؟ [`examples/student-projects/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/student-projects) معرض لمشاريع طلاب آخرين قدَّموها — وملف README الخاص به يحتوي شرحًا كاملًا وودودًا للمبتدئين لإضافة مشروعك عبر **طلب سحب (pull request)**، حتى لو لم تستخدم git من قبل قط: عمل fork للمستودع، وإنشاء فرع، وتثبيت ملفاتك، وفتح طلب السحب، خطوة بخطوة. لا يُفترَض أي خبرة سابقة بـ git. + +مرحبًا بك في كتابة Python خارج المتصفح. 🎓 + + diff --git a/i18n/es/code.json b/i18n/es/code.json index f5965a6..92ebe8b 100644 --- a/i18n/es/code.json +++ b/i18n/es/code.json @@ -901,5 +901,13 @@ "homepage.projects.meetingNotesSummarizer.summary": { "message": "Convierte una transcripción de reunión en bruto en decisiones estructuradas, elementos de acción y preguntas abiertas, usando un LLM de nivel gratuito y un prompt de extracción JSON cuidadosamente diseñado.", "description": "Homepage project card summary" + }, + "homepage.projects.multiAgentResearch.title": { + "message": "Construye un Asistente de Investigación Multi-Agente", + "description": "Homepage project card title" + }, + "homepage.projects.multiAgentResearch.summary": { + "message": "Construye un pequeño sistema multi-agente — un planificador, un investigador y un escritor — que descompone una pregunta de investigación y sintetiza un informe final, usando los sub-agentes de deepagents de LangChain y un LLM de nivel gratuito.", + "description": "Homepage project card summary" } } diff --git a/i18n/es/docusaurus-plugin-content-docs/current/projects/index.mdx b/i18n/es/docusaurus-plugin-content-docs/current/projects/index.mdx index 282cc59..8afe527 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/projects/index.mdx +++ b/i18n/es/docusaurus-plugin-content-docs/current/projects/index.mdx @@ -143,5 +143,11 @@ Son opcionales y no calificados. Explóralos en cualquier momento — la introdu summary: 'Convierte una transcripción de reunión en bruto en decisiones estructuradas, elementos de acción y preguntas abiertas, usando un LLM de nivel gratuito y un prompt de extracción JSON cuidadosamente diseñado.', }, + { + id: 'multi-agent-research', + title: 'Construye un Asistente de Investigación Multi-Agente', + summary: + 'Construye un pequeño sistema multi-agente — un planificador, un investigador y un escritor — que descompone una pregunta de investigación y sintetiza un informe final, usando los sub-agentes de deepagents de LangChain y un LLM de nivel gratuito.', + }, ])} /> diff --git a/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json b/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json new file mode 100644 index 0000000..9d80903 --- /dev/null +++ b/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Asistente de Investigación Multi-Agente", + "position": 7 +} diff --git a/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md b/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md new file mode 100644 index 0000000..25b88ae --- /dev/null +++ b/i18n/es/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md @@ -0,0 +1,278 @@ +--- +id: multi-agent-research +title: "Construye un Asistente de Investigación Multi-Agente" +sidebar_label: "Construye un Asistente de Investigación Multi-Agente" +slug: /projects/multi-agent-research +description: "Da el salto del playground en el navegador a Python real: construye un pequeño sistema multi-agente — un planificador, un investigador y un escritor — que descompone una pregunta de investigación y sintetiza un informe real, usando los sub-agentes de deepagents de LangChain y un LLM de nivel gratuito." +--- + +import ProjectProgressCheckbox from '@site/src/components/ProjectProgressCheckbox'; +import ProjectPublishedDate from '@site/src/components/ProjectPublishedDate'; +import ProjectGreeting from '@site/src/components/ProjectGreeting'; +import {StepChecklist, StepChecklistItem} from '@site/src/components/StepChecklist'; + +# 🌍 Construye un Asistente de Investigación Multi-Agente + + + + + +Un único agente con una pila de herramientas y un largo prompt de sistema funciona bien para tareas pequeñas, pero empieza a flaquear una vez que una tarea tiene *fases* genuinamente distintas que piden instrucciones diferentes — planificar en qué indagar, investigar de verdad cada pieza, y luego escribir todo. Este proyecto divide ese trabajo entre tres agentes pequeños y con instrucciones estrechas en lugar de uno grande: un **planificador** que descompone una pregunta de investigación en un puñado de sub-preguntas, un **investigador** que responde cada sub-pregunta por su cuenta, y un **escritor** que sintetiza todo en un informe final — coordinados con la función de sub-agentes `deepagents` de LangChain. + +Esto asume Python 101, y se construye directamente sobre el [proyecto Agente de IA](/docs/projects/ai-agent) — misma librería `deepagents`, misma configuración de API de nivel gratuito, misma idea de un modelo decidiendo qué llamar y cuándo, solo que aplicada a delegar sub-tareas completas en lugar de llamar herramientas individuales. Hacer ese proyecto primero no es estrictamente requerido, pero es una vía de entrada mucho más suave que empezar aquí en frío. + +Esto es opcional y no calificado. Consulta [Proyectos del mundo real](/docs/projects) para la lista completa y creciente. + +## 🎯 Lo que harás + +1. Instalar `uv`, una herramienta rápida y moderna para gestionar el propio Python y las dependencias de tu proyecto. +2. Obtener una clave de API de IA de nivel gratuito — la misma elección de seis proveedores que el proyecto Agente de IA. +3. Configurar un pequeño proyecto e instalar `deepagents`. +4. Definir tres sub-agentes — planificador, investigador, escritor — cada uno con su propio prompt de sistema estrecho. +5. Cablearlos juntos en un solo agente de nivel superior y ejecutarlo sobre una pregunta de investigación real, de principio a fin. + +## Dónde ejecutar esto + +**Localmente con `uv`** es el camino que siguen los pasos de esta lección, y el recomendado — es Python real ejecutándose en tu propia máquina, el mismo movimiento de "graduarte a Python real" que cada otro proyecto de esta sección. La sección de Configuración de abajo explica cómo instalarlo. + +**GitHub Codespaces** es una alternativa de configuración cero si prefieres no instalar nada localmente todavía: abre [todo el repositorio del curso en un Codespace gratuito](https://codespaces.new/abderrahim-lectures/python-data-analysis-course) (Node, Python y `uv` ya están instalados, según el `.devcontainer/devcontainer.json` del repositorio) y ejecuta exactamente los mismos comandos `uv` desde una terminal en la pestaña de tu navegador. + +**Google Colab, Kaggle Notebooks, o Binder** también funcionan, ya que nada aquí necesita GPU — cada paso es solo una llamada API a un LLM de nivel gratuito. Una versión real y ejecutable en notebook de este proyecto vive en el repositorio en [`examples/multi-agent-research/notebook.ipynb`](https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) — haz clic en una insignia de abajo para lanzarlo con cero configuración local, sin necesidad de archivo `.env` (pide tu clave API interactivamente con `getpass` en su lugar): + + +[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Open in Kaggle](https://kaggle.com/static/images/open-in-kaggle.svg)](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fmulti-agent-research%2Fnotebook.ipynb) + +Es una forma de menor fidelidad de experimentar el proyecto que un proyecto `uv` local real, pero perfectamente funcional para probar la idea rápidamente. + +## Configuración + +Todo lo siguiente deja tu entorno completamente listo antes de que empiece cualquier construcción: instalar `uv`, obtener una clave API gratuita, configurar el proyecto, y configurar tu archivo `.env`. + +### Instalar `uv` + +`uv` es una única herramienta que reemplaza la cadena habitual de "instala Python, luego instala pip, luego instala una herramienta de entorno virtual, luego instala paquetes" — puede instalar y gestionar versiones de Python por sí misma, junto con las dependencias de tu proyecto. + +**macOS / Linux** (terminal): + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +**Windows** (PowerShell): + +```powershell +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +``` + +Cierra y vuelve a abrir tu terminal, luego confirma que se instaló: + +```bash +uv --version +``` + +### Obtener una clave de API de IA gratuita + +**Elige el proveedor que prefieras** — ninguno de ellos requiere una tarjeta de crédito al momento de escribir esto, y este curso no favorece a uno sobre otro. El agente de ejemplo en el repositorio del curso ([`examples/multi-agent-research/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/multi-agent-research)) soporta los seis de fábrica, seleccionados con un solo ajuste, el mismo patrón que el proyecto Agente de IA. + +| Proveedor | Dónde obtener una clave | Por qué podrías elegirlo | +|---|---|---| +| **GitHub Models** *(valor por defecto sugerido)* | [github.com/settings/tokens](https://github.com/settings/tokens) — un token de acceso personal con el alcance `models: read` | Sin registro separado — ya tienes una cuenta de GitHub. Límites de nivel gratuito más generosos que los de Gemini. | +| Gemini | [Google AI Studio](https://aistudio.google.com/) | La opción más comúnmente referenciada. | +| Groq | [console.groq.com/keys](https://console.groq.com/keys) | Inferencia rápida, nivel gratuito generoso, sin tarjeta. | +| Mistral | [console.mistral.ai/api-keys](https://console.mistral.ai/api-keys) | Una de las cuotas gratuitas permanentes más generosas. | +| Cerebras | [cloud.cerebras.ai](https://cloud.cerebras.ai/) | Alto volumen diario de tokens, sin tarjeta. | +| OpenRouter | [openrouter.ai/keys](https://openrouter.ai/keys) | Una API, muchos modelos gratuitos — buena para comparar proveedores. | + +Sea cual sea el que elijas, el proceso es el mismo: + +1. Inicia sesión y genera una clave de API en el sitio de ese proveedor. +2. **Nunca pegues esta clave directamente en el código ni la subas a un repositorio.** En su lugar, configúrala como una variable de entorno: + +```bash +# macOS / Linux (add to ~/.bashrc or ~/.zshrc to persist it) +export GITHUB_TOKEN="your-key-here" # or GOOGLE_API_KEY, GROQ_API_KEY, etc. -- match your provider + +# Windows (PowerShell) +$env:GITHUB_TOKEN = "your-key-here" +``` + +:::tip[Un archivo .env suele ser más conveniente que export] +En lugar de hacer `export` de una clave en cada nueva sesión de terminal, puedes ponerla en un archivo `.env` en la carpeta de tu proyecto (mira el `.env.example` del ejemplo del repositorio) y cargarla automáticamente con el paquete `python-dotenv` — cubierto más abajo. +::: + +### Configurar el proyecto con `uv` + +```bash +uv init multi-agent-research +cd multi-agent-research +uv add deepagents langchain-openai python-dotenv +``` + +`deepagents` es el mismo framework de LangChain usado en el proyecto Agente de IA, y es lo que hace que todo este proyecto sea pequeño: además del uso de herramientas, tiene una función integrada de **sub-agentes** — una forma de entregar parte de una tarea a un agente con instrucciones separadas, en lugar de escribir a mano tu propio bucle que llama al modelo tres veces con tres prompts diferentes y cose los resultados tú mismo. `langchain-openai` habla con GitHub Models (su API es compatible con OpenAI); cámbialo por `langchain-google-genai`, `langchain-groq`, o `langchain-mistralai` si elegiste un proveedor diferente arriba — Cerebras y OpenRouter también son compatibles con OpenAI, así que `langchain-openai` los cubre también, solo que con un `base_url` diferente, exactamente como en el proyecto Agente de IA. + +Crea un archivo `.env` (nunca lo subas al repositorio) con la clave del proveedor que elegiste: + +```bash +# .env +GITHUB_TOKEN=your-key-here +``` + +**✅ Lista de verificación** + + +`uv add deepagents langchain-openai python-dotenv` completado sin errores. +Existe un archivo `.env` en la carpeta del proyecto con una clave real, y git no lo rastrea (`uv init` te da un `.gitignore` — confirma que `.env` está en él). + + +## Paso 1: Define los sub-agentes planificador, investigador y escritor + +Cada sub-agente en `deepagents` es solo un dict simple: un `name`, un `description` (usado por el agente de nivel superior para decidir cuándo delegarle), un `system_prompt` (sus propias instrucciones estrechas), y opcionalmente sus propios `tools`. Crea `agent.py`: + +```python +import os + +from deepagents import create_deep_agent +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +load_dotenv() + +model = ChatOpenAI( + model="gpt-4o-mini", # confirm this still has a free tier before running + api_key=os.environ["GITHUB_TOKEN"], + base_url="https://models.github.ai/inference", +) + +planner_subagent = { + "name": "planner", + "description": "Breaks a research question down into 3-5 focused, independently-answerable sub-questions.", + "system_prompt": ( + "You are a research planner. Given a broad research question, break it " + "into 3 to 5 specific, independently-answerable sub-questions that together " + "cover the topic well. Output ONLY a numbered list of sub-questions -- no " + "preamble, no answers, just the questions themselves." + ), +} + +researcher_subagent = { + "name": "researcher", + "description": "Answers one specific sub-question at a time, concisely and factually.", + "system_prompt": ( + "You are a researcher. Answer the single sub-question you are given as " + "accurately and concisely as you can, using your own knowledge. You have " + "no web search tool in this version -- if you are not confident about a " + "fact, say so explicitly rather than guessing. Answer in 2-4 sentences." + ), +} + +writer_subagent = { + "name": "writer", + "description": "Synthesizes a set of sub-question answers into one coherent final report.", + "system_prompt": ( + "You are a writer. Given a research question and a set of sub-question/answer " + "pairs, synthesize them into one coherent, well-organized report of a few " + "paragraphs. Do not just concatenate the answers -- connect them into prose " + "that reads as a single piece of writing, and note plainly if the underlying " + "research flagged low confidence anywhere." + ), +} +``` + +:::tip[Sé honesto sobre lo que "investigación" significa aquí] +El sub-agente investigador de arriba responde desde el propio conocimiento de entrenamiento del modelo — no hay ninguna herramienta real de búsqueda web conectada. Esa es una simplificación deliberada, no un atajo oculto: mantiene este proyecto pequeño y amigable con el nivel gratuito, pero significa que las respuestas pueden estar desactualizadas o ser incorrectas en cualquier cosa en la que el modelo no fue bien entrenado, sin forma de verificarlas contra una fuente en vivo. Consulta "A dónde ir desde aquí" para ver cómo conectar una herramienta de búsqueda real una vez que te sientas cómodo con esta versión. +::: + +**✅ Lista de verificación** + + +`agent.py` define `planner_subagent`, `researcher_subagent` y `writer_subagent`, cada uno con un `system_prompt` distinto. +Cada `system_prompt` dice claramente qué hace y qué *no* hace ese rol — p. ej. el prompt del planificador dice que no responda las sub-preguntas que genera. + + +**🤔 Pregunta(s) socrática(s)** + +- El prompt de sistema del planificador le prohíbe explícitamente responder sus propias sub-preguntas. ¿Qué crees que le pasaría al resto del pipeline si ignorara esa instrucción y las respondiera de todos modos? +- ¿Por qué podría importar que el `description` de cada sub-agente esté escrito para que lo lea el *agente de nivel superior*, no un humano? ¿Qué te costaría aquí un `description` vago ("hace cosas de investigación")? + +## Paso 2: Conecta los sub-agentes y ejecútalo + +El agente de nivel superior no hace ninguna investigación por sí mismo — todo su trabajo es delegación, en orden: planificar, luego investigar cada sub-pregunta, luego escribir. Añade esto al final de `agent.py`: + +```python +agent = create_deep_agent( + model=model, + subagents=[planner_subagent, researcher_subagent, writer_subagent], + system_prompt=( + "You coordinate a research task using your sub-agents, strictly in this order: " + "1) delegate to the 'planner' sub-agent to get a numbered list of sub-questions. " + "2) delegate each sub-question, one at a time, to the 'researcher' sub-agent. " + "3) delegate to the 'writer' sub-agent, giving it the original question plus every " + "sub-question/answer pair, and have it produce the final report. " + "Return ONLY the writer's final report as your answer -- no intermediate steps." + ), +) + +if __name__ == "__main__": + question = "What makes a programming language good for beginners to learn first?" + result = agent.invoke({"messages": [{"role": "user", "content": question}]}) + print(result["messages"][-1].content) +``` + +Ejecútalo: + +```bash +uv run python agent.py +``` + +`subagents=[...]` es todo el mecanismo: el agente de nivel superior ve el `name` y el `description` de cada sub-agente de la misma manera que vería el nombre y docstring de una herramienta, y decide cuándo entregar a cuál, basándose en las instrucciones del `system_prompt` de nivel superior y el estado de la conversación hasta ahora. Esta es la misma idea enseñada en la sección "A dónde ir desde aquí" del proyecto Agente de IA, solo que aquí se usa para todo el pipeline en lugar de para un especialista extra junto a un agente de propósito general. + +### Qué deberías ver + +Un único bloque de texto impreso — el informe final sintetizado del escritor, unos pocos párrafos cubriendo las sub-preguntas que se le ocurrieron al planificador. Si imprimes la lista completa de `result["messages"]` en su lugar (el mismo patrón que el proyecto Agente de IA), verás toda la traza: la lista numerada del planificador, cada llamada del investigador y su respuesta, y luego la pasada final del escritor — todas como mensajes reales pasados entre el agente de nivel superior y cada sub-agente. + +Si en cambio ves un traceback, comprueba de qué tipo — las mismas tres categorías que el proyecto Agente de IA: una variable de entorno faltante/incorrecta (`KeyError`), una clave mala (401/403), o un límite de tasa (429, mira el escollo de abajo). + +**✅ Lista de verificación** + + +`uv run python agent.py` imprime un informe final, no un traceback. +El informe realmente se lee como una síntesis de varias sub-preguntas, no un solo párrafo superficial. +Imprimir la lista completa de `result["messages"]` muestra que los tres roles fueron realmente invocados — planificador, investigador (varias veces), luego escritor. + + +**🤔 Pregunta(s) socrática(s)** + +- Prueba una pregunta de investigación mucho más estrecha (algo con básicamente una sub-pregunta obvia) y una mucho más amplia (algo que podría dividirse en diez sub-preguntas). ¿Cómo cambia el comportamiento del planificador, y sigue la calidad del informe final a qué tan bien se descompone la pregunta realmente? +- El `system_prompt` de nivel superior dice "devuelve SOLO el informe final del escritor." ¿Qué esperarías ver en la salida si eliminaras esa instrucción? + +:::tip[Consulta la documentación actual antes de confiar en esto] +La API de sub-agentes de `deepagents` es más nueva y menos probada en batalla que su API de llamada de herramientas simple, y ambas ya cambiaron de forma una vez desde borradores anteriores del proyecto Agente de IA. Antes de construir sobre esto más allá de la lección, hojea el propio README de `deepagents` para su forma actual de `subagents=[...]`, el mismo consejo dado en el proyecto Agente de IA para los otros argumentos de palabra clave de `create_deep_agent`. +::: + +## ⚠️ Errores comunes + +- **Fuga de roles.** Si el `system_prompt` de un sub-agente no es lo suficientemente estrecho, empieza a hacer el trabajo de otro rol — un planificador que también responde sus propias preguntas, o un escritor que inventa nuevas sub-preguntas en lugar de sintetizar las que se le dieron. Si la salida se ve rara, la solución es casi siempre apretar el prompt del sub-agente ofensor, no añadir más instrucciones al de nivel superior. +- **Los límites de tasa se multiplican rápido.** Una pregunta de investigación aquí cuesta al menos una llamada del planificador, una llamada del investigador *por sub-pregunta* (típicamente 3-5), y una llamada del escritor — seis a ocho idas y vueltas como mínimo, contra las llamadas de un solo dígito que hace un agente simple de llamada de herramientas. Espera chocar con un 429 antes de lo que lo hiciste en el proyecto Agente de IA; el mismo patrón de reintento con retraso de la función `ask()` de ese proyecto aplica aquí sin cambios. +- **El investigador alucinando con confianza.** Sin una herramienta de búsqueda real, el sub-agente investigador puede producir una respuesta fluida y de sonido correcto pero errónea sobre cualquier cosa oscura o reciente. Su prompt de sistema le pide señalar baja confianza explícitamente, pero no está garantizado que un modelo de lenguaje siga esa instrucción perfectamente cada vez — verifica las respuestas en preguntas donde ya sabes la respuesta. +- **El escritor perdiendo sub-preguntas en lugar de citarlas.** Si el `system_prompt` de nivel superior no le dice claramente al agente de nivel superior que le pase *cada* par sub-pregunta/respuesta al escritor, puede resumir solo algunas, o inventar conexiones entre respuestas que nunca vio realmente. Imprime la traza completa (Paso 2) para confirmar que el escritor recibió realmente todo lo que produjo el investigador. + +## Lo que acabas de construir + +Un pequeño pipeline donde tres agentes con instrucciones estrechas, cada uno con un prompt de sistema acotado exactamente a un trabajo, producen un resultado que ninguno de ellos podría producir bien solo — un planificador bueno descomponiendo, no respondiendo; un investigador bueno respondiendo una pregunta enfocada, no gestionando un informe completo; un escritor bueno sintetizando, no investigando. Esta es la misma idea detrás de los sistemas multi-agente más grandes en producción: no un prompt enorme intentando hacerlo todo, sino varios pequeños, cada uno fácil de razonar y depurar por su cuenta, coordinados por un agente de nivel superior que solo decide *quién* va después. + +## A dónde ir desde aquí + +- **Dale al investigador una herramienta de búsqueda real.** La mayor brecha de honestidad en esta versión es que "investigación" aquí significa "el propio conocimiento de entrenamiento del modelo," no una búsqueda web real. Varios proveedores tienen APIs de búsqueda de nivel gratuito (Tavily y la API no oficial de DuckDuckGo son puntos de partida comunes) — conéctala como una herramienta en `researcher_subagent["tools"]`, el mismo patrón `tools=[...]` del proyecto Agente de IA, y el investigador podrá citar fuentes reales y actuales en lugar de recordar datos de entrenamiento. +- **Añade un cuarto rol**, como un sub-agente crítico que revise el informe del escritor contra las sub-preguntas originales y marque las brechas antes de la salida final — un patrón común una vez que un pipeline tiene más de un par de etapas. +- **Transmite la salida intermedia** en lugar de solo imprimir el informe final, para que puedas ver llegar las sub-preguntas del planificador y cada respuesta del investigador en tiempo real en lugar de esperar a que todo el pipeline termine en silencio. +- Revisita la sección del proyecto Agente de IA sobre la traza interna completa (`result["messages"]`) — la misma técnica para convertir un resultado crudo ruidoso en una cuenta legible paso a paso aplica aquí, solo que con los mensajes de tres roles entrelazados en lugar de uno. + +## Comparte tu proyecto con la clase + +¿Construiste algo de lo que estás orgulloso? [`examples/student-projects/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/student-projects) es una galería de proyectos que otros estudiantes han enviado — y su README tiene un recorrido completo y amigable para principiantes sobre cómo agregar el tuyo vía un **pull request**, incluso si nunca has usado git antes: hacer fork del repositorio, crear una rama, subir tus archivos, y abrir el PR, un paso a la vez. No se asume ninguna experiencia previa con git. + +Bienvenido a escribir Python fuera del navegador. 🎓 + + diff --git a/i18n/fr/code.json b/i18n/fr/code.json index 6e46032..256f4dc 100644 --- a/i18n/fr/code.json +++ b/i18n/fr/code.json @@ -901,5 +901,13 @@ "homepage.projects.meetingNotesSummarizer.summary": { "message": "Transforme une transcription de réunion brute en décisions structurées, éléments d'action et questions ouvertes, en utilisant un LLM de niveau gratuit et un prompt d'extraction JSON soigneusement conçu.", "description": "Homepage project card summary" + }, + "homepage.projects.multiAgentResearch.title": { + "message": "Construire un Assistant de Recherche Multi-Agents", + "description": "Homepage project card title" + }, + "homepage.projects.multiAgentResearch.summary": { + "message": "Construis un petit système multi-agents — un planificateur, un chercheur et un rédacteur — qui décompose une question de recherche et synthétise un rapport final, en utilisant les sous-agents deepagents de LangChain et un LLM de palier gratuit.", + "description": "Homepage project card summary" } } diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/projects/index.mdx b/i18n/fr/docusaurus-plugin-content-docs/current/projects/index.mdx index 76e9d39..dbd27f7 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/projects/index.mdx +++ b/i18n/fr/docusaurus-plugin-content-docs/current/projects/index.mdx @@ -143,5 +143,11 @@ Ils sont optionnels et non notés. Parcourez-les à tout moment — l'introducti summary: "Transforme une transcription de réunion brute en décisions structurées, éléments d'action et questions ouvertes, en utilisant un LLM de niveau gratuit et un prompt d'extraction JSON soigneusement conçu.", }, + { + id: 'multi-agent-research', + title: 'Construire un Assistant de Recherche Multi-Agents', + summary: + "Construis un petit système multi-agents — un planificateur, un chercheur et un rédacteur — qui décompose une question de recherche et synthétise un rapport final, en utilisant les sous-agents deepagents de LangChain et un LLM de palier gratuit.", + }, ])} /> diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json b/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json new file mode 100644 index 0000000..1a2c14d --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Assistant de Recherche Multi-Agents", + "position": 7 +} diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md b/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md new file mode 100644 index 0000000..f1ccd88 --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/projects/multi-agent-research/index.md @@ -0,0 +1,278 @@ +--- +id: multi-agent-research +title: "Construire un Assistant de Recherche Multi-Agents" +sidebar_label: "Construire un Assistant de Recherche Multi-Agents" +slug: /projects/multi-agent-research +description: "Passe du bac à sable dans le navigateur à du vrai Python : construis un petit système multi-agents — un planificateur, un chercheur et un rédacteur — qui décompose une question de recherche et synthétise un vrai rapport, en utilisant les sous-agents de deepagents de LangChain et un LLM de palier gratuit." +--- + +import ProjectProgressCheckbox from '@site/src/components/ProjectProgressCheckbox'; +import ProjectPublishedDate from '@site/src/components/ProjectPublishedDate'; +import ProjectGreeting from '@site/src/components/ProjectGreeting'; +import {StepChecklist, StepChecklistItem} from '@site/src/components/StepChecklist'; + +# 🌍 Construire un Assistant de Recherche Multi-Agents + + + + + +Un seul agent avec une pile d'outils et un long prompt système fonctionne bien pour les petites tâches, mais il commence à craquer dès qu'une tâche a des *phases* vraiment différentes qui demandent des instructions différentes — planifier quoi chercher, chercher réellement chaque morceau, puis tout rédiger. Ce projet répartit ce travail entre trois petits agents aux instructions étroites au lieu d'un seul gros : un **planificateur** qui décompose une question de recherche en une poignée de sous-questions, un **chercheur** qui répond à chaque sous-question par lui-même, et un **rédacteur** qui synthétise tout en un rapport final — coordonnés avec la fonctionnalité de sous-agents `deepagents` de LangChain. + +Cela suppose du Python 101, et cela s'appuie directement sur le [projet Agent IA](/docs/projects/ai-agent) — même bibliothèque `deepagents`, même configuration API de palier gratuit, même idée d'un modèle décidant quoi appeler et quand, juste appliquée à la délégation de sous-tâches entières plutôt qu'à l'appel d'outils individuels. Faire ce projet d'abord n'est pas strictement requis, mais c'est une rampe d'accès bien plus douce que de commencer ici à froid. + +C'est optionnel et non noté. Voir [Projets du monde réel](/docs/projects) pour la liste complète et croissante. + +## 🎯 Ce que tu vas faire + +1. Installer `uv`, un outil rapide et moderne pour gérer Python lui-même et les dépendances de ton projet. +2. Obtenir une clé API IA de palier gratuit — le même choix de six fournisseurs que le projet Agent IA. +3. Configurer un petit projet et installer `deepagents`. +4. Définir trois sous-agents — planificateur, chercheur, rédacteur — chacun avec son propre prompt système étroit. +5. Les relier ensemble en un seul agent de niveau supérieur et l'exécuter sur une vraie question de recherche, de bout en bout. + +## Où exécuter ceci + +**En local avec `uv`** est le chemin que suivent les étapes de cette leçon, et celui recommandé — c'est du vrai Python qui tourne sur ta propre machine, le même mouvement « passage au vrai Python » que chaque autre projet de cette section. La section Configuration ci-dessous explique comment l'installer. + +**GitHub Codespaces** est une alternative sans configuration si tu préfères ne rien installer localement pour l'instant : ouvre [tout le dépôt du cours dans un Codespace gratuit](https://codespaces.new/abderrahim-lectures/python-data-analysis-course) (Node, Python et `uv` sont déjà installés, selon le `.devcontainer/devcontainer.json` du dépôt) et exécute exactement les mêmes commandes `uv` depuis un terminal dans l'onglet de ton navigateur. + +**Google Colab, Kaggle Notebooks, ou Binder** fonctionnent aussi, puisque rien ici n'a besoin de GPU — chaque étape n'est qu'un appel API à un LLM de palier gratuit. Une vraie version notebook exécutable de ce projet se trouve dans le dépôt à [`examples/multi-agent-research/notebook.ipynb`](https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) — clique sur un badge ci-dessous pour la lancer avec zéro configuration locale, sans besoin de fichier `.env` (il demande ta clé API de façon interactive avec `getpass` à la place) : + + +[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Open in Kaggle](https://kaggle.com/static/images/open-in-kaggle.svg)](https://kaggle.com/kernels/welcome?src=https://github.com/abderrahim-lectures/python-data-analysis-course/blob/main/examples/multi-agent-research/notebook.ipynb) +[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/abderrahim-lectures/python-data-analysis-course/main?filepath=examples%2Fmulti-agent-research%2Fnotebook.ipynb) + +C'est une façon moins fidèle de vivre le projet qu'un vrai projet `uv` local, mais parfaitement utilisable pour tester rapidement l'idée. + +## Configuration + +Tout ce qui suit prépare entièrement ton environnement avant que la construction ne commence : installer `uv`, obtenir une clé API gratuite, configurer le projet, et configurer ton fichier `.env`. + +### Installer `uv` + +`uv` est un outil unique qui remplace la chaîne habituelle « installer Python, puis installer pip, puis installer un outil d'environnement virtuel, puis installer les paquets » — il peut installer et gérer lui-même les versions de Python, en plus des dépendances de ton projet. + +**macOS / Linux** (terminal) : + +```bash +curl -LsSf https://astral.sh/uv/install.sh | sh +``` + +**Windows** (PowerShell) : + +```powershell +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +``` + +Ferme et rouvre ton terminal, puis confirme l'installation : + +```bash +uv --version +``` + +### Obtenir une clé API IA gratuite + +**Choisis le fournisseur de ton choix** — aucun d'eux ne nécessite de carte de crédit au moment de l'écriture, et ce cours n'en favorise aucun par rapport aux autres. L'agent d'exemple du dépôt du cours ([`examples/multi-agent-research/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/multi-agent-research)) prend en charge les six directement, sélectionnés avec un seul paramètre, le même modèle que le projet Agent IA. + +| Fournisseur | Où obtenir une clé | Pourquoi tu pourrais le choisir | +|---|---|---| +| **GitHub Models** *(défaut suggéré)* | [github.com/settings/tokens](https://github.com/settings/tokens) — un jeton d'accès personnel avec le scope `models: read` | Pas d'inscription séparée — tu as déjà un compte GitHub. Limites de palier gratuit plus généreuses que celles de Gemini. | +| Gemini | [Google AI Studio](https://aistudio.google.com/) | L'option la plus couramment référencée. | +| Groq | [console.groq.com/keys](https://console.groq.com/keys) | Inférence rapide, palier gratuit généreux, pas de carte. | +| Mistral | [console.mistral.ai/api-keys](https://console.mistral.ai/api-keys) | L'un des quotas gratuits permanents les plus généreux. | +| Cerebras | [cloud.cerebras.ai](https://cloud.cerebras.ai/) | Volume élevé de tokens quotidiens, pas de carte. | +| OpenRouter | [openrouter.ai/keys](https://openrouter.ai/keys) | Une seule API, de nombreux modèles gratuits — bon pour comparer les fournisseurs. | + +Quel que soit celui que tu choisis, le processus est le même : + +1. Connecte-toi et génère une clé API sur le site de ce fournisseur. +2. **Ne colle jamais cette clé directement dans le code ni ne la valide dans un dépôt.** Définis-la plutôt comme une variable d'environnement : + +```bash +# macOS / Linux (add to ~/.bashrc or ~/.zshrc to persist it) +export GITHUB_TOKEN="your-key-here" # or GOOGLE_API_KEY, GROQ_API_KEY, etc. -- match your provider + +# Windows (PowerShell) +$env:GITHUB_TOKEN = "your-key-here" +``` + +:::tip[Un fichier .env est souvent plus pratique qu'export] +Plutôt que de faire `export` d'une clé à chaque nouvelle session de terminal, tu peux la mettre dans un fichier `.env` dans le dossier de ton projet (voir le `.env.example` de l'exemple du dépôt) et la charger automatiquement avec le paquet `python-dotenv` — couvert plus bas. +::: + +### Configurer le projet avec `uv` + +```bash +uv init multi-agent-research +cd multi-agent-research +uv add deepagents langchain-openai python-dotenv +``` + +`deepagents` est le même framework LangChain que celui utilisé dans le projet Agent IA, et c'est ce qui rend tout ce projet petit : en plus de l'utilisation d'outils, il a une fonctionnalité intégrée de **sous-agents** — une façon de transmettre une partie d'une tâche à un agent instruit séparément, plutôt que de coder à la main ta propre boucle qui appelle le modèle trois fois avec trois prompts différents et recoud les résultats toi-même. `langchain-openai` parle à GitHub Models (son API est compatible OpenAI) ; remplace-le par `langchain-google-genai`, `langchain-groq`, ou `langchain-mistralai` si tu as choisi un fournisseur différent ci-dessus — Cerebras et OpenRouter sont aussi compatibles OpenAI, donc `langchain-openai` les couvre aussi, juste avec une `base_url` différente, exactement comme dans le projet Agent IA. + +Crée un fichier `.env` (ne le valide jamais) avec la clé du fournisseur que tu as choisi : + +```bash +# .env +GITHUB_TOKEN=your-key-here +``` + +**✅ Liste de vérification** + + +`uv add deepagents langchain-openai python-dotenv` terminé sans aucune erreur. +Un fichier `.env` existe dans le dossier du projet avec une vraie clé, et il n'est pas suivi par git (`uv init` te donne un `.gitignore` — confirme que `.env` y figure). + + +## Étape 1 : Définis les sous-agents planificateur, chercheur et rédacteur + +Chaque sous-agent dans `deepagents` n'est qu'un simple dict : un `name`, un `description` (utilisé par l'agent de niveau supérieur pour décider quand lui déléguer), un `system_prompt` (ses propres instructions étroites), et éventuellement ses propres `tools`. Crée `agent.py` : + +```python +import os + +from deepagents import create_deep_agent +from dotenv import load_dotenv +from langchain_openai import ChatOpenAI + +load_dotenv() + +model = ChatOpenAI( + model="gpt-4o-mini", # confirm this still has a free tier before running + api_key=os.environ["GITHUB_TOKEN"], + base_url="https://models.github.ai/inference", +) + +planner_subagent = { + "name": "planner", + "description": "Breaks a research question down into 3-5 focused, independently-answerable sub-questions.", + "system_prompt": ( + "You are a research planner. Given a broad research question, break it " + "into 3 to 5 specific, independently-answerable sub-questions that together " + "cover the topic well. Output ONLY a numbered list of sub-questions -- no " + "preamble, no answers, just the questions themselves." + ), +} + +researcher_subagent = { + "name": "researcher", + "description": "Answers one specific sub-question at a time, concisely and factually.", + "system_prompt": ( + "You are a researcher. Answer the single sub-question you are given as " + "accurately and concisely as you can, using your own knowledge. You have " + "no web search tool in this version -- if you are not confident about a " + "fact, say so explicitly rather than guessing. Answer in 2-4 sentences." + ), +} + +writer_subagent = { + "name": "writer", + "description": "Synthesizes a set of sub-question answers into one coherent final report.", + "system_prompt": ( + "You are a writer. Given a research question and a set of sub-question/answer " + "pairs, synthesize them into one coherent, well-organized report of a few " + "paragraphs. Do not just concatenate the answers -- connect them into prose " + "that reads as a single piece of writing, and note plainly if the underlying " + "research flagged low confidence anywhere." + ), +} +``` + +:::tip[Sois honnête sur ce que « recherche » signifie ici] +Le sous-agent chercheur ci-dessus répond depuis les propres connaissances d'entraînement du modèle — aucun véritable outil de recherche web n'est branché. C'est une simplification délibérée, pas un raccourci caché : cela garde ce projet petit et adapté au palier gratuit, mais cela signifie que les réponses peuvent être obsolètes ou fausses sur tout ce sur quoi le modèle n'a pas été bien entraîné, sans moyen de vérifier contre une source en direct. Voir « Où aller à partir d'ici » pour savoir comment brancher un vrai outil de recherche une fois que tu es à l'aise avec cette version. +::: + +**✅ Liste de vérification** + + +`agent.py` définit `planner_subagent`, `researcher_subagent`, et `writer_subagent`, chacun avec un `system_prompt` distinct. +Chaque `system_prompt` dit clairement ce que ce rôle fait et *ne fait pas* — ex. le prompt du planificateur dit de ne pas répondre aux sous-questions qu'il génère. + + +**🤔 Question(s) socratique(s)** + +- Le prompt système du planificateur lui interdit explicitement de répondre à ses propres sous-questions. Que penses-tu qu'il arriverait au reste du pipeline s'il ignorait cette instruction et y répondait quand même ? +- Pourquoi pourrait-il compter que le `description` de chaque sous-agent soit écrit pour que l'*agent de niveau supérieur* le lise, pas un humain ? Que te coûterait ici un `description` vague (« fait des trucs de recherche ») ? + +## Étape 2 : Relie les sous-agents entre eux et exécute-le + +L'agent de niveau supérieur ne fait aucune recherche lui-même — tout son travail est de la délégation, dans l'ordre : planifier, puis rechercher chaque sous-question, puis rédiger. Ajoute ceci en bas de `agent.py` : + +```python +agent = create_deep_agent( + model=model, + subagents=[planner_subagent, researcher_subagent, writer_subagent], + system_prompt=( + "You coordinate a research task using your sub-agents, strictly in this order: " + "1) delegate to the 'planner' sub-agent to get a numbered list of sub-questions. " + "2) delegate each sub-question, one at a time, to the 'researcher' sub-agent. " + "3) delegate to the 'writer' sub-agent, giving it the original question plus every " + "sub-question/answer pair, and have it produce the final report. " + "Return ONLY the writer's final report as your answer -- no intermediate steps." + ), +) + +if __name__ == "__main__": + question = "What makes a programming language good for beginners to learn first?" + result = agent.invoke({"messages": [{"role": "user", "content": question}]}) + print(result["messages"][-1].content) +``` + +Exécute-le : + +```bash +uv run python agent.py +``` + +`subagents=[...]` est tout le mécanisme : l'agent de niveau supérieur voit le `name` et le `description` de chaque sous-agent de la même façon qu'il verrait le nom et la docstring d'un outil, et décide quand transmettre à lequel, en se basant sur les instructions du `system_prompt` de niveau supérieur et l'état de la conversation jusqu'à présent. C'est exactement l'idée enseignée dans la section « Où aller à partir d'ici » du projet Agent IA, juste utilisée ici pour tout le pipeline plutôt que pour un spécialiste supplémentaire aux côtés d'un agent à usage général. + +### Ce que tu devrais voir + +Un seul bloc de texte affiché — le rapport final synthétisé du rédacteur, quelques paragraphes couvrant les sous-questions trouvées par le planificateur. Si tu affiches plutôt la liste complète de `result["messages"]` (le même modèle que le projet Agent IA), tu verras toute la trace : la liste numérotée du planificateur, chaque appel du chercheur et sa réponse, puis le passage final du rédacteur — tous comme de vrais messages échangés entre l'agent de niveau supérieur et chaque sous-agent. + +Si à la place tu vois une trace d'erreur, vérifie laquelle — les mêmes trois catégories que le projet Agent IA : une variable d'environnement manquante/erronée (`KeyError`), une mauvaise clé (401/403), ou une limite de débit (429, voir le piège ci-dessous). + +**✅ Liste de vérification** + + +`uv run python agent.py` affiche un rapport final, pas une trace d'erreur. +Le rapport se lit vraiment comme une synthèse de plusieurs sous-questions, pas un seul paragraphe superficiel. +Afficher la liste complète de `result["messages"]` montre que les trois rôles ont été réellement invoqués — planificateur, chercheur (plusieurs fois), puis rédacteur. + + +**🤔 Question(s) socratique(s)** + +- Essaie une question de recherche bien plus étroite (quelque chose avec fondamentalement une seule sous-question évidente) et une bien plus large (quelque chose qui pourrait se diviser en dix sous-questions). Comment le comportement du planificateur change-t-il, et la qualité du rapport final suit-elle la qualité de la décomposition réelle de la question ? +- Le `system_prompt` de niveau supérieur dit « retourne UNIQUEMENT le rapport final du rédacteur. » Que t'attendrais-tu à voir dans la sortie si tu retirais cette instruction ? + +:::tip[Vérifie la documentation actuelle avant de t'appuyer dessus] +L'API de sous-agents de `deepagents` est plus récente et moins éprouvée que son API d'appel d'outils simple, et les deux ont déjà changé de forme une fois depuis les versions précédentes du projet Agent IA. Avant de construire dessus au-delà de cette leçon, parcours le propre README de `deepagents` pour sa forme actuelle de `subagents=[...]`, le même conseil donné dans le projet Agent IA pour les autres arguments nommés de `create_deep_agent`. +::: + +## ⚠️ Pièges courants + +- **Fuite de rôles.** Si le `system_prompt` d'un sous-agent n'est pas assez étroit, il commence à faire le travail d'un autre rôle — un planificateur qui répond aussi à ses propres questions, ou un rédacteur qui invente de nouvelles sous-questions au lieu de synthétiser celles qu'on lui a données. Si la sortie semble étrange, le correctif est presque toujours de resserrer le prompt du sous-agent fautif, pas d'ajouter plus d'instructions à celui de niveau supérieur. +- **Les limites de débit se multiplient vite.** Une question de recherche ici coûte au moins un appel du planificateur, un appel du chercheur *par sous-question* (typiquement 3-5), et un appel du rédacteur — six à huit allers-retours minimum, contre les appels à un chiffre que fait un simple agent d'appel d'outils. Attends-toi à heurter un 429 plus tôt que dans le projet Agent IA ; le même modèle de réessai avec délai de la fonction `ask()` de ce projet s'applique ici sans changement. +- **Le chercheur hallucine avec assurance.** Sans véritable outil de recherche, le sous-agent chercheur peut produire une réponse fluide qui semble juste mais qui est fausse sur tout ce qui est obscur ou récent. Son prompt système lui demande de signaler explicitement une faible confiance, mais il n'est pas garanti qu'un modèle de langage suive cette instruction parfaitement à chaque fois — vérifie les réponses sur des questions dont tu connais déjà la réponse. +- **Le rédacteur perd les réponses des sous-questions au lieu de les citer.** Si le `system_prompt` de niveau supérieur ne dit pas clairement à l'agent de niveau supérieur de passer *chaque* paire sous-question/réponse au rédacteur, il peut n'en résumer que certaines, ou inventer des connexions entre des réponses qu'il n'a jamais réellement vues. Affiche la trace complète (Étape 2) pour confirmer que le rédacteur a bien reçu tout ce que le chercheur a produit. + +## Ce que tu viens de construire + +Un petit pipeline où trois agents aux instructions étroites, chacun avec un prompt système limité à exactement un travail, produisent un résultat qu'aucun d'eux ne pourrait produire correctement seul — un planificateur doué pour décomposer, pas pour répondre ; un chercheur doué pour répondre à une question ciblée, pas pour gérer un rapport entier ; un rédacteur doué pour synthétiser, pas pour rechercher. C'est la même idée derrière les plus grands systèmes multi-agents en production : pas un énorme prompt essayant de tout faire, mais plusieurs petits, chacun facile à raisonner et à déboguer séparément, coordonnés par un agent de niveau supérieur qui ne décide que *qui* continue. + +## Où aller à partir d'ici + +- **Donne au chercheur un véritable outil de recherche.** La plus grande faille d'honnêteté de cette version est que « recherche » ici signifie « les propres connaissances d'entraînement du modèle », pas une vraie recherche web. Plusieurs fournisseurs ont des API de recherche de palier gratuit (Tavily et l'API non officielle de DuckDuckGo sont des points de départ courants) — branche-en une comme outil sur `researcher_subagent["tools"]`, le même modèle `tools=[...]` du projet Agent IA, et le chercheur pourra citer de vraies sources actuelles au lieu de se rappeler des données d'entraînement. +- **Ajoute un quatrième rôle**, comme un sous-agent critique qui examine le rapport du rédacteur par rapport aux sous-questions originales et signale les lacunes avant la sortie finale — un modèle courant une fois qu'un pipeline a plus de quelques étapes. +- **Diffuse la sortie intermédiaire** au lieu de n'afficher que le rapport final, pour que tu puisses voir arriver les sous-questions du planificateur et chaque réponse du chercheur en temps réel plutôt que d'attendre que tout le pipeline se termine en silence. +- Revisite la section du projet Agent IA sur la trace interne complète (`result["messages"]`) — la même technique pour transformer un résultat brut bruyant en un compte rendu lisible étape par étape s'applique ici, juste avec les messages de trois rôles entrelacés au lieu d'un. + +## Partage ton projet avec la classe + +Tu as construit quelque chose dont tu es fier ? [`examples/student-projects/`](https://github.com/abderrahim-lectures/python-data-analysis-course/tree/main/examples/student-projects) est une galerie de projets que d'autres étudiants ont soumis — et son README a un guide complet et accessible aux débutants pour ajouter le tien via une **pull request**, même si tu n'as jamais utilisé git auparavant : forker le dépôt, créer une branche, valider tes fichiers, et ouvrir la PR, une étape à la fois. Aucune expérience préalable de git n'est présumée. + +Bienvenue dans l'écriture de Python en dehors du navigateur. 🎓 + +