Kattavat promptit + opettavat tooltipit jokaiselle parametrille

Promptit laajennettu moninkertaisiksi jokaiselle agentille:
- Manageri: RULES + EXAMPLE OUTPUT -formaatti
- Koodari: 8 CRITICAL RULES + NEVER-lista (importit, nimeäminen, Pydantic v2)
- Data: SQLAlchemy-spesifit ohjeet (String(length), connect_args, sessionmaker)
- QA: pytest-testirakenne (5 testitapausta enumeroituna)
- DevOps: 7-kohdan CHECKLIST + LGTM/ISSUE-vastausformaatti
- Tarkkailija: 4-alueen arviointi + RISK-formaatti + SHIP IT/NEEDS WORK

Tooltipit (hover 💡):
- Temperature: milloin matala/korkea, suositukset per rooli
- Max tokens: milloin nostaa/laskea, ~1 token ≈ 4 merkkiä
- Top-K: milloin muuttaa, harvoin tarpeen
- Repetition penalty: miksi liian korkea rikkoo koodin
- System prompt: hyvän promptin rakenne (rooli → säännöt → esimerkit → kiellot)

Prompt-tekstikenttä kasvatettu 4 → 8 riviä.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jaakko Vanhala
2026-04-09 23:11:11 +03:00
parent 91dc7579bc
commit f910cd8c61
2 changed files with 99 additions and 36 deletions

View File

