Files
fission-console/console/internal/api/ai_prompts.go
T

231 lines
9.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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"
}
}