Skip to content

Commit dd9a65e

Browse files
feat: Let the user add their own system prompts
Related: #454 This PR is not ready yet. For the moment it adds the system prompts to DB and associates it to a workspace. It's missing to use the system prompt and actually send it to the LLM
1 parent 28af062 commit dd9a65e

File tree

5 files changed

+82
-4
lines changed

5 files changed

+82
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
"""add_workspace_system_prompt
2+
3+
Revision ID: a692c8b52308
4+
Revises: 5c2f3eee5f90
5+
Create Date: 2025-01-17 16:33:58.464223
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = 'a692c8b52308'
16+
down_revision: Union[str, None] = '5c2f3eee5f90'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
# Add column to workspaces table
23+
op.execute("ALTER TABLE workspaces ADD COLUMN system_prompt TEXT DEFAULT NULL;")
24+
25+
26+
def downgrade() -> None:
27+
op.execute("ALTER TABLE workspaces DROP COLUMN system_prompt;")

src/codegate/db/connection.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,20 @@ async def add_workspace(self, workspace_name: str) -> Optional[Workspace]:
275275
raise AlreadyExistsError(f"Workspace {workspace_name} already exists.")
276276
return added_workspace
277277

278+
async def update_workspace(self, workspace: Workspace) -> Optional[Workspace]:
279+
sql = text(
280+
"""
281+
UPDATE workspaces SET
282+
name = :name,
283+
system_prompt = :system_prompt
284+
WHERE id = :id
285+
RETURNING *
286+
"""
287+
)
288+
# We only pass an object to respect the signature of the function
289+
updated_workspace = await self._execute_update_pydantic_model(workspace, sql)
290+
return updated_workspace
291+
278292
async def update_session(self, session: Session) -> Optional[Session]:
279293
sql = text(
280294
"""
@@ -392,11 +406,11 @@ async def get_workspaces(self) -> List[WorkspaceActive]:
392406
workspaces = await self._execute_select_pydantic_model(WorkspaceActive, sql)
393407
return workspaces
394408

395-
async def get_workspace_by_name(self, name: str) -> List[Workspace]:
409+
async def get_workspace_by_name(self, name: str) -> Optional[Workspace]:
396410
sql = text(
397411
"""
398412
SELECT
399-
id, name
413+
id, name, system_prompt
400414
FROM workspaces
401415
WHERE name = :name
402416
"""

src/codegate/db/models.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,18 @@ class Setting(BaseModel):
4343
class Workspace(BaseModel):
4444
id: str
4545
name: str
46+
system_prompt: Optional[str]
4647

4748
@field_validator("name", mode="plain")
4849
@classmethod
49-
def name_must_be_alphanumeric(cls, value):
50+
def validate_name(cls, value):
5051
if not re.match(r"^[a-zA-Z0-9_-]+$", value):
5152
raise ValueError("name must be alphanumeric and can only contain _ and -")
53+
# Avoid workspace names that are the same as commands that way we can do stuff like
54+
# `codegate workspace list` and
55+
# `codegate workspace my-ws system-prompt` without any conflicts
56+
elif value in ["list", "add", "activate", "system-prompt"]:
57+
raise ValueError("name cannot be the same as a command")
5258
return value
5359

5460

src/codegate/pipeline/cli/commands.py

+14
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ async def _activate_workspace(self, args: List[str]) -> str:
104104
return "An error occurred while activating the workspace"
105105
return f"Workspace **{workspace_name}** has been activated"
106106

107+
async def _add_system_prompt(self, workspace_name: str, sys_prompt_lst: List[str]):
108+
updated_worksapce = await self.workspace_crud.update_workspace_system_prompt(workspace_name, sys_prompt_lst)
109+
if not updated_worksapce:
110+
return (
111+
f"Workspace system prompt not updated. "
112+
f"Check if the workspace **{workspace_name}** exists"
113+
)
114+
return (
115+
f"Workspace **{updated_worksapce.name}** system prompt "
116+
f"updated to:\n\n```{updated_worksapce.system_prompt}```"
117+
)
118+
107119
async def run(self, args: List[str]) -> str:
108120
if not args:
109121
return "Please provide a command. Use `codegate workspace -h` to see available commands"
@@ -112,6 +124,8 @@ async def run(self, args: List[str]) -> str:
112124
if command_to_execute is not None:
113125
return await command_to_execute(args[1:])
114126
else:
127+
if len(args) >= 2 and args[1] == "system-prompt":
128+
return await self._add_system_prompt(args[0], args[2:])
115129
return "Command not found. Use `codegate workspace -h` to see available commands"
116130

117131
@property

src/codegate/workspaces/crud.py

+18-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ async def _is_workspace_active(
6060
sessions = await self._db_reader.get_sessions()
6161
# The current implementation expects only one active session
6262
if len(sessions) != 1:
63-
raise RuntimeError("Something went wrong. No active session found.")
63+
raise WorkspaceCrudError("Something went wrong. More than one session found.")
6464

6565
session = sessions[0]
6666
return (session.active_workspace_id == selected_workspace.id, session, selected_workspace)
@@ -82,3 +82,20 @@ async def activate_workspace(self, workspace_name: str):
8282
db_recorder = DbRecorder()
8383
await db_recorder.update_session(session)
8484
return
85+
86+
async def update_workspace_system_prompt(
87+
self, workspace_name: str, sys_prompt_lst: List[str]
88+
) -> Optional[Workspace]:
89+
selected_workspace = await self._db_reader.get_workspace_by_name(workspace_name)
90+
if not selected_workspace:
91+
return None
92+
93+
system_prompt = " ".join(sys_prompt_lst)
94+
workspace_update = Workspace(
95+
id=selected_workspace.id,
96+
name=selected_workspace.name,
97+
system_prompt=system_prompt,
98+
)
99+
db_recorder = DbRecorder()
100+
updated_workspace = await db_recorder.update_workspace(workspace_update)
101+
return updated_workspace

0 commit comments

Comments
 (0)