{ "cells": [ { "cell_type": "markdown", "id": "78d4d2e0", "metadata": {}, "source": [ "# Session 6 – Multi-Step Pipeline (Plan → Execute → Refine)\n", "\n", "Uses routing functions to select models per step, then refines final answer." ] }, { "cell_type": "markdown", "id": "b959acb1", "metadata": {}, "source": [ "### Explanation: Dependency Installation\n", "Installs `foundry-local-sdk` and `openai` needed for per-step chat calls. Safe to re-run." ] }, { "cell_type": "markdown", "id": "58285936", "metadata": {}, "source": [ "# Scenario\n", "Multi-step model pipeline that: (1) Plans a task into discrete steps, (2) Executes each step with intent-based model selection, (3) Refines a final synthesized answer. Demonstrates chaining heterogeneous SLM capabilities for efficiency while preserving quality." ] }, { "cell_type": "code", "execution_count": 13, "id": "bc0b10c8", "metadata": {}, "outputs": [], "source": [ "!pip install -q foundry-local-sdk openai" ] }, { "cell_type": "markdown", "id": "220de1ac", "metadata": {}, "source": [ "### Explanation: Core Imports\n", "Imports regex for intent detection, Foundry Local manager for per-alias attachment, and OpenAI client for chat completions." ] }, { "cell_type": "code", "execution_count": 14, "id": "73d63e3a", "metadata": {}, "outputs": [], "source": [ "import re\n", "from foundry_local import FoundryLocalManager\n", "from openai import OpenAI" ] }, { "cell_type": "markdown", "id": "be17da8d", "metadata": {}, "source": [ "### Explanation: Capability Catalog & Rules\n", "Defines a capability-aware catalog and regex rules used to map step text to intent categories (code, summarize, classification, general). Lower priority values win ties when multiple models support an intent." ] }, { "cell_type": "code", "execution_count": 15, "id": "2ee8e163", "metadata": {}, "outputs": [], "source": [ "CATALOG = {\n", " 'phi-4-mini': {'capabilities':['general','summarize'],'priority':2},\n", " 'qwen2.5-coder-7b': {'capabilities':['code','refactor'],'priority':1},\n", " 'qwen2.5-0.5b': {'capabilities':['classification','fast'],'priority':3},\n", "}\n", "RULES = [\n", " (re.compile('code|refactor|function', re.I), 'code'),\n", " (re.compile('summari|abstract|tl;dr', re.I), 'summarize'),\n", " (re.compile('classif|category|label', re.I), 'classification'),\n", "]" ] }, { "cell_type": "markdown", "id": "a05d29a6", "metadata": {}, "source": [ "### Explanation: Intent, Model Selection & Chat Helper\n", "Provides:\n", "- `detect_intent` for regex-based classification.\n", "- `pick_model` to choose best alias by capability + priority.\n", "- `chat` convenience wrapper that instantiates a client per alias and returns a single-turn response." ] }, { "cell_type": "code", "execution_count": 16, "id": "c9fe43d2", "metadata": {}, "outputs": [], "source": [ "def detect_intent(text: str):\n", " \"\"\"Return an intent label based on simple regex rules; falls back to 'general'.\"\"\"\n", " for pat, intent in RULES:\n", " if pat.search(text):\n", " return intent\n", " return 'general'\n", "\n", "def pick_model(intent: str) -> str:\n", " \"\"\"Pick the best model for an intent using capability match first, then priority.\"\"\"\n", " ranked = []\n", " for name, meta in CATALOG.items():\n", " ranked.append((name, intent in meta['capabilities'], meta['priority']))\n", " # Sort: capability match (True first), then lower priority value\n", " ranked.sort(key=lambda t: (not t[1], t[2]))\n", " return ranked[0][0]\n", "\n", "def chat(alias: str, content: str, temp: float = 0.4) -> str:\n", " \"\"\"Simple helper to send a single user message to a Foundry Local model via OpenAI client.\"\"\"\n", " m = FoundryLocalManager(alias)\n", " client = OpenAI(base_url=m.endpoint, api_key=m.api_key or 'not-needed')\n", " mid = m.get_model_info(alias).id\n", " resp = client.chat.completions.create(\n", " model=mid,\n", " messages=[{'role': 'user', 'content': content}],\n", " max_tokens=180,\n", " temperature=temp,\n", " )\n", " return resp.choices[0].message.content" ] }, { "cell_type": "markdown", "id": "3c4ba53d", "metadata": {}, "source": [ "### Explanation: Multi-Step Pipeline Function\n", "Implements the pipeline: plan → parse steps → execute each with intent-based routing → refine combined outputs. Returns structured dict for inspection or evaluation." ] }, { "cell_type": "code", "execution_count": 17, "id": "22bf8e4b", "metadata": {}, "outputs": [], "source": [ "def pipeline(task: str):\n", " \"\"\"Multi-step pipeline: plan → execute steps → refine final answer.\n", "\n", " Returns dict with keys: plan (raw plan text), steps (list of tuples), final (refined answer).\n", " Each step tuple: (index, step_text, step_result, model_alias_used)\n", " \"\"\"\n", " # 1. Plan\n", " plan_alias = pick_model('general')\n", " plan_prompt = (\n", " \"Break the task into 3 concise, actionable steps (no extra commentary).\\n\"\n", " f\"Task: {task}\"\n", " )\n", " plan = chat(plan_alias, plan_prompt)\n", "\n", " # 2. Parse steps (robust to numbering or bullet styles)\n", " raw_lines = [l.strip() for l in plan.splitlines() if l.strip()]\n", " steps = []\n", " for line in raw_lines:\n", " cleaned = re.sub(r'^\\d+[).:-]?\\s*', '', line) # remove leading numbering\n", " cleaned = re.sub(r'^[-*]\\s*', '', cleaned) # remove bullet markers\n", " if cleaned:\n", " steps.append(cleaned)\n", " if len(steps) == 3:\n", " break\n", " if not steps:\n", " steps = [task]\n", "\n", " # 3. Execute steps\n", " outputs = []\n", " for idx, step in enumerate(steps, 1):\n", " intent = detect_intent(step)\n", " exec_alias = pick_model(intent)\n", " exec_prompt = (\n", " f\"Execute step {idx} for the overall task.\\n\"\n", " f\"Overall task: {task}\\n\"\n", " f\"Step {idx}: {step}\\n\"\n", " \"Return a concise result focusing only on the step objective.\"\n", " )\n", " result = chat(exec_alias, exec_prompt)\n", " outputs.append((idx, step, result, exec_alias))\n", "\n", " # 4. Refine final answer\n", " refine_alias = pick_model('summarize')\n", " combined = \"\\n\\n\".join(\n", " f\"Step {idx} ({alias}) Output:\\n{res}\" for idx, _step, res, alias in outputs\n", " )\n", " refine_prompt = (\n", " \"You are a senior assistant. Synthesize these step outputs into a cohesive final answer.\\n\"\n", " \"Ensure clarity, avoid repetition, and highlight improvements or key insights if relevant.\\n\\n\"\n", " f\"Task: {task}\\n\\n\"\n", " f\"Step Outputs:\\n{combined}\"\n", " )\n", " final_ans = chat(refine_alias, refine_prompt)\n", "\n", " return {\"plan\": plan, \"steps\": outputs, \"final\": final_ans}" ] }, { "cell_type": "markdown", "id": "282472b0", "metadata": {}, "source": [ "### Explanation: Run Example Task\n", "Executes the full pipeline on a refactor-oriented task illustrating mixed intents (code + summarize). Result dict shows raw plan, per-step outputs with chosen model aliases, and final synthesized answer." ] }, { "cell_type": "code", "execution_count": 18, "id": "8ac0f568", "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'plan': '1. Profile the existing slow Python loop to identify bottlenecks.\\n2. Refactor the loop using optimized techniques (e.g., list comprehensions, map, or itertools).\\n3. Compare the performance of the refactored loop with the original using a benchmarking tool and summarize the gains.',\n", " 'steps': [(1,\n", " 'Profile the existing slow Python loop to identify bottlenecks.',\n", " \"To execute step 1, you would use a profiling tool like `cProfile` in Python to analyze the performance of the existing slow loop. Here's an example of how you might do this:\\n\\n```python\\nimport cProfile\\n\\ndef slow_loop():\\n # Example of a slow loop\\n result = []\\n for i in range(1000000):\\n result.append(i * i)\\n return result\\n\\n# Profile the slow loop\\ncProfile.run('slow_loop()', 'profile_stats')\\n\\n# To see the results, you can use pstats module\\nimport pstats\\np = pstats.Stats('profile_stats')\\np.sort_stats('cumulative').print_stats()\\n```\\n\\nThis code will run the `slow_loop` function and profile it, saving the results to 'profile_stats'. The `pstats` module can then be used to analyze the profiling data, which will show\",\n", " 'phi-4-mini'),\n", " (2,\n", " 'Refactor the loop using optimized techniques (e.g., list comprehensions, map, or itertools).',\n", " 'To refactor a slow Python loop using optimized techniques such as list comprehensions, `map`, or `itertools`, follow these steps:\\n\\n1. **Identify the Loop**: Determine which loop in your code is causing the slowdown.\\n2. **Understand the Loop**: Analyze what the loop does, including any operations performed on each element.\\n3. **Choose an Optimization Technique**:\\n - **List Comprehension**: If the loop constructs a new list, use a list comprehension.\\n - **Map Function**: Use `map` if you need to apply a function to each item in an iterable.\\n - **Itertools**: Utilize functions from the `itertools` module for more efficient looping patterns.\\n4. **Refactor the Loop**: Replace the original loop with the chosen optimization technique.\\n5. **Test the Code**: Ensure that the refactored code produces the same',\n", " 'qwen2.5-coder-7b'),\n", " (3,\n", " 'Compare the performance of the refactored loop with the original using a benchmarking tool and summarize the gains.',\n", " 'To compare the performance of the refactored loop with the original using a benchmarking tool, follow these steps:\\n\\n1. **Choose a Benchmarking Tool**: Select an appropriate benchmarking tool such as `timeit`, `cProfile`, or `line_profiler` depending on your needs.\\n\\n2. **Set Up Your Environment**: Ensure that both the original and refactored code snippets are in separate functions or scripts so they can be easily compared.\\n\\n3. **Run Benchmarks**:\\n - Use the chosen tool to measure the execution time of the original loop.\\n - Repeat the process for the refactored loop.\\n\\n4. **Compare Results**: Analyze the results from both benchmarks to determine the performance gain achieved by the refactoring.\\n\\n5. **Summarize Gains**: Provide a concise summary of the performance improvements, including any specific metrics (e.g., speedup factor',\n", " 'qwen2.5-coder-7b')],\n", " 'final': 'To optimize a slow Python loop, you can use profiling tools like `cProfile` to identify the loop causing the slowdown. Once identified, you can refactor the loop using techniques such as list comprehensions, `map`, or `itertools` for more efficient looping patterns. After refactoring, you can use benchmarking tools like `timeit`, `cProfile`, or `line_profiler` to compare the performance of the original and refactored loops. The performance gains can be summarized in terms of speedup factor or other relevant metrics. This process can significantly improve the performance of your Python code.'}" ] }, "execution_count": 18, "metadata": {}, "output_type": "execute_result" } ], "source": [ "result = pipeline('Generate a refactored version of a slow Python loop and summarize performance gains.')\n", "result" ] }, { "cell_type": "markdown", "id": "f4251879", "metadata": {}, "source": [ "### Explanation: Display Result Object\n", "Shows structured pipeline output for quick inspection or downstream evaluation (e.g., measuring step quality or refinement efficacy)." ] } ], "metadata": { "kernelspec": { "display_name": "demo", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.15" } }, "nbformat": 4, "nbformat_minor": 5 }