Skip to content

Commit

Permalink
Rename workspaces system-prompt to custom-instructions (#713)
Browse files Browse the repository at this point in the history
* Rename workspaces system-prompt to custom-instructions

Check the [Discord discussion](https://discord.com/channels/1184987096302239844/1317203257051054120/1331520854101856327)
for further context. There was a poll conducted and we decided
to carry on the renaming

* Fix unit tests
aponcedeleonch authored Jan 22, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 7c85486 commit c9d4737
Showing 11 changed files with 99 additions and 69 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
"""rename system_prompt
Revision ID: 90d5471db49a
Revises: 4dec3e456c9e
Create Date: 2025-01-22 09:56:21.520839+00:00
"""

from typing import Sequence, Union

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "90d5471db49a"
down_revision: Union[str, None] = "4dec3e456c9e"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None


def upgrade() -> None:
op.execute("ALTER TABLE workspaces RENAME COLUMN system_prompt TO custom_instructions;")


def downgrade() -> None:
op.execute("ALTER TABLE workspaces RENAME COLUMN custom_instructions TO system_prompt;")
26 changes: 14 additions & 12 deletions src/codegate/api/v1.py
Original file line number Diff line number Diff line change
@@ -228,35 +228,37 @@ async def get_workspace_messages(workspace_name: str) -> List[Conversation]:


@v1.get(
"/workspaces/{workspace_name}/system-prompt",
"/workspaces/{workspace_name}/custom-instructions",
tags=["Workspaces"],
generate_unique_id_function=uniq_name,
)
async def get_workspace_system_prompt(workspace_name: str) -> v1_models.SystemPrompt:
"""Get the system prompt for a workspace."""
async def get_workspace_custom_instructions(workspace_name: str) -> v1_models.CustomInstructions:
"""Get the custom instructions of a workspace."""
try:
ws = await wscrud.get_workspace_by_name(workspace_name)
except crud.WorkspaceDoesNotExistError:
raise HTTPException(status_code=404, detail="Workspace does not exist")
except Exception:
raise HTTPException(status_code=500, detail="Internal server error")

if ws.system_prompt is None:
return v1_models.SystemPrompt(prompt="")
if ws.custom_instructions is None:
return v1_models.CustomInstructions(prompt="")

return v1_models.SystemPrompt(prompt=ws.system_prompt)
return v1_models.CustomInstructions(prompt=ws.custom_instructions)


@v1.put(
"/workspaces/{workspace_name}/system-prompt",
"/workspaces/{workspace_name}/custom-instructions",
tags=["Workspaces"],
generate_unique_id_function=uniq_name,
status_code=204,
)
async def set_workspace_system_prompt(workspace_name: str, request: v1_models.SystemPrompt):
async def set_workspace_custom_instructions(
workspace_name: str, request: v1_models.CustomInstructions
):
try:
# This already checks if the workspace exists
await wscrud.update_workspace_system_prompt(workspace_name, [request.prompt])
await wscrud.update_workspace_custom_instructions(workspace_name, [request.prompt])
except crud.WorkspaceDoesNotExistError:
raise HTTPException(status_code=404, detail="Workspace does not exist")
except Exception:
@@ -266,15 +268,15 @@ async def set_workspace_system_prompt(workspace_name: str, request: v1_models.Sy


@v1.delete(
"/workspaces/{workspace_name}/system-prompt",
"/workspaces/{workspace_name}/custom-instructions",
tags=["Workspaces"],
generate_unique_id_function=uniq_name,
status_code=204,
)
async def delete_workspace_system_prompt(workspace_name: str):
async def delete_workspace_custom_instructions(workspace_name: str):
try:
# This already checks if the workspace exists
await wscrud.update_workspace_system_prompt(workspace_name, [])
await wscrud.update_workspace_custom_instructions(workspace_name, [])
except crud.WorkspaceDoesNotExistError:
raise HTTPException(status_code=404, detail="Workspace does not exist")
except Exception:
2 changes: 1 addition & 1 deletion src/codegate/api/v1_models.py
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ class Workspace(pydantic.BaseModel):
is_active: bool


class SystemPrompt(pydantic.BaseModel):
class CustomInstructions(pydantic.BaseModel):
prompt: str


12 changes: 6 additions & 6 deletions src/codegate/db/connection.py
Original file line number Diff line number Diff line change
@@ -271,7 +271,7 @@ async def add_workspace(self, workspace_name: str) -> Workspace:
It may raise a ValidationError if the workspace name is invalid.
or a AlreadyExistsError if the workspace already exists.
"""
workspace = Workspace(id=str(uuid.uuid4()), name=workspace_name, system_prompt=None)
workspace = Workspace(id=str(uuid.uuid4()), name=workspace_name, custom_instructions=None)
sql = text(
"""
INSERT INTO workspaces (id, name)
@@ -294,7 +294,7 @@ async def update_workspace(self, workspace: Workspace) -> Workspace:
"""
UPDATE workspaces SET
name = :name,
system_prompt = :system_prompt
custom_instructions = :custom_instructions
WHERE id = :id
RETURNING *
"""
@@ -477,7 +477,7 @@ async def get_archived_workspaces(self) -> List[Workspace]:
sql = text(
"""
SELECT
id, name, system_prompt
id, name, custom_instructions
FROM workspaces
WHERE deleted_at IS NOT NULL
ORDER BY deleted_at DESC
@@ -490,7 +490,7 @@ async def get_workspace_by_name(self, name: str) -> Optional[Workspace]:
sql = text(
"""
SELECT
id, name, system_prompt
id, name, custom_instructions
FROM workspaces
WHERE name = :name AND deleted_at IS NULL
"""
@@ -505,7 +505,7 @@ async def get_archived_workspace_by_name(self, name: str) -> Optional[Workspace]
sql = text(
"""
SELECT
id, name, system_prompt
id, name, custom_instructions
FROM workspaces
WHERE name = :name AND deleted_at IS NOT NULL
"""
@@ -531,7 +531,7 @@ async def get_active_workspace(self) -> Optional[ActiveWorkspace]:
sql = text(
"""
SELECT
w.id, w.name, w.system_prompt, s.id as session_id, s.last_update
w.id, w.name, w.custom_instructions, s.id as session_id, s.last_update
FROM sessions s
INNER JOIN workspaces w ON w.id = s.active_workspace_id
"""
4 changes: 2 additions & 2 deletions src/codegate/db/models.py
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@ class Setting(BaseModel):
class Workspace(BaseModel):
id: str
name: WorskpaceNameStr
system_prompt: Optional[str]
custom_instructions: Optional[str]


class Session(BaseModel):
@@ -99,6 +99,6 @@ class WorkspaceActive(BaseModel):
class ActiveWorkspace(BaseModel):
id: str
name: str
system_prompt: Optional[str]
custom_instructions: Optional[str]
session_id: str
last_update: datetime.datetime
4 changes: 2 additions & 2 deletions src/codegate/pipeline/cli/cli.py
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
PipelineResult,
PipelineStep,
)
from codegate.pipeline.cli.commands import SystemPrompt, Version, Workspace
from codegate.pipeline.cli.commands import CustomInstructions, Version, Workspace

HELP_TEXT = """
## CodeGate CLI\n
@@ -32,7 +32,7 @@ async def codegate_cli(command):
available_commands = {
"version": Version().exec,
"workspace": Workspace().exec,
"system-prompt": SystemPrompt().exec,
"custom-instructions": CustomInstructions().exec,
}
out_func = available_commands.get(command[0])
if out_func is None:
59 changes: 30 additions & 29 deletions src/codegate/pipeline/cli/commands.py
Original file line number Diff line number Diff line change
@@ -355,40 +355,40 @@ def help(self) -> str:
)


class SystemPrompt(CodegateCommandSubcommand):
class CustomInstructions(CodegateCommandSubcommand):

def __init__(self):
self.workspace_crud = crud.WorkspaceCrud()

@property
def command_name(self) -> str:
return "system-prompt"
return "custom-instructions"

@property
def flags(self) -> List[str]:
"""
Flags for the system-prompt command.
Flags for the custom-instructions command.
-w: Workspace name
"""
return ["-w"]

@property
def subcommands(self) -> Dict[str, Callable[[List[str]], Awaitable[str]]]:
return {
"set": self._set_system_prompt,
"show": self._show_system_prompt,
"reset": self._reset_system_prompt,
"set": self._set_custom_instructions,
"show": self._show_custom_instructions,
"reset": self._reset_custom_instructions,
}

async def _set_system_prompt(self, flags: Dict[str, str], args: List[str]) -> str:
async def _set_custom_instructions(self, flags: Dict[str, str], args: List[str]) -> str:
"""
Set the system prompt of a workspace
Set the custom instructions of a workspace
If a workspace name is not provided, the active workspace is used
"""
if len(args) == 0:
return (
"Please provide a workspace name and a system prompt. "
"Use `codegate workspace system-prompt -w <workspace_name> <system_prompt>`"
"Please provide a workspace name and custom instructions to use. "
"Use `codegate workspace custom-instructions -w <workspace_name> <instructions>`"
)

workspace_name = flags.get("-w")
@@ -397,19 +397,20 @@ async def _set_system_prompt(self, flags: Dict[str, str], args: List[str]) -> st
workspace_name = active_workspace.name

try:
updated_worksapce = await self.workspace_crud.update_workspace_system_prompt(
updated_worksapce = await self.workspace_crud.update_workspace_instructions(
workspace_name, args
)
except crud.WorkspaceDoesNotExistError:
return (
f"Workspace system prompt not updated. Workspace `{workspace_name}` doesn't exist"
f"Workspace custom instructions not updated. "
f"Workspace `{workspace_name}` doesn't exist"
)

return f"Workspace `{updated_worksapce.name}` system prompt updated."
return f"Workspace `{updated_worksapce.name}` custom instructions updated."

async def _show_system_prompt(self, flags: Dict[str, str], args: List[str]) -> str:
async def _show_custom_instructions(self, flags: Dict[str, str], args: List[str]) -> str:
"""
Show the system prompt of a workspace
Show the custom instructions of a workspace
If a workspace name is not provided, the active workspace is used
"""
workspace_name = flags.get("-w")
@@ -422,15 +423,15 @@ async def _show_system_prompt(self, flags: Dict[str, str], args: List[str]) -> s
except crud.WorkspaceDoesNotExistError:
return f"Workspace `{workspace_name}` doesn't exist"

sysprompt = workspace.system_prompt
sysprompt = workspace.custom_instructions
if not sysprompt:
return f"Workspace **{workspace.name}** system prompt is unset."
return f"Workspace **{workspace.name}** custom instructions is unset."

return f"Workspace **{workspace.name}** system prompt:\n\n{sysprompt}."
return f"Workspace **{workspace.name}** custom instructions:\n\n{sysprompt}."

async def _reset_system_prompt(self, flags: Dict[str, str], args: List[str]) -> str:
async def _reset_custom_instructions(self, flags: Dict[str, str], args: List[str]) -> str:
"""
Reset the system prompt of a workspace
Reset the custom instructions of a workspace
If a workspace name is not provided, the active workspace is used
"""
workspace_name = flags.get("-w")
@@ -439,28 +440,28 @@ async def _reset_system_prompt(self, flags: Dict[str, str], args: List[str]) ->
workspace_name = active_workspace.name

try:
updated_worksapce = await self.workspace_crud.update_workspace_system_prompt(
updated_worksapce = await self.workspace_crud.update_workspace_custom_instructions(
workspace_name, [""]
)
except crud.WorkspaceDoesNotExistError:
return f"Workspace `{workspace_name}` doesn't exist"

return f"Workspace `{updated_worksapce.name}` system prompt reset."
return f"Workspace `{updated_worksapce.name}` custom instructions reset."

@property
def help(self) -> str:
return (
"### CodeGate System Prompt\n"
"Manage the system prompts of workspaces.\n\n"
"*Note*: If you want to update the system prompt using files please go to the "
"### CodeGate Custom Instructions\n"
"Manage the custom instructionss of workspaces.\n\n"
"*Note*: If you want to update the custom instructions using files please go to the "
"[dashboard](http://localhost:9090).\n\n"
"**Usage**: `codegate system-prompt -w <workspace_name> <command>`\n\n"
"**Usage**: `codegate custom-instructions -w <workspace_name> <command>`\n\n"
"*args*:\n"
"- `workspace_name`: Optional workspace name. If not specified will use the "
"active workspace\n\n"
"Available commands:\n"
"- `set`: Set the system prompt of the workspace\n"
"- `set`: Set the custom instructions of the workspace\n"
" - *args*:\n"
" - `system_prompt`: The system prompt to set\n"
" - **Usage**: `codegate system-prompt -w <workspace_name> set <system_prompt>`\n"
" - `instructions`: The custom instructions to set\n"
" - **Usage**: `codegate custom-instructions -w <workspace_name> set <instructions>`\n"
)
16 changes: 8 additions & 8 deletions src/codegate/pipeline/system_prompt/codegate.py
Original file line number Diff line number Diff line change
@@ -26,17 +26,17 @@ def name(self) -> str:
"""
return "system-prompt"

async def _get_workspace_system_prompt(self) -> str:
async def _get_workspace_custom_instructions(self) -> str:
wksp_crud = WorkspaceCrud()
workspace = await wksp_crud.get_active_workspace()
if not workspace:
return ""

return workspace.system_prompt
return workspace.custom_instructions

async def _construct_system_prompt(
self,
wrksp_sys_prompt: str,
wrksp_custom_instr: str,
req_sys_prompt: Optional[str],
should_add_codegate_sys_prompt: bool,
) -> ChatCompletionSystemMessage:
@@ -52,8 +52,8 @@ def _start_or_append(existing_prompt: str, new_prompt: str) -> str:
system_prompt = _start_or_append(system_prompt, self.codegate_system_prompt)

# Add workspace system prompt if present
if wrksp_sys_prompt:
system_prompt = _start_or_append(system_prompt, wrksp_sys_prompt)
if wrksp_custom_instr:
system_prompt = _start_or_append(system_prompt, wrksp_custom_instr)

# Add request system prompt if present
if req_sys_prompt and "codegate" not in req_sys_prompt.lower():
@@ -72,12 +72,12 @@ async def process(
to the existing system prompt
"""

wrksp_sys_prompt = await self._get_workspace_system_prompt()
wrksp_custom_instructions = await self._get_workspace_custom_instructions()
should_add_codegate_sys_prompt = await self._should_add_codegate_system_prompt(context)

# Nothing to do if no secrets or bad_packages are found and we don't have a workspace
# system prompt
if not should_add_codegate_sys_prompt and not wrksp_sys_prompt:
if not should_add_codegate_sys_prompt and not wrksp_custom_instructions:
return PipelineResult(request=request, context=context)

new_request = request.copy()
@@ -92,7 +92,7 @@ async def process(
req_sys_prompt = request_system_message.get("content")

system_prompt = await self._construct_system_prompt(
wrksp_sys_prompt, req_sys_prompt, should_add_codegate_sys_prompt
wrksp_custom_instructions, req_sys_prompt, should_add_codegate_sys_prompt
)
context.add_alert(self.name, trigger_string=system_prompt)
if not request_system_message:
Loading

0 comments on commit c9d4737

Please sign in to comment.