first commit
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
"""Default L1/L2/L3 prompt templates."""
|
||||
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.prompts.service import PromptService
|
||||
|
||||
DEFAULT_TEMPLATES = {
|
||||
("code_review", "L1"): {
|
||||
"body": """You are a code reviewer. Review the following code diff and identify any potential bugs or issues.
|
||||
Only list what is wrong; do not provide locations or fixes.
|
||||
|
||||
Language: {{ language }}
|
||||
Diff:
|
||||
```
|
||||
{{ diff }}
|
||||
```
|
||||
|
||||
Report issues as a plain list.""",
|
||||
"variables_schema": {
|
||||
"language": {"type": "string"},
|
||||
"diff": {"type": "string"},
|
||||
},
|
||||
},
|
||||
("code_review", "L2"): {
|
||||
"body": """You are a code reviewer. Review the following code diff and identify potential bugs or issues.
|
||||
For each issue, provide:
|
||||
1. The defect type (one line)
|
||||
2. The line number range where it occurs
|
||||
3. A brief explanation
|
||||
|
||||
Language: {{ language }}
|
||||
Diff:
|
||||
```
|
||||
{{ diff }}
|
||||
```
|
||||
|
||||
Format each issue as:
|
||||
- Type: <type>
|
||||
Lines: <start>-<end>
|
||||
Explanation: <explanation>""",
|
||||
"variables_schema": {
|
||||
"language": {"type": "string"},
|
||||
"diff": {"type": "string"},
|
||||
},
|
||||
},
|
||||
("code_review", "L3"): {
|
||||
"body": """You are a code reviewer. Review the following code diff and identify potential bugs or issues.
|
||||
For each issue, provide:
|
||||
1. The defect type (one line)
|
||||
2. The line number range where it occurs
|
||||
3. A brief explanation
|
||||
4. A concrete fix suggestion
|
||||
|
||||
Language: {{ language }}
|
||||
Diff:
|
||||
```
|
||||
{{ diff }}
|
||||
```
|
||||
|
||||
Format each issue as:
|
||||
- Type: <type>
|
||||
Lines: <start>-<end>
|
||||
Explanation: <explanation>
|
||||
Fix: <fix>""",
|
||||
"variables_schema": {
|
||||
"language": {"type": "string"},
|
||||
"diff": {"type": "string"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def seed_default_templates(db: Session) -> None:
|
||||
service = PromptService(db)
|
||||
for (strategy_id, level), data in DEFAULT_TEMPLATES.items():
|
||||
existing = service.list_versions(strategy_id, level)
|
||||
if existing:
|
||||
continue
|
||||
service.create_version(
|
||||
strategy_id=strategy_id,
|
||||
level=level,
|
||||
body=data["body"],
|
||||
variables_schema=data["variables_schema"],
|
||||
)
|
||||
@@ -0,0 +1,113 @@
|
||||
"""Prompt template storage, versioning, and rendering service."""
|
||||
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from jinja2 import BaseLoader, Environment
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models import PromptTemplate, PromptTemplateVersion
|
||||
|
||||
|
||||
class PromptService:
|
||||
def __init__(self, db: Session):
|
||||
self.db = db
|
||||
self.jinja = Environment(loader=BaseLoader())
|
||||
|
||||
def get_or_create_template(self, strategy_id: str, level: str) -> PromptTemplate:
|
||||
template = (
|
||||
self.db.query(PromptTemplate)
|
||||
.filter_by(strategy_id=strategy_id, level=level)
|
||||
.first()
|
||||
)
|
||||
if not template:
|
||||
template = PromptTemplate(strategy_id=strategy_id, level=level)
|
||||
self.db.add(template)
|
||||
self.db.commit()
|
||||
self.db.refresh(template)
|
||||
return template
|
||||
|
||||
def create_version(
|
||||
self,
|
||||
strategy_id: str,
|
||||
level: str,
|
||||
body: str,
|
||||
variables_schema: Optional[Dict[str, Any]] = None,
|
||||
) -> PromptTemplateVersion:
|
||||
template = self.get_or_create_template(strategy_id, level)
|
||||
next_version = (
|
||||
self.db.query(PromptTemplateVersion)
|
||||
.filter_by(template_id=template.id)
|
||||
.count()
|
||||
+ 1
|
||||
)
|
||||
version = PromptTemplateVersion(
|
||||
template_id=template.id,
|
||||
version_number=next_version,
|
||||
body=body,
|
||||
variables_schema=variables_schema or self._infer_schema(body),
|
||||
)
|
||||
self.db.add(version)
|
||||
self.db.commit()
|
||||
self.db.refresh(version)
|
||||
return version
|
||||
|
||||
def get_version(self, version_id: str) -> Optional[PromptTemplateVersion]:
|
||||
from uuid import UUID
|
||||
|
||||
try:
|
||||
return self.db.query(PromptTemplateVersion).filter_by(id=UUID(version_id)).first()
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def list_versions(self, strategy_id: str, level: str) -> List[PromptTemplateVersion]:
|
||||
template = (
|
||||
self.db.query(PromptTemplate)
|
||||
.filter_by(strategy_id=strategy_id, level=level)
|
||||
.first()
|
||||
)
|
||||
if not template:
|
||||
return []
|
||||
return (
|
||||
self.db.query(PromptTemplateVersion)
|
||||
.filter_by(template_id=template.id)
|
||||
.order_by(PromptTemplateVersion.version_number)
|
||||
.all()
|
||||
)
|
||||
|
||||
def render(
|
||||
self,
|
||||
strategy_id: str,
|
||||
version: Optional[int],
|
||||
context: Dict[str, Any],
|
||||
) -> str:
|
||||
template = (
|
||||
self.db.query(PromptTemplate)
|
||||
.filter_by(strategy_id=strategy_id)
|
||||
.first()
|
||||
)
|
||||
if not template:
|
||||
raise ValueError(f"Prompt template not found: {strategy_id}")
|
||||
|
||||
query = self.db.query(PromptTemplateVersion).filter_by(template_id=template.id)
|
||||
if version:
|
||||
version_obj = query.filter_by(version_number=version).first()
|
||||
else:
|
||||
version_obj = query.order_by(PromptTemplateVersion.version_number.desc()).first()
|
||||
|
||||
if not version_obj:
|
||||
raise ValueError(f"Prompt version not found: {strategy_id} v{version}")
|
||||
|
||||
jinja_template = self.jinja.from_string(version_obj.body)
|
||||
return jinja_template.render(**context)
|
||||
|
||||
def _infer_schema(self, body: str) -> Dict[str, Any]:
|
||||
"""Infer required variables from Jinja2 template."""
|
||||
from jinja2.meta import find_undeclared_variables
|
||||
|
||||
ast = self.jinja.parse(body)
|
||||
variables = find_undeclared_variables(ast)
|
||||
return {var: {"type": "string"} for var in variables}
|
||||
|
||||
|
||||
def get_prompt_service(db: Session) -> PromptService:
|
||||
return PromptService(db)
|
||||
Reference in New Issue
Block a user