一、背景与目标

在传统的OJ中,用户提交代码后只能看到简单的判题结果,例如 AcceptedWrong AnswerCompile Error 等,这样只能给到用户有限的帮助,而我们的项目希望借助AI,快速地给出有价值的引导与教学,从而帮助用户理解学习,提高效率。

本项目(面向算法学习的智能在线 OJ 平台)在传统判题能力之上,引入 AI 辅导能力,目标是:

在判题结果基础上,向用户提供有学习价值的解释与引导,包括错误原因分析、复杂度说明、思路提示、优化建议等。

这是我有关这次项目的第一篇博客,重点介绍 AI Agent 工作流的设计与实现,即:如何将题目信息、用户代码、判题结果作为输入,通过大模型生成结构化的学习辅导内容。

二、整体架构设计

2.1 调用链路

并没有想象中那么复杂。调用链路如下:

用户提交代码
    ↓
Docker 沙箱判题
    ↓
判题结果 + 题目信息 + 用户代码
    ↓
AI Agent(组装Prompt → 调用大模型)
    ↓
结构化讲解输出
    ↓
前端展示

2.2 输入数据

数据类型 具体字段 来源
题目信息 标题、难度、知识点标签、题目描述 数据库(题目表)
用户代码 源码文本、编程语言 提交记录
判题结果 结果类型、错误信息、运行日志 判题沙箱(Docker)

2.3 输出格式

AI 返回的内容需要包含三个部分:

  1. 问题定位:用户代码可能存在的问题是什么?

  2. 原因分析:为什么会出现这个结果?

  3. 改进方向:如何修改代码或调整思路?

三、技术选型

组件 选型
后端框架 GoFrame
大模型 API 通义千问(qwen3.6-plus)
超时阈值 60s

暂时先使用qwen,后面再按需求更改

四、核心代码实现

4.1 API 调用核心函数

func CallQwen(prompt string) (string, error) {
	// 请求体
	reqBody := ChatRequest{
		Model: ModelName,
		Messages: []Message{
			{Role: "user", Content: prompt},
		},
		Stream:    false,
		MaxTokens: 800,
	}

	jsonData, err := json.Marshal(reqBody)
	if err != nil {
		return "", fmt.Errorf("JSON编码失败: %v", err)
	}

	// 创建请求
	req, err := http.NewRequest("POST", APIURL, bytes.NewBuffer(jsonData))
	if err != nil {
		return "", fmt.Errorf("创建请求失败: %v", err)
	}

	// 设置请求头
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Authorization", "Bearer "+APIKey)

	// 发送请求
	client := &http.Client{Timeout: TimeoutSec * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return "", fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return "", fmt.Errorf("读取响应失败: %v", err)
	}

	// 检查 HTTP 状态码
	if resp.StatusCode != 200 {
		return "", fmt.Errorf("HTTP错误 %d: %s", resp.StatusCode, string(body))
	}

	// 解析响应
	var chatResp ChatResponse
	if err := json.Unmarshal(body, &chatResp); err != nil {
		return "", fmt.Errorf("JSON解析失败: %v", err)
	}

	// 检查 API 错误
	if chatResp.Error.Message != "" {
		return "", fmt.Errorf("API错误: %s", chatResp.Error.Message)
	}

	// 提取结果
	if len(chatResp.Choices) == 0 {
		return "", fmt.Errorf("没有返回结果")
	}

	return chatResp.Choices[0].Message.Content, nil
}

4.2 Prompt 模板

func BuildPrompt(problemTitle, problemDesc, userCode, judgeResult, errorMsg string) string {
	return fmt.Sprintf(`你是一个算法学习辅导老师。请根据以下信息,为学生提供学习辅导。

题目信息:
1.标题:%s
2.描述:%s

代码:
%s

判题结果:
1.结果类型:%s
2.错误信息:%s

请按以下格式输出:
1.问题定位:代码可能存在的问题是什么?
2.原因分析:为什么会出现这个结果?
3.改进方向:如何修改代码或调整思路?

注意:
1.不要直接给出完整可运行的代码
2.不要重复任何句子   //不加会出现很多重复的句子
3.简明扼要地表述每个要点,最好每个要点控制在150字之内`,
		problemTitle, problemDesc, userCode, judgeResult, errorMsg)
}

4.3 完整调用示例

prompt := BuildPrompt(problemTitle, problemDesc, userCode, judgeResult, errorMsg)

	result, err := CallQwen(prompt)
	if err != nil {
		fmt.Printf("调用失败: %v\n", err)
		return
	}

五、运行结果展示

5.1 测试场景

根据设计的Prompt,整了个场景进行测试

//测试
	problemTitle := "两数之和"
	problemDesc := "给定一个整数数组 nums 和一个目标值 target,请找出和为目标值的那两个整数,并返回下标。"
	userCode := `vector<int> twoSum(vector<int>& nums, int target) {
    for (int i = 0; i < nums.size(); i++) {
        for (int j = 0; j < nums.size(); j++) {
            if (nums[i] + nums[j] == target) {
                return {i, j};
            }
        }
    }
    return {};
	}`
	judgeResult := "Wrong Answer"
	errorMsg := "预期输出 {0,1},实际输出 {0,0}"

第一次调用的时候重复生成了十几句 “就是判题系统返回WA的核心原因”,查了下是大模型调用的正常现象,加上不要重复任何句子和限制每点的字数后就没事了。

5.2 AI 返回结果

PS D:\learn\go\mygo> go run main.go
正在急头白脸地分析中---

1.问题定位:内层循环的初始条件设置不当,未限制两个下标必须互不相同。代码允许i与j取值重合,导致单个元素被重复参与求和运算。

2.原因分析:当i遍历至首元素时,j同样从0开始匹配。若该元素数值的两倍恰好等于target,判断语句立刻成立,程序提前返回{0,0}。这违背了题目选取两个不同位置元素的核心要求。

3.改进方向:将内层循环的起始边界调整为i+1,确保每次比较的都是数组中靠后的元素。该改动可直接避开索引重叠的陷阱,同时消除约一半的无效配对,使算法逻辑与性能均符合标准解法。

run老卡住,总是run好几次才能成功调用一次,不知道什么情况,这篇先这样了后续再解决一下。

还以为是哪里整错了,拉了个test测试,把prompt设成一句很简单的话尝试了一下,还是卡死。最后没办法了多run了几遍忽然就打印正在急头白脸地分析中了,舒服。

六、出现的问题

其实没有什么,整体工作流程比较少也比较简单。key和url输错几次,还有前面说的重复生成语句的情况,以及run卡住的时候我排查问题试图用终端直接调用api丢些简单句子。问了ai怎么写命令,但是输入后终端没有一点反应,最后放弃了写了个test。

七、收获

把一个api调用跑起来了,设计了一个prompt模板,走出了项目的第一步

八、下一步计划

  • 扩展其他场景的 Prompt 模板(CE、TLE 等)

  • 接入 RAG 检索模块,实现检索增强讲解

Logo

小龙虾开发者社区是 CSDN 旗下专注 OpenClaw 生态的官方阵地,聚焦技能开发、插件实践与部署教程,为开发者提供可直接落地的方案、工具与交流平台,助力高效构建与落地 AI 应用

更多推荐