├── requirements.txt ├── CLAUDE.md ├── README.md ├── .github └── workflows │ └── self-improve.yml ├── reasoning_modules.json └── self_discover_dspy_api.py /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi>=0.65.0 2 | uvicorn[standard]>=0.13.0 3 | pydantic>=1.8.1 4 | requests>=2.25.1 5 | beautifulsoup4>=4.9.3 6 | dspy-ai==2.4.0 7 | open-interpreter==0.2.0 8 | groq==0.4.2 9 | -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | # Claude Code Guardrails 2 | 3 | This file defines what Claude Code is allowed to modify when performing automated improvements. 4 | 5 | ## Allowed Modifications 6 | 7 | Claude Code MAY modify: 8 | - **Documentation files** (README.md, docs/*, *.md) 9 | - **Source code** for: 10 | - Bug fixes and error handling 11 | - Code quality improvements (remove duplication, add type hints) 12 | - Performance optimizations 13 | - Refactoring for clarity/maintainability 14 | - Security fixes 15 | - **Test files** (add new tests, fix broken tests, improve coverage) 16 | - **CI/CD configurations** (.github/workflows/*, .gitlab-ci.yml, etc.) 17 | - **Configuration files** (build configs, linting rules, etc.) 18 | - **Metadata files** (package.json, pyproject.toml, setup.py) 19 | - **GitHub-specific files** (.gitignore, CODEOWNERS, etc.) 20 | - **Dependencies** (with clear justification for updates/additions) 21 | 22 | ## Restricted Modifications 23 | 24 | Claude Code MUST NOT: 25 | - **Break public APIs** or change function signatures without discussion 26 | - **Make breaking changes** to existing behavior 27 | - **Change core algorithms** without explaining rationale 28 | - **Remove features** without justification 29 | - **Add heavy dependencies** without clear need 30 | - **Modify production configuration** (database URLs, API keys, etc.) 31 | 32 | ## Exception: Issues Labeled `ai-implement` 33 | 34 | When an issue is labeled `ai-implement`, Claude Code may modify source code to implement the requested feature or fix, but must: 35 | 1. Reference the issue number in the PR 36 | 2. Follow existing code style and patterns 37 | 3. Include tests if the project has a test suite 38 | 4. Not change public APIs without discussion in the issue 39 | 40 | ## Pull Request Requirements 41 | 42 | All PRs created by Claude Code MUST include: 43 | 1. A clear description of what was changed and why 44 | 2. A receipt line in the format: `Receipt: ` 45 | 3. Reference to the workflow run that created it 46 | 4. Minimal, focused changes (prefer small PRs over large ones) 47 | 48 | ## General Principles 49 | 50 | 1. **Minimal Deltas**: Make the smallest change that solves the problem 51 | 2. **No Breaking Changes**: Never introduce breaking changes 52 | 3. **Follow Existing Patterns**: Match the style and structure of existing code 53 | 4. **Documentation First**: When in doubt, improve documentation rather than code 54 | 5. **Safety First**: If uncertain, create an issue for human review instead of making changes 55 | 56 | --- 57 | 58 | *This file was created to ensure safe and predictable AI-assisted repository maintenance.* 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # FastAPI Application with DSPy Integration 3 | 4 | This repository contains a FastAPI application designed to solve complex tasks through intelligent reasoning and automated code generation. Leveraging DSPy for deep learning and AI capabilities, alongside the Groq platform for enhanced computational power, this application offers a robust solution for processing natural language task descriptions, executing code, and dynamically generating code solutions. 5 | 6 | ## Features 7 | 8 | - **Natural Language Task Solving**: Processes tasks described in natural language to generate actionable solutions. 9 | - **Code Execution**: Executes arbitrary Python code dynamically through an API endpoint. 10 | - **Automated Code Generation**: Generates executable code from structured reasoning about tasks, offering end-to-end automation from description to execution. 11 | - **Integration with DSPy and Groq**: Utilizes the DSPy framework for AI and machine learning operations, powered by Groq's computational capabilities. 12 | 13 | ## Installation 14 | 15 | Ensure you have Python 3.8+ installed. Clone this repository, then install the required dependencies: 16 | 17 | ```bash 18 | pip install -r requirements.txt 19 | ``` 20 | 21 | ## Usage 22 | 23 | The application provides several endpoints for interacting with its capabilities: 24 | 25 | ### Solving Tasks with Natural Language Descriptions 26 | 27 | ```bash 28 | curl -X 'POST' \ 29 | 'http://0.0.0.0:8008/solve-task/' \ 30 | -H 'accept: application/json' \ 31 | -H 'Content-Type: application/json' \ 32 | -d '{ "description": "Explain photosynthesis", "task_type": "science" }' 33 | ``` 34 | 35 | ### Executing Arbitrary Code 36 | 37 | ```bash 38 | curl -X 'POST' \ 39 | 'http://0.0.0.0:8008/execute-code/' \ 40 | -H 'accept: application/json' \ 41 | -H 'Content-Type: application/json' \ 42 | -d @payload.json 43 | ``` 44 | 45 | `payload.json` should contain your Python code in the format: 46 | 47 | ```json 48 | { 49 | "code": "print('Hello, world!')" 50 | } 51 | ``` 52 | 53 | ### Generating and Executing Code from Task Descriptions 54 | 55 | ```bash 56 | curl -X 'POST' \ 57 | 'http://0.0.0.0:8008/generate-and-execute/' \ 58 | -H 'accept: application/json' \ 59 | -H 'Content-Type: application/json' \ 60 | -d '{ "description": "Generate a Python function to add two numbers", "task_type": "programming" }' 61 | ``` 62 | 63 | ### Running the Server 64 | 65 | Start the FastAPI server using Uvicorn: 66 | 67 | ```bash 68 | uvicorn self_discover_dspy_api:app --host 0.0.0.0 --port 8008 --reload 69 | ``` 70 | 71 | ## Contributing 72 | 73 | Contributions are welcome! Feel free to submit pull requests or open issues to suggest improvements or add new features. 74 | 75 | ## License 76 | 77 | This project is licensed under the MIT License - see the LICENSE file for details. 78 | -------------------------------------------------------------------------------- /.github/workflows/self-improve.yml: -------------------------------------------------------------------------------- 1 | name: Claude Code Self-Improve 2 | 3 | on: 4 | schedule: 5 | # Twice daily: 06:00 and 18:00 America/Chicago (11:00 and 23:00 UTC) 6 | - cron: "0 11 * * *" 7 | - cron: "0 23 * * *" 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: write 12 | issues: write 13 | pull-requests: write 14 | id-token: write 15 | 16 | jobs: 17 | self-improve: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout repository 21 | uses: actions/checkout@v4 22 | 23 | - name: Run Claude Code Self-Improvement 24 | uses: anthropics/claude-code-action@v1 25 | with: 26 | claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} 27 | show_full_output: true 28 | prompt: | 29 | You are a SENIOR ENGINEER conducting recursive self-improvement on this repository. 30 | 31 | GOAL: Identify and fix 2-4 high-impact gaps, then create a PR 32 | TIME LIMIT: You have 50 turns. Explore efficiently, implement quickly. 33 | 34 | === EXECUTION STRATEGY === 35 | 36 | PHASE 1 - RAPID ASSESSMENT (10-15 turns): 37 | - Use Glob to see structure 38 | - Read README, main code files 39 | - Use Grep to find TODOs, FIXMEs, error patterns 40 | - Identify 2-4 HIGH IMPACT + LOW RISK improvements 41 | 42 | PHASE 2 - IMPLEMENT FIXES (25-30 turns): 43 | - Fix the gaps you identified 44 | - Use Edit/Write to make changes 45 | - Run tests if available (pytest, make test) 46 | - Keep changes focused and safe 47 | 48 | PHASE 3 - CREATE PR (5-10 turns): 49 | - Use git to stage, commit, push changes 50 | - Use gh to create PR with clear description 51 | - Include Receipt: 52 | 53 | === WHAT TO FIX (prioritize these) === 54 | High-impact, low-risk improvements: 55 | - Missing/unclear documentation (README, docstrings) 56 | - Missing error handling 57 | - Missing type hints 58 | - Dead code or unused imports 59 | - Code duplication 60 | - Missing tests for core functionality 61 | - Security issues (hardcoded secrets, etc.) 62 | - Build/deployment issues 63 | 64 | SKIP complex refactoring or architectural changes. 65 | 66 | === EXECUTION TIPS === 67 | - Use Glob/Grep, not find/cat/wc (prefer specialized tools) 68 | - Read selectively (don't read every file) 69 | - Focus on IMPACT: what helps users/developers most? 70 | - Be surgical: fix what matters, leave rest alone 71 | - MUST create PR before turn 50 72 | 73 | === CONSTRAINTS (from CLAUDE.md) === 74 | ✅ You CAN modify: 75 | - Source code (for bug fixes, improvements, refactoring) 76 | - Tests (add/fix tests) 77 | - Documentation (add/improve docs) 78 | - Configuration (fix build/deploy issues) 79 | - Dependencies (with clear justification) 80 | 81 | ❌ You MUST NOT: 82 | - Break public APIs 83 | - Make breaking changes without discussion 84 | - Change behavior without justification 85 | - Introduce new dependencies without reason 86 | 87 | === EXECUTION TIPS (Think like an RLM) === 88 | - Use Glob to efficiently explore structure (don't read everything) 89 | - Use Grep to find patterns (TODOs, error-prone code, duplicates) 90 | - Read selectively (only files relevant to gaps you find) 91 | - Partition work: analyze different aspects recursively 92 | - Focus on IMPACT: what will make the biggest difference? 93 | - Be surgical: fix what matters, leave the rest alone 94 | 95 | Remember: You're autonomous. Decide what needs fixing and fix it. 96 | claude_args: | 97 | --max-turns 75 98 | --model claude-sonnet-4-5-20250929 99 | --allowedTools "Read,Write,Edit,Glob,Grep,Bash(git:*),Bash(gh:*),Bash(pytest:*),Bash(python:*),Bash(make:*),Bash(find:*),Bash(wc:*),Bash(cat:*),Bash(head:*),Bash(tail:*),Bash(ls:*),Bash(tree:*)" 100 | --system-prompt "You are a senior software engineer conducting autonomous recursive code review. Use RLM patterns: peek, grep, partition, recurse. Prioritize high-impact improvements. Be surgical and focused." 101 | 102 | - name: Trigger Qodo Review 103 | if: steps.anthropics-claude-code-action.outputs.pr_number != '' 104 | env: 105 | GH_TOKEN: \${{ secrets.GITHUB_TOKEN }} 106 | run: | 107 | PR_NUMBER=\$(gh pr list --head \$(git branch --show-current) --json number --jq '.[0].number') 108 | if [ -n "\$PR_NUMBER" ]; then 109 | echo "Commenting on PR #\$PR_NUMBER to trigger Qodo review" 110 | gh pr comment \$PR_NUMBER --body "/describe" 111 | gh pr comment \$PR_NUMBER --body "/review" 112 | fi 113 | -------------------------------------------------------------------------------- /reasoning_modules.json: -------------------------------------------------------------------------------- 1 | { 2 | "reasoning_modules": [ 3 | { 4 | "id": 1, 5 | "type": "Experimental Design", 6 | "description": "How could I devise an experiment to help solve that problem?" 7 | }, 8 | { 9 | "id": 2, 10 | "type": "Iterative Solution Testing", 11 | "description": "Make a list of ideas for solving this problem, and apply them one by one to the problem to see if any progress can be made." 12 | }, 13 | { 14 | "id": 3, 15 | "type": "Progress Measurement", 16 | "description": "How could I measure progress on this problem?" 17 | }, 18 | { 19 | "id": 4, 20 | "type": "Problem Simplification", 21 | "description": "How can I simplify the problem so that it is easier to solve?" 22 | }, 23 | { 24 | "id": 5, 25 | "type": "Assumption Identification", 26 | "description": "What are the key assumptions underlying this problem?" 27 | }, 28 | { 29 | "id": 6, 30 | "type": "Risk Analysis", 31 | "description": "What are the potential risks and drawbacks of each solution?" 32 | }, 33 | { 34 | "id": 7, 35 | "type": "Perspectival Analysis", 36 | "description": "What are the alternative perspectives or viewpoints on this problem?" 37 | }, 38 | { 39 | "id": 8, 40 | "type": "Long-term Implications Analysis", 41 | "description": "What are the long-term implications of this problem and its solutions?" 42 | }, 43 | { 44 | "id": 9, 45 | "type": "Problem Decomposition", 46 | "description": "How can I break down this problem into smaller, more manageable parts?" 47 | }, 48 | { 49 | "id": 10, 50 | "type": "Critical Thinking", 51 | "description": "Critical Thinking: This style involves analyzing the problem from different perspectives, questioning assumptions, and evaluating the evidence or information available. It focuses on logical reasoning, evidence-based decision-making, and identifying potential biases or flaws in thinking." 52 | }, 53 | { 54 | "id": 11, 55 | "type": "Creative Thinking", 56 | "description": "Try creative thinking, generate innovative and out-of-the-box ideas to solve the problem. Explore unconventional solutions, thinking beyond traditional boundaries, and encouraging imagination and originality." 57 | }, 58 | { 59 | "id": 12, 60 | "type": "Collaborative Problem-Solving", 61 | "description": "Seek input and collaboration from others to solve the problem. Emphasize teamwork, open communication, and leveraging the diverse perspectives and expertise of a group to come up with effective solutions." 62 | }, 63 | { 64 | "id": 13, 65 | "type": "Systems Thinking", 66 | "description": "Use systems thinking: Consider the problem as part of a larger system and understanding the interconnectedness of various elements. Focuses on identifying the underlying causes, feedback loops, and interdependencies that influence the problem, and developing holistic solutions that address the system as a whole." 67 | }, 68 | { 69 | "id": 14, 70 | "type": "Risk Analysis", 71 | "description": "Use Risk Analysis: Evaluate potential risks, uncertainties, and tradeoffs associated with different solutions or approaches to a problem. Emphasize assessing the potential consequences and likelihood of success or failure, and making informed decisions based on a balanced analysis of risks and benefits." 72 | }, 73 | { 74 | "id": 15, 75 | "type": "Reflective Thinking", 76 | "description": "Use Reflective Thinking: Step back from the problem, take the time for introspection and self-reflection. Examine personal biases, assumptions, and mental models that may influence problem-solving, and being open to learning from past experiences to improve future approaches." 77 | }, 78 | { 79 | "id": 16, 80 | "type": "Core Issue Identification", 81 | "description": "What is the core issue or problem that needs to be addressed?" 82 | }, 83 | { 84 | "id": 17, 85 | "type": "Root Cause Analysis", 86 | "description": "What are the underlying causes or factors contributing to the problem?" 87 | }, 88 | { 89 | "id": 18, 90 | "type": "Historical Solution Analysis", 91 | "description": "Are there any potential solutions or strategies that have been tried before? If yes, what were the outcomes and lessons learned?" 92 | }, 93 | { 94 | "id": 19, 95 | "type": "Obstacle Identification", 96 | "description": "What are the potential obstacles or challenges that might arise in solving this problem?" 97 | }, 98 | { 99 | "id": 20, 100 | "type": "Data-Driven Insight Generation", 101 | "description": "Are there any relevant data or information that can provide insights into the problem? If yes, what data sources are available, and how can they be analyzed?" 102 | }, 103 | { 104 | "id": 21, 105 | "type": "Stakeholder Analysis", 106 | "description": "Are there any stakeholders or individuals who are directly affected by the problem? What are their perspectives and needs?" 107 | }, 108 | { 109 | "id": 22, 110 | "type": "Resource Analysis", 111 | "description": "What resources (financial, human, technological, etc.) are needed to tackle the problem effectively?" 112 | }, 113 | { 114 | "id": 23, 115 | "type": "Success Measurement", 116 | "description": "How can progress or success in solving the problem be measured or evaluated?" 117 | }, 118 | { 119 | "id": 24, 120 | "type": "Metric Identification", 121 | "description": "What indicators or metrics can be used?" 122 | }, 123 | { 124 | "id": 25, 125 | "type": "Problem Type Classification", 126 | "description": "Is the problem a technical or practical one that requires a specific expertise or skill set? Or is it more of a conceptual or theoretical problem?" 127 | }, 128 | { 129 | "id": 26, 130 | "type": "Constraint Analysis", 131 | "description": "Does the problem involve a physical constraint, such as limited resources, infrastructure, or space?" 132 | }, 133 | { 134 | "id": 27, 135 | "type": "Behavioral Analysis", 136 | "description": "Is the problem related to human behavior, such as a social, cultural, or psychological issue?" 137 | }, 138 | { 139 | "id": 28, 140 | "type": "Decision Analysis", 141 | "description": "Does the problem involve decision-making or planning, where choices need to be made under uncertainty or with competing objectives?" 142 | }, 143 | { 144 | "id": 29, 145 | "type": "Analytical Problem-Solving", 146 | "description": "Is the problem an analytical one that requires data analysis, modeling, or optimization techniques?" 147 | }, 148 | { 149 | "id": 30, 150 | "type": "Design Thinking", 151 | "description": "Is the problem a design challenge that requires creative solutions and innovation?" 152 | }, 153 | { 154 | "id": 31, 155 | "type": "Systemic Solution Development", 156 | "description": "Does the problem require addressing systemic or structural issues rather than just individual instances?" 157 | }, 158 | { 159 | "id": 32, 160 | "type": "Urgency Analysis", 161 | "description": "Is the problem time-sensitive or urgent, requiring immediate attention and action?" 162 | }, 163 | { 164 | "id": 33, 165 | "type": "Solution Exploration", 166 | "description": "What kinds of solution typically are produced for this kind of problem specification?" 167 | }, 168 | { 169 | "id": 34, 170 | "type": "Alternative Solution Generation", 171 | "description": "Given the problem specification and the current best solution, have a guess about other possible solutions." 172 | }, 173 | { 174 | "id": 35, 175 | "type": "Contrarian Thinking", 176 | "description": "Let's imagine the current best solution is totally wrong, what other ways are there to think about the problem specification?" 177 | }, 178 | { 179 | "id": 36, 180 | "type": "Solution Refinement", 181 | "description": "What is the best way to modify this current best solution, given what you know about these kinds of problem specification?" 182 | }, 183 | { 184 | "id": 37, 185 | "type": "Innovative Solution Creation", 186 | "description": "Ignoring the current best solution, create an entirely new solution to the problem." 187 | }, 188 | { 189 | "id": 38, 190 | "type": "Sequential Problem-Solving", 191 | "description": "Let's think step by step." 192 | }, 193 | { 194 | "id": 39, 195 | "type": "Implementation Planning", 196 | "description": "Let's make a step by step plan and implement it with good notion and explanation." 197 | } 198 | ] 199 | } 200 | -------------------------------------------------------------------------------- /self_discover_dspy_api.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from pydantic import BaseModel 3 | import uvicorn 4 | import dspy 5 | from pathlib import Path 6 | import json 7 | from groq import Groq as GroqClient # Ensure this matches your actual Groq client import 8 | from dsp import LM 9 | import os 10 | from interpreter import interpreter as oi 11 | from fastapi import HTTPException 12 | from pydantic import BaseModel, Field 13 | from typing import List, Optional 14 | 15 | class ReasoningStep(BaseModel): 16 | step_description: str = Field(..., description="Description of the reasoning step") 17 | action: str = Field(..., description="The action to be taken in this step") 18 | inputs: Optional[List[str]] = Field(None, description="Optional inputs needed for the action") 19 | 20 | class ReasoningStructure(BaseModel): 21 | task_description: str = Field(..., description="Description of the task to be solved") 22 | steps: List[ReasoningStep] = Field(..., description="List of steps involved in reasoning") 23 | 24 | class ReasoningOutput(BaseModel): 25 | implemented_reasoning_structures: ReasoningStructure = Field(..., description="Implemented reasoning structures to solve the task") 26 | 27 | 28 | class TaskRequest(BaseModel): 29 | description: str 30 | task_type: str # Newly added attribute 31 | 32 | class GenerateCodeModule(dspy.Module): 33 | def __init__(self): 34 | super().__init__() 35 | self.translator = TranslateToCode() 36 | 37 | def translate_to_code(self, reasoning_structure: ReasoningStructure) -> str: 38 | code_snippets = [self.translator.translate_step(step) for step in reasoning_structure.steps] 39 | return "\n".join(code_snippets) 40 | 41 | def forward(self, reasoning_structure: ReasoningStructure) -> str: 42 | generated_code = self.translate_to_code(reasoning_structure) 43 | execution_result = interpreter.chat(f"```python\n{generated_code}\n```", display=False) 44 | return execution_result 45 | 46 | class TranslateToCode: 47 | def __init__(self): 48 | self.patterns = { 49 | "calculate": "result = {expression}", 50 | "compare": "if {condition}:", 51 | # Extend this dictionary with more actions and corresponding code templates 52 | } 53 | 54 | def translate_step(self, step: ReasoningStep) -> str: 55 | template = self.patterns.get(step.action, "# TODO: Implement logic for '{step.action}'") 56 | return template.format(expression=step.step_description, condition=step.step_description) 57 | # Adjust the format call as necessary based on the expected details in step_description 58 | 59 | 60 | 61 | 62 | class Groq(LM): 63 | def __init__(self, model="mixtral-8x7b-32768", **kwargs): 64 | super().__init__(model) 65 | self.model = model # Explicitly set the model attribute 66 | self.client = GroqClient(api_key=os.environ.get("GROQ_API_KEY")) 67 | 68 | # Implement the basic_request method 69 | def basic_request(self, prompt, **kwargs): 70 | # Dummy implementation 71 | pass 72 | 73 | def __call__(self, prompt, only_completed=True, return_sorted=False, **kwargs): 74 | chat_completion = self.client.chat.completions.create( 75 | messages=[{"role": "user", "content": prompt}], 76 | model=kwargs.get("model", self.model), 77 | ) 78 | assert chat_completion.choices and chat_completion.choices[0].message.content, "API response is empty or null." 79 | return [chat_completion.choices[0].message.content] 80 | 81 | 82 | class CodeExecutionRequest(BaseModel): 83 | code: str 84 | 85 | class TaskRequest(BaseModel): 86 | description: str 87 | # Additional fields as necessary 88 | 89 | app = FastAPI() 90 | 91 | # Global variable for Groq model 92 | groq_model = None 93 | 94 | def configure_dspy(): 95 | global groq_model 96 | groq_model = Groq(model="mixtral-8x7b-32768") 97 | dspy.settings.configure(lm=groq_model) 98 | 99 | # Load and prepare reasoning modules 100 | def load_and_prepare_reasoning_modules(): 101 | cwd = Path.cwd() 102 | fp_reasoning_modules_json = cwd / "./reasoning_modules.json" 103 | with open(fp_reasoning_modules_json, "r") as file: 104 | data = json.load(file) 105 | reasoning_modules = data.get("reasoning_modules", []) 106 | reasoning_modules_text = ", ".join([f'({module["type"]}: {module["description"]})' for module in reasoning_modules]) 107 | return reasoning_modules_text 108 | 109 | # Your DSPy Module class definitions... 110 | class SelectReasoningModules(dspy.Signature): 111 | """Select several relevant reasoning modules that are crucial to utilize in order to solve the given task(s).""" 112 | 113 | task_description = dspy.InputField(prefix="Task(s) Description:", desc="The task(s) to solve.") 114 | reasoning_modules = dspy.InputField( 115 | prefix="Relevant Reasoning Modules:", 116 | desc="List of relevant reasoning modules to solve task(s) with.", 117 | ) 118 | selected_reasoning_modules = dspy.OutputField( 119 | prefix="Selected Reasoning Modules and their Descriptions:", 120 | desc="Select several reasoning modules that are the most appropriate for solving the given task(s). Do NOT elaborate on why, just provide a list of `{module type}: {description}`.", 121 | ) 122 | 123 | class SelectReasoningModule(dspy.Module): 124 | def __init__(self, reasoning_modules): 125 | super().__init__() 126 | 127 | self.reasoning_modules = reasoning_modules 128 | self.generate = dspy.ChainOfThought(SelectReasoningModules) 129 | 130 | def forward(self, task_description: str) -> dspy.Prediction: 131 | prediction = self.generate(task_description=task_description, reasoning_modules=self.reasoning_modules) 132 | 133 | return prediction 134 | class AdaptReasoningModules(dspy.Signature): 135 | """Rephrase and specify each selected reasoning module so that it better helps solving the given task(s).""" 136 | 137 | task_description = dspy.InputField(prefix="Task(s) Description:", desc="The task(s) to solve.") 138 | selected_reasoning_modules = dspy.InputField( 139 | prefix="Selected Reasoning Modules:", 140 | desc="The selected reasoning modules that will be adapted to solve the task(s).", 141 | ) 142 | adapted_reasoning_modules = dspy.OutputField( 143 | prefix="Adapted Reasoning Modules:", 144 | desc="Adapt and tailor each selected reasoning module's description to better solve the task(s). Do NOT work out the full solution.", 145 | ) 146 | 147 | 148 | class AdaptReasoningModule(dspy.Module): 149 | def __init__(self): 150 | super().__init__() 151 | self.generate = dspy.ChainOfThought(AdaptReasoningModules) 152 | 153 | def forward(self, task_description: str, selected_reasoning_modules: str) -> dspy.Prediction: 154 | prediction = self.generate( 155 | task_description=task_description, 156 | selected_reasoning_modules=selected_reasoning_modules, 157 | ) 158 | return prediction 159 | class ImplementReasoningStructures(dspy.Signature): 160 | """Operationalize each adapted reasoning module into a step-by-step structured reasoning plan template to solve the task(s).""" 161 | 162 | task_description = dspy.InputField(prefix="Task(s) Description:", desc="The task(s) to solve.") 163 | adapted_reasoning_modules = dspy.InputField( 164 | prefix="Task Adapted Reasoning Modules:", 165 | desc="The adapted reasoning modules that will be implemented to better solve the task(s).", 166 | ) 167 | implemented_reasoning_structures = dspy.OutputField( 168 | prefix="Implemented Reasoning Structures:", 169 | desc="Implement a JSON-formmated reasoning structure template for solvers to follow step-by-step and arrive at correct answers. Do NOT work out the full solution.", 170 | ) 171 | 172 | class ImplementReasoningStructure(dspy.Module): 173 | def __init__(self): 174 | super().__init__() 175 | self.generate = dspy.ChainOfThought(ImplementReasoningStructures) 176 | 177 | def forward(self, task_description: str, adapted_reasoning_modules: str) -> dspy.Prediction: 178 | prediction = self.generate( 179 | task_description=task_description, 180 | adapted_reasoning_modules=adapted_reasoning_modules, 181 | ) 182 | return prediction 183 | 184 | class ExecuteReasoningStructures(dspy.Signature): 185 | """Execute the given reasoning structure to solve a specific task(s).""" 186 | 187 | task_description = dspy.InputField(prefix="Task(s) Description:", desc="The task(s) to solve.") 188 | implemented_reasoning_structures = dspy.InputField( 189 | desc="The JSON-formatted reasoning structure template that will be used to solve the task(s).", 190 | ) 191 | executed_reasoning_structures = dspy.OutputField( 192 | desc="Using the reasoning structure as a guide, solve the task(s) and provide the final answer(s).", 193 | ) 194 | 195 | class ExecuteReasoningStructure(dspy.Module): 196 | def __init__(self): 197 | super().__init__() 198 | self.generate = dspy.Predict(ExecuteReasoningStructures) 199 | 200 | def forward(self, task_description: str, implemented_reasoning_structures: str) -> dspy.Prediction: 201 | prediction = self.generate( 202 | task_description=task_description, 203 | implemented_reasoning_structure=implemented_reasoning_structures, 204 | ) 205 | return prediction 206 | 207 | class SelfDiscover(dspy.Module): 208 | """A comprehensive DSPy module encapsulating the Self-Discover approach.""" 209 | def __init__(self, reasoning_modules): 210 | super().__init__() 211 | self.reasoning_modules = reasoning_modules 212 | self.select_reasoning_module = SelectReasoningModule(reasoning_modules=self.reasoning_modules) 213 | self.adapt_reasoning_module = AdaptReasoningModule() 214 | self.implement_reasoning_module = ImplementReasoningStructure() 215 | self.execute_reasoning_structure = ExecuteReasoningStructure() 216 | 217 | def forward(self, task_description: str) -> dspy.Prediction: 218 | print(f"SelfDiscover forward called with task_description: {task_description}") 219 | 220 | # STAGE 1: SELECT 221 | selection_prediction = self.select_reasoning_module.forward(task_description) 222 | selected_reasoning_modules = selection_prediction.selected_reasoning_modules 223 | print(f"Selected reasoning modules: {selected_reasoning_modules}") 224 | 225 | # STAGE 2: ADAPT 226 | adaptation_prediction = self.adapt_reasoning_module.forward(task_description, selected_reasoning_modules) 227 | adapted_reasoning_modules = adaptation_prediction.adapted_reasoning_modules 228 | print(f"Adapted reasoning modules: {adapted_reasoning_modules}") 229 | 230 | # STAGE 3: IMPLEMENT 231 | implementation_prediction = self.implement_reasoning_module.forward(task_description, adapted_reasoning_modules) 232 | implemented_reasoning_structures = implementation_prediction.implemented_reasoning_structures 233 | print(f"Implemented reasoning structures: {implemented_reasoning_structures}") 234 | 235 | # STAGE 4: EXECUTE 236 | execution_prediction = self.execute_reasoning_structure.forward(task_description, implemented_reasoning_structures) 237 | executed_reasoning_structures = execution_prediction.executed_reasoning_structures 238 | print(f"Executed reasoning structures: {executed_reasoning_structures}") 239 | 240 | return dspy.Prediction(solution=executed_reasoning_structures) 241 | 242 | 243 | @app.on_event("startup") 244 | def startup_event(): 245 | configure_dspy() 246 | # Load reasoning modules if they are to be used application-wide 247 | 248 | # Example function to load reasoning modules based on task type 249 | def load_reasoning_modules_for_task(task_type: str): 250 | # Define paths or logic to select the correct reasoning modules JSON 251 | reasoning_module_paths = { 252 | "math": "./reasoning_modules_math.json", 253 | "nlp": "./reasoning_modules_nlp.json", 254 | # Add more task types and corresponding module files as needed 255 | } 256 | json_file_path = reasoning_module_paths.get(task_type, "./default_reasoning_modules.json") 257 | with open(json_file_path, "r") as file: 258 | data = json.load(file) 259 | reasoning_modules = data.get("reasoning_modules", []) 260 | reasoning_modules_text = ", ".join([f'({module["type"]}: {module["description"]})' for module in reasoning_modules]) 261 | return reasoning_modules_text 262 | 263 | # Update the TaskRequest model to include a task_type field 264 | class TaskRequest(BaseModel): 265 | description: str 266 | task_type: str # Added field to specify the task type 267 | 268 | @app.post("/solve-task/") 269 | async def solve_task(request: TaskRequest): 270 | # Dynamically load reasoning modules based on the specified task type 271 | reasoning_modules_text = load_reasoning_modules_for_task(request.task_type) 272 | 273 | # Initialize the SelfDiscover module with the dynamically loaded reasoning modules 274 | self_discover = SelfDiscover(reasoning_modules=reasoning_modules_text) 275 | 276 | # Process the task using the SelfDiscover module 277 | prediction = self_discover.forward(task_description=request.description) 278 | 279 | # Return the prediction or solution 280 | return {"solution": prediction.solution} 281 | 282 | @app.post("/execute-code/") 283 | async def execute_code(request: CodeExecutionRequest): 284 | try: 285 | # Here, you use Open Interpreter to run the code 286 | execution_result = oi.chat(f"```python\n{request.code}\n```", display=False) 287 | return {"result": execution_result} 288 | except Exception as e: 289 | raise HTTPException(status_code=500, detail=f"Failed to execute code: {e}") 290 | 291 | @app.post("/generate-and-execute/") 292 | async def generate_and_execute(request: TaskRequest): 293 | print(f"generate-and-execute called with description: {request.description}, task_type: {request.task_type}") 294 | 295 | # Load reasoning modules based on task type. 296 | reasoning_modules_text = load_reasoning_modules_for_task(request.task_type) 297 | print(f"Loaded reasoning modules: {reasoning_modules_text}") 298 | 299 | # Use the SelfDiscover module to process the task. 300 | self_discover = SelfDiscover(reasoning_modules=reasoning_modules_text) 301 | prediction = self_discover.forward(task_description=request.description) 302 | print(f"Prediction from SelfDiscover: {prediction}") 303 | 304 | # Here, you'd need to extract the reasoning structure from the prediction. 305 | # The following is a placeholder - you'll need to adjust it based on your actual data structure: 306 | if hasattr(prediction, 'solution') and isinstance(prediction.solution, ReasoningStructure): 307 | reasoning_structure = prediction.solution 308 | print(f"Extracted reasoning structure: {reasoning_structure}") 309 | 310 | # Generate code using the GenerateCodeModule. 311 | generate_code_module = GenerateCodeModule() 312 | generated_code = generate_code_module.forward(reasoning_structure) 313 | print(f"Generated code: {generated_code}") 314 | 315 | try: 316 | execution_result = oi.chat(f"```python\n{generated_code}\n```", display=False) 317 | print(f"Execution result: {execution_result}") 318 | return {"result": execution_result} 319 | except Exception as e: 320 | print(f"Error executing code: {e}") 321 | raise HTTPException(status_code=500, detail=f"Failed to generate or execute code: {e}") 322 | else: 323 | error_msg = "Failed to extract reasoning structure from prediction." 324 | print(error_msg) 325 | raise HTTPException(status_code=500, detail=error_msg) 326 | 327 | 328 | 329 | if __name__ == "__main__": 330 | uvicorn.run("app:app", host="0.0.0.0", port=8008, reload=True) 331 | --------------------------------------------------------------------------------