feat: add fission-aware ai prompts

This commit is contained in:
Naeel
2026-04-28 07:31:19 +03:00
parent 9168fc2d9e
commit 82eba079f6
4 changed files with 529 additions and 18 deletions
+230
View File
@@ -0,0 +1,230 @@
package api
import (
"fmt"
"strings"
)
const (
aiModeChat = "chat"
aiModeCodegen = "codegen"
aiModeExplain = "explain"
)
type llmMessage struct {
Role string `json:"role"`
Content string `json:"content"`
}
type aiPromptRequest struct {
Mode string `json:"mode"`
Language string `json:"language"`
Name string `json:"name"`
Description string `json:"description"`
Code string `json:"code"`
Question string `json:"question"`
}
type llmChatRequest struct {
Model string `json:"model"`
Messages []llmMessage `json:"messages"`
MaxTokens int `json:"max_tokens"`
}
func buildLLMChatRequest(req aiPromptRequest) (llmChatRequest, error) {
mode := normalizeAIMode(req.Mode)
lang := normalizeLanguage(req.Language)
switch mode {
case aiModeCodegen:
if lang == "" {
return llmChatRequest{}, fmt.Errorf("language is required")
}
return llmChatRequest{
Model: "gpt-oss-120b",
Messages: []llmMessage{
{Role: "system", Content: buildCodegenSystemPrompt(lang)},
{Role: "user", Content: buildCodegenUserPrompt(lang, req.Name, req.Description)},
},
MaxTokens: 1024,
}, nil
case aiModeExplain:
if lang == "" {
return llmChatRequest{}, fmt.Errorf("language is required")
}
if strings.TrimSpace(req.Code) == "" {
return llmChatRequest{}, fmt.Errorf("code is required")
}
return llmChatRequest{
Model: "gpt-oss-120b",
Messages: []llmMessage{
{Role: "system", Content: buildExplainSystemPrompt(lang)},
{Role: "user", Content: buildExplainUserPrompt(lang, req.Code)},
},
MaxTokens: 1024,
}, nil
default:
question := strings.TrimSpace(req.Question)
if question == "" {
return llmChatRequest{}, fmt.Errorf("question is required")
}
return llmChatRequest{
Model: "gpt-oss-120b",
Messages: []llmMessage{
{Role: "system", Content: buildChatSystemPrompt()},
{Role: "user", Content: question},
},
MaxTokens: 1024,
}, nil
}
}
func normalizeAIMode(mode string) string {
switch strings.ToLower(strings.TrimSpace(mode)) {
case aiModeCodegen:
return aiModeCodegen
case aiModeExplain:
return aiModeExplain
default:
return aiModeChat
}
}
func normalizeLanguage(language string) string {
return strings.ToLower(strings.TrimSpace(language))
}
func buildCodegenSystemPrompt(lang string) string {
switch lang {
case "python":
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable Python code.
Канон для Python: файл main.py, entrypoint main.main, функция def main(): без аргументов.
Не генерируй def main(ctx), def handler, Flask-приложение или обычный CLI-main.
Если нужен ответ HTTP-подобного вида, возвращай dict со status/body/headers или строку; не выдумывай лишние зависимости.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
case "nodejs":
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable Node.js code.
Канон для Node.js: user code должен быть CommonJS-style, обычно module.exports = async function (context) { ... }.
Не используй ESM import/export в user code. Не пиши обычный CLI main.
Возвращай объект вида { status, body, headers } или строку/JSON, совместимые с Fission node wrapper.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
case "go":
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable Go code.
Канон для Go: package main, экспортированная функция func Handler(w http.ResponseWriter, r *http.Request).
Не генерируй func main() как entrypoint и не делай CLI-программу.
Импортируй net/http и другие пакеты только если они реально нужны.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
case "php":
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable PHP code.
Канон для PHP: файл main.php, entrypoint main.php::handler, функция function handler($context).
Не пиши CLI-скрипт и не выдумывай другой entrypoint.
Для ответа используй $context["response"] или совместимый Fission response pattern.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
case "ruby":
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable Ruby code.
Канон для Ruby: файл handler.rb, entrypoint handler, функция def handler.
Не пиши CLI-скрипт и не выдумывай другой entrypoint.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
default:
return strings.TrimSpace(`Ты генератор кода для Fission Console.
Возвращай ТОЛЬКО код, без markdown, без пояснений, без fenced-блоков.
Генерируй только Fission-usable code.
Если язык не распознан, выбери минимальную рабочую реализацию без лишней обвязки.
Если описание пользователя расплывчатое, выбери минимальную рабочую Fission-функцию.`)
}
}
func buildCodegenUserPrompt(lang, name, description string) string {
funcName := strings.TrimSpace(name)
if funcName == "" {
funcName = defaultPromptFunctionName(lang)
}
goal := strings.TrimSpace(description)
if goal == "" {
goal = "Сгенерируй минимальную рабочую Fission-функцию."
}
return strings.TrimSpace(fmt.Sprintf(`Сгенерируй функцию для Fission.
Language: %s
Function name: %s
What to do: %s
Правила:
1) Верни только код.
2) Соблюдай канон Fission для этого языка.
3) Если пользователь описал задачу плохо или противоречиво, выбери самый безопасный и минимальный рабочий вариант.
4) Не добавляй markdown, пояснений и лишних файлов.
5) Код должен быть пригоден для вставки в console и запуска в Fission без ручной правки entrypoint.`, lang, funcName, goal))
}
func buildExplainSystemPrompt(lang string) string {
return strings.TrimSpace(fmt.Sprintf(`Ты анализатор кода для Fission Console.
Отвечай кратко, по делу и без markdown-блоков.
Сначала объясни, что делает код.
Затем отдельно скажи, подходит ли он для Fission %s и почему.
Если entrypoint, сигнатура или return shape не совпадают с каноном Fission, скажи это прямо.
Не переписывай код и не выдумывай поведение, которого нет.`, prettyLanguageName(lang)))
}
func buildExplainUserPrompt(lang, code string) string {
return strings.TrimSpace(fmt.Sprintf(`Объясни этот %s код и проверь его на совместимость с Fission.
Требования к ответу:
1) Что делает код.
2) Совместим ли он с Fission.
3) Если не совместим — что именно сломано (entrypoint, сигнатура, return, экспорт, файл).
Код:
%s`, prettyLanguageName(lang), strings.TrimSpace(code)))
}
func buildChatSystemPrompt() string {
return "Ты краткий и полезный ассистент для Fission Console. Отвечай по делу и без лишней болтовни."
}
func prettyLanguageName(lang string) string {
switch normalizeLanguage(lang) {
case "nodejs":
return "Node.js"
case "python":
return "Python"
case "go":
return "Go"
case "php":
return "PHP"
case "ruby":
return "Ruby"
default:
return "этот язык"
}
}
func defaultPromptFunctionName(lang string) string {
switch normalizeLanguage(lang) {
case "go":
return "Handler"
case "php":
return "handler"
case "ruby":
return "handler"
case "nodejs":
return "main"
default:
return "main"
}
}