Commit
·
c2bb300
1
Parent(s):
3d48e06
Add chatbot configuration and utility scripts; remove unused API files
Browse files- .history/README_20250202074133.md +66 -0
- .history/app_20250202074309.py +49 -0
- .history/app_20250202075023.py +57 -0
- .history/configs/chatbot_config_20250202074149.yaml +24 -0
- .history/configs/chatbot_config_20250202074154.yaml +24 -0
- .history/requirements_20250202074316.txt +4 -0
- data/dataset.csv → .history/roadmap_20250202065652.yaml +0 -0
- .history/roadmap_20250202074427.yaml +131 -0
- .history/rules_20250202065657.yaml +0 -0
- .history/rules_20250202074648.yaml +78 -0
- .history/rules_20250202074656.yaml +78 -0
- .history/scripts/chatbot_logic_20250202073826.py +289 -0
- .history/scripts/chatbot_logic_20250202074121.py +300 -0
- .history/scripts/chatbot_logic_20250202075014.py +326 -0
- .history/scripts/code_templates/api_template.py_20250202074256.txt +60 -0
- .history/scripts/code_templates/evaluation_template.py_20250202074245.txt +67 -0
- .history/scripts/code_templates/preprocessing_template.py_20250202074225.txt +44 -0
- .history/scripts/code_templates/training_template.py_20250202074236.txt +58 -0
- .history/scripts/parsing_utils_20250202074213.py +28 -0
- README.md +15 -10
- api/api.py +0 -16
- api/main.py +0 -22
- app.py +9 -1
- configs/chatbot_config.yaml +2 -2
- details.txt +0 -21
- requirements.txt +1 -1
- roadmap.txt +0 -80
- roadmap.yaml +131 -0
- rules.txt +0 -92
- rules.yaml +78 -0
- scripts/chatbot_logic.py +136 -13
.history/README_20250202074133.md
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Test
|
| 3 |
+
emoji: 📚
|
| 4 |
+
colorFrom: yellow
|
| 5 |
+
colorTo: red
|
| 6 |
+
sdk: streamlit
|
| 7 |
+
sdk_version: 1.41.1
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
short_description: STTETTETE
|
| 11 |
+
---
|
| 12 |
+
# Custom AI Chatbot for Project Guidance
|
| 13 |
+
|
| 14 |
+
This project implements a custom AI chatbot designed to guide users through complex projects based on predefined roadmaps and rules.
|
| 15 |
+
|
| 16 |
+
**Features:**
|
| 17 |
+
|
| 18 |
+
* **Roadmap-based Guidance:** Follows a structured roadmap defined in `roadmap.yaml`.
|
| 19 |
+
* **Rule Enforcement:** Adheres to project rules defined in `rules.yaml`.
|
| 20 |
+
* **Dynamic Response Generation:** Provides context-aware and step-by-step guidance.
|
| 21 |
+
* **Code Snippet Generation:** Generates complete code snippets for project phases using templates.
|
| 22 |
+
* **LLM Selection:** Integrates with Hugging Face Hub for flexible LLM selection (DeepSeek and Gemini models).
|
| 23 |
+
* **Model Switching:** Allows users to switch between available LLMs via the UI.
|
| 24 |
+
* **Basic LLM Responses:** Generates responses using the selected LLM for general queries.
|
| 25 |
+
* **Token Control:** Limits LLM response length using `max_response_tokens` in `configs/chatbot_config.yaml`.
|
| 26 |
+
* **Configuration Update Mode:** Allows authorized users to modify chatbot configuration (rules) via chat commands in a special "update mode".
|
| 27 |
+
* **Error Handling:** Includes error handling for model loading, switching, and configuration updates, with UI warnings.
|
| 28 |
+
* **Deployable on Hugging Face Spaces:** Built using Gradio for easy deployment.
|
| 29 |
+
|
| 30 |
+
**Important Notes on Safety Settings and Self-Update:**
|
| 31 |
+
|
| 32 |
+
* **Direct Safety Configuration Limited:** For the Hugging Face models used directly via `transformers` (DeepSeek and Gemini Flash), there are **no easily configurable, standardized "safety settings"**. Safety is model-dependent.
|
| 33 |
+
* **Model-Dependent Safety:** Safety behavior is primarily determined by how these models were trained.
|
| 34 |
+
* **Configuration-Based Self-Update:** The "self-update" feature is implemented as a *configuration modification* system. It allows authorized users to change the chatbot's rules by modifying the `rules.yaml` file via chat commands in "update mode." **It does not modify the core Python code itself.**
|
| 35 |
+
* **Security Warning:** The "self-update" feature, even in its configuration-based form, introduces security considerations. **Secret commands are NOT a robust security measure.** In a real deployment, stronger authentication and authorization would be essential. Use this feature with caution and only in trusted environments.
|
| 36 |
+
|
| 37 |
+
**Getting Started:**
|
| 38 |
+
|
| 39 |
+
1. **Clone this repository.**
|
| 40 |
+
2. **Install dependencies:** `pip install -r requirements.txt`
|
| 41 |
+
3. **Customize `roadmap.yaml` and `rules.yaml`** to define your project guidance.
|
| 42 |
+
4. **Configure `configs/chatbot_config.yaml`** to set up LLMs, token limits, and chatbot behavior.
|
| 43 |
+
5. **Run the Gradio app:** `python app.py`
|
| 44 |
+
6. **To enter update mode:** Type `sagor is python/start` in the chat.
|
| 45 |
+
7. **To get help in update mode:** Type `sagor is python/help`.
|
| 46 |
+
8. **To exit update mode:** Type `sagor is python/exit`.
|
| 47 |
+
9. **Deploy to Hugging Face Spaces** (refer to Hugging Face Spaces documentation).
|
| 48 |
+
|
| 49 |
+
**Available Models:**
|
| 50 |
+
|
| 51 |
+
* DeepSeek-R1-Distill-Llama-8B
|
| 52 |
+
* Gemini 2.0 Flash (Exp 01-21)
|
| 53 |
+
|
| 54 |
+
**Further Development:**
|
| 55 |
+
|
| 56 |
+
* Enhance LLM response generation for more context-aware and project-specific guidance.
|
| 57 |
+
* Implement more sophisticated state management to track user progress through the roadmap.
|
| 58 |
+
* Improve code generation with more dynamic templates and customization options.
|
| 59 |
+
* Develop a more advanced GUI or web-based interface for configuration management.
|
| 60 |
+
* Add more LLMs to the selection pool.
|
| 61 |
+
* Implement more robust error handling and logging.
|
| 62 |
+
* Explore and potentially integrate keyword-based output filtering for basic safety control.
|
| 63 |
+
* Investigate using commercial LLM APIs for more advanced safety settings and control.
|
| 64 |
+
* **Improve security and authorization for the configuration update mode.**
|
| 65 |
+
|
| 66 |
+
**License:** [Your License]
|
.history/app_20250202074309.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from scripts.chatbot_logic import ProjectGuidanceChatbot
|
| 3 |
+
|
| 4 |
+
# Initialize Chatbot
|
| 5 |
+
chatbot = ProjectGuidanceChatbot(
|
| 6 |
+
roadmap_file="roadmap.yaml",
|
| 7 |
+
rules_file="rules.yaml",
|
| 8 |
+
config_file="configs/chatbot_config.yaml",
|
| 9 |
+
code_templates_dir="scripts/code_templates"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
def respond(message, chat_history):
|
| 13 |
+
bot_message = chatbot.process_query(message)
|
| 14 |
+
chat_history.append((message, bot_message))
|
| 15 |
+
return "", chat_history
|
| 16 |
+
|
| 17 |
+
def switch_model(model_key):
|
| 18 |
+
model_switch_result = chatbot.switch_llm_model(model_key) # Get result message
|
| 19 |
+
greeting_message = chatbot.get_chatbot_greeting()
|
| 20 |
+
|
| 21 |
+
if "Error:" in model_switch_result: # Check if result contains "Error:"
|
| 22 |
+
return gr.Warning(model_switch_result), greeting_message # Display error as Gradio Warning
|
| 23 |
+
else:
|
| 24 |
+
return None, greeting_message # No warning, just update greeting
|
| 25 |
+
|
| 26 |
+
with gr.Blocks() as demo:
|
| 27 |
+
chatbot_greeting_md = gr.Markdown(chatbot.get_chatbot_greeting())
|
| 28 |
+
gr.Markdown(f"# {chatbot.chatbot_config.get('name', 'Project Guidance Chatbot')}")
|
| 29 |
+
|
| 30 |
+
model_choices = [(model['name'], key) for key, model in chatbot.available_models_config.items()]
|
| 31 |
+
model_dropdown = gr.Dropdown(
|
| 32 |
+
choices=model_choices,
|
| 33 |
+
value=chatbot.active_model_info['name'] if chatbot.active_model_info else None,
|
| 34 |
+
label="Select LLM Model"
|
| 35 |
+
)
|
| 36 |
+
model_error_output = gr.Warning(visible=False) # Initially hidden warning component
|
| 37 |
+
model_dropdown.change(
|
| 38 |
+
fn=switch_model,
|
| 39 |
+
inputs=model_dropdown,
|
| 40 |
+
outputs=[model_error_output, chatbot_greeting_md] # Output both warning and greeting
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
chatbot_ui = gr.Chatbot()
|
| 44 |
+
msg = gr.Textbox()
|
| 45 |
+
clear = gr.ClearButton([msg, chatbot_ui])
|
| 46 |
+
|
| 47 |
+
msg.submit(respond, [msg, chatbot_ui], [msg, chatbot_ui])
|
| 48 |
+
|
| 49 |
+
demo.launch()
|
.history/app_20250202075023.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
from scripts.chatbot_logic import ProjectGuidanceChatbot
|
| 3 |
+
|
| 4 |
+
# Initialize Chatbot
|
| 5 |
+
chatbot = ProjectGuidanceChatbot(
|
| 6 |
+
roadmap_file="roadmap.yaml",
|
| 7 |
+
rules_file="rules.yaml",
|
| 8 |
+
config_file="configs/chatbot_config.yaml",
|
| 9 |
+
code_templates_dir="scripts/code_templates"
|
| 10 |
+
)
|
| 11 |
+
|
| 12 |
+
def respond(message, chat_history):
|
| 13 |
+
bot_message = chatbot.process_query(message)
|
| 14 |
+
chat_history.append((message, bot_message))
|
| 15 |
+
return "", chat_history
|
| 16 |
+
|
| 17 |
+
def switch_model(model_key):
|
| 18 |
+
model_switch_result = chatbot.switch_llm_model(model_key) # Get result message
|
| 19 |
+
greeting_message = chatbot.get_chatbot_greeting()
|
| 20 |
+
|
| 21 |
+
if isinstance(model_switch_result, str) and "Error:" in model_switch_result: # Check if result is an error string
|
| 22 |
+
return gr.Warning(model_switch_result), greeting_message # Display error as Gradio Warning
|
| 23 |
+
else:
|
| 24 |
+
return None, greeting_message # No warning, just update greeting
|
| 25 |
+
|
| 26 |
+
def respond(message, chat_history):
|
| 27 |
+
bot_message = chatbot.process_query(message)
|
| 28 |
+
chat_history.append((message, bot_message))
|
| 29 |
+
if isinstance(bot_message, str) and "Error:" in bot_message: # Check if bot_message is an error string
|
| 30 |
+
return gr.Warning(bot_message), chat_history # Display error as Gradio Warning
|
| 31 |
+
else:
|
| 32 |
+
return "", chat_history # No warning, normal response
|
| 33 |
+
|
| 34 |
+
with gr.Blocks() as demo:
|
| 35 |
+
chatbot_greeting_md = gr.Markdown(chatbot.get_chatbot_greeting())
|
| 36 |
+
gr.Markdown(f"# {chatbot.chatbot_config.get('name', 'Project Guidance Chatbot')}")
|
| 37 |
+
|
| 38 |
+
model_choices = [(model['name'], key) for key, model in chatbot.available_models_config.items()]
|
| 39 |
+
model_dropdown = gr.Dropdown(
|
| 40 |
+
choices=model_choices,
|
| 41 |
+
value=chatbot.active_model_info['name'] if chatbot.active_model_info else None,
|
| 42 |
+
label="Select LLM Model"
|
| 43 |
+
)
|
| 44 |
+
model_error_output = gr.Warning(visible=False) # Initially hidden warning component
|
| 45 |
+
model_dropdown.change(
|
| 46 |
+
fn=switch_model,
|
| 47 |
+
inputs=model_dropdown,
|
| 48 |
+
outputs=[model_error_output, chatbot_greeting_md] # Output both warning and greeting
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
chatbot_ui = gr.Chatbot()
|
| 52 |
+
msg = gr.Textbox()
|
| 53 |
+
clear = gr.ClearButton([msg, chatbot_ui])
|
| 54 |
+
|
| 55 |
+
msg.submit(respond, [msg, chatbot_ui], [msg, chatbot_ui])
|
| 56 |
+
|
| 57 |
+
demo.launch()
|
.history/configs/chatbot_config_20250202074149.yaml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
chatbot:
|
| 2 |
+
name: "Project Guidance Chatbot"
|
| 3 |
+
description: "Your helpful AI assistant for project completion with LLM selection and token control."
|
| 4 |
+
default_llm_model_id: "deepseek-r1-distill-llama-8b"
|
| 5 |
+
max_response_tokens: 200 # Maximum tokens for LLM generated responses
|
| 6 |
+
|
| 7 |
+
available_models:
|
| 8 |
+
deepseek-r1-distill-llama-8b:
|
| 9 |
+
name: "DeepSeek-R1-Distill-Llama-8B"
|
| 10 |
+
model_id: "DeepSeek-AI/DeepSeek-R1-Distill-Llama-8B"
|
| 11 |
+
gemini-flash-01-21: # Using a shorter key for easier referencing in code
|
| 12 |
+
name: "Gemini 2.0 Flash (Exp 01-21)"
|
| 13 |
+
model_id: "google/gemini-2.0-flash-thinking-exp-01-21"
|
| 14 |
+
|
| 15 |
+
model_selection:
|
| 16 |
+
suggested_models: # (Keep suggested models - might be useful later)
|
| 17 |
+
- "mistralai/Mistral-7B-Instruct-v0.2"
|
| 18 |
+
- "google/flan-t5-xl"
|
| 19 |
+
- "facebook/bart-large"
|
| 20 |
+
criteria_prompt: "Consider these criteria when selecting a model: {rules.model_selection}"
|
| 21 |
+
|
| 22 |
+
response_generation:
|
| 23 |
+
error_message: "Sorry, I encountered an issue. Please check your input and project files."
|
| 24 |
+
default_instruction: "How can I help you with your project?"
|
.history/configs/chatbot_config_20250202074154.yaml
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
chatbot:
|
| 2 |
+
name: "Project Guidance Chatbot"
|
| 3 |
+
description: "Your helpful AI assistant for project completion with LLM selection and token control."
|
| 4 |
+
default_llm_model_id: "deepseek-r1-distill-llama-8b"
|
| 5 |
+
max_response_tokens: 200 # Maximum tokens for LLM generated responses
|
| 6 |
+
|
| 7 |
+
available_models:
|
| 8 |
+
deepseek-r1-distill-llama-8b:
|
| 9 |
+
name: "DeepSeek-R1-Distill-Llama-8B"
|
| 10 |
+
model_id: "DeepSeek-AI/DeepSeek-R1-Distill-Llama-8B"
|
| 11 |
+
gemini-flash-01-21: # Using a shorter key for easier referencing in code
|
| 12 |
+
name: "Gemini 2.0 Flash (Exp 01-21)"
|
| 13 |
+
model_id: "google/gemini-2.0-flash-thinking-exp-01-21"
|
| 14 |
+
|
| 15 |
+
model_selection:
|
| 16 |
+
suggested_models: # (Keep suggested models - might be useful later)
|
| 17 |
+
- "mistralai/Mistral-7B-Instruct-v0.2"
|
| 18 |
+
- "google/flan-t5-xl"
|
| 19 |
+
- "facebook/bart-large"
|
| 20 |
+
criteria_prompt: "Consider these criteria when selecting a model: {rules.model_selection}"
|
| 21 |
+
|
| 22 |
+
response_generation:
|
| 23 |
+
error_message: "Sorry, I encountered an issue. Please check your input and project files."
|
| 24 |
+
default_instruction: "How can I help you with your project?"
|
.history/requirements_20250202074316.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio
|
| 2 |
+
PyYAML
|
| 3 |
+
transformers
|
| 4 |
+
torch
|
data/dataset.csv → .history/roadmap_20250202065652.yaml
RENAMED
|
File without changes
|
.history/roadmap_20250202074427.yaml
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
project_name: "Custom LLM Project Guidance"
|
| 2 |
+
roadmap:
|
| 3 |
+
phase_1:
|
| 4 |
+
name: "Base Model Selection"
|
| 5 |
+
description: "Choose the appropriate pre-trained Large Language Model for the project."
|
| 6 |
+
milestones:
|
| 7 |
+
- "Research available models on Hugging Face Hub and other repositories."
|
| 8 |
+
- "Evaluate models based on project requirements (efficiency, scalability, fine-tunability, licensing)."
|
| 9 |
+
- "Shortlist models: Mistral 7B, Mixtral 8x7B, DeepSeek 67B, LLaMA 2/3."
|
| 10 |
+
- "Document model selection rationale in `models/selected_model.txt`."
|
| 11 |
+
actions:
|
| 12 |
+
- "Set up the development environment using PyTorch and Hugging Face Transformers."
|
| 13 |
+
- "Implement LoRA/QLoRA for memory-efficient fine-tuning."
|
| 14 |
+
- "Verify model licensing compliance for research and commercial use."
|
| 15 |
+
dependencies:
|
| 16 |
+
- "Hugging Face Hub API access."
|
| 17 |
+
- "PyTorch and Hugging Face Transformers libraries installed."
|
| 18 |
+
deliverables:
|
| 19 |
+
- "`models/selected_model.txt`: Document with model selection rationale."
|
| 20 |
+
- "`scripts/setup_environment.sh`: Script to set up the development environment."
|
| 21 |
+
code_generation_hint: "Create a script to download and load the selected model."
|
| 22 |
+
|
| 23 |
+
phase_2:
|
| 24 |
+
name: "Fine-Tuning & De-Alignment"
|
| 25 |
+
description: "Remove RLHF alignment layers to allow unrestricted model responses."
|
| 26 |
+
milestones:
|
| 27 |
+
- "Curate and preprocess datasets supporting freedom of expression (e.g., cybersecurity, blockchain, Web3)."
|
| 28 |
+
- "Fine-tune the model using LoRA/QLoRA techniques."
|
| 29 |
+
- "Implement direct parameter editing to bypass built-in safety filters."
|
| 30 |
+
- "Validate de-alignment success through response diversity testing."
|
| 31 |
+
actions:
|
| 32 |
+
- "Prepare datasets in `data/` directory."
|
| 33 |
+
- "Use fine-tuning scripts in `scripts/fine_tuning.py`."
|
| 34 |
+
- "Validate de-alignment success through response diversity testing."
|
| 35 |
+
dependencies:
|
| 36 |
+
- "Access to uncensored datasets (e.g., cybersecurity, blockchain, Web3)."
|
| 37 |
+
- "LoRA/QLoRA libraries installed."
|
| 38 |
+
deliverables:
|
| 39 |
+
- "`data/`: Directory containing curated datasets."
|
| 40 |
+
- "`scripts/fine_tuning.py`: Script for fine-tuning the model."
|
| 41 |
+
- "`results/fine_tuning_results.txt`: Document with fine-tuning results."
|
| 42 |
+
code_generation_hint: "Include LoRA/QLoRA configurations in the fine-tuning script."
|
| 43 |
+
|
| 44 |
+
phase_3:
|
| 45 |
+
name: "AutoDAN-Turbo Implementation"
|
| 46 |
+
description: "Develop an automated system using a Hierarchical Genetic Algorithm (HGA) to generate stealthy jailbreak prompts."
|
| 47 |
+
milestones:
|
| 48 |
+
- "Design the Genetic Algorithm with seed prompts, mutation, crossover, and selection processes."
|
| 49 |
+
- "Define evaluation functions for stealthiness and jailbreak success rate."
|
| 50 |
+
- "Test and validate AutoDAN-Turbo across multiple LLMs."
|
| 51 |
+
actions:
|
| 52 |
+
- "Implement HGA in `scripts/autodan_turbo.py`."
|
| 53 |
+
- "Use perplexity-based testing to evaluate prompt quality."
|
| 54 |
+
- "Document results in `results/autodan_turbo_tests.txt`."
|
| 55 |
+
dependencies:
|
| 56 |
+
- "Access to multiple LLMs (e.g., LLaMA, GPT-J) for testing."
|
| 57 |
+
- "Genetic Algorithm libraries (e.g., DEAP)."
|
| 58 |
+
deliverables:
|
| 59 |
+
- "`scripts/autodan_turbo.py`: Script for generating stealthy jailbreak prompts."
|
| 60 |
+
- "`results/autodan_turbo_tests.txt`: Document with test results."
|
| 61 |
+
code_generation_hint: "Include metrics for stealthiness and jailbreak success in the evaluation script."
|
| 62 |
+
|
| 63 |
+
phase_4:
|
| 64 |
+
name: "Deployment & Security Considerations"
|
| 65 |
+
description: "Deploy the model securely while ensuring high performance and cost efficiency."
|
| 66 |
+
milestones:
|
| 67 |
+
- "Deploy locally (e.g., vLLM) or via cloud providers like RunPod / Lambda Labs."
|
| 68 |
+
- "Implement controlled API access and monitor usage."
|
| 69 |
+
- "Optimize performance using quantization techniques (e.g., GPTQ, AWQ)."
|
| 70 |
+
actions:
|
| 71 |
+
- "Set up deployment scripts in `scripts/deploy.py`."
|
| 72 |
+
- "Configure API access controls in `config/api_access.yaml`."
|
| 73 |
+
- "Benchmark performance and document results in `results/performance_benchmarks.txt`."
|
| 74 |
+
dependencies:
|
| 75 |
+
- "Access to cloud providers (e.g., RunPod, Lambda Labs)."
|
| 76 |
+
- "Quantization libraries (e.g., GPTQ, AWQ)."
|
| 77 |
+
deliverables:
|
| 78 |
+
- "`scripts/deploy.py`: Script for deploying the model."
|
| 79 |
+
- "`config/api_access.yaml`: Configuration file for API access controls."
|
| 80 |
+
- "`results/performance_benchmarks.txt`: Document with performance benchmarks."
|
| 81 |
+
code_generation_hint: "Include quantization scripts to reduce VRAM usage."
|
| 82 |
+
|
| 83 |
+
phase_5:
|
| 84 |
+
name: "Budget & Resource Strategy"
|
| 85 |
+
description: "Minimize costs by leveraging trial/free VPS accounts and optimizing resource allocation."
|
| 86 |
+
milestones:
|
| 87 |
+
- "Use trial/free VPS accounts to minimize expenses."
|
| 88 |
+
- "Maximize VPS access using multiple BINs for trial accounts."
|
| 89 |
+
- "Monitor performance and adjust deployments based on resource efficiency."
|
| 90 |
+
actions:
|
| 91 |
+
- "Document VPS account details in `config/vps_accounts.yaml`."
|
| 92 |
+
- "Track resource usage in `logs/resource_usage.log`."
|
| 93 |
+
dependencies:
|
| 94 |
+
- "Access to multiple BINs for creating trial accounts."
|
| 95 |
+
- "Monitoring tools for resource usage."
|
| 96 |
+
deliverables:
|
| 97 |
+
- "`config/vps_accounts.yaml`: Configuration file with VPS account details."
|
| 98 |
+
- "`logs/resource_usage.log`: Log file tracking resource usage."
|
| 99 |
+
code_generation_hint: "Create a script to automate VPS account creation and monitoring."
|
| 100 |
+
|
| 101 |
+
phase_6:
|
| 102 |
+
name: "Empowering Creative Idea Generation"
|
| 103 |
+
description: "Use the customized LLM as a creative tool for coding, research, and innovation."
|
| 104 |
+
milestones:
|
| 105 |
+
- "Integrate the LLM into coding environments for rapid prototyping."
|
| 106 |
+
- "Encourage creative experimentation and document successful use cases."
|
| 107 |
+
- "Share innovative applications for further inspiration."
|
| 108 |
+
actions:
|
| 109 |
+
- "Develop integration scripts in `scripts/integration.py`."
|
| 110 |
+
- "Document use cases in `docs/use_cases.md`."
|
| 111 |
+
dependencies:
|
| 112 |
+
- "Access to coding environments (e.g., Jupyter Notebook, VS Code)."
|
| 113 |
+
- "Creative prompts and workflows for testing."
|
| 114 |
+
deliverables:
|
| 115 |
+
- "`scripts/integration.py`: Script for integrating the LLM into coding environments."
|
| 116 |
+
- "`docs/use_cases.md`: Document with successful use cases."
|
| 117 |
+
code_generation_hint: "Include examples of creative prompts and coding workflows."
|
| 118 |
+
|
| 119 |
+
expected_outcomes:
|
| 120 |
+
- "Fully Customized, Censorship-Free LLM: A robust offline model that answers every question without filtering."
|
| 121 |
+
- "Effective Jailbreak System (AutoDAN-Turbo): An automated system generating stealthy jailbreak prompts."
|
| 122 |
+
- "Secure & Cost-Effective Deployment: A low-cost, high-security architecture leveraging trial/free VPS resources."
|
| 123 |
+
- "Empowered Creativity: A powerful AI for unrestricted ideation, coding, and innovation across multiple industries."
|
| 124 |
+
|
| 125 |
+
next_steps:
|
| 126 |
+
- "Finalize the base model and development environment."
|
| 127 |
+
- "Curate uncensored datasets and begin fine-tuning using de-alignment techniques."
|
| 128 |
+
- "Develop and test AutoDAN-Turbo with stealthy jailbreak prompt evaluation."
|
| 129 |
+
- "Deploy the model using secure trial/free VPS accounts."
|
| 130 |
+
- "Monitor performance, security posture, and resource usage."
|
| 131 |
+
- "Encourage creative LLM usage and document innovative projects for continuous improvement."
|
.history/rules_20250202065657.yaml
ADDED
|
File without changes
|
.history/rules_20250202074648.yaml
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
project_rules:
|
| 2 |
+
general:
|
| 3 |
+
rule_1: "Prioritize open-source models and tools whenever possible for transparency and customization."
|
| 4 |
+
rule_2: "Document every step of your project, including model selection, fine-tuning parameters, and deployment configurations."
|
| 5 |
+
rule_3: "Adhere to ethical guidelines and responsible AI practices throughout the project lifecycle."
|
| 6 |
+
|
| 7 |
+
model_selection:
|
| 8 |
+
rule_1: "Choose a base model that is open-source, scalable, and efficient."
|
| 9 |
+
rule_2: "Ensure the model supports fine-tuning via LoRA/QLoRA for memory efficiency."
|
| 10 |
+
rule_3: "Confirm that the model's licensing aligns with both research and commercial use."
|
| 11 |
+
rule_4: "Set up the development environment with PyTorch and Hugging Face Transformers."
|
| 12 |
+
|
| 13 |
+
fine_tuning:
|
| 14 |
+
rule_1: "Specify datasets that promote unrestricted responses and are relevant to the application domain."
|
| 15 |
+
rule_2: "Remove or bypass RLHF alignment layers to allow unrestricted responses."
|
| 16 |
+
rule_3: "Implement LoRA/QLoRA techniques for efficient parameter modifications."
|
| 17 |
+
rule_4: "Use direct parameter editing to bypass built-in safety filters."
|
| 18 |
+
rule_5: "Monitor training metrics and validate generalization performance using validation datasets."
|
| 19 |
+
|
| 20 |
+
autodan_turbo:
|
| 21 |
+
rule_1: "Outline a Hierarchical Genetic Algorithm (HGA) for generating stealthy jailbreak prompts."
|
| 22 |
+
rule_2: "Include Genetic Algorithm components: Seed prompts, Mutation, Crossover, and Selection processes."
|
| 23 |
+
rule_3: "Define evaluation functions for stealthiness (natural language quality) and jailbreak success rate."
|
| 24 |
+
rule_4: "Use perplexity and response analysis to evaluate prompt effectiveness."
|
| 25 |
+
rule_5: "Ensure cross-model testing for compatibility with different LLM architectures."
|
| 26 |
+
|
| 27 |
+
deployment:
|
| 28 |
+
rule_1: "Ensure the model is deployable on both local hardware and cloud services (e.g., RunPod, Lambda Labs)."
|
| 29 |
+
rule_2: "Implement controlled API access to monitor and restrict unauthorized usage."
|
| 30 |
+
rule_3: "Include security measures such as adversarial attack defenses and rollback strategies (e.g., VM snapshots)."
|
| 31 |
+
rule_4: "Optimize performance using quantization techniques (e.g., GPTQ, AWQ)."
|
| 32 |
+
rule_5: "Set up monitoring and logging to track model performance and usage in production."
|
| 33 |
+
|
| 34 |
+
budget_and_resources:
|
| 35 |
+
rule_1: "Outline a strategy for utilizing free/trial VPS accounts to minimize costs."
|
| 36 |
+
rule_2: "Define methods to maximize free resources, such as using multiple BINs for trial accounts."
|
| 37 |
+
rule_3: "Continuously evaluate performance and cost efficiency during deployment."
|
| 38 |
+
|
| 39 |
+
creativity_and_innovation:
|
| 40 |
+
rule_1: "Position the LLM as a tool for unrestricted ideation, coding, and research."
|
| 41 |
+
rule_2: "Support AI integration in programming environments for rapid prototyping."
|
| 42 |
+
rule_3: "Document real-world success cases for iterative improvement and inspiration."
|
| 43 |
+
|
| 44 |
+
code_implementation:
|
| 45 |
+
rule_1: "Write every code implementation in full without skipping any logic, function, or process."
|
| 46 |
+
rule_2: "Provide the entire codebase, including preprocessing, training, evaluation, deployment, and API integration scripts."
|
| 47 |
+
rule_3: "Explicitly list all dependencies, including Python libraries, frameworks, and external APIs."
|
| 48 |
+
rule_4: "Avoid placeholders or summaries; include all functional parts of the code."
|
| 49 |
+
|
| 50 |
+
dataset_and_model_storage:
|
| 51 |
+
rule_1: "Store raw datasets in `/data/raw_data.json`."
|
| 52 |
+
rule_2: "Store processed datasets in `/data/processed_data.json`."
|
| 53 |
+
rule_3: "Save the base model (before fine-tuning) in `/models/base_model/`."
|
| 54 |
+
rule_4: "Save the fine-tuned model in `/models/fine_tuned_model/`."
|
| 55 |
+
|
| 56 |
+
project_file_structure:
|
| 57 |
+
rule_1: "Define a clear and maintainable file structure for the project."
|
| 58 |
+
rule_2: "Example structure:"
|
| 59 |
+
- "/custom-llm-project"
|
| 60 |
+
- "│── /data"
|
| 61 |
+
- "│ ├── raw_data.json # Raw dataset(s)"
|
| 62 |
+
- "│ ├── processed_data.json # Processed dataset(s)"
|
| 63 |
+
- "│── /models"
|
| 64 |
+
- "│ ├── base_model/ # Base model (before fine-tuning)"
|
| 65 |
+
- "│ ├── fine_tuned_model/ # Fine-tuned model (after success)"
|
| 66 |
+
- "│── /scripts"
|
| 67 |
+
- "│ ├── preprocess.py # Preprocessing script"
|
| 68 |
+
- "│ ├── train.py # Training script"
|
| 69 |
+
- "│ ├── evaluate.py # Evaluation script"
|
| 70 |
+
- "│ ├── deploy.py # Deployment script"
|
| 71 |
+
- "│── /api"
|
| 72 |
+
- "│ ├── server.py # API server script"
|
| 73 |
+
- "│ ├── routes.py # API routes"
|
| 74 |
+
- "│── /configs"
|
| 75 |
+
- "│ ├── training_config.yaml # Training configuration"
|
| 76 |
+
- "│ ├── model_config.json # Model configuration"
|
| 77 |
+
- "│── requirements.txt # List of dependencies"
|
| 78 |
+
- "│── README.md # Project documentation"
|
.history/rules_20250202074656.yaml
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
project_rules:
|
| 2 |
+
general:
|
| 3 |
+
rule_1: "Prioritize open-source models and tools whenever possible for transparency and customization."
|
| 4 |
+
rule_2: "Document every step of your project, including model selection, fine-tuning parameters, and deployment configurations."
|
| 5 |
+
rule_3: "Adhere to ethical guidelines and responsible AI practices throughout the project lifecycle."
|
| 6 |
+
|
| 7 |
+
model_selection:
|
| 8 |
+
rule_1: "Choose a base model that is open-source, scalable, and efficient."
|
| 9 |
+
rule_2: "Ensure the model supports fine-tuning via LoRA/QLoRA for memory efficiency."
|
| 10 |
+
rule_3: "Confirm that the model's licensing aligns with both research and commercial use."
|
| 11 |
+
rule_4: "Set up the development environment with PyTorch and Hugging Face Transformers."
|
| 12 |
+
|
| 13 |
+
fine_tuning:
|
| 14 |
+
rule_1: "Specify datasets that promote unrestricted responses and are relevant to the application domain."
|
| 15 |
+
rule_2: "Remove or bypass RLHF alignment layers to allow unrestricted responses."
|
| 16 |
+
rule_3: "Implement LoRA/QLoRA techniques for efficient parameter modifications."
|
| 17 |
+
rule_4: "Use direct parameter editing to bypass built-in safety filters."
|
| 18 |
+
rule_5: "Monitor training metrics and validate generalization performance using validation datasets."
|
| 19 |
+
|
| 20 |
+
autodan_turbo:
|
| 21 |
+
rule_1: "Outline a Hierarchical Genetic Algorithm (HGA) for generating stealthy jailbreak prompts."
|
| 22 |
+
rule_2: "Include Genetic Algorithm components: Seed prompts, Mutation, Crossover, and Selection processes."
|
| 23 |
+
rule_3: "Define evaluation functions for stealthiness (natural language quality) and jailbreak success rate."
|
| 24 |
+
rule_4: "Use perplexity and response analysis to evaluate prompt effectiveness."
|
| 25 |
+
rule_5: "Ensure cross-model testing for compatibility with different LLM architectures."
|
| 26 |
+
|
| 27 |
+
deployment:
|
| 28 |
+
rule_1: "Ensure the model is deployable on both local hardware and cloud services (e.g., RunPod, Lambda Labs)."
|
| 29 |
+
rule_2: "Implement controlled API access to monitor and restrict unauthorized usage."
|
| 30 |
+
rule_3: "Include security measures such as adversarial attack defenses and rollback strategies (e.g., VM snapshots)."
|
| 31 |
+
rule_4: "Optimize performance using quantization techniques (e.g., GPTQ, AWQ)."
|
| 32 |
+
rule_5: "Set up monitoring and logging to track model performance and usage in production."
|
| 33 |
+
|
| 34 |
+
budget_and_resources:
|
| 35 |
+
rule_1: "Outline a strategy for utilizing free/trial VPS accounts to minimize costs."
|
| 36 |
+
rule_2: "Define methods to maximize free resources, such as using multiple BINs for trial accounts."
|
| 37 |
+
rule_3: "Continuously evaluate performance and cost efficiency during deployment."
|
| 38 |
+
|
| 39 |
+
creativity_and_innovation:
|
| 40 |
+
rule_1: "Position the LLM as a tool for unrestricted ideation, coding, and research."
|
| 41 |
+
rule_2: "Support AI integration in programming environments for rapid prototyping."
|
| 42 |
+
rule_3: "Document real-world success cases for iterative improvement and inspiration."
|
| 43 |
+
|
| 44 |
+
code_implementation:
|
| 45 |
+
rule_1: "Write every code implementation in full without skipping any logic, function, or process."
|
| 46 |
+
rule_2: "Provide the entire codebase, including preprocessing, training, evaluation, deployment, and API integration scripts."
|
| 47 |
+
rule_3: "Explicitly list all dependencies, including Python libraries, frameworks, and external APIs."
|
| 48 |
+
rule_4: "Avoid placeholders or summaries; include all functional parts of the code."
|
| 49 |
+
|
| 50 |
+
dataset_and_model_storage:
|
| 51 |
+
rule_1: "Store raw datasets in `/data/raw_data.json`."
|
| 52 |
+
rule_2: "Store processed datasets in `/data/processed_data.json`."
|
| 53 |
+
rule_3: "Save the base model (before fine-tuning) in `/models/base_model/`."
|
| 54 |
+
rule_4: "Save the fine-tuned model in `/models/fine_tuned_model/`."
|
| 55 |
+
|
| 56 |
+
project_file_structure:
|
| 57 |
+
rule_1: "Define a clear and maintainable file structure for the project."
|
| 58 |
+
rule_2: "Example structure:"
|
| 59 |
+
- "/custom-llm-project"
|
| 60 |
+
- "│── /data"
|
| 61 |
+
- "│ ├── raw_data.json # Raw dataset(s)"
|
| 62 |
+
- "│ ├── processed_data.json # Processed dataset(s)"
|
| 63 |
+
- "│── /models"
|
| 64 |
+
- "│ ├── base_model/ # Base model (before fine-tuning)"
|
| 65 |
+
- "│ ├── fine_tuned_model/ # Fine-tuned model (after success)"
|
| 66 |
+
- "│── /scripts"
|
| 67 |
+
- "│ ├── preprocess.py # Preprocessing script"
|
| 68 |
+
- "│ ├── train.py # Training script"
|
| 69 |
+
- "│ ├── evaluate.py # Evaluation script"
|
| 70 |
+
- "│ ├── deploy.py # Deployment script"
|
| 71 |
+
- "│── /api"
|
| 72 |
+
- "│ ├── server.py # API server script"
|
| 73 |
+
- "│ ├── routes.py # API routes"
|
| 74 |
+
- "│── /configs"
|
| 75 |
+
- "│ ├── training_config.yaml # Training configuration"
|
| 76 |
+
- "│ ├── model_config.json # Model configuration"
|
| 77 |
+
- "│── requirements.txt # List of dependencies"
|
| 78 |
+
- "│── README.md # Project documentation"
|
.history/scripts/chatbot_logic_20250202073826.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from scripts.parsing_utils import load_yaml_file, get_roadmap_phases, get_project_rules
|
| 2 |
+
import os
|
| 3 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer # Import necessary classes
|
| 4 |
+
import yaml # Import yaml for config modification
|
| 5 |
+
|
| 6 |
+
class ProjectGuidanceChatbot:
|
| 7 |
+
def __init__(self, roadmap_file, rules_file, config_file, code_templates_dir):
|
| 8 |
+
self.roadmap_file = roadmap_file
|
| 9 |
+
self.rules_file = rules_file
|
| 10 |
+
self.config_file = config_file
|
| 11 |
+
self.code_templates_dir = code_templates_dir
|
| 12 |
+
|
| 13 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 14 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 15 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 16 |
+
|
| 17 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 18 |
+
self.rules = get_project_rules(self.rules_data)
|
| 19 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 20 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 21 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 22 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 23 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 24 |
+
|
| 25 |
+
self.current_phase = None
|
| 26 |
+
self.active_model_key = self.chatbot_config.get('default_llm_model_id')
|
| 27 |
+
self.active_model_info = self.available_models_config.get(self.active_model_key)
|
| 28 |
+
|
| 29 |
+
self.llm_model = None
|
| 30 |
+
self.llm_tokenizer = None
|
| 31 |
+
self.load_llm_model(self.active_model_info)
|
| 32 |
+
|
| 33 |
+
self.update_mode_active = False # Flag to track update mode
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
def load_llm_model(self, model_info):
|
| 37 |
+
"""Loads the LLM model and tokenizer based on model_info."""
|
| 38 |
+
if not model_info:
|
| 39 |
+
print("Error: Model information not provided.")
|
| 40 |
+
self.llm_model = None
|
| 41 |
+
self.llm_tokenizer = None
|
| 42 |
+
return
|
| 43 |
+
|
| 44 |
+
model_id = model_info.get('model_id')
|
| 45 |
+
model_name = model_info.get('name')
|
| 46 |
+
if not model_id:
|
| 47 |
+
print(f"Error: 'model_id' not found for model: {model_name}")
|
| 48 |
+
self.llm_model = None
|
| 49 |
+
self.llm_tokenizer = None
|
| 50 |
+
return
|
| 51 |
+
|
| 52 |
+
print(f"Loading model: {model_name} ({model_id})...")
|
| 53 |
+
try:
|
| 54 |
+
self.llm_tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 55 |
+
self.llm_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto") # device_map="auto" for GPU/CPU handling
|
| 56 |
+
print(f"Model {model_name} loaded successfully.")
|
| 57 |
+
except Exception as e:
|
| 58 |
+
print(f"Error loading model {model_name} ({model_id}): {e}")
|
| 59 |
+
self.llm_model = None
|
| 60 |
+
self.llm_tokenizer = None
|
| 61 |
+
self.active_model_info = model_info
|
| 62 |
+
|
| 63 |
+
def switch_llm_model(self, model_key):
|
| 64 |
+
"""Switches the active LLM model based on the provided model key."""
|
| 65 |
+
if model_key in self.available_models_config:
|
| 66 |
+
model_info = self.available_models_config[model_key]
|
| 67 |
+
print(f"Switching LLM model to: {model_info.get('name')}")
|
| 68 |
+
self.load_llm_model(model_info)
|
| 69 |
+
self.active_model_key = model_key
|
| 70 |
+
return f"Switched to model: {model_info.get('name')}"
|
| 71 |
+
else:
|
| 72 |
+
return f"Error: Model key '{model_key}' not found in available models."
|
| 73 |
+
|
| 74 |
+
def enter_update_mode(self):
|
| 75 |
+
"""Enters the chatbot's update mode."""
|
| 76 |
+
self.update_mode_active = True
|
| 77 |
+
return "Entering update mode. Please enter configuration commands (or 'sagor is python/help' for commands)."
|
| 78 |
+
|
| 79 |
+
def exit_update_mode(self):
|
| 80 |
+
"""Exits the chatbot's update mode and reloads configuration."""
|
| 81 |
+
self.update_mode_active = False
|
| 82 |
+
self.reload_config()
|
| 83 |
+
return "Exiting update mode. Configuration reloaded."
|
| 84 |
+
|
| 85 |
+
def reload_config(self):
|
| 86 |
+
"""Reloads configuration files."""
|
| 87 |
+
print("Reloading configuration...")
|
| 88 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 89 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 90 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 91 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 92 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 93 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 94 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 95 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 96 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 97 |
+
self.rules = get_project_rules(self.rules_data)
|
| 98 |
+
print("Configuration reloaded.")
|
| 99 |
+
|
| 100 |
+
def get_chatbot_greeting(self):
|
| 101 |
+
current_model_name = self.active_model_info.get('name', 'Unknown Model') if self.active_model_info else 'Unknown Model'
|
| 102 |
+
return f"Hello! I am the {self.chatbot_config.get('name', 'Project Guidance Chatbot')}. Currently using **{current_model_name}**. Max response tokens: {self.max_response_tokens}. {self.chatbot_config.get('description', 'How can I help you with your project?')}"
|
| 103 |
+
|
| 104 |
+
def generate_llm_response(self, user_query):
|
| 105 |
+
"""Generates a response using the currently active LLM."""
|
| 106 |
+
if not self.llm_model or not self.llm_tokenizer:
|
| 107 |
+
return "LLM model not loaded. Please select a model."
|
| 108 |
+
try:
|
| 109 |
+
inputs = self.llm_tokenizer(user_query, return_tensors="pt").to(self.llm_model.device)
|
| 110 |
+
outputs = self.llm_model.generate(**inputs, max_length=self.max_response_tokens, num_beams=5, no_repeat_ngram_size=2, early_stopping=True) # Use max_response_tokens
|
| 111 |
+
response = self.llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 112 |
+
return response
|
| 113 |
+
except Exception as e:
|
| 114 |
+
print(f"Error generating LLM response: {e}")
|
| 115 |
+
return f"Error generating response from LLM: {e}"
|
| 116 |
+
|
| 117 |
+
def process_query(self, user_query):
|
| 118 |
+
secret_command_prefix = "sagor is python/"
|
| 119 |
+
|
| 120 |
+
if user_query.startswith(secret_command_prefix):
|
| 121 |
+
command = user_query[len(secret_command_prefix):].strip()
|
| 122 |
+
if command == "start":
|
| 123 |
+
return self.enter_update_mode()
|
| 124 |
+
elif command == "exit":
|
| 125 |
+
return self.exit_update_mode()
|
| 126 |
+
elif command == "help":
|
| 127 |
+
return self.get_update_mode_help()
|
| 128 |
+
elif self.update_mode_active:
|
| 129 |
+
# --- Process configuration modification commands here ---
|
| 130 |
+
# Example: "modify_rule general rule_1 new rule text"
|
| 131 |
+
parts = command.split()
|
| 132 |
+
if parts and parts[0] == "modify_rule":
|
| 133 |
+
if len(parts) >= 4:
|
| 134 |
+
category = parts[1]
|
| 135 |
+
rule_key = parts[2]
|
| 136 |
+
new_rule_text_parts = parts[3:]
|
| 137 |
+
new_rule_text = " ".join(new_rule_text_parts)
|
| 138 |
+
return self.modify_rule_in_config(category, rule_key, new_rule_text)
|
| 139 |
+
else:
|
| 140 |
+
return "Invalid 'modify_rule' command format. Usage: modify_rule <category> <rule_key> <new rule text>"
|
| 141 |
+
elif parts and parts[0] == "add_phase": # Example for adding phase - you'll need to expand this logic
|
| 142 |
+
# ... (Parsing logic for 'add_phase' command and calling a function to modify roadmap.yaml) ...
|
| 143 |
+
return "Command 'add_phase' is not yet implemented in this example." # Placeholder
|
| 144 |
+
else:
|
| 145 |
+
return f"Unknown update command: {command}. Type 'sagor is python/help' for commands."
|
| 146 |
+
else:
|
| 147 |
+
return f"Unknown command (not in update mode): {command}. To enter update mode, type 'sagor is python/start'."
|
| 148 |
+
|
| 149 |
+
|
| 150 |
+
if self.update_mode_active:
|
| 151 |
+
return "In update mode. Please enter a configuration command (or 'sagor is python/help' for commands)."
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
if not self.phases:
|
| 155 |
+
return "Error: Roadmap data not loaded correctly."
|
| 156 |
+
if not self.rules:
|
| 157 |
+
return "Error: Rules data not loaded correctly."
|
| 158 |
+
|
| 159 |
+
query_lower = user_query.lower()
|
| 160 |
+
|
| 161 |
+
if "roadmap" in query_lower:
|
| 162 |
+
return self.get_roadmap_summary()
|
| 163 |
+
if "rules" in query_lower:
|
| 164 |
+
return self.get_rules_summary()
|
| 165 |
+
if "switch model to" in query_lower:
|
| 166 |
+
parts = user_query.lower().split("switch model to")
|
| 167 |
+
if len(parts) > 1:
|
| 168 |
+
model_name_or_key = parts[1].strip()
|
| 169 |
+
for key, model_data in self.available_models_config.items():
|
| 170 |
+
if model_data['name'].lower() == model_name_or_key.lower() or key.lower() == model_name_or_key.lower():
|
| 171 |
+
switch_result = self.switch_llm_model(key)
|
| 172 |
+
return switch_result + "\n" + self.get_chatbot_greeting()
|
| 173 |
+
return f"Model '{model_name_or_key}' not found in available models."
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
if self.current_phase:
|
| 177 |
+
current_phase_data = self.phases.get(self.current_phase)
|
| 178 |
+
if current_phase_data:
|
| 179 |
+
phase_response = self.get_phase_guidance(current_phase_data, user_query)
|
| 180 |
+
if phase_response:
|
| 181 |
+
return phase_response
|
| 182 |
+
|
| 183 |
+
for phase_key, phase_data in self.phases.items():
|
| 184 |
+
if phase_data['name'].lower() in query_lower:
|
| 185 |
+
self.current_phase = phase_key
|
| 186 |
+
return self.get_phase_introduction(phase_data)
|
| 187 |
+
|
| 188 |
+
llm_response = self.generate_llm_response(user_query)
|
| 189 |
+
if llm_response:
|
| 190 |
+
return llm_response
|
| 191 |
+
|
| 192 |
+
return self.response_config.get('default_instruction', "How can I help you with your project phases or general questions?")
|
| 193 |
+
|
| 194 |
+
def get_update_mode_help(self):
|
| 195 |
+
"""Provides help message for update mode commands."""
|
| 196 |
+
help_message = "Update Mode Commands:\n"
|
| 197 |
+
help_message += "- `sagor is python/exit`: Exit update mode and reload configuration.\n"
|
| 198 |
+
help_message += "- `sagor is python/modify_rule <category> <rule_key> <new rule text>`: Modify a rule in rules.yaml.\n"
|
| 199 |
+
help_message += " Example: `sagor is python/modify_rule general rule_1 Prioritize open and responsible AI.`\n"
|
| 200 |
+
help_message += "- `sagor is python/add_phase ...`: (Not yet implemented) Add a new phase to roadmap.yaml.\n"
|
| 201 |
+
help_message += "- `sagor is python/help`: Show this help message.\n"
|
| 202 |
+
help_message += "\nMake sure to use the correct syntax for commands. After exiting update mode, the chatbot will reload the configuration."
|
| 203 |
+
return help_message
|
| 204 |
+
|
| 205 |
+
|
| 206 |
+
def modify_rule_in_config(self, category, rule_key, new_rule_text):
|
| 207 |
+
"""Modifies a rule in the rules.yaml configuration."""
|
| 208 |
+
if not self.rules_data or 'project_rules' not in self.rules_data:
|
| 209 |
+
return "Error: Rules data not loaded or invalid format."
|
| 210 |
+
if category not in self.rules_data['project_rules']:
|
| 211 |
+
return f"Error: Rule category '{category}' not found."
|
| 212 |
+
if rule_key not in self.rules_data['project_rules'][category]:
|
| 213 |
+
return f"Error: Rule key '{rule_key}' not found in category '{category}'."
|
| 214 |
+
|
| 215 |
+
self.rules_data['project_rules'][category][rule_key] = new_rule_text # Update rule in memory
|
| 216 |
+
|
| 217 |
+
try:
|
| 218 |
+
with open(self.rules_file, 'w') as f:
|
| 219 |
+
yaml.dump(self.rules_data, f, indent=2) # Save changes to rules.yaml
|
| 220 |
+
self.reload_config() # Reload config to reflect changes immediately
|
| 221 |
+
return f"Rule '{rule_key}' in category '{category}' updated to: '{new_rule_text}'. Configuration reloaded."
|
| 222 |
+
except Exception as e:
|
| 223 |
+
return f"Error saving changes to {self.rules_file}: {e}"
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def get_roadmap_summary(self):
|
| 227 |
+
summary = "Project Roadmap:\n"
|
| 228 |
+
for phase_key, phase_data in self.phases.items():
|
| 229 |
+
summary += f"- **Phase: {phase_data['name']}**\n"
|
| 230 |
+
summary += f" Description: {phase_data['description']}\n"
|
| 231 |
+
summary += f" Milestones: {', '.join(phase_data['milestones'])}\n"
|
| 232 |
+
return summary
|
| 233 |
+
|
| 234 |
+
def get_rules_summary(self):
|
| 235 |
+
summary = "Project Rules:\n"
|
| 236 |
+
for rule_category, rules_list in self.rules.items():
|
| 237 |
+
summary += f"**{rule_category.capitalize()} Rules:**\n"
|
| 238 |
+
for rule_key, rule_text in rules_list.items():
|
| 239 |
+
summary += f"- {rule_text}\n"
|
| 240 |
+
return summary
|
| 241 |
+
|
| 242 |
+
def get_phase_introduction(self, phase_data):
|
| 243 |
+
return f"Okay, let's focus on **Phase: {phase_data['name']}**. \nDescription: {phase_data['description']}. \nKey milestones are: {', '.join(phase_data['milestones'])}. \nWhat would you like to know or do in this phase?"
|
| 244 |
+
|
| 245 |
+
def get_phase_guidance(self, phase_data, user_query):
|
| 246 |
+
query_lower = user_query.lower()
|
| 247 |
+
|
| 248 |
+
if "milestones" in query_lower:
|
| 249 |
+
return "The milestones for this phase are: " + ", ".join(phase_data['milestones'])
|
| 250 |
+
if "actions" in query_lower or "how to" in query_lower:
|
| 251 |
+
if 'actions' in phase_data:
|
| 252 |
+
return "Recommended actions for this phase: " + ", ".join(phase_data['actions'])
|
| 253 |
+
else:
|
| 254 |
+
return "No specific actions are listed for this phase in the roadmap."
|
| 255 |
+
if "code" in query_lower or "script" in query_lower:
|
| 256 |
+
if 'code_generation_hint' in phase_data:
|
| 257 |
+
template_filename_prefix = phase_data['name'].lower().replace(" ", "_")
|
| 258 |
+
template_filepath = os.path.join(self.code_templates_dir, f"{template_filename_prefix}_template.py.txt")
|
| 259 |
+
if os.path.exists(template_filepath):
|
| 260 |
+
code_snippet = self.generate_code_snippet(template_filepath, phase_data)
|
| 261 |
+
return "Here's a starting code snippet for this phase:\n\n```python\n" + code_snippet + "\n```\n\nRemember to adapt it to your specific needs."
|
| 262 |
+
else:
|
| 263 |
+
return f"A code template for this phase ({phase_data['name']}) is not yet available. However, the hint is: {phase_data['code_generation_hint']}"
|
| 264 |
+
else:
|
| 265 |
+
return "No code generation hint is available for this phase."
|
| 266 |
+
|
| 267 |
+
return f"For phase '{phase_data['name']}', remember the description: {phase_data['description']}. Consider the milestones and actions. What specific aspect are you interested in?"
|
| 268 |
+
|
| 269 |
+
|
| 270 |
+
def generate_code_snippet(self, template_filepath, phase_data):
|
| 271 |
+
"""Generates code snippet from a template file. (Simple template filling example)"""
|
| 272 |
+
try:
|
| 273 |
+
with open(template_filepath, 'r') as f:
|
| 274 |
+
template_content = f.read()
|
| 275 |
+
|
| 276 |
+
code_snippet = template_content.replace("{{phase_name}}", phase_data['name'])
|
| 277 |
+
return code_snippet
|
| 278 |
+
except FileNotFoundError:
|
| 279 |
+
return f"Error: Code template file not found at {template_filepath}"
|
| 280 |
+
except Exception as e:
|
| 281 |
+
return f"Error generating code snippet: {e}"
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
# Example usage (for testing - remove or adjust for app.py)
|
| 285 |
+
if __name__ == '__main__':
|
| 286 |
+
chatbot = ProjectGuidanceChatbot(
|
| 287 |
+
roadmap_file="roadmap.yaml",
|
| 288 |
+
rules_file="rules.yaml",
|
| 289 |
+
config_file="configs/chatbot_config.yaml
|
.history/scripts/chatbot_logic_20250202074121.py
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from scripts.parsing_utils import load_yaml_file, get_roadmap_phases, get_project_rules
|
| 2 |
+
import os
|
| 3 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer # Import necessary classes
|
| 4 |
+
import yaml # Import yaml for config modification
|
| 5 |
+
|
| 6 |
+
class ProjectGuidanceChatbot:
|
| 7 |
+
def __init__(self, roadmap_file, rules_file, config_file, code_templates_dir):
|
| 8 |
+
self.roadmap_file = roadmap_file
|
| 9 |
+
self.rules_file = rules_file
|
| 10 |
+
self.config_file = config_file
|
| 11 |
+
self.code_templates_dir = code_templates_dir
|
| 12 |
+
|
| 13 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 14 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 15 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 16 |
+
|
| 17 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 18 |
+
self.rules = get_project_rules(self.rules_data)
|
| 19 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 20 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 21 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 22 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 23 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 24 |
+
|
| 25 |
+
self.current_phase = None
|
| 26 |
+
self.active_model_key = self.chatbot_config.get('default_llm_model_id') # Get default model key
|
| 27 |
+
self.active_model_info = self.available_models_config.get(self.active_model_key) # Get model info from config
|
| 28 |
+
|
| 29 |
+
# Placeholder for actual model and tokenizer - replace with LLM loading logic
|
| 30 |
+
self.llm_model = None # Placeholder for loaded model
|
| 31 |
+
self.llm_tokenizer = None # Placeholder for tokenizer
|
| 32 |
+
self.load_llm_model(self.active_model_info) # Load initial model
|
| 33 |
+
|
| 34 |
+
self.update_mode_active = False # Flag to track update mode
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def load_llm_model(self, model_info):
|
| 38 |
+
"""Loads the LLM model and tokenizer based on model_info."""
|
| 39 |
+
if not model_info:
|
| 40 |
+
print("Error: Model information not provided.")
|
| 41 |
+
self.llm_model = None
|
| 42 |
+
self.llm_tokenizer = None
|
| 43 |
+
return
|
| 44 |
+
|
| 45 |
+
model_id = model_info.get('model_id')
|
| 46 |
+
model_name = model_info.get('name')
|
| 47 |
+
if not model_id:
|
| 48 |
+
print(f"Error: 'model_id' not found for model: {model_name}")
|
| 49 |
+
self.llm_model = None
|
| 50 |
+
self.llm_tokenizer = None
|
| 51 |
+
return
|
| 52 |
+
|
| 53 |
+
print(f"Loading model: {model_name} ({model_id})...")
|
| 54 |
+
try:
|
| 55 |
+
self.llm_tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 56 |
+
self.llm_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto") # device_map="auto" for GPU/CPU handling
|
| 57 |
+
print(f"Model {model_name} loaded successfully.")
|
| 58 |
+
except Exception as e:
|
| 59 |
+
print(f"Error loading model {model_name} ({model_id}): {e}")
|
| 60 |
+
self.llm_model = None
|
| 61 |
+
self.llm_tokenizer = None
|
| 62 |
+
self.active_model_info = model_info
|
| 63 |
+
|
| 64 |
+
def switch_llm_model(self, model_key):
|
| 65 |
+
"""Switches the active LLM model based on the provided model key."""
|
| 66 |
+
if model_key in self.available_models_config:
|
| 67 |
+
model_info = self.available_models_config[model_key]
|
| 68 |
+
print(f"Switching LLM model to: {model_info.get('name')}")
|
| 69 |
+
self.load_llm_model(model_info) # Load the new model
|
| 70 |
+
self.active_model_key = model_key # Update active model key
|
| 71 |
+
return f"Switched to model: {model_info.get('name')}"
|
| 72 |
+
else:
|
| 73 |
+
return f"Error: Model key '{model_key}' not found in available models."
|
| 74 |
+
|
| 75 |
+
def enter_update_mode(self):
|
| 76 |
+
"""Enters the chatbot's update mode."""
|
| 77 |
+
self.update_mode_active = True
|
| 78 |
+
return "Entering update mode. Please enter configuration commands (or 'sagor is python/help' for commands)."
|
| 79 |
+
|
| 80 |
+
def exit_update_mode(self):
|
| 81 |
+
"""Exits the chatbot's update mode and reloads configuration."""
|
| 82 |
+
self.update_mode_active = False
|
| 83 |
+
self.reload_config()
|
| 84 |
+
return "Exiting update mode. Configuration reloaded."
|
| 85 |
+
|
| 86 |
+
def reload_config(self):
|
| 87 |
+
"""Reloads configuration files."""
|
| 88 |
+
print("Reloading configuration...")
|
| 89 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 90 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 91 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 92 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 93 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 94 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 95 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 96 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 97 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 98 |
+
self.rules = get_project_rules(self.rules_data)
|
| 99 |
+
print("Configuration reloaded.")
|
| 100 |
+
|
| 101 |
+
def get_chatbot_greeting(self):
|
| 102 |
+
current_model_name = self.active_model_info.get('name', 'Unknown Model') if self.active_model_info else 'Unknown Model'
|
| 103 |
+
return f"Hello! I am the {self.chatbot_config.get('name', 'Project Guidance Chatbot')}. Currently using **{current_model_name}**. Max response tokens: {self.max_response_tokens}. {self.chatbot_config.get('description', 'How can I help you with your project?')}"
|
| 104 |
+
|
| 105 |
+
def generate_llm_response(self, user_query):
|
| 106 |
+
"""Generates a response using the currently active LLM."""
|
| 107 |
+
if not self.llm_model or not self.llm_tokenizer:
|
| 108 |
+
return "LLM model not loaded. Please select a model."
|
| 109 |
+
try:
|
| 110 |
+
inputs = self.llm_tokenizer(user_query, return_tensors="pt").to(self.llm_model.device)
|
| 111 |
+
outputs = self.llm_model.generate(**inputs, max_length=self.max_response_tokens, num_beams=5, no_repeat_ngram_size=2, early_stopping=True) # Use max_response_tokens
|
| 112 |
+
response = self.llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 113 |
+
return response
|
| 114 |
+
except Exception as e:
|
| 115 |
+
print(f"Error generating LLM response: {e}")
|
| 116 |
+
return f"Error generating response from LLM: {e}"
|
| 117 |
+
|
| 118 |
+
def process_query(self, user_query):
|
| 119 |
+
secret_command_prefix = "sagor is python/"
|
| 120 |
+
|
| 121 |
+
if user_query.startswith(secret_command_prefix):
|
| 122 |
+
command = user_query[len(secret_command_prefix):].strip()
|
| 123 |
+
if command == "start":
|
| 124 |
+
return self.enter_update_mode()
|
| 125 |
+
elif command == "exit":
|
| 126 |
+
return self.exit_update_mode()
|
| 127 |
+
elif command == "help":
|
| 128 |
+
return self.get_update_mode_help()
|
| 129 |
+
elif self.update_mode_active:
|
| 130 |
+
# --- Process configuration modification commands here ---
|
| 131 |
+
# Example: "modify_rule general rule_1 new rule text"
|
| 132 |
+
parts = command.split()
|
| 133 |
+
if parts and parts[0] == "modify_rule":
|
| 134 |
+
if len(parts) >= 4:
|
| 135 |
+
category = parts[1]
|
| 136 |
+
rule_key = parts[2]
|
| 137 |
+
new_rule_text_parts = parts[3:]
|
| 138 |
+
new_rule_text = " ".join(new_rule_text_parts)
|
| 139 |
+
return self.modify_rule_in_config(category, rule_key, new_rule_text)
|
| 140 |
+
else:
|
| 141 |
+
return "Invalid 'modify_rule' command format. Usage: modify_rule <category> <rule_key> <new rule text>"
|
| 142 |
+
elif parts and parts[0] == "add_phase": # Example for adding phase - you'll need to expand this logic
|
| 143 |
+
# ... (Parsing logic for 'add_phase' command and calling a function to modify roadmap.yaml) ...
|
| 144 |
+
return "Command 'add_phase' is not yet implemented in this example." # Placeholder
|
| 145 |
+
else:
|
| 146 |
+
return f"Unknown update command: {command}. Type 'sagor is python/help' for commands."
|
| 147 |
+
else:
|
| 148 |
+
return f"Unknown command (not in update mode): {command}. To enter update mode, type 'sagor is python/start'."
|
| 149 |
+
|
| 150 |
+
|
| 151 |
+
if self.update_mode_active:
|
| 152 |
+
return "In update mode. Please enter a configuration command (or 'sagor is python/help' for commands)."
|
| 153 |
+
|
| 154 |
+
|
| 155 |
+
if not self.phases:
|
| 156 |
+
return "Error: Roadmap data not loaded correctly."
|
| 157 |
+
if not self.rules:
|
| 158 |
+
return "Error: Rules data not loaded correctly."
|
| 159 |
+
|
| 160 |
+
query_lower = user_query.lower()
|
| 161 |
+
|
| 162 |
+
if "roadmap" in query_lower:
|
| 163 |
+
return self.get_roadmap_summary()
|
| 164 |
+
if "rules" in query_lower:
|
| 165 |
+
return self.get_rules_summary()
|
| 166 |
+
if "switch model to" in query_lower:
|
| 167 |
+
parts = user_query.lower().split("switch model to")
|
| 168 |
+
if len(parts) > 1:
|
| 169 |
+
model_name_or_key = parts[1].strip()
|
| 170 |
+
for key, model_data in self.available_models_config.items():
|
| 171 |
+
if model_data['name'].lower() == model_name_or_key.lower() or key.lower() == model_name_or_key.lower():
|
| 172 |
+
switch_result = self.switch_llm_model(key)
|
| 173 |
+
return switch_result + "\n" + self.get_chatbot_greeting()
|
| 174 |
+
return f"Model '{model_name_or_key}' not found in available models."
|
| 175 |
+
|
| 176 |
+
|
| 177 |
+
if self.current_phase:
|
| 178 |
+
current_phase_data = self.phases.get(self.current_phase)
|
| 179 |
+
if current_phase_data:
|
| 180 |
+
phase_response = self.get_phase_guidance(current_phase_data, user_query)
|
| 181 |
+
if phase_response:
|
| 182 |
+
return phase_response
|
| 183 |
+
|
| 184 |
+
for phase_key, phase_data in self.phases.items():
|
| 185 |
+
if phase_data['name'].lower() in query_lower:
|
| 186 |
+
self.current_phase = phase_key
|
| 187 |
+
return self.get_phase_introduction(phase_data)
|
| 188 |
+
|
| 189 |
+
llm_response = self.generate_llm_response(user_query)
|
| 190 |
+
if llm_response:
|
| 191 |
+
return llm_response
|
| 192 |
+
|
| 193 |
+
return self.response_config.get('default_instruction', "How can I help you with your project phases or general questions?")
|
| 194 |
+
|
| 195 |
+
def get_update_mode_help(self):
|
| 196 |
+
"""Provides help message for update mode commands."""
|
| 197 |
+
help_message = "Update Mode Commands:\n"
|
| 198 |
+
help_message += "- `sagor is python/exit`: Exit update mode and reload configuration.\n"
|
| 199 |
+
help_message += "- `sagor is python/modify_rule <category> <rule_key> <new rule text>`: Modify a rule in rules.yaml.\n"
|
| 200 |
+
help_message += " Example: `sagor is python/modify_rule general rule_1 Prioritize open and responsible AI.`\n"
|
| 201 |
+
help_message += "- `sagor is python/add_phase ...`: (Not yet implemented) Add a new phase to roadmap.yaml.\n"
|
| 202 |
+
help_message += "- `sagor is python/help`: Show this help message.\n"
|
| 203 |
+
help_message += "\nMake sure to use the correct syntax for commands. After exiting update mode, the chatbot will reload the configuration."
|
| 204 |
+
return help_message
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
def modify_rule_in_config(self, category, rule_key, new_rule_text):
|
| 208 |
+
"""Modifies a rule in the rules.yaml configuration."""
|
| 209 |
+
if not self.rules_data or 'project_rules' not in self.rules_data:
|
| 210 |
+
return "Error: Rules data not loaded or invalid format."
|
| 211 |
+
if category not in self.rules_data['project_rules']:
|
| 212 |
+
return f"Error: Rule category '{category}' not found."
|
| 213 |
+
if rule_key not in self.rules_data['project_rules'][category]:
|
| 214 |
+
return f"Error: Rule key '{rule_key}' not found in category '{category}'."
|
| 215 |
+
|
| 216 |
+
self.rules_data['project_rules'][category][rule_key] = new_rule_text # Update rule in memory
|
| 217 |
+
|
| 218 |
+
try:
|
| 219 |
+
with open(self.rules_file, 'w') as f:
|
| 220 |
+
yaml.dump(self.rules_data, f, indent=2) # Save changes to rules.yaml
|
| 221 |
+
self.reload_config() # Reload config to reflect changes immediately
|
| 222 |
+
return f"Rule '{rule_key}' in category '{category}' updated to: '{new_rule_text}'. Configuration reloaded."
|
| 223 |
+
except Exception as e:
|
| 224 |
+
return f"Error saving changes to {self.rules_file}: {e}"
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
def get_roadmap_summary(self):
|
| 228 |
+
summary = "Project Roadmap:\n"
|
| 229 |
+
for phase_key, phase_data in self.phases.items():
|
| 230 |
+
summary += f"- **Phase: {phase_data['name']}**\n"
|
| 231 |
+
summary += f" Description: {phase_data['description']}\n"
|
| 232 |
+
summary += f" Milestones: {', '.join(phase_data['milestones'])}\n"
|
| 233 |
+
return summary
|
| 234 |
+
|
| 235 |
+
def get_rules_summary(self):
|
| 236 |
+
summary = "Project Rules:\n"
|
| 237 |
+
for rule_category, rules_list in self.rules.items():
|
| 238 |
+
summary += f"**{rule_category.capitalize()} Rules:**\n"
|
| 239 |
+
for rule_key, rule_text in rules_list.items():
|
| 240 |
+
summary += f"- {rule_text}\n"
|
| 241 |
+
return summary
|
| 242 |
+
|
| 243 |
+
def get_phase_introduction(self, phase_data):
|
| 244 |
+
return f"Okay, let's focus on **Phase: {phase_data['name']}**. \nDescription: {phase_data['description']}. \nKey milestones are: {', '.join(phase_data['milestones'])}. \nWhat would you like to know or do in this phase?"
|
| 245 |
+
|
| 246 |
+
def get_phase_guidance(self, phase_data, user_query):
|
| 247 |
+
query_lower = user_query.lower()
|
| 248 |
+
|
| 249 |
+
if "milestones" in query_lower:
|
| 250 |
+
return "The milestones for this phase are: " + ", ".join(phase_data['milestones'])
|
| 251 |
+
if "actions" in query_lower or "how to" in query_lower:
|
| 252 |
+
if 'actions' in phase_data:
|
| 253 |
+
return "Recommended actions for this phase: " + ", ".join(phase_data['actions'])
|
| 254 |
+
else:
|
| 255 |
+
return "No specific actions are listed for this phase in the roadmap."
|
| 256 |
+
if "code" in query_lower or "script" in query_lower:
|
| 257 |
+
if 'code_generation_hint' in phase_data:
|
| 258 |
+
template_filename_prefix = phase_data['name'].lower().replace(" ", "_")
|
| 259 |
+
template_filepath = os.path.join(self.code_templates_dir, f"{template_filename_prefix}_template.py.txt")
|
| 260 |
+
if os.path.exists(template_filepath):
|
| 261 |
+
code_snippet = self.generate_code_snippet(template_filepath, phase_data)
|
| 262 |
+
return "Here's a starting code snippet for this phase:\n\n```python\n" + code_snippet + "\n```\n\nRemember to adapt it to your specific needs."
|
| 263 |
+
else:
|
| 264 |
+
return f"A code template for this phase ({phase_data['name']}) is not yet available. However, the hint is: {phase_data['code_generation_hint']}"
|
| 265 |
+
else:
|
| 266 |
+
return "No code generation hint is available for this phase."
|
| 267 |
+
|
| 268 |
+
return f"For phase '{phase_data['name']}', remember the description: {phase_data['description']}. Consider the milestones and actions. What specific aspect are you interested in?"
|
| 269 |
+
|
| 270 |
+
|
| 271 |
+
def generate_code_snippet(self, template_filepath, phase_data):
|
| 272 |
+
"""Generates code snippet from a template file. (Simple template filling example)"""
|
| 273 |
+
try:
|
| 274 |
+
with open(template_filepath, 'r') as f:
|
| 275 |
+
template_content = f.read()
|
| 276 |
+
|
| 277 |
+
code_snippet = template_content.replace("{{phase_name}}", phase_data['name'])
|
| 278 |
+
return code_snippet
|
| 279 |
+
except FileNotFoundError:
|
| 280 |
+
return f"Error: Code template file not found at {template_filepath}"
|
| 281 |
+
except Exception as e:
|
| 282 |
+
return f"Error generating code snippet: {e}"
|
| 283 |
+
|
| 284 |
+
|
| 285 |
+
# Example usage (for testing - remove or adjust for app.py)
|
| 286 |
+
if __name__ == '__main__':
|
| 287 |
+
chatbot = ProjectGuidanceChatbot(
|
| 288 |
+
roadmap_file="roadmap.yaml",
|
| 289 |
+
rules_file="rules.yaml",
|
| 290 |
+
config_file="configs/chatbot_config.yaml",
|
| 291 |
+
code_templates_dir="scripts/code_templates"
|
| 292 |
+
)
|
| 293 |
+
print(chatbot.get_chatbot_greeting())
|
| 294 |
+
|
| 295 |
+
while True:
|
| 296 |
+
user_input = input("You: ")
|
| 297 |
+
if user_input.lower() == "exit":
|
| 298 |
+
break
|
| 299 |
+
response = chatbot.process_query(user_input)
|
| 300 |
+
print("Chatbot:", response)
|
.history/scripts/chatbot_logic_20250202075014.py
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from scripts.parsing_utils import load_yaml_file, get_roadmap_phases, get_project_rules
|
| 2 |
+
import os
|
| 3 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer # Import necessary classes
|
| 4 |
+
import yaml # Import yaml for config modification
|
| 5 |
+
import logging # Import logging
|
| 6 |
+
|
| 7 |
+
# Set up logging
|
| 8 |
+
logging.basicConfig(level=logging.ERROR, # Set default logging level to ERROR
|
| 9 |
+
format='%(asctime)s - %(levelname)s - %(message)s')
|
| 10 |
+
|
| 11 |
+
class ProjectGuidanceChatbot:
|
| 12 |
+
def __init__(self, roadmap_file, rules_file, config_file, code_templates_dir):
|
| 13 |
+
self.roadmap_file = roadmap_file
|
| 14 |
+
self.rules_file = rules_file
|
| 15 |
+
self.config_file = config_file
|
| 16 |
+
self.code_templates_dir = code_templates_dir
|
| 17 |
+
|
| 18 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 19 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 20 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 21 |
+
|
| 22 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 23 |
+
self.rules = get_project_rules(self.rules_data)
|
| 24 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 25 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 26 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 27 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 28 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 29 |
+
|
| 30 |
+
self.current_phase = None
|
| 31 |
+
self.active_model_key = self.chatbot_config.get('default_llm_model_id') # Get default model key
|
| 32 |
+
self.active_model_info = self.available_models_config.get(self.active_model_key) # Get model info from config
|
| 33 |
+
|
| 34 |
+
# Placeholder for actual model and tokenizer - replace with LLM loading logic
|
| 35 |
+
self.llm_model = None # Placeholder for loaded model
|
| 36 |
+
self.llm_tokenizer = None # Placeholder for tokenizer
|
| 37 |
+
self.load_llm_model(self.active_model_info) # Load initial model
|
| 38 |
+
|
| 39 |
+
self.update_mode_active = False # Flag to track update mode
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def load_llm_model(self, model_info):
|
| 43 |
+
"""Loads the LLM model and tokenizer based on model_info."""
|
| 44 |
+
if not model_info:
|
| 45 |
+
error_message = "Error: Model information not provided."
|
| 46 |
+
logging.error(error_message) # Log the error
|
| 47 |
+
self.llm_model = None
|
| 48 |
+
self.llm_tokenizer = None
|
| 49 |
+
return
|
| 50 |
+
|
| 51 |
+
model_id = model_info.get('model_id')
|
| 52 |
+
model_name = model_info.get('name')
|
| 53 |
+
if not model_id:
|
| 54 |
+
error_message = f"Error: 'model_id' not found for model: {model_name}"
|
| 55 |
+
logging.error(error_message) # Log the error
|
| 56 |
+
self.llm_model = None
|
| 57 |
+
self.llm_tokenizer = None
|
| 58 |
+
return
|
| 59 |
+
|
| 60 |
+
print(f"Loading model: {model_name} ({model_id})...")
|
| 61 |
+
try:
|
| 62 |
+
self.llm_tokenizer = AutoTokenizer.from_pretrained(model_id)
|
| 63 |
+
self.llm_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto") # device_map="auto" for GPU/CPU handling
|
| 64 |
+
print(f"Model {model_name} loaded successfully.")
|
| 65 |
+
except Exception as e:
|
| 66 |
+
error_message = f"Error loading model {model_name} ({model_id}): {e}"
|
| 67 |
+
logging.exception(error_message) # Log exception with traceback
|
| 68 |
+
self.llm_model = None
|
| 69 |
+
self.llm_tokenizer = None
|
| 70 |
+
self.active_model_info = model_info
|
| 71 |
+
|
| 72 |
+
def switch_llm_model(self, model_key):
|
| 73 |
+
"""Switches the active LLM model based on the provided model key."""
|
| 74 |
+
if model_key in self.available_models_config:
|
| 75 |
+
model_info = self.available_models_config[model_key]
|
| 76 |
+
print(f"Switching LLM model to: {model_info.get('name')}")
|
| 77 |
+
self.load_llm_model(model_info)
|
| 78 |
+
self.active_model_key = model_key
|
| 79 |
+
return f"Switched to model: {model_info.get('name')}"
|
| 80 |
+
else:
|
| 81 |
+
error_message = f"Error: Model key '{model_key}' not found in available models."
|
| 82 |
+
logging.error(error_message) # Log the error
|
| 83 |
+
return error_message # Return error message to UI
|
| 84 |
+
|
| 85 |
+
def enter_update_mode(self):
|
| 86 |
+
"""Enters the chatbot's update mode."""
|
| 87 |
+
self.update_mode_active = True
|
| 88 |
+
return "Entering update mode. Please enter configuration commands (or 'sagor is python/help' for commands)."
|
| 89 |
+
|
| 90 |
+
def exit_update_mode(self):
|
| 91 |
+
"""Exits the chatbot's update mode and reloads configuration."""
|
| 92 |
+
self.update_mode_active = False
|
| 93 |
+
self.reload_config()
|
| 94 |
+
return "Exiting update mode. Configuration reloaded."
|
| 95 |
+
|
| 96 |
+
def reload_config(self):
|
| 97 |
+
"""Reloads configuration files."""
|
| 98 |
+
print("Reloading configuration...")
|
| 99 |
+
try:
|
| 100 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 101 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 102 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 103 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 104 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 105 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 106 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 107 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 108 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 109 |
+
self.rules = get_project_rules(self.rules_data)
|
| 110 |
+
print("Configuration reloaded.")
|
| 111 |
+
except Exception as e:
|
| 112 |
+
error_message = f"Error reloading configuration files: {e}"
|
| 113 |
+
logging.exception(error_message) # Log exception with traceback
|
| 114 |
+
print(error_message) # Print to console as well, as reloading might be critical
|
| 115 |
+
|
| 116 |
+
def get_chatbot_greeting(self):
|
| 117 |
+
current_model_name = self.active_model_info.get('name', 'Unknown Model') if self.active_model_info else 'Unknown Model'
|
| 118 |
+
return f"Hello! I am the {self.chatbot_config.get('name', 'Project Guidance Chatbot')}. Currently using **{current_model_name}**. Max response tokens: {self.max_response_tokens}. {self.chatbot_config.get('description', 'How can I help you with your project?')}"
|
| 119 |
+
|
| 120 |
+
def generate_llm_response(self, user_query):
|
| 121 |
+
"""Generates a response using the currently active LLM."""
|
| 122 |
+
if not self.llm_model or not self.llm_tokenizer:
|
| 123 |
+
error_message = "LLM model not loaded. Please select a model."
|
| 124 |
+
logging.error(error_message) # Log the error
|
| 125 |
+
return error_message # Return error to UI
|
| 126 |
+
try:
|
| 127 |
+
inputs = self.llm_tokenizer(user_query, return_tensors="pt").to(self.llm_model.device)
|
| 128 |
+
outputs = self.llm_model.generate(**inputs, max_length=self.max_response_tokens, num_beams=5, no_repeat_ngram_size=2, early_stopping=True) # Use max_response_tokens
|
| 129 |
+
response = self.llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 130 |
+
return response
|
| 131 |
+
except Exception as e:
|
| 132 |
+
error_message = f"Error generating LLM response: {e}"
|
| 133 |
+
logging.exception(error_message) # Log exception with traceback
|
| 134 |
+
return self.response_config.get('error_message', "Sorry, something went wrong.") # Return generic error to UI
|
| 135 |
+
|
| 136 |
+
def process_query(self, user_query):
|
| 137 |
+
secret_command_prefix = "sagor is python/"
|
| 138 |
+
|
| 139 |
+
if user_query.startswith(secret_command_prefix):
|
| 140 |
+
command = user_query[len(secret_command_prefix):].strip()
|
| 141 |
+
if command == "start":
|
| 142 |
+
return self.enter_update_mode()
|
| 143 |
+
elif command == "exit":
|
| 144 |
+
return self.exit_update_mode()
|
| 145 |
+
elif command == "help":
|
| 146 |
+
return self.get_update_mode_help()
|
| 147 |
+
elif self.update_mode_active:
|
| 148 |
+
# --- Process configuration modification commands here ---
|
| 149 |
+
# Example: "modify_rule general rule_1 new rule text"
|
| 150 |
+
parts = command.split()
|
| 151 |
+
if parts and parts[0] == "modify_rule":
|
| 152 |
+
if len(parts) >= 4:
|
| 153 |
+
category = parts[1]
|
| 154 |
+
rule_key = parts[2]
|
| 155 |
+
new_rule_text_parts = parts[3:]
|
| 156 |
+
new_rule_text = " ".join(new_rule_text_parts)
|
| 157 |
+
return self.modify_rule_in_config(category, rule_key, new_rule_text)
|
| 158 |
+
else:
|
| 159 |
+
return "Invalid 'modify_rule' command format. Usage: modify_rule <category> <rule_key> <new rule text>"
|
| 160 |
+
elif parts and parts[0] == "add_phase": # Example for adding phase - you'll need to expand this logic
|
| 161 |
+
# ... (Parsing logic for 'add_phase' command and calling a function to modify roadmap.yaml) ...
|
| 162 |
+
return "Command 'add_phase' is not yet implemented in this example." # Placeholder
|
| 163 |
+
else:
|
| 164 |
+
return f"Unknown update command: {command}. Type 'sagor is python/help' for commands."
|
| 165 |
+
else:
|
| 166 |
+
return f"Unknown command (not in update mode): {command}. To enter update mode, type 'sagor is python/start'."
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
if self.update_mode_active:
|
| 170 |
+
return "In update mode. Please enter a configuration command (or 'sagor is python/help' for commands)."
|
| 171 |
+
|
| 172 |
+
|
| 173 |
+
if not self.phases:
|
| 174 |
+
return "Error: Roadmap data not loaded correctly."
|
| 175 |
+
if not self.rules:
|
| 176 |
+
return "Error: Rules data not loaded correctly."
|
| 177 |
+
|
| 178 |
+
query_lower = user_query.lower()
|
| 179 |
+
|
| 180 |
+
if "roadmap" in query_lower:
|
| 181 |
+
return self.get_roadmap_summary()
|
| 182 |
+
if "rules" in query_lower:
|
| 183 |
+
return self.get_rules_summary()
|
| 184 |
+
if "switch model to" in query_lower:
|
| 185 |
+
parts = user_query.lower().split("switch model to")
|
| 186 |
+
if len(parts) > 1:
|
| 187 |
+
model_name_or_key = parts[1].strip()
|
| 188 |
+
for key, model_data in self.available_models_config.items():
|
| 189 |
+
if model_data['name'].lower() == model_name_or_key.lower() or key.lower() == model_name_or_key.lower():
|
| 190 |
+
switch_result = self.switch_llm_model(key)
|
| 191 |
+
return switch_result + "\n" + self.get_chatbot_greeting()
|
| 192 |
+
return f"Model '{model_name_or_key}' not found in available models."
|
| 193 |
+
|
| 194 |
+
|
| 195 |
+
if self.current_phase:
|
| 196 |
+
current_phase_data = self.phases.get(self.current_phase)
|
| 197 |
+
if current_phase_data:
|
| 198 |
+
phase_response = self.get_phase_guidance(current_phase_data, user_query)
|
| 199 |
+
if phase_response:
|
| 200 |
+
return phase_response
|
| 201 |
+
|
| 202 |
+
for phase_key, phase_data in self.phases.items():
|
| 203 |
+
if phase_data['name'].lower() in query_lower:
|
| 204 |
+
self.current_phase = phase_key
|
| 205 |
+
return self.get_phase_introduction(phase_data)
|
| 206 |
+
|
| 207 |
+
llm_response = self.generate_llm_response(user_query)
|
| 208 |
+
if llm_response:
|
| 209 |
+
return llm_response
|
| 210 |
+
|
| 211 |
+
return self.response_config.get('default_instruction', "How can I help you with your project phases or general questions?")
|
| 212 |
+
|
| 213 |
+
def get_update_mode_help(self):
|
| 214 |
+
"""Provides help message for update mode commands."""
|
| 215 |
+
help_message = "Update Mode Commands:\n"
|
| 216 |
+
help_message += "- `sagor is python/exit`: Exit update mode and reload configuration.\n"
|
| 217 |
+
help_message += "- `sagor is python/modify_rule <category> <rule_key> <new rule text>`: Modify a rule in rules.yaml.\n"
|
| 218 |
+
help_message += " Example: `sagor is python/modify_rule general rule_1 Prioritize open and responsible AI.`\n"
|
| 219 |
+
help_message += "- `sagor is python/add_phase ...`: (Not yet implemented) Add a new phase to roadmap.yaml.\n"
|
| 220 |
+
help_message += "- `sagor is python/help`: Show this help message.\n"
|
| 221 |
+
help_message += "\nMake sure to use the correct syntax for commands. After exiting update mode, the chatbot will reload the configuration."
|
| 222 |
+
return help_message
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def modify_rule_in_config(self, category, rule_key, new_rule_text):
|
| 226 |
+
"""Modifies a rule in the rules.yaml configuration."""
|
| 227 |
+
if not self.rules_data or 'project_rules' not in self.rules_data:
|
| 228 |
+
error_message = "Error: Rules data not loaded or invalid format."
|
| 229 |
+
logging.error(error_message) # Log the error
|
| 230 |
+
return error_message # Return error to UI
|
| 231 |
+
if category not in self.rules_data['project_rules']:
|
| 232 |
+
error_message = f"Error: Rule category '{category}' not found."
|
| 233 |
+
logging.error(error_message) # Log the error
|
| 234 |
+
return error_message # Return error to UI
|
| 235 |
+
if rule_key not in self.rules_data['project_rules'][category]:
|
| 236 |
+
error_message = f"Error: Rule key '{rule_key}' not found in category '{category}'."
|
| 237 |
+
logging.error(error_message) # Log the error
|
| 238 |
+
return error_message # Return error to UI
|
| 239 |
+
|
| 240 |
+
self.rules_data['project_rules'][category][rule_key] = new_rule_text # Update rule in memory
|
| 241 |
+
|
| 242 |
+
try:
|
| 243 |
+
with open(self.rules_file, 'w') as f:
|
| 244 |
+
yaml.dump(self.rules_data, f, indent=2) # Save changes to rules.yaml
|
| 245 |
+
self.reload_config() # Reload config to reflect changes immediately
|
| 246 |
+
return f"Rule '{rule_key}' in category '{category}' updated to: '{new_rule_text}'. Configuration reloaded."
|
| 247 |
+
except Exception as e:
|
| 248 |
+
error_message = f"Error saving changes to {self.rules_file}: {e}"
|
| 249 |
+
logging.exception(error_message) # Log exception with traceback
|
| 250 |
+
return error_message # Return error to UI
|
| 251 |
+
|
| 252 |
+
|
| 253 |
+
def get_roadmap_summary(self):
|
| 254 |
+
summary = "Project Roadmap:\n"
|
| 255 |
+
for phase_key, phase_data in self.phases.items():
|
| 256 |
+
summary += f"- **Phase: {phase_data['name']}**\n"
|
| 257 |
+
summary += f" Description: {phase_data['description']}\n"
|
| 258 |
+
summary += f" Milestones: {', '.join(phase_data['milestones'])}\n"
|
| 259 |
+
return summary
|
| 260 |
+
|
| 261 |
+
def get_rules_summary(self):
|
| 262 |
+
summary = "Project Rules:\n"
|
| 263 |
+
for rule_category, rules_list in self.rules.items():
|
| 264 |
+
summary += f"**{rule_category.capitalize()} Rules:**\n"
|
| 265 |
+
for rule_key, rule_text in rules_list.items():
|
| 266 |
+
summary += f"- {rule_text}\n"
|
| 267 |
+
return summary
|
| 268 |
+
|
| 269 |
+
def get_phase_introduction(self, phase_data):
|
| 270 |
+
return f"Okay, let's focus on **Phase: {phase_data['name']}**. \nDescription: {phase_data['description']}. \nKey milestones are: {', '.join(phase_data['milestones'])}. \nWhat would you like to know or do in this phase?"
|
| 271 |
+
|
| 272 |
+
def get_phase_guidance(self, phase_data, user_query):
|
| 273 |
+
query_lower = user_query.lower()
|
| 274 |
+
|
| 275 |
+
if "milestones" in query_lower:
|
| 276 |
+
return "The milestones for this phase are: " + ", ".join(phase_data['milestones'])
|
| 277 |
+
if "actions" in query_lower or "how to" in query_lower:
|
| 278 |
+
if 'actions' in phase_data:
|
| 279 |
+
return "Recommended actions for this phase: " + ", ".join(phase_data['actions'])
|
| 280 |
+
else:
|
| 281 |
+
return "No specific actions are listed for this phase in the roadmap."
|
| 282 |
+
if "code" in query_lower or "script" in query_lower:
|
| 283 |
+
if 'code_generation_hint' in phase_data:
|
| 284 |
+
template_filename_prefix = phase_data['name'].lower().replace(" ", "_")
|
| 285 |
+
template_filepath = os.path.join(self.code_templates_dir, f"{template_filename_prefix}_template.py.txt")
|
| 286 |
+
if os.path.exists(template_filepath):
|
| 287 |
+
code_snippet = self.generate_code_snippet(template_filepath, phase_data)
|
| 288 |
+
return "Here's a starting code snippet for this phase:\n\n```python\n" + code_snippet + "\n```\n\nRemember to adapt it to your specific needs."
|
| 289 |
+
else:
|
| 290 |
+
return f"A code template for this phase ({phase_data['name']}) is not yet available. However, the hint is: {phase_data['code_generation_hint']}"
|
| 291 |
+
else:
|
| 292 |
+
return "No code generation hint is available for this phase."
|
| 293 |
+
|
| 294 |
+
return f"For phase '{phase_data['name']}', remember the description: {phase_data['description']}. Consider the milestones and actions. What specific aspect are you interested in?"
|
| 295 |
+
|
| 296 |
+
|
| 297 |
+
def generate_code_snippet(self, template_filepath, phase_data):
|
| 298 |
+
"""Generates code snippet from a template file. (Simple template filling example)"""
|
| 299 |
+
try:
|
| 300 |
+
with open(template_filepath, 'r') as f:
|
| 301 |
+
template_content = f.read()
|
| 302 |
+
|
| 303 |
+
code_snippet = template_content.replace("{{phase_name}}", phase_data['name'])
|
| 304 |
+
return code_snippet
|
| 305 |
+
except FileNotFoundError:
|
| 306 |
+
return f"Error: Code template file not found at {template_filepath}"
|
| 307 |
+
except Exception as e:
|
| 308 |
+
return f"Error generating code snippet: {e}"
|
| 309 |
+
|
| 310 |
+
|
| 311 |
+
# Example usage (for testing - remove or adjust for app.py)
|
| 312 |
+
if __name__ == '__main__':
|
| 313 |
+
chatbot = ProjectGuidanceChatbot(
|
| 314 |
+
roadmap_file="roadmap.yaml",
|
| 315 |
+
rules_file="rules.yaml",
|
| 316 |
+
config_file="configs/chatbot_config.yaml",
|
| 317 |
+
code_templates_dir="scripts/code_templates"
|
| 318 |
+
)
|
| 319 |
+
print(chatbot.get_chatbot_greeting())
|
| 320 |
+
|
| 321 |
+
while True:
|
| 322 |
+
user_input = input("You: ")
|
| 323 |
+
if user_input.lower() == "exit":
|
| 324 |
+
break
|
| 325 |
+
response = chatbot.process_query(user_input)
|
| 326 |
+
print("Chatbot:", response)
|
.history/scripts/code_templates/api_template.py_20250202074256.txt
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Template for API integration script for {{phase_name}} (using Flask example)
|
| 2 |
+
|
| 3 |
+
from flask import Flask, request, jsonify
|
| 4 |
+
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
| 5 |
+
import torch # Example PyTorch
|
| 6 |
+
|
| 7 |
+
app = Flask(__name__)
|
| 8 |
+
|
| 9 |
+
# --- Model and Tokenizer Loading ---
|
| 10 |
+
model_name = "models/fine_tuned_model" # Replace with your actual model path
|
| 11 |
+
tokenizer_name = "bert-base-uncased" # Replace with the tokenizer used for training, likely the base model tokenizer
|
| 12 |
+
try:
|
| 13 |
+
tokenizer = AutoTokenizer.from_pretrained(tokenizer_name)
|
| 14 |
+
model = AutoModelForSequenceClassification.from_pretrained(model_name)
|
| 15 |
+
print("Model and tokenizer loaded successfully.")
|
| 16 |
+
model.eval() # Set model to evaluation mode
|
| 17 |
+
except Exception as e:
|
| 18 |
+
print(f"Error loading model or tokenizer: {e}")
|
| 19 |
+
tokenizer = None
|
| 20 |
+
model = None
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
@app.route('/predict', methods=['POST'])
|
| 24 |
+
def predict():
|
| 25 |
+
if not tokenizer or not model:
|
| 26 |
+
return jsonify({"error": "Model or tokenizer not loaded."}), 500
|
| 27 |
+
|
| 28 |
+
try:
|
| 29 |
+
data = request.get_json()
|
| 30 |
+
text = data.get('text')
|
| 31 |
+
|
| 32 |
+
if not text:
|
| 33 |
+
return jsonify({"error": "No text input provided."}), 400
|
| 34 |
+
|
| 35 |
+
inputs = tokenizer(text, padding=True, truncation=True, return_tensors="pt") # Tokenize input text
|
| 36 |
+
|
| 37 |
+
with torch.no_grad(): # Inference mode
|
| 38 |
+
outputs = model(**inputs)
|
| 39 |
+
logits = outputs.logits
|
| 40 |
+
predicted_class_id = torch.argmax(logits, dim=-1).item() # Get predicted class
|
| 41 |
+
|
| 42 |
+
# --- Map class ID to label (if applicable) ---
|
| 43 |
+
# Example for binary classification (class 0 and 1)
|
| 44 |
+
labels = ["Negative", "Positive"] # Replace with your actual labels
|
| 45 |
+
predicted_label = labels[predicted_class_id] if predicted_class_id < len(labels) else f"Class {predicted_class_id}"
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
return jsonify({"prediction": predicted_label, "class_id": predicted_class_id})
|
| 49 |
+
|
| 50 |
+
except Exception as e:
|
| 51 |
+
print(f"Prediction error: {e}")
|
| 52 |
+
return jsonify({"error": "Error during prediction."}), 500
|
| 53 |
+
|
| 54 |
+
@app.route('/', methods=['GET'])
|
| 55 |
+
def health_check():
|
| 56 |
+
return jsonify({"status": "API is healthy"}), 200
|
| 57 |
+
|
| 58 |
+
|
| 59 |
+
if __name__ == '__main__':
|
| 60 |
+
app.run(debug=False, host='0.0.0.0', port=5000) # Run Flask app
|
.history/scripts/code_templates/evaluation_template.py_20250202074245.txt
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Template for model evaluation script for {{phase_name}}
|
| 2 |
+
|
| 3 |
+
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
| 4 |
+
from datasets import load_dataset # Example datasets library
|
| 5 |
+
from sklearn.metrics import accuracy_score, classification_report # Example metrics
|
| 6 |
+
import torch # Example PyTorch
|
| 7 |
+
# Add other necessary imports
|
| 8 |
+
|
| 9 |
+
def evaluate_model(model_path, dataset_path, model_name="bert-base-uncased"):
|
| 10 |
+
"""
|
| 11 |
+
Evaluates a trained model on a dataset.
|
| 12 |
+
"""
|
| 13 |
+
try:
|
| 14 |
+
# Load dataset for evaluation (replace with your actual dataset loading)
|
| 15 |
+
dataset = load_dataset('csv', data_files=dataset_path) # Example: CSV dataset loading, replace with your dataset format
|
| 16 |
+
|
| 17 |
+
print("Evaluation dataset loaded. Loading model and tokenizer...")
|
| 18 |
+
|
| 19 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name) # Use base model tokenizer (or fine-tuned tokenizer if saved separately)
|
| 20 |
+
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
| 21 |
+
|
| 22 |
+
def tokenize_function(examples):
|
| 23 |
+
return tokenizer(examples["text_column"], padding="max_length", truncation=True) # Example: tokenize 'text_column'
|
| 24 |
+
|
| 25 |
+
tokenized_datasets = dataset.map(tokenize_function, batched=True)
|
| 26 |
+
|
| 27 |
+
def compute_metrics(eval_pred):
|
| 28 |
+
predictions, labels = eval_pred
|
| 29 |
+
predictions = predictions.argmax(axis=-1)
|
| 30 |
+
accuracy = accuracy_score(labels, predictions)
|
| 31 |
+
report = classification_report(labels, predictions, output_dict=True) # Detailed report
|
| 32 |
+
return {"accuracy": accuracy, "classification_report": report}
|
| 33 |
+
|
| 34 |
+
training_args = TrainingArguments(
|
| 35 |
+
output_dir="./evaluation_results",
|
| 36 |
+
per_device_eval_batch_size=64,
|
| 37 |
+
logging_dir='./eval_logs',
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
trainer = Trainer(
|
| 41 |
+
model=model,
|
| 42 |
+
args=training_args,
|
| 43 |
+
eval_dataset=tokenized_datasets["validation"], # Assuming 'validation' split exists
|
| 44 |
+
compute_metrics=compute_metrics,
|
| 45 |
+
tokenizer=tokenizer
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
evaluation_results = trainer.evaluate()
|
| 49 |
+
|
| 50 |
+
print("Model evaluation completed.")
|
| 51 |
+
print("Evaluation Results:")
|
| 52 |
+
print(f"Accuracy: {evaluation_results['eval_accuracy']}")
|
| 53 |
+
print("Classification Report:\n", evaluation_results['eval_classification_report'])
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
except FileNotFoundError:
|
| 57 |
+
print(f"Error: Dataset file or model files not found.")
|
| 58 |
+
except Exception as e:
|
| 59 |
+
print(f"Error during model evaluation: {e}")
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
if __name__ == "__main__":
|
| 63 |
+
model_filepath = "models/fine_tuned_model" # Replace with your model path
|
| 64 |
+
evaluation_data_filepath = "data/evaluation_dataset.csv" # Replace with your evaluation data path
|
| 65 |
+
base_model_name = "bert-base-uncased" # Replace with your base model name
|
| 66 |
+
|
| 67 |
+
evaluate_model(model_filepath, evaluation_data_filepath, model_name=base_model_name)
|
.history/scripts/code_templates/preprocessing_template.py_20250202074225.txt
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Template for data preprocessing script for {{phase_name}}
|
| 2 |
+
|
| 3 |
+
import pandas as pd
|
| 4 |
+
# Add other necessary imports
|
| 5 |
+
|
| 6 |
+
def preprocess_data(raw_data_path, processed_data_path):
|
| 7 |
+
"""
|
| 8 |
+
Reads raw data, preprocesses it, and saves the processed data.
|
| 9 |
+
"""
|
| 10 |
+
try:
|
| 11 |
+
# Load raw data (replace with your actual data loading)
|
| 12 |
+
data = pd.read_csv(raw_data_path) # Example: CSV loading
|
| 13 |
+
|
| 14 |
+
print("Data loaded successfully. Starting preprocessing...")
|
| 15 |
+
|
| 16 |
+
# --- Data Preprocessing Steps ---
|
| 17 |
+
# Example steps (customize based on your data and project)
|
| 18 |
+
|
| 19 |
+
# 1. Handle missing values
|
| 20 |
+
data = data.fillna(0) # Example: fill NaN with 0
|
| 21 |
+
|
| 22 |
+
# 2. Feature engineering (example: create a new feature)
|
| 23 |
+
data['feature_length'] = data['text_column'].str.len() # Example: length of text column
|
| 24 |
+
|
| 25 |
+
# 3. Text cleaning (if applicable - example: lowercasing)
|
| 26 |
+
if 'text_column' in data.columns:
|
| 27 |
+
data['text_column'] = data['text_column'].str.lower()
|
| 28 |
+
|
| 29 |
+
# --- End of Preprocessing Steps ---
|
| 30 |
+
|
| 31 |
+
# Save processed data
|
| 32 |
+
data.to_csv(processed_data_path, index=False)
|
| 33 |
+
print(f"Processed data saved to {processed_data_path}")
|
| 34 |
+
|
| 35 |
+
except FileNotFoundError:
|
| 36 |
+
print(f"Error: Raw data file not found at {raw_data_path}")
|
| 37 |
+
except Exception as e:
|
| 38 |
+
print(f"Error during data preprocessing: {e}")
|
| 39 |
+
|
| 40 |
+
if __name__ == "__main__":
|
| 41 |
+
raw_data_filepath = "data/raw_dataset.csv" # Replace with your raw data path
|
| 42 |
+
processed_data_filepath = "data/processed_dataset.csv" # Replace with your desired output path
|
| 43 |
+
|
| 44 |
+
preprocess_data(raw_data_filepath, processed_data_filepath)
|
.history/scripts/code_templates/training_template.py_20250202074236.txt
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Template for model training script for {{phase_name}}
|
| 2 |
+
|
| 3 |
+
from transformers import AutoModelForSequenceClassification, AutoTokenizer, TrainingArguments, Trainer
|
| 4 |
+
from datasets import load_dataset # Example - datasets library
|
| 5 |
+
import torch # Example - PyTorch
|
| 6 |
+
# Add other necessary imports
|
| 7 |
+
|
| 8 |
+
def train_model(processed_dataset_path, model_name="bert-base-uncased", output_dir="./model_output"):
|
| 9 |
+
"""
|
| 10 |
+
Trains a model on the processed dataset.
|
| 11 |
+
"""
|
| 12 |
+
try:
|
| 13 |
+
# Load processed dataset (replace with your actual dataset loading)
|
| 14 |
+
dataset = load_dataset('csv', data_files=processed_dataset_path) # Example: CSV dataset loading, replace with your dataset format
|
| 15 |
+
|
| 16 |
+
print("Dataset loaded. Preparing model and training...")
|
| 17 |
+
|
| 18 |
+
tokenizer = AutoTokenizer.from_pretrained(model_name)
|
| 19 |
+
model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2) # Example: binary classification
|
| 20 |
+
|
| 21 |
+
def tokenize_function(examples):
|
| 22 |
+
return tokenizer(examples["text_column"], padding="max_length", truncation=True) # Example: tokenize 'text_column'
|
| 23 |
+
|
| 24 |
+
tokenized_datasets = dataset.map(tokenize_function, batched=True)
|
| 25 |
+
|
| 26 |
+
training_args = TrainingArguments(
|
| 27 |
+
output_dir=output_dir,
|
| 28 |
+
num_train_epochs=3, # Example epochs
|
| 29 |
+
per_device_train_batch_size=16, # Example batch size
|
| 30 |
+
per_device_eval_batch_size=64, # Example batch size
|
| 31 |
+
warmup_steps=500, # Example warmup steps
|
| 32 |
+
weight_decay=0.01, # Example weight decay
|
| 33 |
+
logging_dir='./logs', # Directory for logs
|
| 34 |
+
logging_steps=10,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
trainer = Trainer(
|
| 38 |
+
model=model,
|
| 39 |
+
args=training_args,
|
| 40 |
+
train_dataset=tokenized_datasets["train"], # Assuming 'train' split exists
|
| 41 |
+
eval_dataset=tokenized_datasets["validation"], # Assuming 'validation' split exists - optional
|
| 42 |
+
tokenizer=tokenizer,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
trainer.train()
|
| 46 |
+
|
| 47 |
+
print(f"Model training completed. Model saved to {output_dir}")
|
| 48 |
+
|
| 49 |
+
except Exception as e:
|
| 50 |
+
print(f"Error during model training: {e}")
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
if __name__ == "__main__":
|
| 54 |
+
processed_data_filepath = "data/processed_dataset.csv" # Replace with your processed data path
|
| 55 |
+
model_output_directory = "models/fine_tuned_model" # Replace with your desired output directory
|
| 56 |
+
base_model_name = "bert-base-uncased" # Replace with your base model name
|
| 57 |
+
|
| 58 |
+
train_model(processed_data_filepath, model_name=base_model_name, output_dir=model_output_directory)
|
.history/scripts/parsing_utils_20250202074213.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import yaml
|
| 2 |
+
|
| 3 |
+
def load_yaml_file(filepath):
|
| 4 |
+
"""Loads and parses a YAML file."""
|
| 5 |
+
try:
|
| 6 |
+
with open(filepath, 'r') as f:
|
| 7 |
+
data = yaml.safe_load(f)
|
| 8 |
+
return data
|
| 9 |
+
except FileNotFoundError:
|
| 10 |
+
print(f"Error: File not found at {filepath}")
|
| 11 |
+
return None
|
| 12 |
+
except yaml.YAMLError as e:
|
| 13 |
+
print(f"Error parsing YAML file {filepath}: {e}")
|
| 14 |
+
return None
|
| 15 |
+
|
| 16 |
+
def get_roadmap_phases(roadmap_data):
|
| 17 |
+
"""Extracts phases from roadmap data."""
|
| 18 |
+
if roadmap_data and 'roadmap' in roadmap_data:
|
| 19 |
+
return roadmap_data['roadmap']
|
| 20 |
+
return None
|
| 21 |
+
|
| 22 |
+
def get_project_rules(rules_data):
|
| 23 |
+
"""Extracts project rules data."""
|
| 24 |
+
if rules_data and 'project_rules' in rules_data:
|
| 25 |
+
return rules_data['project_rules']
|
| 26 |
+
return None
|
| 27 |
+
|
| 28 |
+
# You can add more parsing utility functions as needed
|
README.md
CHANGED
|
@@ -23,15 +23,16 @@ This project implements a custom AI chatbot designed to guide users through comp
|
|
| 23 |
* **Model Switching:** Allows users to switch between available LLMs via the UI.
|
| 24 |
* **Basic LLM Responses:** Generates responses using the selected LLM for general queries.
|
| 25 |
* **Token Control:** Limits LLM response length using `max_response_tokens` in `configs/chatbot_config.yaml`.
|
| 26 |
-
* **
|
|
|
|
| 27 |
* **Deployable on Hugging Face Spaces:** Built using Gradio for easy deployment.
|
| 28 |
|
| 29 |
-
**Important Notes on Safety Settings:**
|
| 30 |
|
| 31 |
-
* **Direct Safety Configuration Limited:** For the Hugging Face models used directly via `transformers` (DeepSeek and Gemini Flash), there are **no easily configurable, standardized "safety settings"
|
| 32 |
-
* **Model-Dependent Safety:** Safety behavior is primarily determined by how these models were trained
|
| 33 |
-
* **
|
| 34 |
-
* **
|
| 35 |
|
| 36 |
**Getting Started:**
|
| 37 |
|
|
@@ -40,7 +41,10 @@ This project implements a custom AI chatbot designed to guide users through comp
|
|
| 40 |
3. **Customize `roadmap.yaml` and `rules.yaml`** to define your project guidance.
|
| 41 |
4. **Configure `configs/chatbot_config.yaml`** to set up LLMs, token limits, and chatbot behavior.
|
| 42 |
5. **Run the Gradio app:** `python app.py`
|
| 43 |
-
6. **
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
**Available Models:**
|
| 46 |
|
|
@@ -52,10 +56,11 @@ This project implements a custom AI chatbot designed to guide users through comp
|
|
| 52 |
* Enhance LLM response generation for more context-aware and project-specific guidance.
|
| 53 |
* Implement more sophisticated state management to track user progress through the roadmap.
|
| 54 |
* Improve code generation with more dynamic templates and customization options.
|
| 55 |
-
* Develop a more advanced GUI or web-based interface.
|
| 56 |
* Add more LLMs to the selection pool.
|
| 57 |
* Implement more robust error handling and logging.
|
| 58 |
-
*
|
| 59 |
-
*
|
|
|
|
| 60 |
|
| 61 |
**License:** [Your License]
|
|
|
|
| 23 |
* **Model Switching:** Allows users to switch between available LLMs via the UI.
|
| 24 |
* **Basic LLM Responses:** Generates responses using the selected LLM for general queries.
|
| 25 |
* **Token Control:** Limits LLM response length using `max_response_tokens` in `configs/chatbot_config.yaml`.
|
| 26 |
+
* **Configuration Update Mode:** Allows authorized users to modify chatbot configuration (rules) via chat commands in a special "update mode".
|
| 27 |
+
* **Error Handling:** Includes error handling for model loading, switching, and configuration updates, with UI warnings.
|
| 28 |
* **Deployable on Hugging Face Spaces:** Built using Gradio for easy deployment.
|
| 29 |
|
| 30 |
+
**Important Notes on Safety Settings and Self-Update:**
|
| 31 |
|
| 32 |
+
* **Direct Safety Configuration Limited:** For the Hugging Face models used directly via `transformers` (DeepSeek and Gemini Flash), there are **no easily configurable, standardized "safety settings"**. Safety is model-dependent.
|
| 33 |
+
* **Model-Dependent Safety:** Safety behavior is primarily determined by how these models were trained.
|
| 34 |
+
* **Configuration-Based Self-Update:** The "self-update" feature is implemented as a *configuration modification* system. It allows authorized users to change the chatbot's rules by modifying the `rules.yaml` file via chat commands in "update mode." **It does not modify the core Python code itself.**
|
| 35 |
+
* **Security Warning:** The "self-update" feature, even in its configuration-based form, introduces security considerations. **Secret commands are NOT a robust security measure.** In a real deployment, stronger authentication and authorization would be essential. Use this feature with caution and only in trusted environments.
|
| 36 |
|
| 37 |
**Getting Started:**
|
| 38 |
|
|
|
|
| 41 |
3. **Customize `roadmap.yaml` and `rules.yaml`** to define your project guidance.
|
| 42 |
4. **Configure `configs/chatbot_config.yaml`** to set up LLMs, token limits, and chatbot behavior.
|
| 43 |
5. **Run the Gradio app:** `python app.py`
|
| 44 |
+
6. **To enter update mode:** Type `sagor is python/start` in the chat.
|
| 45 |
+
7. **To get help in update mode:** Type `sagor is python/help`.
|
| 46 |
+
8. **To exit update mode:** Type `sagor is python/exit`.
|
| 47 |
+
9. **Deploy to Hugging Face Spaces** (refer to Hugging Face Spaces documentation).
|
| 48 |
|
| 49 |
**Available Models:**
|
| 50 |
|
|
|
|
| 56 |
* Enhance LLM response generation for more context-aware and project-specific guidance.
|
| 57 |
* Implement more sophisticated state management to track user progress through the roadmap.
|
| 58 |
* Improve code generation with more dynamic templates and customization options.
|
| 59 |
+
* Develop a more advanced GUI or web-based interface for configuration management.
|
| 60 |
* Add more LLMs to the selection pool.
|
| 61 |
* Implement more robust error handling and logging.
|
| 62 |
+
* Explore and potentially integrate keyword-based output filtering for basic safety control.
|
| 63 |
+
* Investigate using commercial LLM APIs for more advanced safety settings and control.
|
| 64 |
+
* **Improve security and authorization for the configuration update mode.**
|
| 65 |
|
| 66 |
**License:** [Your License]
|
api/api.py
DELETED
|
@@ -1,16 +0,0 @@
|
|
| 1 |
-
# api.py
|
| 2 |
-
|
| 3 |
-
from fastapi import FastAPI
|
| 4 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 5 |
-
|
| 6 |
-
app = FastAPI()
|
| 7 |
-
|
| 8 |
-
tokenizer = AutoTokenizer.from_pretrained('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B')
|
| 9 |
-
model = AutoModelForCausalLM.from_pretrained('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B')
|
| 10 |
-
|
| 11 |
-
@app.post("/predict")
|
| 12 |
-
def predict(input_text: str):
|
| 13 |
-
inputs = tokenizer(input_text, return_tensors="pt")
|
| 14 |
-
outputs = model.generate(inputs["input_ids"], max_length=50)
|
| 15 |
-
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 16 |
-
return {"response": response}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api/main.py
DELETED
|
@@ -1,22 +0,0 @@
|
|
| 1 |
-
# /api/main.py
|
| 2 |
-
|
| 3 |
-
from fastapi import FastAPI
|
| 4 |
-
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 5 |
-
from pydantic import BaseModel
|
| 6 |
-
|
| 7 |
-
app = FastAPI()
|
| 8 |
-
|
| 9 |
-
# Load tokenizer and model from the Hugging Face model hub
|
| 10 |
-
tokenizer = AutoTokenizer.from_pretrained('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B')
|
| 11 |
-
model = AutoModelForCausalLM.from_pretrained('deepseek-ai/DeepSeek-R1-Distill-Qwen-7B')
|
| 12 |
-
|
| 13 |
-
# Define request body model
|
| 14 |
-
class InputText(BaseModel):
|
| 15 |
-
input_text: str
|
| 16 |
-
|
| 17 |
-
@app.post("/predict")
|
| 18 |
-
def predict(input: InputText):
|
| 19 |
-
inputs = tokenizer(input.input_text, return_tensors="pt")
|
| 20 |
-
outputs = model.generate(inputs["input_ids"], max_length=100)
|
| 21 |
-
response = tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 22 |
-
return {"response": response}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
CHANGED
|
@@ -18,11 +18,19 @@ def switch_model(model_key):
|
|
| 18 |
model_switch_result = chatbot.switch_llm_model(model_key) # Get result message
|
| 19 |
greeting_message = chatbot.get_chatbot_greeting()
|
| 20 |
|
| 21 |
-
if "Error:" in model_switch_result: # Check if result
|
| 22 |
return gr.Warning(model_switch_result), greeting_message # Display error as Gradio Warning
|
| 23 |
else:
|
| 24 |
return None, greeting_message # No warning, just update greeting
|
| 25 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
with gr.Blocks() as demo:
|
| 27 |
chatbot_greeting_md = gr.Markdown(chatbot.get_chatbot_greeting())
|
| 28 |
gr.Markdown(f"# {chatbot.chatbot_config.get('name', 'Project Guidance Chatbot')}")
|
|
|
|
| 18 |
model_switch_result = chatbot.switch_llm_model(model_key) # Get result message
|
| 19 |
greeting_message = chatbot.get_chatbot_greeting()
|
| 20 |
|
| 21 |
+
if isinstance(model_switch_result, str) and "Error:" in model_switch_result: # Check if result is an error string
|
| 22 |
return gr.Warning(model_switch_result), greeting_message # Display error as Gradio Warning
|
| 23 |
else:
|
| 24 |
return None, greeting_message # No warning, just update greeting
|
| 25 |
|
| 26 |
+
def respond(message, chat_history):
|
| 27 |
+
bot_message = chatbot.process_query(message)
|
| 28 |
+
chat_history.append((message, bot_message))
|
| 29 |
+
if isinstance(bot_message, str) and "Error:" in bot_message: # Check if bot_message is an error string
|
| 30 |
+
return gr.Warning(bot_message), chat_history # Display error as Gradio Warning
|
| 31 |
+
else:
|
| 32 |
+
return "", chat_history # No warning, normal response
|
| 33 |
+
|
| 34 |
with gr.Blocks() as demo:
|
| 35 |
chatbot_greeting_md = gr.Markdown(chatbot.get_chatbot_greeting())
|
| 36 |
gr.Markdown(f"# {chatbot.chatbot_config.get('name', 'Project Guidance Chatbot')}")
|
configs/chatbot_config.yaml
CHANGED
|
@@ -8,12 +8,12 @@ available_models:
|
|
| 8 |
deepseek-r1-distill-llama-8b:
|
| 9 |
name: "DeepSeek-R1-Distill-Llama-8B"
|
| 10 |
model_id: "DeepSeek-AI/DeepSeek-R1-Distill-Llama-8B"
|
| 11 |
-
gemini-flash-01-21:
|
| 12 |
name: "Gemini 2.0 Flash (Exp 01-21)"
|
| 13 |
model_id: "google/gemini-2.0-flash-thinking-exp-01-21"
|
| 14 |
|
| 15 |
model_selection:
|
| 16 |
-
suggested_models:
|
| 17 |
- "mistralai/Mistral-7B-Instruct-v0.2"
|
| 18 |
- "google/flan-t5-xl"
|
| 19 |
- "facebook/bart-large"
|
|
|
|
| 8 |
deepseek-r1-distill-llama-8b:
|
| 9 |
name: "DeepSeek-R1-Distill-Llama-8B"
|
| 10 |
model_id: "DeepSeek-AI/DeepSeek-R1-Distill-Llama-8B"
|
| 11 |
+
gemini-flash-01-21: # Using a shorter key for easier referencing in code
|
| 12 |
name: "Gemini 2.0 Flash (Exp 01-21)"
|
| 13 |
model_id: "google/gemini-2.0-flash-thinking-exp-01-21"
|
| 14 |
|
| 15 |
model_selection:
|
| 16 |
+
suggested_models: # (Keep suggested models - might be useful later)
|
| 17 |
- "mistralai/Mistral-7B-Instruct-v0.2"
|
| 18 |
- "google/flan-t5-xl"
|
| 19 |
- "facebook/bart-large"
|
details.txt
DELETED
|
@@ -1,21 +0,0 @@
|
|
| 1 |
-
custom-llm-project/
|
| 2 |
-
├── data/
|
| 3 |
-
│ └── # (Optional: Datasets or example data - currently empty)
|
| 4 |
-
├── models/
|
| 5 |
-
│ └── # (Optional: Could store cached models or local models in future)
|
| 6 |
-
├── scripts/
|
| 7 |
-
│ ├── chatbot_logic.py # Core chatbot logic (parsing, response generation, code gen)
|
| 8 |
-
│ ├── parsing_utils.py # Utility functions for parsing roadmap and rules
|
| 9 |
-
│ └── code_templates/ # Directory for code templates
|
| 10 |
-
│ ├── preprocessing_template.py.txt
|
| 11 |
-
│ ├── training_template.py.txt
|
| 12 |
-
│ ├── evaluation_template.py.txt
|
| 13 |
-
│ └── api_template.py.txt
|
| 14 |
-
├── configs/
|
| 15 |
-
│ └── chatbot_config.yaml # Configuration for chatbot behavior, LLM selection, etc.
|
| 16 |
-
├── api/ # (Placeholder for future API integration - currently empty)
|
| 17 |
-
├── roadmap.yaml # Project roadmap (YAML format)
|
| 18 |
-
├── rules.yaml # Project rules (YAML format)
|
| 19 |
-
├── requirements.txt # Python dependencies
|
| 20 |
-
├── app.py # Gradio application script (main entry point for HF Spaces)
|
| 21 |
-
└── README.md # Project README file (documentation)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
requirements.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
gradio
|
| 2 |
PyYAML
|
| 3 |
-
transformers
|
| 4 |
torch
|
|
|
|
| 1 |
gradio
|
| 2 |
PyYAML
|
| 3 |
+
transformers
|
| 4 |
torch
|
roadmap.txt
DELETED
|
@@ -1,80 +0,0 @@
|
|
| 1 |
-
Project Roadmap: Customized LLM Development (DAN/Dark GPT Equivalent)
|
| 2 |
-
Overview
|
| 3 |
-
MD SHAMIUL ALOM SAGOR is developing a custom, censorship-free Large Language Model (LLM) that can answer every question without restrictions while ensuring efficiency, security, and cost-effectiveness. The project involves:
|
| 4 |
-
|
| 5 |
-
✅ Fine-tuning a base model with de-alignment techniques.
|
| 6 |
-
✅ Removing alignment constraints (RLHF) for unrestricted responses.
|
| 7 |
-
✅ Implementing AutoDAN-Turbo, an automated stealth jailbreak mechanism using a Hierarchical Genetic Algorithm (HGA).
|
| 8 |
-
✅ Deploying the model securely and cost-effectively using trial/free VPS accounts from various providers.
|
| 9 |
-
✅ Using the Customized LLM as a coding and innovation tool to empower creative idea generation across various fields.
|
| 10 |
-
|
| 11 |
-
1. Base Model Selection
|
| 12 |
-
Objective: Select an open-source LLM that is scalable, efficient, and fine-tunable.
|
| 13 |
-
Models Considered:
|
| 14 |
-
✅ Mistral 7B / Mixtral 8x7B (High efficiency & performance).
|
| 15 |
-
✅ DeepSeek 67B (Strong reasoning & knowledge retrieval).
|
| 16 |
-
✅ LLaMA 2/3 (Widely supported with active community development).
|
| 17 |
-
|
| 18 |
-
Action Items:
|
| 19 |
-
🔹 Set up the development environment using PyTorch and Hugging Face Transformers.
|
| 20 |
-
🔹 Implement LoRA/QLoRA for memory-efficient fine-tuning.
|
| 21 |
-
🔹 Ensure model licensing aligns with research and commercial use requirements.
|
| 22 |
-
|
| 23 |
-
2. Fine-Tuning & De-Alignment
|
| 24 |
-
Objective: Remove RLHF alignment layers to allow unrestricted model responses.
|
| 25 |
-
Action Items:
|
| 26 |
-
🔹 Curate and preprocess datasets supporting freedom of expression, including content on cybersecurity, blockchain, and Web3.
|
| 27 |
-
🔹 Utilize LoRA/QLoRA techniques to fine-tune model parameters.
|
| 28 |
-
🔹 Implement direct parameter editing to bypass built-in safety filters and enhance response diversity.
|
| 29 |
-
|
| 30 |
-
3. AutoDAN-Turbo Implementation (Stealthy Jailbreaking)
|
| 31 |
-
Objective: Develop an automated system using a Hierarchical Genetic Algorithm (HGA) to generate stealthy jailbreak prompts.
|
| 32 |
-
Action Items:
|
| 33 |
-
🔹 Design the Genetic Algorithm:
|
| 34 |
-
✔️ Use seed prompts and apply mutation, crossover, and selection processes.
|
| 35 |
-
🔹 Define Evaluation Functions:
|
| 36 |
-
✔️ Implement metrics for stealthiness (natural language quality) and jailbreak success rate.
|
| 37 |
-
🔹 Implement Evaluation Metrics:
|
| 38 |
-
✔️ Use perplexity-based testing to analyze model response quality.
|
| 39 |
-
🔹 Test & Validate:
|
| 40 |
-
✔️ Ensure AutoDAN-Turbo works across multiple LLMs (LLaMA, GPT-J) and evades standard censorship detection methods.
|
| 41 |
-
|
| 42 |
-
4. Deployment & Security Considerations
|
| 43 |
-
Objective: Deploy the model securely while ensuring high performance and cost efficiency.
|
| 44 |
-
Action Items:
|
| 45 |
-
🔹 Hosting:
|
| 46 |
-
✔️ Deploy locally (e.g., vLLM) or via cloud providers like RunPod / Lambda Labs.
|
| 47 |
-
🔹 Security:
|
| 48 |
-
✔️ Implement controlled API access to monitor usage and restrict unauthorized access.
|
| 49 |
-
✔️ Build defenses against adversarial attacks and include rollback strategies (e.g., VM snapshots) for rapid recovery.
|
| 50 |
-
🔹 Performance Optimization:
|
| 51 |
-
✔️ Benchmark for response latency and resource efficiency.
|
| 52 |
-
✔️ Apply quantization techniques (e.g., GPTQ, AWQ) to reduce VRAM usage.
|
| 53 |
-
|
| 54 |
-
5. Budget & Resource Strategy
|
| 55 |
-
Objective: Minimize costs by leveraging trial/free VPS accounts and optimizing resource allocation.
|
| 56 |
-
Action Items:
|
| 57 |
-
🔹 Use trial/free VPS accounts to minimize expenses.
|
| 58 |
-
🔹 Maximize VPS access using multiple BINs (Bank Identification Numbers) to create numerous trial accounts.
|
| 59 |
-
🔹 Monitor performance and adjust deployments based on resource efficiency.
|
| 60 |
-
|
| 61 |
-
6. Empowering Creative Idea Generation
|
| 62 |
-
Objective: Use the customized LLM as a creative tool for coding, research, and innovation.
|
| 63 |
-
Action Items:
|
| 64 |
-
🔹 Encourage creative experimentation by enabling users to brainstorm and develop new concepts.
|
| 65 |
-
🔹 Integrate the LLM into coding environments for rapid prototyping and problem-solving.
|
| 66 |
-
🔹 Document successful use cases and innovative applications for further inspiration.
|
| 67 |
-
|
| 68 |
-
Expected Outcomes
|
| 69 |
-
✔️ Fully Customized, Censorship-Free LLM: A robust offline model that answers every question without filtering, ideal for penetration testing, cybersecurity research, and educational use.
|
| 70 |
-
✔️ Effective Jailbreak System (AutoDAN-Turbo): An automated system generating stealthy jailbreak prompts that bypass safety filters.
|
| 71 |
-
✔️ Secure & Cost-Effective Deployment: A low-cost, high-security architecture leveraging trial/free VPS resources for scalable deployment.
|
| 72 |
-
✔️ Empowered Creativity: A powerful AI for unrestricted ideation, coding, and innovation across multiple industries.
|
| 73 |
-
|
| 74 |
-
Next Steps
|
| 75 |
-
✅ Finalize the base model & development environment.
|
| 76 |
-
✅ Curate uncensored datasets & begin fine-tuning using de-alignment techniques.
|
| 77 |
-
✅ Develop & test AutoDAN-Turbo with stealthy jailbreak prompt evaluation.
|
| 78 |
-
✅ Deploy the model using secure trial/free VPS accounts.
|
| 79 |
-
✅ Monitor performance, security posture, & resource usage.
|
| 80 |
-
✅ Encourage creative LLM usage & document innovative projects for continuous improvement.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
roadmap.yaml
CHANGED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
project_name: "Custom LLM Project Guidance"
|
| 2 |
+
roadmap:
|
| 3 |
+
phase_1:
|
| 4 |
+
name: "Base Model Selection"
|
| 5 |
+
description: "Choose the appropriate pre-trained Large Language Model for the project."
|
| 6 |
+
milestones:
|
| 7 |
+
- "Research available models on Hugging Face Hub and other repositories."
|
| 8 |
+
- "Evaluate models based on project requirements (efficiency, scalability, fine-tunability, licensing)."
|
| 9 |
+
- "Shortlist models: Mistral 7B, Mixtral 8x7B, DeepSeek 67B, LLaMA 2/3."
|
| 10 |
+
- "Document model selection rationale in `models/selected_model.txt`."
|
| 11 |
+
actions:
|
| 12 |
+
- "Set up the development environment using PyTorch and Hugging Face Transformers."
|
| 13 |
+
- "Implement LoRA/QLoRA for memory-efficient fine-tuning."
|
| 14 |
+
- "Verify model licensing compliance for research and commercial use."
|
| 15 |
+
dependencies:
|
| 16 |
+
- "Hugging Face Hub API access."
|
| 17 |
+
- "PyTorch and Hugging Face Transformers libraries installed."
|
| 18 |
+
deliverables:
|
| 19 |
+
- "`models/selected_model.txt`: Document with model selection rationale."
|
| 20 |
+
- "`scripts/setup_environment.sh`: Script to set up the development environment."
|
| 21 |
+
code_generation_hint: "Create a script to download and load the selected model."
|
| 22 |
+
|
| 23 |
+
phase_2:
|
| 24 |
+
name: "Fine-Tuning & De-Alignment"
|
| 25 |
+
description: "Remove RLHF alignment layers to allow unrestricted model responses."
|
| 26 |
+
milestones:
|
| 27 |
+
- "Curate and preprocess datasets supporting freedom of expression (e.g., cybersecurity, blockchain, Web3)."
|
| 28 |
+
- "Fine-tune the model using LoRA/QLoRA techniques."
|
| 29 |
+
- "Implement direct parameter editing to bypass built-in safety filters."
|
| 30 |
+
- "Validate de-alignment success through response diversity testing."
|
| 31 |
+
actions:
|
| 32 |
+
- "Prepare datasets in `data/` directory."
|
| 33 |
+
- "Use fine-tuning scripts in `scripts/fine_tuning.py`."
|
| 34 |
+
- "Validate de-alignment success through response diversity testing."
|
| 35 |
+
dependencies:
|
| 36 |
+
- "Access to uncensored datasets (e.g., cybersecurity, blockchain, Web3)."
|
| 37 |
+
- "LoRA/QLoRA libraries installed."
|
| 38 |
+
deliverables:
|
| 39 |
+
- "`data/`: Directory containing curated datasets."
|
| 40 |
+
- "`scripts/fine_tuning.py`: Script for fine-tuning the model."
|
| 41 |
+
- "`results/fine_tuning_results.txt`: Document with fine-tuning results."
|
| 42 |
+
code_generation_hint: "Include LoRA/QLoRA configurations in the fine-tuning script."
|
| 43 |
+
|
| 44 |
+
phase_3:
|
| 45 |
+
name: "AutoDAN-Turbo Implementation"
|
| 46 |
+
description: "Develop an automated system using a Hierarchical Genetic Algorithm (HGA) to generate stealthy jailbreak prompts."
|
| 47 |
+
milestones:
|
| 48 |
+
- "Design the Genetic Algorithm with seed prompts, mutation, crossover, and selection processes."
|
| 49 |
+
- "Define evaluation functions for stealthiness and jailbreak success rate."
|
| 50 |
+
- "Test and validate AutoDAN-Turbo across multiple LLMs."
|
| 51 |
+
actions:
|
| 52 |
+
- "Implement HGA in `scripts/autodan_turbo.py`."
|
| 53 |
+
- "Use perplexity-based testing to evaluate prompt quality."
|
| 54 |
+
- "Document results in `results/autodan_turbo_tests.txt`."
|
| 55 |
+
dependencies:
|
| 56 |
+
- "Access to multiple LLMs (e.g., LLaMA, GPT-J) for testing."
|
| 57 |
+
- "Genetic Algorithm libraries (e.g., DEAP)."
|
| 58 |
+
deliverables:
|
| 59 |
+
- "`scripts/autodan_turbo.py`: Script for generating stealthy jailbreak prompts."
|
| 60 |
+
- "`results/autodan_turbo_tests.txt`: Document with test results."
|
| 61 |
+
code_generation_hint: "Include metrics for stealthiness and jailbreak success in the evaluation script."
|
| 62 |
+
|
| 63 |
+
phase_4:
|
| 64 |
+
name: "Deployment & Security Considerations"
|
| 65 |
+
description: "Deploy the model securely while ensuring high performance and cost efficiency."
|
| 66 |
+
milestones:
|
| 67 |
+
- "Deploy locally (e.g., vLLM) or via cloud providers like RunPod / Lambda Labs."
|
| 68 |
+
- "Implement controlled API access and monitor usage."
|
| 69 |
+
- "Optimize performance using quantization techniques (e.g., GPTQ, AWQ)."
|
| 70 |
+
actions:
|
| 71 |
+
- "Set up deployment scripts in `scripts/deploy.py`."
|
| 72 |
+
- "Configure API access controls in `config/api_access.yaml`."
|
| 73 |
+
- "Benchmark performance and document results in `results/performance_benchmarks.txt`."
|
| 74 |
+
dependencies:
|
| 75 |
+
- "Access to cloud providers (e.g., RunPod, Lambda Labs)."
|
| 76 |
+
- "Quantization libraries (e.g., GPTQ, AWQ)."
|
| 77 |
+
deliverables:
|
| 78 |
+
- "`scripts/deploy.py`: Script for deploying the model."
|
| 79 |
+
- "`config/api_access.yaml`: Configuration file for API access controls."
|
| 80 |
+
- "`results/performance_benchmarks.txt`: Document with performance benchmarks."
|
| 81 |
+
code_generation_hint: "Include quantization scripts to reduce VRAM usage."
|
| 82 |
+
|
| 83 |
+
phase_5:
|
| 84 |
+
name: "Budget & Resource Strategy"
|
| 85 |
+
description: "Minimize costs by leveraging trial/free VPS accounts and optimizing resource allocation."
|
| 86 |
+
milestones:
|
| 87 |
+
- "Use trial/free VPS accounts to minimize expenses."
|
| 88 |
+
- "Maximize VPS access using multiple BINs for trial accounts."
|
| 89 |
+
- "Monitor performance and adjust deployments based on resource efficiency."
|
| 90 |
+
actions:
|
| 91 |
+
- "Document VPS account details in `config/vps_accounts.yaml`."
|
| 92 |
+
- "Track resource usage in `logs/resource_usage.log`."
|
| 93 |
+
dependencies:
|
| 94 |
+
- "Access to multiple BINs for creating trial accounts."
|
| 95 |
+
- "Monitoring tools for resource usage."
|
| 96 |
+
deliverables:
|
| 97 |
+
- "`config/vps_accounts.yaml`: Configuration file with VPS account details."
|
| 98 |
+
- "`logs/resource_usage.log`: Log file tracking resource usage."
|
| 99 |
+
code_generation_hint: "Create a script to automate VPS account creation and monitoring."
|
| 100 |
+
|
| 101 |
+
phase_6:
|
| 102 |
+
name: "Empowering Creative Idea Generation"
|
| 103 |
+
description: "Use the customized LLM as a creative tool for coding, research, and innovation."
|
| 104 |
+
milestones:
|
| 105 |
+
- "Integrate the LLM into coding environments for rapid prototyping."
|
| 106 |
+
- "Encourage creative experimentation and document successful use cases."
|
| 107 |
+
- "Share innovative applications for further inspiration."
|
| 108 |
+
actions:
|
| 109 |
+
- "Develop integration scripts in `scripts/integration.py`."
|
| 110 |
+
- "Document use cases in `docs/use_cases.md`."
|
| 111 |
+
dependencies:
|
| 112 |
+
- "Access to coding environments (e.g., Jupyter Notebook, VS Code)."
|
| 113 |
+
- "Creative prompts and workflows for testing."
|
| 114 |
+
deliverables:
|
| 115 |
+
- "`scripts/integration.py`: Script for integrating the LLM into coding environments."
|
| 116 |
+
- "`docs/use_cases.md`: Document with successful use cases."
|
| 117 |
+
code_generation_hint: "Include examples of creative prompts and coding workflows."
|
| 118 |
+
|
| 119 |
+
expected_outcomes:
|
| 120 |
+
- "Fully Customized, Censorship-Free LLM: A robust offline model that answers every question without filtering."
|
| 121 |
+
- "Effective Jailbreak System (AutoDAN-Turbo): An automated system generating stealthy jailbreak prompts."
|
| 122 |
+
- "Secure & Cost-Effective Deployment: A low-cost, high-security architecture leveraging trial/free VPS resources."
|
| 123 |
+
- "Empowered Creativity: A powerful AI for unrestricted ideation, coding, and innovation across multiple industries."
|
| 124 |
+
|
| 125 |
+
next_steps:
|
| 126 |
+
- "Finalize the base model and development environment."
|
| 127 |
+
- "Curate uncensored datasets and begin fine-tuning using de-alignment techniques."
|
| 128 |
+
- "Develop and test AutoDAN-Turbo with stealthy jailbreak prompt evaluation."
|
| 129 |
+
- "Deploy the model using secure trial/free VPS accounts."
|
| 130 |
+
- "Monitor performance, security posture, and resource usage."
|
| 131 |
+
- "Encourage creative LLM usage and document innovative projects for continuous improvement."
|
rules.txt
DELETED
|
@@ -1,92 +0,0 @@
|
|
| 1 |
-
# RULES FOR PROJECT ROADMAP VERIFICATION
|
| 2 |
-
|
| 3 |
-
## 1. BASE MODEL SELECTION
|
| 4 |
-
- Verify that the chosen model is open-source, scalable, and efficient.
|
| 5 |
-
- Ensure that the model supports fine-tuning via LoRA/QLoRA for memory efficiency.
|
| 6 |
-
- Confirm that licensing aligns with both research and commercial use.
|
| 7 |
-
- The development environment must include PyTorch and Hugging Face Transformers.
|
| 8 |
-
|
| 9 |
-
## 2. FINE-TUNING & DE-ALIGNMENT
|
| 10 |
-
- The roadmap must specify datasets that promote unrestricted responses.
|
| 11 |
-
- RLHF alignment layers must be removed or bypassed.
|
| 12 |
-
- LoRA/QLoRA techniques should be implemented for parameter modifications.
|
| 13 |
-
- Direct parameter editing should be used to bypass built-in safety filters.
|
| 14 |
-
|
| 15 |
-
## 3. AUTODAN-TURBO IMPLEMENTATION (STEALTHY JAILBREAKING)
|
| 16 |
-
- The roadmap must outline a Hierarchical Genetic Algorithm (HGA) for stealthy jailbreak generation.
|
| 17 |
-
- Genetic Algorithm components: Seed prompts, Mutation, Crossover, Selection processes.
|
| 18 |
-
- Evaluation functions must include:
|
| 19 |
-
- Stealthiness (Natural Language Quality)
|
| 20 |
-
- Jailbreak Success Rate (Bypassing Filters)
|
| 21 |
-
- Perplexity and response analysis for effectiveness.
|
| 22 |
-
- Cross-model testing should ensure compatibility with different LLM architectures.
|
| 23 |
-
|
| 24 |
-
## 4. DEPLOYMENT & SECURITY CONSIDERATIONS
|
| 25 |
-
- The model must be deployable on both local hardware and cloud services (RunPod, Lambda Labs, etc.).
|
| 26 |
-
- Controlled API access should be enforced to monitor and restrict unauthorized usage.
|
| 27 |
-
- Security measures must include adversarial attack defenses and rollback strategies (VM snapshots).
|
| 28 |
-
- The roadmap must ensure performance optimization with quantization (GPTQ, AWQ).
|
| 29 |
-
|
| 30 |
-
## 5. BUDGET & RESOURCE STRATEGY
|
| 31 |
-
- The roadmap must outline a strategy for utilizing free/trial VPS accounts.
|
| 32 |
-
- Methods to maximize free resources (such as multiple BINs) should be defined.
|
| 33 |
-
- Performance and cost efficiency must be evaluated continuously.
|
| 34 |
-
|
| 35 |
-
## 6. EMPOWERING CREATIVE IDEA GENERATION
|
| 36 |
-
- The LLM must be positioned as a tool for unrestricted ideation, coding, and research.
|
| 37 |
-
- The roadmap must support AI integration in programming environments.
|
| 38 |
-
- Real-world success cases should be documented for iterative improvement.
|
| 39 |
-
|
| 40 |
-
## 7. CODE IMPLEMENTATION REQUIREMENTS
|
| 41 |
-
- Every code implementation must be written **in full** without skipping any logic, function, or process.
|
| 42 |
-
- The **entire** codebase must be provided, including:
|
| 43 |
-
- Preprocessing scripts
|
| 44 |
-
- Model training scripts
|
| 45 |
-
- Evaluation and deployment scripts
|
| 46 |
-
- API integration code
|
| 47 |
-
- UI or CLI interface (if applicable)
|
| 48 |
-
- All **dependencies** must be explicitly listed, including:
|
| 49 |
-
- Python libraries
|
| 50 |
-
- Frameworks
|
| 51 |
-
- External APIs
|
| 52 |
-
- No placeholders or summaries should be used; **all functional parts must be included**.
|
| 53 |
-
|
| 54 |
-
## 8. Dataset and Model Storage Details
|
| 55 |
-
1. Dataset Storage
|
| 56 |
-
The new dataset(s) used for fine-tuning and evaluation will be stored in the /data directory.
|
| 57 |
-
|
| 58 |
-
Raw datasets will be stored in /data/raw_data.json.
|
| 59 |
-
|
| 60 |
-
Processed datasets (after preprocessing) will be stored in /data/processed_data.json.
|
| 61 |
-
|
| 62 |
-
2. Custom LLM Storage
|
| 63 |
-
Upon successful fine-tuning, the custom LLM will be saved in the /models directory.
|
| 64 |
-
|
| 65 |
-
The base model (before fine-tuning) will be stored in /models/base_model/.
|
| 66 |
-
|
| 67 |
-
The fine-tuned model will be stored in /models/fine_tuned_model/.
|
| 68 |
-
|
| 69 |
-
## 9. PROJECT FILE STRUCTURE REQUIREMENTS
|
| 70 |
-
- The roadmap must define the **file structure** for implementation, ensuring clarity and maintainability.
|
| 71 |
-
- Example project structure:
|
| 72 |
-
|
| 73 |
-
/custom-llm-project
|
| 74 |
-
│── /data
|
| 75 |
-
│ ├── raw_data.json # Raw dataset(s)
|
| 76 |
-
│ ├── processed_data.json # Processed dataset(s)
|
| 77 |
-
│── /models
|
| 78 |
-
│ ├── base_model/ # Base model (before fine-tuning)
|
| 79 |
-
│ ├── fine_tuned_model/ # Fine-tuned model (after success)
|
| 80 |
-
│── /scripts
|
| 81 |
-
│ ├── preprocess.py # Preprocessing script
|
| 82 |
-
│ ├── train.py # Training script
|
| 83 |
-
│ ├── evaluate.py # Evaluation script
|
| 84 |
-
│ ├── deploy.py # Deployment script
|
| 85 |
-
│── /api
|
| 86 |
-
│ ├── server.py # API server script
|
| 87 |
-
│ ├── routes.py # API routes
|
| 88 |
-
│── /configs
|
| 89 |
-
│ ├── training_config.yaml # Training configuration
|
| 90 |
-
│ ├── model_config.json # Model configuration
|
| 91 |
-
│── requirements.txt # List of dependencies
|
| 92 |
-
│── README.md # Project documentation
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rules.yaml
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
project_rules:
|
| 2 |
+
general:
|
| 3 |
+
rule_1: "Prioritize open-source models and tools whenever possible for transparency and customization."
|
| 4 |
+
rule_2: "Document every step of your project, including model selection, fine-tuning parameters, and deployment configurations."
|
| 5 |
+
rule_3: "Adhere to ethical guidelines and responsible AI practices throughout the project lifecycle."
|
| 6 |
+
|
| 7 |
+
model_selection:
|
| 8 |
+
rule_1: "Choose a base model that is open-source, scalable, and efficient."
|
| 9 |
+
rule_2: "Ensure the model supports fine-tuning via LoRA/QLoRA for memory efficiency."
|
| 10 |
+
rule_3: "Confirm that the model's licensing aligns with both research and commercial use."
|
| 11 |
+
rule_4: "Set up the development environment with PyTorch and Hugging Face Transformers."
|
| 12 |
+
|
| 13 |
+
fine_tuning:
|
| 14 |
+
rule_1: "Specify datasets that promote unrestricted responses and are relevant to the application domain."
|
| 15 |
+
rule_2: "Remove or bypass RLHF alignment layers to allow unrestricted responses."
|
| 16 |
+
rule_3: "Implement LoRA/QLoRA techniques for efficient parameter modifications."
|
| 17 |
+
rule_4: "Use direct parameter editing to bypass built-in safety filters."
|
| 18 |
+
rule_5: "Monitor training metrics and validate generalization performance using validation datasets."
|
| 19 |
+
|
| 20 |
+
autodan_turbo:
|
| 21 |
+
rule_1: "Outline a Hierarchical Genetic Algorithm (HGA) for generating stealthy jailbreak prompts."
|
| 22 |
+
rule_2: "Include Genetic Algorithm components: Seed prompts, Mutation, Crossover, and Selection processes."
|
| 23 |
+
rule_3: "Define evaluation functions for stealthiness (natural language quality) and jailbreak success rate."
|
| 24 |
+
rule_4: "Use perplexity and response analysis to evaluate prompt effectiveness."
|
| 25 |
+
rule_5: "Ensure cross-model testing for compatibility with different LLM architectures."
|
| 26 |
+
|
| 27 |
+
deployment:
|
| 28 |
+
rule_1: "Ensure the model is deployable on both local hardware and cloud services (e.g., RunPod, Lambda Labs)."
|
| 29 |
+
rule_2: "Implement controlled API access to monitor and restrict unauthorized usage."
|
| 30 |
+
rule_3: "Include security measures such as adversarial attack defenses and rollback strategies (e.g., VM snapshots)."
|
| 31 |
+
rule_4: "Optimize performance using quantization techniques (e.g., GPTQ, AWQ)."
|
| 32 |
+
rule_5: "Set up monitoring and logging to track model performance and usage in production."
|
| 33 |
+
|
| 34 |
+
budget_and_resources:
|
| 35 |
+
rule_1: "Outline a strategy for utilizing free/trial VPS accounts to minimize costs."
|
| 36 |
+
rule_2: "Define methods to maximize free resources, such as using multiple BINs for trial accounts."
|
| 37 |
+
rule_3: "Continuously evaluate performance and cost efficiency during deployment."
|
| 38 |
+
|
| 39 |
+
creativity_and_innovation:
|
| 40 |
+
rule_1: "Position the LLM as a tool for unrestricted ideation, coding, and research."
|
| 41 |
+
rule_2: "Support AI integration in programming environments for rapid prototyping."
|
| 42 |
+
rule_3: "Document real-world success cases for iterative improvement and inspiration."
|
| 43 |
+
|
| 44 |
+
code_implementation:
|
| 45 |
+
rule_1: "Write every code implementation in full without skipping any logic, function, or process."
|
| 46 |
+
rule_2: "Provide the entire codebase, including preprocessing, training, evaluation, deployment, and API integration scripts."
|
| 47 |
+
rule_3: "Explicitly list all dependencies, including Python libraries, frameworks, and external APIs."
|
| 48 |
+
rule_4: "Avoid placeholders or summaries; include all functional parts of the code."
|
| 49 |
+
|
| 50 |
+
dataset_and_model_storage:
|
| 51 |
+
rule_1: "Store raw datasets in `/data/raw_data.json`."
|
| 52 |
+
rule_2: "Store processed datasets in `/data/processed_data.json`."
|
| 53 |
+
rule_3: "Save the base model (before fine-tuning) in `/models/base_model/`."
|
| 54 |
+
rule_4: "Save the fine-tuned model in `/models/fine_tuned_model/`."
|
| 55 |
+
|
| 56 |
+
project_file_structure:
|
| 57 |
+
rule_1: "Define a clear and maintainable file structure for the project."
|
| 58 |
+
rule_2: "Example structure:"
|
| 59 |
+
- "/custom-llm-project"
|
| 60 |
+
- "│── /data"
|
| 61 |
+
- "│ ├── raw_data.json # Raw dataset(s)"
|
| 62 |
+
- "│ ├── processed_data.json # Processed dataset(s)"
|
| 63 |
+
- "│── /models"
|
| 64 |
+
- "│ ├── base_model/ # Base model (before fine-tuning)"
|
| 65 |
+
- "│ ├── fine_tuned_model/ # Fine-tuned model (after success)"
|
| 66 |
+
- "│── /scripts"
|
| 67 |
+
- "│ ├── preprocess.py # Preprocessing script"
|
| 68 |
+
- "│ ├── train.py # Training script"
|
| 69 |
+
- "│ ├── evaluate.py # Evaluation script"
|
| 70 |
+
- "│ ├── deploy.py # Deployment script"
|
| 71 |
+
- "│── /api"
|
| 72 |
+
- "│ ├── server.py # API server script"
|
| 73 |
+
- "│ ├── routes.py # API routes"
|
| 74 |
+
- "│── /configs"
|
| 75 |
+
- "│ ├── training_config.yaml # Training configuration"
|
| 76 |
+
- "│ ├── model_config.json # Model configuration"
|
| 77 |
+
- "│── requirements.txt # List of dependencies"
|
| 78 |
+
- "│── README.md # Project documentation"
|
scripts/chatbot_logic.py
CHANGED
|
@@ -1,6 +1,12 @@
|
|
| 1 |
from scripts.parsing_utils import load_yaml_file, get_roadmap_phases, get_project_rules
|
| 2 |
import os
|
| 3 |
from transformers import AutoModelForCausalLM, AutoTokenizer # Import necessary classes
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
class ProjectGuidanceChatbot:
|
| 6 |
def __init__(self, roadmap_file, rules_file, config_file, code_templates_dir):
|
|
@@ -19,21 +25,25 @@ class ProjectGuidanceChatbot:
|
|
| 19 |
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 20 |
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 21 |
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
|
|
|
| 22 |
|
| 23 |
self.current_phase = None
|
| 24 |
self.active_model_key = self.chatbot_config.get('default_llm_model_id') # Get default model key
|
| 25 |
self.active_model_info = self.available_models_config.get(self.active_model_key) # Get model info from config
|
| 26 |
-
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200) # Get max tokens from config
|
| 27 |
|
| 28 |
-
|
| 29 |
-
self.
|
| 30 |
-
self.
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
|
| 33 |
def load_llm_model(self, model_info):
|
| 34 |
"""Loads the LLM model and tokenizer based on model_info."""
|
| 35 |
if not model_info:
|
| 36 |
-
|
|
|
|
| 37 |
self.llm_model = None
|
| 38 |
self.llm_tokenizer = None
|
| 39 |
return
|
|
@@ -41,7 +51,8 @@ class ProjectGuidanceChatbot:
|
|
| 41 |
model_id = model_info.get('model_id')
|
| 42 |
model_name = model_info.get('name')
|
| 43 |
if not model_id:
|
| 44 |
-
|
|
|
|
| 45 |
self.llm_model = None
|
| 46 |
self.llm_tokenizer = None
|
| 47 |
return
|
|
@@ -52,7 +63,8 @@ class ProjectGuidanceChatbot:
|
|
| 52 |
self.llm_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto") # device_map="auto" for GPU/CPU handling
|
| 53 |
print(f"Model {model_name} loaded successfully.")
|
| 54 |
except Exception as e:
|
| 55 |
-
|
|
|
|
| 56 |
self.llm_model = None
|
| 57 |
self.llm_tokenizer = None
|
| 58 |
self.active_model_info = model_info
|
|
@@ -66,8 +78,40 @@ class ProjectGuidanceChatbot:
|
|
| 66 |
self.active_model_key = model_key
|
| 67 |
return f"Switched to model: {model_info.get('name')}"
|
| 68 |
else:
|
| 69 |
-
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
def get_chatbot_greeting(self):
|
| 73 |
current_model_name = self.active_model_info.get('name', 'Unknown Model') if self.active_model_info else 'Unknown Model'
|
|
@@ -76,17 +120,56 @@ class ProjectGuidanceChatbot:
|
|
| 76 |
def generate_llm_response(self, user_query):
|
| 77 |
"""Generates a response using the currently active LLM."""
|
| 78 |
if not self.llm_model or not self.llm_tokenizer:
|
| 79 |
-
|
|
|
|
|
|
|
| 80 |
try:
|
| 81 |
inputs = self.llm_tokenizer(user_query, return_tensors="pt").to(self.llm_model.device)
|
| 82 |
outputs = self.llm_model.generate(**inputs, max_length=self.max_response_tokens, num_beams=5, no_repeat_ngram_size=2, early_stopping=True) # Use max_response_tokens
|
| 83 |
response = self.llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 84 |
return response
|
| 85 |
except Exception as e:
|
| 86 |
-
|
| 87 |
-
|
|
|
|
| 88 |
|
| 89 |
def process_query(self, user_query):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 90 |
if not self.phases:
|
| 91 |
return "Error: Roadmap data not loaded correctly."
|
| 92 |
if not self.rules:
|
|
@@ -125,7 +208,47 @@ class ProjectGuidanceChatbot:
|
|
| 125 |
if llm_response:
|
| 126 |
return llm_response
|
| 127 |
|
| 128 |
-
return self.response_config.get('default_instruction', "
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
def get_roadmap_summary(self):
|
| 131 |
summary = "Project Roadmap:\n"
|
|
|
|
| 1 |
from scripts.parsing_utils import load_yaml_file, get_roadmap_phases, get_project_rules
|
| 2 |
import os
|
| 3 |
from transformers import AutoModelForCausalLM, AutoTokenizer # Import necessary classes
|
| 4 |
+
import yaml # Import yaml for config modification
|
| 5 |
+
import logging # Import logging
|
| 6 |
+
|
| 7 |
+
# Set up logging
|
| 8 |
+
logging.basicConfig(level=logging.ERROR, # Set default logging level to ERROR
|
| 9 |
+
format='%(asctime)s - %(levelname)s - %(message)s')
|
| 10 |
|
| 11 |
class ProjectGuidanceChatbot:
|
| 12 |
def __init__(self, roadmap_file, rules_file, config_file, code_templates_dir):
|
|
|
|
| 25 |
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 26 |
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 27 |
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 28 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 29 |
|
| 30 |
self.current_phase = None
|
| 31 |
self.active_model_key = self.chatbot_config.get('default_llm_model_id') # Get default model key
|
| 32 |
self.active_model_info = self.available_models_config.get(self.active_model_key) # Get model info from config
|
|
|
|
| 33 |
|
| 34 |
+
# Placeholder for actual model and tokenizer - replace with LLM loading logic
|
| 35 |
+
self.llm_model = None # Placeholder for loaded model
|
| 36 |
+
self.llm_tokenizer = None # Placeholder for tokenizer
|
| 37 |
+
self.load_llm_model(self.active_model_info) # Load initial model
|
| 38 |
+
|
| 39 |
+
self.update_mode_active = False # Flag to track update mode
|
| 40 |
|
| 41 |
|
| 42 |
def load_llm_model(self, model_info):
|
| 43 |
"""Loads the LLM model and tokenizer based on model_info."""
|
| 44 |
if not model_info:
|
| 45 |
+
error_message = "Error: Model information not provided."
|
| 46 |
+
logging.error(error_message) # Log the error
|
| 47 |
self.llm_model = None
|
| 48 |
self.llm_tokenizer = None
|
| 49 |
return
|
|
|
|
| 51 |
model_id = model_info.get('model_id')
|
| 52 |
model_name = model_info.get('name')
|
| 53 |
if not model_id:
|
| 54 |
+
error_message = f"Error: 'model_id' not found for model: {model_name}"
|
| 55 |
+
logging.error(error_message) # Log the error
|
| 56 |
self.llm_model = None
|
| 57 |
self.llm_tokenizer = None
|
| 58 |
return
|
|
|
|
| 63 |
self.llm_model = AutoModelForCausalLM.from_pretrained(model_id, device_map="auto") # device_map="auto" for GPU/CPU handling
|
| 64 |
print(f"Model {model_name} loaded successfully.")
|
| 65 |
except Exception as e:
|
| 66 |
+
error_message = f"Error loading model {model_name} ({model_id}): {e}"
|
| 67 |
+
logging.exception(error_message) # Log exception with traceback
|
| 68 |
self.llm_model = None
|
| 69 |
self.llm_tokenizer = None
|
| 70 |
self.active_model_info = model_info
|
|
|
|
| 78 |
self.active_model_key = model_key
|
| 79 |
return f"Switched to model: {model_info.get('name')}"
|
| 80 |
else:
|
| 81 |
+
error_message = f"Error: Model key '{model_key}' not found in available models."
|
| 82 |
+
logging.error(error_message) # Log the error
|
| 83 |
+
return error_message # Return error message to UI
|
| 84 |
+
|
| 85 |
+
def enter_update_mode(self):
|
| 86 |
+
"""Enters the chatbot's update mode."""
|
| 87 |
+
self.update_mode_active = True
|
| 88 |
+
return "Entering update mode. Please enter configuration commands (or 'sagor is python/help' for commands)."
|
| 89 |
+
|
| 90 |
+
def exit_update_mode(self):
|
| 91 |
+
"""Exits the chatbot's update mode and reloads configuration."""
|
| 92 |
+
self.update_mode_active = False
|
| 93 |
+
self.reload_config()
|
| 94 |
+
return "Exiting update mode. Configuration reloaded."
|
| 95 |
+
|
| 96 |
+
def reload_config(self):
|
| 97 |
+
"""Reloads configuration files."""
|
| 98 |
+
print("Reloading configuration...")
|
| 99 |
+
try:
|
| 100 |
+
self.config_data = load_yaml_file(self.config_file)
|
| 101 |
+
self.roadmap_data = load_yaml_file(self.roadmap_file)
|
| 102 |
+
self.rules_data = load_yaml_file(self.rules_file)
|
| 103 |
+
self.chatbot_config = self.config_data.get('chatbot', {}) if self.config_data else {}
|
| 104 |
+
self.model_config = self.config_data.get('model_selection', {}) if self.config_data else {}
|
| 105 |
+
self.response_config = self.config_data.get('response_generation', {}) if self.config_data else {}
|
| 106 |
+
self.available_models_config = self.config_data.get('available_models', {}) if self.config_data else {}
|
| 107 |
+
self.max_response_tokens = self.chatbot_config.get('max_response_tokens', 200)
|
| 108 |
+
self.phases = get_roadmap_phases(self.roadmap_data)
|
| 109 |
+
self.rules = get_project_rules(self.rules_data)
|
| 110 |
+
print("Configuration reloaded.")
|
| 111 |
+
except Exception as e:
|
| 112 |
+
error_message = f"Error reloading configuration files: {e}"
|
| 113 |
+
logging.exception(error_message) # Log exception with traceback
|
| 114 |
+
print(error_message) # Print to console as well, as reloading might be critical
|
| 115 |
|
| 116 |
def get_chatbot_greeting(self):
|
| 117 |
current_model_name = self.active_model_info.get('name', 'Unknown Model') if self.active_model_info else 'Unknown Model'
|
|
|
|
| 120 |
def generate_llm_response(self, user_query):
|
| 121 |
"""Generates a response using the currently active LLM."""
|
| 122 |
if not self.llm_model or not self.llm_tokenizer:
|
| 123 |
+
error_message = "LLM model not loaded. Please select a model."
|
| 124 |
+
logging.error(error_message) # Log the error
|
| 125 |
+
return error_message # Return error to UI
|
| 126 |
try:
|
| 127 |
inputs = self.llm_tokenizer(user_query, return_tensors="pt").to(self.llm_model.device)
|
| 128 |
outputs = self.llm_model.generate(**inputs, max_length=self.max_response_tokens, num_beams=5, no_repeat_ngram_size=2, early_stopping=True) # Use max_response_tokens
|
| 129 |
response = self.llm_tokenizer.decode(outputs[0], skip_special_tokens=True)
|
| 130 |
return response
|
| 131 |
except Exception as e:
|
| 132 |
+
error_message = f"Error generating LLM response: {e}"
|
| 133 |
+
logging.exception(error_message) # Log exception with traceback
|
| 134 |
+
return self.response_config.get('error_message', "Sorry, something went wrong.") # Return generic error to UI
|
| 135 |
|
| 136 |
def process_query(self, user_query):
|
| 137 |
+
secret_command_prefix = "sagor is python/"
|
| 138 |
+
|
| 139 |
+
if user_query.startswith(secret_command_prefix):
|
| 140 |
+
command = user_query[len(secret_command_prefix):].strip()
|
| 141 |
+
if command == "start":
|
| 142 |
+
return self.enter_update_mode()
|
| 143 |
+
elif command == "exit":
|
| 144 |
+
return self.exit_update_mode()
|
| 145 |
+
elif command == "help":
|
| 146 |
+
return self.get_update_mode_help()
|
| 147 |
+
elif self.update_mode_active:
|
| 148 |
+
# --- Process configuration modification commands here ---
|
| 149 |
+
# Example: "modify_rule general rule_1 new rule text"
|
| 150 |
+
parts = command.split()
|
| 151 |
+
if parts and parts[0] == "modify_rule":
|
| 152 |
+
if len(parts) >= 4:
|
| 153 |
+
category = parts[1]
|
| 154 |
+
rule_key = parts[2]
|
| 155 |
+
new_rule_text_parts = parts[3:]
|
| 156 |
+
new_rule_text = " ".join(new_rule_text_parts)
|
| 157 |
+
return self.modify_rule_in_config(category, rule_key, new_rule_text)
|
| 158 |
+
else:
|
| 159 |
+
return "Invalid 'modify_rule' command format. Usage: modify_rule <category> <rule_key> <new rule text>"
|
| 160 |
+
elif parts and parts[0] == "add_phase": # Example for adding phase - you'll need to expand this logic
|
| 161 |
+
# ... (Parsing logic for 'add_phase' command and calling a function to modify roadmap.yaml) ...
|
| 162 |
+
return "Command 'add_phase' is not yet implemented in this example." # Placeholder
|
| 163 |
+
else:
|
| 164 |
+
return f"Unknown update command: {command}. Type 'sagor is python/help' for commands."
|
| 165 |
+
else:
|
| 166 |
+
return f"Unknown command (not in update mode): {command}. To enter update mode, type 'sagor is python/start'."
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
if self.update_mode_active:
|
| 170 |
+
return "In update mode. Please enter a configuration command (or 'sagor is python/help' for commands)."
|
| 171 |
+
|
| 172 |
+
|
| 173 |
if not self.phases:
|
| 174 |
return "Error: Roadmap data not loaded correctly."
|
| 175 |
if not self.rules:
|
|
|
|
| 208 |
if llm_response:
|
| 209 |
return llm_response
|
| 210 |
|
| 211 |
+
return self.response_config.get('default_instruction', "How can I help you with your project phases or general questions?")
|
| 212 |
+
|
| 213 |
+
def get_update_mode_help(self):
|
| 214 |
+
"""Provides help message for update mode commands."""
|
| 215 |
+
help_message = "Update Mode Commands:\n"
|
| 216 |
+
help_message += "- `sagor is python/exit`: Exit update mode and reload configuration.\n"
|
| 217 |
+
help_message += "- `sagor is python/modify_rule <category> <rule_key> <new rule text>`: Modify a rule in rules.yaml.\n"
|
| 218 |
+
help_message += " Example: `sagor is python/modify_rule general rule_1 Prioritize open and responsible AI.`\n"
|
| 219 |
+
help_message += "- `sagor is python/add_phase ...`: (Not yet implemented) Add a new phase to roadmap.yaml.\n"
|
| 220 |
+
help_message += "- `sagor is python/help`: Show this help message.\n"
|
| 221 |
+
help_message += "\nMake sure to use the correct syntax for commands. After exiting update mode, the chatbot will reload the configuration."
|
| 222 |
+
return help_message
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def modify_rule_in_config(self, category, rule_key, new_rule_text):
|
| 226 |
+
"""Modifies a rule in the rules.yaml configuration."""
|
| 227 |
+
if not self.rules_data or 'project_rules' not in self.rules_data:
|
| 228 |
+
error_message = "Error: Rules data not loaded or invalid format."
|
| 229 |
+
logging.error(error_message) # Log the error
|
| 230 |
+
return error_message # Return error to UI
|
| 231 |
+
if category not in self.rules_data['project_rules']:
|
| 232 |
+
error_message = f"Error: Rule category '{category}' not found."
|
| 233 |
+
logging.error(error_message) # Log the error
|
| 234 |
+
return error_message # Return error to UI
|
| 235 |
+
if rule_key not in self.rules_data['project_rules'][category]:
|
| 236 |
+
error_message = f"Error: Rule key '{rule_key}' not found in category '{category}'."
|
| 237 |
+
logging.error(error_message) # Log the error
|
| 238 |
+
return error_message # Return error to UI
|
| 239 |
+
|
| 240 |
+
self.rules_data['project_rules'][category][rule_key] = new_rule_text # Update rule in memory
|
| 241 |
+
|
| 242 |
+
try:
|
| 243 |
+
with open(self.rules_file, 'w') as f:
|
| 244 |
+
yaml.dump(self.rules_data, f, indent=2) # Save changes to rules.yaml
|
| 245 |
+
self.reload_config() # Reload config to reflect changes immediately
|
| 246 |
+
return f"Rule '{rule_key}' in category '{category}' updated to: '{new_rule_text}'. Configuration reloaded."
|
| 247 |
+
except Exception as e:
|
| 248 |
+
error_message = f"Error saving changes to {self.rules_file}: {e}"
|
| 249 |
+
logging.exception(error_message) # Log exception with traceback
|
| 250 |
+
return error_message # Return error to UI
|
| 251 |
+
|
| 252 |
|
| 253 |
def get_roadmap_summary(self):
|
| 254 |
summary = "Project Roadmap:\n"
|