diff --git a/.gitignore b/.gitignore index b65ee5d..de621dd 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ go.work.sum # env file .env .vscode/ + +.exe \ No newline at end of file diff --git a/backend/agent/basicAgent.go b/backend/agent/basicAgent.go index e373079..1846506 100644 --- a/backend/agent/basicAgent.go +++ b/backend/agent/basicAgent.go @@ -8,6 +8,7 @@ import ( "github.com/tmc/langchaingo/llms" "github.com/tmc/langchaingo/prompts" + "github.com/tmc/langchaingo/outputparser" ) func Call(llm llms.Model, ctx context.Context) (response string) { @@ -42,7 +43,7 @@ func CallWithMessage(llm llms.Model, ctx context.Context, prompt string) (respon return response } -func CallWithAgent(llm llms.Model, ctx context.Context, topic string, promptPath string) (response string) { +func CallWithAgent(llm llms.Model, ctx context.Context, topic string, promptPath string,) (response string) { content, err := os.ReadFile(promptPath) if err != nil { fmt.Printf("File err: %v", err) @@ -63,3 +64,49 @@ func CallWithAgent(llm llms.Model, ctx context.Context, topic string, promptPath response = CallWithMessage(llm, ctx, prompt) return response } + +func CallWithAgentDefined[T any](llm llms.Model, ctx context.Context, topic string, promptPath string, responseType T) (response T) { + + parse, err := outputparser.NewDefined(responseType) + if err != nil { + fmt.Printf("CreateParse err: %v", err) + return + } + + content, err := os.ReadFile(promptPath) + if err != nil { + fmt.Printf("File err: %v", err) + return + } + + text := string(content) + + textWithFormatInstruction := text + "\n" + parse.GetFormatInstructions() + + template := prompts.NewPromptTemplate(textWithFormatInstruction, []string{".Knowledge"}) + prompt, err := template.Format(map[string]any{ + "Knowledge": topic, + }) + + fmt.Println("Me: ", prompt) + if err != nil { + fmt.Printf("Prompt err: %v", err) + } + + responseString, err := llms.GenerateFromSinglePrompt( + ctx, + llm, + "用户正在学习Go语言,你是用户的助手。\n"+prompt, + ) + if err != nil { + log.Fatal(err) + } + + response, err = parse.Parse(responseString) + if err != nil { + fmt.Printf("Parse err: %v", err) + return + } + + return response +} diff --git a/backend/agent/response_struct/card_test.go b/backend/agent/response_struct/card_test.go deleted file mode 100644 index f66ddd0..0000000 --- a/backend/agent/response_struct/card_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package agent - -import ( - "testing" - - "github.com/tmc/langchaingo/outputparser" -) - -func TestCard(t *testing.T) { - definedCard, err := outputparser.NewDefined(Card{}) - - if err != nil { - t.Fatalf("%v", err) - } - - output := definedCard.GetFormatInstructions() - t.Log(output) -} diff --git a/backend/handlers/agent.go b/backend/handlers/agent.go index cee80fd..ef9900f 100644 --- a/backend/handlers/agent.go +++ b/backend/handlers/agent.go @@ -2,6 +2,7 @@ package handle import ( "agent/agent" + "agent/response_struct" "context" "fmt" @@ -18,38 +19,38 @@ var files = []string{ ".\\prompt\\scenario.txt", } -func GetCard(llm llms.Model, ctx context.Context, topic string) (response string) { +func GetCard(llm llms.Model, ctx context.Context, topic string) (response response_struct.Card) { file := files[0] - response = agent.CallWithAgent(llm, ctx, topic, file) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Card{}) return } -func GetGuodegang(llm llms.Model, ctx context.Context, topic string) (response string) { +func GetGuodegang(llm llms.Model, ctx context.Context, topic string) (response response_struct.Guodegang) { file := files[1] - response = agent.CallWithAgent(llm, ctx, topic, file) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Guodegang{}) return } -func GetMermaid(llm llms.Model, ctx context.Context, topic string) (response string) { +func GetMermaid(llm llms.Model, ctx context.Context, topic string) (response response_struct.Mermaid) { file := files[2] - response = agent.CallWithAgent(llm, ctx, topic, file) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Mermaid{}) return } -func GetQuiz(llm llms.Model, ctx context.Context, topic string) (response string) { +func GetQuiz(llm llms.Model, ctx context.Context, topic string) (response response_struct.Quiz) { file := files[3] - response = agent.CallWithAgent(llm, ctx, topic, file) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Quiz{}) return } -func GetScenario(llm llms.Model, ctx context.Context, topic string) (response string) { +func GetScenario(llm llms.Model, ctx context.Context, topic string) (response response_struct.Scenario) { file := files[4] - response = agent.CallWithAgent(llm, ctx, topic, file) + response = agent.CallWithAgentDefined(llm, ctx, topic, file, response_struct.Scenario{}) return } -func GetAll(llm llms.Model, ctx context.Context, topic string) (response map[string]string) { - response = make(map[string]string) + +func GetAll(llm llms.Model, ctx context.Context, topic string) (response *response_struct.AllStruct) { var wg sync.WaitGroup @@ -57,30 +58,31 @@ func GetAll(llm llms.Model, ctx context.Context, topic string) (response map[str go func() { defer wg.Done() - response["card"] = GetCard(llm, ctx, topic) + response.CardStruct = GetCard(llm, ctx, topic) }() go func() { defer wg.Done() - response["guodegang"] = GetGuodegang(llm, ctx, topic) + response.GuodegangStruct = GetGuodegang(llm, ctx, topic) }() go func() { defer wg.Done() - response["mermaid"] = GetMermaid(llm, ctx, topic) + response.MermaidStruct = GetMermaid(llm, ctx, topic) }() go func() { defer wg.Done() - response["quiz"] = GetQuiz(llm, ctx, topic) + response.QuizStruct = GetQuiz(llm, ctx, topic) }() go func() { defer wg.Done() - response["scenario"] = GetScenario(llm, ctx, topic) + response.ScenarioStruct = GetScenario(llm, ctx, topic) }() wg.Wait() + fmt.Println("======== All responses received ========") diff --git a/backend/response_struct/allstruct.go b/backend/response_struct/allstruct.go new file mode 100644 index 0000000..a9c0038 --- /dev/null +++ b/backend/response_struct/allstruct.go @@ -0,0 +1,9 @@ +package response_struct + +type AllStruct struct { + CardStruct Card `json:"card"` + GuodegangStruct Guodegang `json:"guodegang"` + MermaidStruct Mermaid `json:"mermaid"` + QuizStruct Quiz `json:"quiz"` + ScenarioStruct Scenario `json:"scenario"` +} \ No newline at end of file diff --git a/backend/agent/response_struct/card.go b/backend/response_struct/card.go similarity index 98% rename from backend/agent/response_struct/card.go rename to backend/response_struct/card.go index 4ed0176..723ba4b 100644 --- a/backend/agent/response_struct/card.go +++ b/backend/response_struct/card.go @@ -1,4 +1,4 @@ -package agent +package response_struct // Card 是顶层结构体,包含所有关于 Go map 的笔记内容 type Card struct { diff --git a/backend/response_struct/guodegang.go b/backend/response_struct/guodegang.go new file mode 100644 index 0000000..d309fa4 --- /dev/null +++ b/backend/response_struct/guodegang.go @@ -0,0 +1,6 @@ +package response_struct + +type Guodegang struct { + Name string `json:"name"` + Content string `json:"content"` +} \ No newline at end of file diff --git a/backend/response_struct/mermaid.go b/backend/response_struct/mermaid.go new file mode 100644 index 0000000..f77fa48 --- /dev/null +++ b/backend/response_struct/mermaid.go @@ -0,0 +1,6 @@ +package response_struct + +type Mermaid struct { + Type string `json:"type"` + Content string `json:"content"` +} \ No newline at end of file diff --git a/backend/response_struct/quiz.go b/backend/response_struct/quiz.go new file mode 100644 index 0000000..fdeb856 --- /dev/null +++ b/backend/response_struct/quiz.go @@ -0,0 +1,12 @@ +package response_struct + +type Quiz struct { + Questions []Question `json:"questions"` +} + +type Question struct { + Question string `json:"question"` + Options []string `json:"options"` + Answer string `json:"answer"` + Explanation string `json:"explanation"` +} \ No newline at end of file diff --git a/backend/response_struct/response_test.go b/backend/response_struct/response_test.go new file mode 100644 index 0000000..8deef04 --- /dev/null +++ b/backend/response_struct/response_test.go @@ -0,0 +1,62 @@ +package response_struct + +import ( + "testing" + + "github.com/tmc/langchaingo/outputparser" +) + +func TestCard(t *testing.T) { + definedCard, err := outputparser.NewDefined(Card{}) + + if err != nil { + t.Fatalf("%v", err) + } + + output := definedCard.GetFormatInstructions() + t.Log(output) +} + +func TestGuodegang(t *testing.T) { + definedGuodegang, err := outputparser.NewDefined(Guodegang{}) + + if err != nil { + t.Fatalf("%v", err) + } + + output := definedGuodegang.GetFormatInstructions() + t.Log(output) +} + +func TestMermaid(t *testing.T) { + definedMermaid, err := outputparser.NewDefined(Mermaid{}) + + if err != nil { + t.Fatalf("%v", err) + } + + output := definedMermaid.GetFormatInstructions() + t.Log(output) +} + +func TestQuiz(t *testing.T) { + definedQuiz, err := outputparser.NewDefined(Quiz{}) + + if err != nil { + t.Fatalf("%v", err) + } + + output := definedQuiz.GetFormatInstructions() + t.Log(output) +} + +func TestScenario(t *testing.T) { + definedScenario, err := outputparser.NewDefined(Scenario{}) + + if err != nil { + t.Fatalf("%v", err) + } + + output := definedScenario.GetFormatInstructions() + t.Log(output) +} \ No newline at end of file diff --git a/backend/response_struct/scenario.go b/backend/response_struct/scenario.go new file mode 100644 index 0000000..8d1c35a --- /dev/null +++ b/backend/response_struct/scenario.go @@ -0,0 +1,14 @@ +package response_struct + +type ScenarioResponse struct { + Scenarios []Scenario `json:"scenarios"` +} + +type Scenario struct { + Name string `json:"name"` + Background string `json:"background"` + Solution string `json:"solution"` + CodeExample string `json:"code_example"` + CoreProblemSolved string `json:"core_problem_solved"` + KeyConsiderations []string `json:"key_considerations"` +}