Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://doi.org/10.5281/zenodo.15281299
25 April 2025, 10:06:35 UTC
  • Code
  • Branches (0)
  • Releases (1)
  • Visits
    • Branches
    • Releases
      • 1
      • 1
    • c999079
    • /
    • conradhuebler-ALIMA-9149c20
    • /
    • prompt_edit.py
    Raw File Download

    To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
    Select below a type of object currently browsed in order to display its associated SWHID and permalink.

    • content
    • directory
    • snapshot
    • release
    origin badgecontent badge
    swh:1:cnt:7bed183ff89cac58df2535b4279be74ba931b9c7
    origin badgedirectory badge
    swh:1:dir:9c72c77c294e128e1d4610d12e313488bc084d66
    origin badgesnapshot badge
    swh:1:snp:4ca73675f00499f7788b560b527d2d3608e24808
    origin badgerelease badge
    swh:1:rel:536b651fe52569a0b29d9afb23a4c016482765cb

    This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
    Select below a type of object currently browsed in order to generate citations for them.

    • content
    • directory
    • snapshot
    • release
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    (requires biblatex-software package)
    Generating citation ...
    prompt_edit.py
    import sys
    import json
    import os
    from PyQt6.QtWidgets import (
        QApplication, QMainWindow, QTabWidget, QWidget, QVBoxLayout, QHBoxLayout, 
        QLabel, QLineEdit, QTextEdit, QPushButton, QComboBox, QScrollArea, 
        QFileDialog, QMessageBox, QListWidget, QGroupBox, QDoubleSpinBox, QSplitter,
        QGridLayout, QFormLayout, QTreeWidget, QTreeWidgetItem, QFrame, QDialog,
        QDialogButtonBox, QInputDialog, QListWidgetItem
    )
    from PyQt6.QtCore import Qt, QSize
    from PyQt6.QtGui import QFont, QIcon
    
    class PromptConfigEditor(QMainWindow):
        def __init__(self):
            super().__init__()
            self.initUI()
            self.config_data = None
            self.current_file = None
            self.current_task = None
            self.current_prompt_set_index = None
            
        def initUI(self):
            self.setWindowTitle("Prompt Configuration Editor")
            self.setGeometry(100, 100, 1200, 800)
            
            # Create main layout
            main_widget = QWidget()
            self.setCentralWidget(main_widget)
            main_layout = QVBoxLayout(main_widget)
            
            # Create toolbar
            toolbar_layout = QHBoxLayout()
            main_layout.addLayout(toolbar_layout)
            
            # File operations
            self.new_btn = QPushButton("New")
            self.new_btn.clicked.connect(self.new_config)
            toolbar_layout.addWidget(self.new_btn)
            
            self.open_btn = QPushButton("Open")
            self.open_btn.clicked.connect(self.open_config)
            toolbar_layout.addWidget(self.open_btn)
            
            self.save_btn = QPushButton("Save")
            self.save_btn.clicked.connect(self.save_config)
            toolbar_layout.addWidget(self.save_btn)
            
            self.save_as_btn = QPushButton("Save As")
            self.save_as_btn.clicked.connect(self.save_config_as)
            toolbar_layout.addWidget(self.save_as_btn)
            
            toolbar_layout.addStretch()
            
            # Main content splitter
            splitter = QSplitter(Qt.Orientation.Horizontal)
            main_layout.addWidget(splitter, 1)
            
            # Left panel - Tree view
            left_panel = QWidget()
            left_layout = QVBoxLayout(left_panel)
            left_layout.setContentsMargins(0, 0, 0, 0)
            
            # Task tree
            self.task_tree = QTreeWidget()
            self.task_tree.setHeaderLabel("Tasks & Prompts")
            self.task_tree.setMinimumWidth(250)
            self.task_tree.itemClicked.connect(self.on_tree_item_clicked)
            left_layout.addWidget(self.task_tree)
            
            # Task operations
            task_btns_layout = QHBoxLayout()
            self.add_task_btn = QPushButton("Add Task")
            self.add_task_btn.clicked.connect(self.add_task)
            task_btns_layout.addWidget(self.add_task_btn)
            
            self.remove_task_btn = QPushButton("Remove Task")
            self.remove_task_btn.clicked.connect(self.remove_task)
            task_btns_layout.addWidget(self.remove_task_btn)
            left_layout.addLayout(task_btns_layout)
            
            # Prompt set operations
            prompt_btns_layout = QHBoxLayout()
            self.add_prompt_btn = QPushButton("Add Prompt Set")
            self.add_prompt_btn.clicked.connect(self.add_prompt_set)
            prompt_btns_layout.addWidget(self.add_prompt_btn)
            
            self.remove_prompt_btn = QPushButton("Remove Prompt Set")
            self.remove_prompt_btn.clicked.connect(self.remove_prompt_set)
            prompt_btns_layout.addWidget(self.remove_prompt_btn)
            left_layout.addLayout(prompt_btns_layout)
            
            splitter.addWidget(left_panel)
            
            # Right panel - Editor
            self.editor_panel = QScrollArea()
            self.editor_panel.setWidgetResizable(True)
            self.editor_content = QWidget()
            self.editor_layout = QVBoxLayout(self.editor_content)
            self.editor_panel.setWidget(self.editor_content)
            
            # Display "No config loaded" message
            self.no_config_label = QLabel("No configuration loaded.\nUse New or Open to start editing.")
            self.no_config_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
            self.no_config_label.setFont(QFont("Arial", 14))
            self.editor_layout.addWidget(self.no_config_label)
            
            splitter.addWidget(self.editor_panel)
            
            # Set initial state
            self.update_ui_state(False)
            
            # Set the splitter proportions
            splitter.setSizes([300, 900])
        
        def update_ui_state(self, config_loaded):
            """Update the UI based on whether a config is loaded"""
            self.save_btn.setEnabled(config_loaded)
            self.save_as_btn.setEnabled(config_loaded)
            self.add_task_btn.setEnabled(config_loaded)
            self.remove_task_btn.setEnabled(config_loaded and self.current_task is not None)
            self.add_prompt_btn.setEnabled(config_loaded and self.current_task is not None)
            self.remove_prompt_btn.setEnabled(config_loaded and self.current_prompt_set_index is not None)
        
        def new_config(self):
            """Create a new empty configuration"""
            self.config_data = {
                "abstract": {
                    "fields": ["prompt", "system", "temp", "p-value", "model"],
                    "required": ["abstract", "keywords"],
                    "prompts": []
                },
                "keywords": {},
                "dk_list": {},
                "dk_class": {}
            }
            self.current_file = None
            self.refresh_task_tree()
            self.update_ui_state(True)
            self.setWindowTitle("Prompt Configuration Editor - New Config")
        
        def open_config(self):
            """Open a configuration file"""
            file_path, _ = QFileDialog.getOpenFileName(
                self, "Open Configuration File", "", "JSON Files (*.json);;All Files (*)"
            )
            
            if file_path:
                try:
                    with open(file_path, 'r', encoding='utf-8') as file:
                        self.config_data = json.load(file)
                    self.current_file = file_path
                    self.refresh_task_tree()
                    self.update_ui_state(True)
                    self.setWindowTitle(f"Prompt Configuration Editor - {os.path.basename(file_path)}")
                except Exception as e:
                    QMessageBox.critical(self, "Error", f"Failed to open configuration file: {str(e)}")
        
        def save_config(self):
            """Save the current configuration"""
            if self.current_file:
                self.save_to_file(self.current_file)
            else:
                self.save_config_as()
        
        def save_config_as(self):
            """Save the configuration to a new file"""
            file_path, _ = QFileDialog.getSaveFileName(
                self, "Save Configuration File", "", "JSON Files (*.json);;All Files (*)"
            )
            
            if file_path:
                self.save_to_file(file_path)
                self.current_file = file_path
                self.setWindowTitle(f"Prompt Configuration Editor - {os.path.basename(file_path)}")
        
        def save_to_file(self, file_path):
            """Save the configuration data to the specified file"""
            # First, collect any data from the current editor if it's open
            self.collect_current_editor_data()
            
            try:
                with open(file_path, 'w', encoding='utf-8') as file:
                    json.dump(self.config_data, file, indent=4, ensure_ascii=False)
                QMessageBox.information(self, "Success", "Configuration saved successfully!")
            except Exception as e:
                QMessageBox.critical(self, "Error", f"Failed to save configuration file: {str(e)}")
        
        def refresh_task_tree(self):
            """Refresh the task tree with the current configuration"""
            self.task_tree.clear()
            
            if not self.config_data:
                return
            
            # Add each task to the tree
            for task_name, task_data in self.config_data.items():
                task_item = QTreeWidgetItem(self.task_tree, [task_name])
                task_item.setData(0, Qt.ItemDataRole.UserRole, {"type": "task", "name": task_name})
                
                # Add prompt sets under each task
                if "prompts" in task_data and isinstance(task_data["prompts"], list):
                    for idx, prompt_set in enumerate(task_data["prompts"]):
                        models = prompt_set[4] if len(prompt_set) > 4 and isinstance(prompt_set[4], list) else []
                        models_str = ", ".join(models) if models else "No models"
                        prompt_item = QTreeWidgetItem(task_item, [f"Prompt Set {idx+1} ({models_str})"])
                        prompt_item.setData(0, Qt.ItemDataRole.UserRole, {
                            "type": "prompt_set", 
                            "task": task_name, 
                            "index": idx
                        })
            
            self.task_tree.expandAll()
        
        def on_tree_item_clicked(self, item, column):
            """Handle tree item selection"""
            # Save any changes from the current editor before switching
            self.collect_current_editor_data()
            
            item_data = item.data(0, Qt.ItemDataRole.UserRole)
            if not item_data:
                return
            
            item_type = item_data.get("type")
            
            if item_type == "task":
                task_name = item_data.get("name")
                self.current_task = task_name
                self.current_prompt_set_index = None
                self.load_task_editor(task_name)
            
            elif item_type == "prompt_set":
                task_name = item_data.get("task")
                prompt_idx = item_data.get("index")
                self.current_task = task_name
                self.current_prompt_set_index = prompt_idx
                self.load_prompt_set_editor(task_name, prompt_idx)
            
            self.update_ui_state(True)
        
        def add_task(self):
            """Add a new task to the configuration"""
            task_name, ok = QInputDialog.getText(self, "Add Task", "Enter the name of the new task:")
            
            if ok and task_name:
                if task_name in self.config_data:
                    QMessageBox.warning(self, "Warning", f"Task '{task_name}' already exists.")
                    return
                
                self.config_data[task_name] = {
                    "fields": ["prompt", "system", "temp", "p-value", "model"],
                    "required": [],
                    "prompts": []
                }
                
                self.refresh_task_tree()
                
                # Find and select the new task
                for i in range(self.task_tree.topLevelItemCount()):
                    item = self.task_tree.topLevelItem(i)
                    if item.text(0) == task_name:
                        self.task_tree.setCurrentItem(item)
                        self.on_tree_item_clicked(item, 0)
                        break
        
        def remove_task(self):
            """Remove the current task from the configuration"""
            if not self.current_task:
                return
            
            reply = QMessageBox.question(
                self, "Confirm Deletion", 
                f"Are you sure you want to delete the task '{self.current_task}'?\nThis action cannot be undone.",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                del self.config_data[self.current_task]
                self.current_task = None
                self.current_prompt_set_index = None
                self.refresh_task_tree()
                self.clear_editor()
                self.update_ui_state(True)
        
        def add_prompt_set(self):
            """Add a new prompt set to the current task"""
            if not self.current_task:
                return
            
            # Ensure the task has the 'prompts' key and it's a list
            if "prompts" not in self.config_data[self.current_task]:
                self.config_data[self.current_task]["prompts"] = []
            
            # Create a new prompt set with default values
            new_prompt_set = [
                "Enter your prompt here...",  # Prompt
                "Enter your system prompt here...",  # System prompt
                "0.25",  # Temperature
                "0.1",  # P-value
                ["default"]  # Models
            ]
            
            self.config_data[self.current_task]["prompts"].append(new_prompt_set)
            
            # Refresh the tree and select the new prompt set
            self.refresh_task_tree()
            self.current_prompt_set_index = len(self.config_data[self.current_task]["prompts"]) - 1
            
            # Find and select the new prompt set
            task_items = self.task_tree.findItems(self.current_task, Qt.MatchFlag.MatchExactly, 0)
            if task_items:
                task_item = task_items[0]
                if task_item.childCount() > 0:
                    new_item = task_item.child(self.current_prompt_set_index)
                    self.task_tree.setCurrentItem(new_item)
                    self.on_tree_item_clicked(new_item, 0)
        
        def remove_prompt_set(self):
            """Remove the current prompt set from the current task"""
            if not self.current_task or self.current_prompt_set_index is None:
                return
            
            reply = QMessageBox.question(
                self, "Confirm Deletion", 
                f"Are you sure you want to delete Prompt Set {self.current_prompt_set_index + 1}?\nThis action cannot be undone.",
                QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No
            )
            
            if reply == QMessageBox.StandardButton.Yes:
                # Remove the prompt set
                self.config_data[self.current_task]["prompts"].pop(self.current_prompt_set_index)
                
                # Reset the current prompt set index and refresh
                self.current_prompt_set_index = None
                self.refresh_task_tree()
                self.clear_editor()
                self.update_ui_state(True)
        
        def clear_editor(self):
            """Clear the editor panel"""
            # Remove all widgets except the no_config_label
            for i in reversed(range(self.editor_layout.count())):
                widget = self.editor_layout.itemAt(i).widget()
                if widget and widget is not self.no_config_label:
                    widget.setParent(None)
            
            # Show the no config label if no config is loaded
            if not self.config_data:
                self.no_config_label.setVisible(True)
        
        def load_task_editor(self, task_name):
            """Load the editor for a task"""
            self.clear_editor()
            self.no_config_label.setVisible(False)
            
            task_data = self.config_data[task_name]
            
            # Create task editor form
            form_group = QGroupBox(f"Edit Task: {task_name}")
            form_layout = QFormLayout()
            
            # Fields
            fields_label = QLabel("Fields (comma separated):")
            self.fields_edit = QLineEdit()
            if "fields" in task_data:
                self.fields_edit.setText(", ".join(task_data["fields"]))
            form_layout.addRow(fields_label, self.fields_edit)
            
            # Required fields
            required_label = QLabel("Required fields (comma separated):")
            self.required_edit = QLineEdit()
            if "required" in task_data:
                self.required_edit.setText(", ".join(task_data["required"]))
            form_layout.addRow(required_label, self.required_edit)
            
            form_group.setLayout(form_layout)
            self.editor_layout.addWidget(form_group)
            
            # Add a save button
            save_btn = QPushButton("Apply Changes")
            save_btn.clicked.connect(self.save_task_data)
            self.editor_layout.addWidget(save_btn)
            
            # Add stretch to push everything to the top
            self.editor_layout.addStretch()
        
        def save_task_data(self):
            """Save the task data from the editor"""
            if not self.current_task:
                return
            
            # Get fields and required fields
            fields_text = self.fields_edit.text().strip()
            fields = [field.strip() for field in fields_text.split(",") if field.strip()]
            
            required_text = self.required_edit.text().strip()
            required = [field.strip() for field in required_text.split(",") if field.strip()]
            
            # Update the config data
            self.config_data[self.current_task]["fields"] = fields
            self.config_data[self.current_task]["required"] = required
            
            QMessageBox.information(self, "Success", "Task data saved successfully!")
        
        def load_prompt_set_editor(self, task_name, prompt_idx):
            """Load the editor for a prompt set"""
            self.clear_editor()
            self.no_config_label.setVisible(False)
            
            prompt_set = self.config_data[task_name]["prompts"][prompt_idx]
            
            # Create scroll area for the prompt editor
            editor_widget = QWidget()
            editor_layout = QVBoxLayout(editor_widget)
            
            # Prompt
            prompt_group = QGroupBox("Prompt")
            prompt_layout = QVBoxLayout()
            self.prompt_edit = QTextEdit()
            self.prompt_edit.setMinimumHeight(200)
            if len(prompt_set) > 0:
                self.prompt_edit.setPlainText(prompt_set[0])
            prompt_layout.addWidget(self.prompt_edit)
            prompt_group.setLayout(prompt_layout)
            editor_layout.addWidget(prompt_group)
            
            # System prompt
            system_group = QGroupBox("System Prompt")
            system_layout = QVBoxLayout()
            self.system_edit = QTextEdit()
            self.system_edit.setMinimumHeight(150)
            if len(prompt_set) > 1:
                self.system_edit.setPlainText(prompt_set[1])
            system_layout.addWidget(self.system_edit)
            system_group.setLayout(system_layout)
            editor_layout.addWidget(system_group)
            
            # Temperature and P-value
            params_group = QGroupBox("Parameters")
            params_layout = QFormLayout()
            
            self.temp_spinbox = QDoubleSpinBox()
            self.temp_spinbox.setRange(0.0, 2.0)
            self.temp_spinbox.setSingleStep(0.01)
            self.temp_spinbox.setDecimals(2)
            if len(prompt_set) > 2:
                try:
                    self.temp_spinbox.setValue(float(prompt_set[2]))
                except (ValueError, TypeError):
                    self.temp_spinbox.setValue(0.25)
            else:
                self.temp_spinbox.setValue(0.25)
            params_layout.addRow("Temperature:", self.temp_spinbox)
            
            self.p_value_spinbox = QDoubleSpinBox()
            self.p_value_spinbox.setRange(0.0, 1.0)
            self.p_value_spinbox.setSingleStep(0.01)
            self.p_value_spinbox.setDecimals(2)
            if len(prompt_set) > 3:
                try:
                    self.p_value_spinbox.setValue(float(prompt_set[3]))
                except (ValueError, TypeError):
                    self.p_value_spinbox.setValue(0.1)
            else:
                self.p_value_spinbox.setValue(0.1)
            params_layout.addRow("P-value:", self.p_value_spinbox)
            
            params_group.setLayout(params_layout)
            editor_layout.addWidget(params_group)
            
            # Models
            models_group = QGroupBox("Models")
            models_layout = QVBoxLayout()
            
            self.models_list = QListWidget()
            if len(prompt_set) > 4 and isinstance(prompt_set[4], list):
                for model in prompt_set[4]:
                    self.models_list.addItem(model)
            models_layout.addWidget(self.models_list)
            
            models_buttons_layout = QHBoxLayout()
            self.add_model_btn = QPushButton("Add Model")
            self.add_model_btn.clicked.connect(self.add_model)
            models_buttons_layout.addWidget(self.add_model_btn)
            
            self.remove_model_btn = QPushButton("Remove Model")
            self.remove_model_btn.clicked.connect(self.remove_model)
            models_buttons_layout.addWidget(self.remove_model_btn)
            
            models_layout.addLayout(models_buttons_layout)
            models_group.setLayout(models_layout)
            editor_layout.addWidget(models_group)
            
            # Apply button
            save_btn = QPushButton("Apply Changes")
            save_btn.clicked.connect(self.save_prompt_set_data)
            editor_layout.addWidget(save_btn)
            
            # Add the editor widget to the scroll area
            self.editor_layout.addWidget(editor_widget)
        
        def add_model(self):
            """Add a model to the models list"""
            model_name, ok = QInputDialog.getText(self, "Add Model", "Enter the model name:")
            
            if ok and model_name:
                self.models_list.addItem(model_name)
        
        def remove_model(self):
            """Remove the selected model from the models list"""
            current_item = self.models_list.currentItem()
            if current_item:
                row = self.models_list.row(current_item)
                self.models_list.takeItem(row)
        
        def save_prompt_set_data(self):
            """Save the prompt set data from the editor"""
            if not self.current_task or self.current_prompt_set_index is None:
                return
            
            # Collect data from the editor
            prompt = self.prompt_edit.toPlainText()
            system = self.system_edit.toPlainText()
            temp = str(self.temp_spinbox.value())
            p_value = str(self.p_value_spinbox.value())
            
            # Get models from the list widget
            models = []
            for i in range(self.models_list.count()):
                models.append(self.models_list.item(i).text())
            
            # Update the prompt set
            self.config_data[self.current_task]["prompts"][self.current_prompt_set_index] = [
                prompt, system, temp, p_value, models
            ]
            
            # Update the tree item text to reflect the models
            task_items = self.task_tree.findItems(self.current_task, Qt.MatchFlag.MatchExactly, 0)
            if task_items and task_items[0].childCount() > self.current_prompt_set_index:
                models_str = ", ".join(models) if models else "No models"
                task_items[0].child(self.current_prompt_set_index).setText(0, f"Prompt Set {self.current_prompt_set_index + 1} ({models_str})")
            
            QMessageBox.information(self, "Success", "Prompt set saved successfully!")
        
        def collect_current_editor_data(self):
            """Collect data from the current editor if it's open"""
            if not self.current_task:
                return
            
            # If editing a task
            if hasattr(self, 'fields_edit') and hasattr(self, 'required_edit'):
                self.save_task_data()
            
            # If editing a prompt set
            if self.current_prompt_set_index is not None and hasattr(self, 'prompt_edit'):
                self.save_prompt_set_data()
    
    
    def main():
        app = QApplication(sys.argv)
        editor = PromptConfigEditor()
        editor.show()
        sys.exit(app.exec())
    
    
    if __name__ == "__main__":
        main()
    

    back to top

    Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
    The source code of Software Heritage itself is available on our development forge.
    The source code files archived by Software Heritage are available under their own copyright and licenses.
    Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API