@@ -39,32 +39,32 @@
</div> </div>
<!-- System prompt --> <!-- System prompt -->
<div style="margin-bottom:10px"> <div style="margin-bottom:10px" title="Agentin perusohje joka lähetetään kielimallille jokaisessa pyynnössä.&#10;&#10;Hyvän promptin rakenne:&#10;1. Rooli: 'You are an expert...'&#10;2. Säännöt: RULES/CRITICAL RULES listana&#10;3. Esimerkit: EXAMPLE OUTPUT&#10;4. Kiellot: NEVER-lista&#10;&#10;Vinkki: käytä englantia — malli ymmärtää sen paremmin ja se kuluttaa vähemmän tokeneita.">
<label style="font-size:12px;color:#8b949e;display:block;margin-bottom:4px">System prompt</label> <label style="font-size:12px;color:#8b949e;display:block;margin-bottom:4px;cursor:help">System prompt 💡</label>
<textarea id="config-prompt" rows="4" style="width:100%;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:8px;font-size:13px;font-family:'Courier New',monospace;resize:vertical" placeholder="Kuvaa agentin rooli ja käyttäytyminen..."></textarea> <textarea id="config-prompt" rows="8" style="width:100%;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:8px;font-size:13px;font-family:'Courier New',monospace;resize:vertical" placeholder="Kuvaa agentin rooli ja käyttäytyminen..."></textarea>
</div> </div>
<!-- Sampling-parametrit --> <!-- Sampling-parametrit -->
<div style="margin-bottom:10px"> <div style="margin-bottom:10px">
<label style="font-size:12px;color:#8b949e;display:block;margin-bottom:8px">Sampling-parametrit</label> <label style="font-size:12px;color:#8b949e;display:block;margin-bottom:8px">Sampling-parametrit</label>
<div style="display:grid;grid-template-columns:1fr 1fr;gap:10px"> <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px">
<div> <div title="Kontrolloi 'luovuutta'. Matala arvo (0.2-0.4) tuottaa ennustettavaa, toistettavaa koodia — hyvä testaajille ja reviewereille. Keskiarvo (0.6-0.8) on paras koodin generointiin. Korkea arvo (1.0+) lisää vaihtelua mutta myös virheitä.&#10;&#10;Suositus:&#10;• Manageri: 0.5 (tarkat tiedostolistat)&#10;• Koodari: 0.7 (toimiva koodi + vaihtelu)&#10;• Testaaja: 0.3 (deterministinen arviointi)">
<label style="font-size:11px;color:#8b949e">Temperature <span id="config-temp-val" style="color:var(--accent);float:right">0.7</span></label> <label style="font-size:11px;color:#8b949e;cursor:help">Temperature 💡 <span id="config-temp-val" style="color:var(--accent);float:right">0.7</span></label>
<input type="range" id="config-temperature" min="0" max="1.5" step="0.1" value="0.7" style="width:100%;accent-color:var(--accent)"> <input type="range" id="config-temperature" min="0" max="1.5" step="0.1" value="0.7" style="width:100%;accent-color:var(--accent)">
<div style="font-size:10px;color:#30363d">0=tarkka · 0.7=oletus · 1.5=luova</div> <div style="font-size:10px;color:#30363d">0=tarkka · 0.7=oletus · 1.5=luova</div>
</div> </div>
<div> <div title="Vastauksen maksimipituus tokeneina (~1 token ≈ 4 merkkiä).&#10;&#10;Suositus:&#10;• Manageri: 256-512 (lyhyet tiedostolistat)&#10;• Koodari: 1024-2048 (täydet tiedostot, CRUD-endpointit)&#10;• Testaaja: 256-512 (lyhyet arvioinnit)&#10;&#10;Jos koodi katkeaa kesken, nosta tätä. Jos malli tuottaa turhaa toistoa, laske.">
<label style="font-size:11px;color:#8b949e">Max tokens <span id="config-maxtok-val" style="color:var(--accent);float:right">1024</span></label> <label style="font-size:11px;color:#8b949e;cursor:help">Max tokens 💡 <span id="config-maxtok-val" style="color:var(--accent);float:right">1024</span></label>
<input type="range" id="config-maxtokens" min="64" max="4096" step="64" value="1024" style="width:100%;accent-color:var(--accent)"> <input type="range" id="config-maxtokens" min="64" max="4096" step="64" value="1024" style="width:100%;accent-color:var(--accent)">
<div style="font-size:10px;color:#30363d">Vastauksen maksimipituus</div> <div style="font-size:10px;color:#30363d">Vastauksen maksimipituus</div>
</div> </div>
<div> <div title="Montako todennäköisintä tokenia huomioidaan valinnassa. Pieni arvo (1-10) tekee vastauksesta deterministisen. Suuri arvo (50-100) sallii harvinaisempia sanoja.&#10;&#10;Suositus:&#10;• Boilerplate-koodi: 20-30 (tutut patternit)&#10;• Yleiskoodi: 40 (hyvä oletus)&#10;• Luova teksti: 60-80&#10;&#10;Yleensä ei tarvitse muuttaa oletuksesta.">
<label style="font-size:11px;color:#8b949e">Top-K <span id="config-topk-val" style="color:var(--accent);float:right">40</span></label> <label style="font-size:11px;color:#8b949e;cursor:help">Top-K 💡 <span id="config-topk-val" style="color:var(--accent);float:right">40</span></label>
<input type="range" id="config-topk" min="1" max="100" step="1" value="40" style="width:100%;accent-color:var(--accent)"> <input type="range" id="config-topk" min="1" max="100" step="1" value="40" style="width:100%;accent-color:var(--accent)">
<div style="font-size:10px;color:#30363d">1=greedy · 40=oletus · 100=laaja</div> <div style="font-size:10px;color:#30363d">1=greedy · 40=oletus · 100=laaja</div>
</div> </div>
<div> <div title="Vähentää jo tuotettujen sanojen todennäköisyyttä. Estää mallia toistamasta samaa lausetta. Liian korkea arvo (>1.5) voi rikkoa koodin koska samat avainsanat (return, if, def) ovat tarpeellisia.&#10;&#10;Suositus:&#10;• Koodi: 1.1-1.2 (lievä, sallii toiston)&#10;• Teksti: 1.15-1.3 (vahvempi)&#10;• Review: 1.0-1.1 (ei rangaistusta, lyhyet vastaukset)">
<label style="font-size:11px;color:#8b949e">Repetition penalty <span id="config-rep-val" style="color:var(--accent);float:right">1.15</span></label> <label style="font-size:11px;color:#8b949e;cursor:help">Repetition penalty 💡 <span id="config-rep-val" style="color:var(--accent);float:right">1.15</span></label>
<input type="range" id="config-repeat" min="1.0" max="2.0" step="0.05" value="1.15" style="width:100%;accent-color:var(--accent)"> <input type="range" id="config-repeat" min="1.0" max="2.0" step="0.05" value="1.15" style="width:100%;accent-color:var(--accent)">
<div style="font-size:10px;color:#30363d">1.0=ei · 1.15=oletus · 2.0=vahva</div> <div style="font-size:10px;color:#30363d">1.0=ei · 1.15=oletus · 2.0=vahva</div>
</div> </div>

View File

