analize
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
package antigravity
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StudyElement represents the extracted study content from a question.
|
||||
type StudyElement struct {
|
||||
QuestionID int `json:"questionId"`
|
||||
Source string `json:"source"`
|
||||
Category string `json:"category"`
|
||||
Content string `json:"content"` // Markdown content containing formulas, charts, etc.
|
||||
}
|
||||
|
||||
// GeneratedQuestion matches the structure to be saved in QuizQuestions DB.
|
||||
type GeneratedQuestion struct {
|
||||
QuestionText string `json:"questionText"`
|
||||
Choice1 string `json:"choice1"`
|
||||
Choice2 string `json:"choice2"`
|
||||
Choice3 string `json:"choice3"`
|
||||
Choice4 string `json:"choice4"`
|
||||
CorrectAnswer int `json:"correctAnswer"`
|
||||
Explanation string `json:"explanation"`
|
||||
Difficulty string `json:"difficulty"`
|
||||
Subject string `json:"subject"`
|
||||
}
|
||||
|
||||
// CallAgy runs the agy CLI with the given prompt.
|
||||
func CallAgy(ctx context.Context, prompt string) (string, error) {
|
||||
cmd := exec.CommandContext(ctx, "agy", "--dangerously-skip-permissions", "--print", prompt)
|
||||
var stdout, stderr bytes.Buffer
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("agy error: %v, stderr: %s", err, stderr.String())
|
||||
}
|
||||
|
||||
return strings.TrimSpace(stdout.String()), nil
|
||||
}
|
||||
|
||||
// ExtractStudyElement requests the AI to generate a comprehensive study sheet/note for a specific quiz question.
|
||||
func ExtractStudyElement(ctx context.Context, questionText, choice1, choice2, choice3, choice4, correctAnswer, explanation string) (string, error) {
|
||||
prompt := fmt.Sprintf("아래 기출문제의 문제, 보기, 정답, 해설을 철저히 분석하여 핵심 개념을 담은 \"학습요소(개념 정리)\"를 작성해 주세요.\n"+
|
||||
"이 학습요소는 사용자가 이 문제를 완벽하게 이해하고 관련된 이론적 배경까지 학습할 수 있도록 돕는 학습 노트입니다.\n\n"+
|
||||
"[기출문제]\n"+
|
||||
"문제: %s\n"+
|
||||
"보기 1: %s\n"+
|
||||
"보기 2: %s\n"+
|
||||
"보기 3: %s\n"+
|
||||
"보기 4: %s\n"+
|
||||
"정답: %s\n"+
|
||||
"해설: %s\n\n"+
|
||||
"[작성 지침]\n"+
|
||||
"1. 단순 정답 해설을 넘어, 문제에 포함된 핵심 개념(예: 특정 암호화 알고리즘, 시스템 보안 기술, 네트워크 프로토콜 등)의 정의, 특징, 작동 방식, 장단점을 일목요연하게 정리해 주세요.\n"+
|
||||
"2. 가독성을 위해 마크다운 포맷을 사용해 주세요. (예: 표, 리스트)\n"+
|
||||
"3. 수식이나 암호학적 기호가 필요한 경우 KaTeX 문법(예: $E_k(M) = C$)을 적극적으로 사용해 주세요.\n"+
|
||||
"4. 아키텍처나 흐름을 시각화할 수 있도록 Mermaid 다이어그램(예: ```mermaid ... ```) 또는 간단한 아스키 차트(ASCII Chart/Plot)를 본문에 반드시 하나 이상 포함해 주세요.\n"+
|
||||
"5. 다른 잡다한 설명(예: \"네, 작성해 드리겠습니다\" 등)은 모두 제외하고, 오직 마크다운으로 구성된 학습요소 내용만 반환해 주세요.",
|
||||
questionText, choice1, choice2, choice3, choice4, correctAnswer, explanation)
|
||||
|
||||
return CallAgy(ctx, prompt)
|
||||
}
|
||||
|
||||
// GenerateDescriptiveQuestion generates a new descriptive/practical exam question based on given reference questions.
|
||||
func GenerateDescriptiveQuestion(ctx context.Context, referenceExams []string) (*GeneratedQuestion, error) {
|
||||
refs := strings.Join(referenceExams, "\n---\n")
|
||||
prompt := fmt.Sprintf("기존 정보보호기사 실기 문제들을 분석하여, 이와 유사한 출제 패턴과 난이도를 가진 \"새로운 정보보호기사 실기 문제\"를 만들어 주세요.\n\n"+
|
||||
"[기존 실기 문제 예시]\n"+
|
||||
"%s\n\n"+
|
||||
"[출제 지침]\n"+
|
||||
"1. 문제 유형은 정보보호기사 실기 시험의 단답형 또는 서술형 형태여야 합니다. (지문을 제시하고 빈칸 채우기, 또는 특정 시나리오를 주고 대처 방안 서술하기 등)\n"+
|
||||
"2. 문제의 설명, 예시, 지문이 풍부하고 실무적이어야 합니다.\n"+
|
||||
"3. 생성된 문제는 반드시 아래의 JSON 포맷으로만 출력되어야 합니다. 마크다운 코드 블록(```json ... ```)을 사용하지 말고, 원시 JSON 텍스트만 출력하세요.\n\n"+
|
||||
"JSON 구조:\n"+
|
||||
"{\n"+
|
||||
" \"questionText\": \"문제 지문 및 지시 사항 (예: 다음 지문을 읽고 빈칸 A, B에 들어갈 단어를 기술하시오...)\",\n"+
|
||||
" \"explanation\": \"이 문제에 대한 모범 답안 및 상세한 해설\",\n"+
|
||||
" \"difficulty\": \"실기(Go)\",\n"+
|
||||
" \"subject\": \"만든 자료\"\n"+
|
||||
"}\n\n"+
|
||||
"오직 JSON만 출력해야 합니다. 다른 텍스트는 절대 포함하지 마십시오.", refs)
|
||||
|
||||
resp, err := CallAgy(ctx, prompt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Clean JSON response (sometimes LLM might return markdown code blocks despite instructions)
|
||||
cleaned := resp
|
||||
if idx := strings.Index(cleaned, "{"); idx != -1 {
|
||||
cleaned = cleaned[idx:]
|
||||
}
|
||||
if idx := strings.LastIndex(cleaned, "}"); idx != -1 {
|
||||
cleaned = cleaned[:idx+1]
|
||||
}
|
||||
|
||||
var gq GeneratedQuestion
|
||||
err = json.Unmarshal([]byte(cleaned), &gq)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON from AI: %v, raw output: %s", err, resp)
|
||||
}
|
||||
|
||||
return &gq, nil
|
||||
}
|
||||
Reference in New Issue
Block a user