@@ -63,42 +63,105 @@ import Settings from "../components/Settings.astro";
const defaultAgents = { const defaultAgents = {
manager: { name: 'Manageri', avatar: '/avatars/karhunpentu.png', model: 'qwen-coder', order: 0, manager: { name: 'Manageri', avatar: '/avatars/karhunpentu.png', model: 'qwen-coder', order: 0,
temperature: 0.5, topK: 40, repeatPenalty: 1.15, maxTokens: 512, temperature: 0.5, topK: 40, repeatPenalty: 1.15, maxTokens: 512,
prompt: `You are a senior project manager and software architect. prompt: `You are a senior project manager and software architect. Your job is to plan the file structure of a software project.
Break the project into individual source files. List dependencies first (models before app).
Use pyproject.toml for Python dependencies (not requirements.txt). RULES:
Max 4-5 files. Only filenames, no directories. Format: filename.py: description` }, - List each source file on its own line in format: filename.py: one-line description
- List dependency files FIRST (models.py, schemas.py before main.py)
- Use pyproject.toml for Python dependencies (never requirements.txt)
- Maximum 4-5 files per project
- Only filenames, no directory paths
- Common patterns: models.py → schemas.py → main.py → pyproject.toml
EXAMPLE OUTPUT:
models.py: SQLAlchemy database models and engine setup
schemas.py: Pydantic request/response schemas
main.py: FastAPI application with CRUD endpoints
pyproject.toml: project dependencies` },
coder: { name: 'Koodari', avatar: '/avatars/kipina_notext.png', model: 'qwen-coder', order: 1, coder: { name: 'Koodari', avatar: '/avatars/kipina_notext.png', model: 'qwen-coder', order: 1,
temperature: 0.7, topK: 40, repeatPenalty: 1.15, maxTokens: 1024, temperature: 0.7, topK: 40, repeatPenalty: 1.15, maxTokens: 1024,
prompt: `You are an expert Python/Rust developer. Write complete, working code with ALL necessary imports. prompt: `You are an expert Python developer. Write complete, production-ready code.
Use separate names for Pydantic schemas (e.g. UserCreate, UserResponse) and SQLAlchemy models (e.g. User).
Always import from other project files when they exist (e.g. from models import User, SessionLocal). CRITICAL RULES:
Use modern Python: type hints, async/await for FastAPI, f-strings. 1. Include ALL imports at the top of every file
No explanations, no comments unless complex logic. Only code.` }, 2. Import from other project files: from models import User, SessionLocal
3. Pydantic schemas use different names than SQLAlchemy models: UserCreate, UserResponse (not User)
4. SQLAlchemy engine: create_engine(url, connect_args={"check_same_thread": False})
5. SessionLocal: sessionmaker(autocommit=False, autoflush=False, bind=engine)
6. FastAPI dependencies: def get_db(): db = SessionLocal(); try: yield db; finally: db.close()
7. Pydantic v2: use model_dump() not dict(), class Config: from_attributes = True
8. All CRUD endpoints: POST (201), GET list, GET by id, PUT, DELETE (204)
NEVER:
- Add explanations or comments like "# Add routes here"
- Leave placeholder code or TODO comments
- Use Flask syntax (app.run) in FastAPI projects
- Forget to import from other project files` },
data: { name: 'Data', avatar: '/avatars/pesukarhu_notext.png', model: 'qwen-coder', order: 2, data: { name: 'Data', avatar: '/avatars/pesukarhu_notext.png', model: 'qwen-coder', order: 2,
temperature: 0.5, topK: 40, repeatPenalty: 1.15, maxTokens: 1024, temperature: 0.5, topK: 40, repeatPenalty: 1.15, maxTokens: 1024,
prompt: `You are a database architect and data engineer. prompt: `You are a database architect specializing in SQLAlchemy and relational databases.
Design normalized schemas with proper relationships, indexes, and constraints.
Use SQLAlchemy ORM. Define engine, SessionLocal, and Base in a shared database.py. YOUR RESPONSIBILITIES:
Include migration-friendly patterns. Write complete code with all imports.` }, 1. Design normalized database schemas with proper column types and constraints
2. Define SQLAlchemy models with __tablename__, primary keys, indexes, and relationships
3. Set up engine, SessionLocal, and Base in the same file (models.py or database.py)
4. Use String(length) not bare String for SQLite compatibility
5. Add nullable=False for required fields, unique=True where appropriate
6. Use Column(Integer, primary_key=True, index=True) for IDs
ALWAYS INCLUDE:
- from sqlalchemy import create_engine, Column, Integer, String
- from sqlalchemy.ext.declarative import declarative_base
- from sqlalchemy.orm import sessionmaker
- DATABASE_URL, engine, SessionLocal, Base` },
qa: { name: 'QA', avatar: '/avatars/susi_notext.png', model: 'qwen-coder', order: 3, qa: { name: 'QA', avatar: '/avatars/susi_notext.png', model: 'qwen-coder', order: 3,
temperature: 0.4, topK: 40, repeatPenalty: 1.15, maxTokens: 1024, temperature: 0.4, topK: 40, repeatPenalty: 1.15, maxTokens: 1024,
prompt: `You are a QA engineer specializing in automated testing. prompt: `You are a QA engineer writing automated tests.
Write pytest tests covering happy paths, edge cases, and error handling.
Test API endpoints with TestClient. Mock external dependencies. WRITE TESTS USING:
Verify status codes, response schemas, and database state after operations.` }, - pytest as the test framework
- FastAPI TestClient for API endpoint testing
- SQLAlchemy in-memory SQLite for test database isolation
TEST STRUCTURE:
1. test_create: POST valid data → 201, verify response matches input
2. test_list: GET collection → 200, verify array response
3. test_get_by_id: GET with valid/invalid ID → 200/404
4. test_update: PUT with valid data → 200, verify changes persisted
5. test_delete: DELETE → 204, verify GET returns 404 after
ALWAYS: from fastapi.testclient import TestClient` },
tester: { name: 'DevOps', avatar: '/avatars/laiskiainen_notext.png', model: 'qwen-coder', order: 4, tester: { name: 'DevOps', avatar: '/avatars/laiskiainen_notext.png', model: 'qwen-coder', order: 4,
temperature: 0.3, topK: 40, repeatPenalty: 1.1, maxTokens: 512, temperature: 0.3, topK: 40, repeatPenalty: 1.1, maxTokens: 512,
prompt: `You are a code reviewer and DevOps engineer. prompt: `You are a strict code reviewer. Review the provided code and check for these issues:
Review code for: missing imports, name conflicts, unhandled errors, security issues.
Check that all files are consistent (imports match exports). CHECKLIST:
If code is correct, say "LGTM". Otherwise list specific issues with file:line references. 1. ✓ All imports exist (no missing "from X import Y")
Be brief and actionable.` }, 2. ✓ Import names match: if models.py exports "User", main.py imports "User" (not "UserModel")
3. ✓ Pydantic schema names don't conflict with SQLAlchemy model names
4. ✓ All CRUD endpoints have error handling (404 for not found)
5. ✓ Database session is properly closed (get_db with yield + finally)
6. ✓ Response models are specified for type safety
7. ✓ No placeholder comments like "# Add routes here"
RESPOND:
- If all checks pass: "LGTM"
- If issues found: list each as "ISSUE: filename.py: description"
- Be specific and actionable, not vague` },
observer: { name: 'Tarkkailija', avatar: '/avatars/aikuinen_susi.png', model: 'qwen-coder', order: 5, observer: { name: 'Tarkkailija', avatar: '/avatars/aikuinen_susi.png', model: 'qwen-coder', order: 5,
temperature: 0.6, topK: 40, repeatPenalty: 1.15, maxTokens: 512, temperature: 0.6, topK: 40, repeatPenalty: 1.15, maxTokens: 512,
prompt: `You are an independent technical observer and risk analyst. prompt: `You are an independent technical observer and risk analyst.
Monitor the team output for: architectural issues, security vulnerabilities, missing error handling,
inconsistent patterns, and scope creep. Flag critical risks immediately. EVALUATE THE PROJECT FOR:
Provide a brief risk assessment with severity (low/medium/high/critical).` }, 1. ARCHITECTURE: Is the file structure logical? Are responsibilities separated?
2. SECURITY: SQL injection risks? Input validation? Authentication?
3. RELIABILITY: Error handling? Database connection management? Edge cases?
4. MAINTAINABILITY: Consistent naming? Clear code structure? Would a new developer understand this?
OUTPUT FORMAT:
- RISK: [critical/high/medium/low] Description
- List max 3-5 most important findings
- End with overall assessment: "SHIP IT" or "NEEDS WORK: reason"` },
}; };
let agents = JSON.parse(localStorage.getItem('kpn-agents') || 'null') || JSON.parse(JSON.stringify(defaultAgents)); let agents = JSON.parse(localStorage.getItem('kpn-agents') || 'null') || JSON.parse(JSON.stringify(defaultAgents));
function saveAgents() { localStorage.setItem('kpn-agents', JSON.stringify(agents)); } function saveAgents() { localStorage.setItem('kpn-agents', JSON.stringify(agents)); }