OJ搭建:Judge0服务器、DeepSeek服务接入简介
序
各大OJ平台上有很多很好的资源,但作为自己的“备课本”总有各种不便,教学生时间久了总是有一些自己的题目和想法,这在教初学的学生时非常突出。所以,很多年前就搞了一些尝试,包括:在机房搭建ubuntu服务器,找一个开源OJ安上,这过程中几经折腾,上梯翻墙的,别提多难受;然后想在云上搞一个,就可以随时访问了,由于学生少所以在阿里云上搞了仅2VCPU2G的配置,判题机制是轮询、本地判题,一直用了很多年。恰逢前两年被学校征用,于是升级了一次OJ,因为改了很多东西,所以又是几经折腾;之后DeepSeek火了,萌生了使用DeepSeek改学生代码的想法,建立了一个新的OJ。截至今天,当代的AI也没有多强的能力来完成编程题,当然成熟算法它们做的比较好。于是又几经折腾,通过一些技术方法达成让它可以正确的分析和解决学生被判定错误的当前代码并给予指导的目的。
这一篇主要是介绍流程,由于对PHP和YII的熟练度差亿点,整个过程断断续续做了好几个月。作为一个记录,也给有想法的一点参考。
一、OJ搭建
这个没有多难的地方,首先去云上租一个服务器,有公网IP即可,域名和是否备案不影响我们搭建实际服务。
0、找一个云服务商,我用的是阿里云,你要根据你所在地区来租用服务器,本省、隔壁省可能都行,太远的就很容易呵呵掉,别问我咋知道的,一问一个不吱声。
1、找一个开源OJ,我使用的是LPSZOJ,它是Php写的,提供了好几种安装脚本。
2、阅读其安装需求,然后在云服务器上安装对应版本。我使用的是阿里云,直接选择作者说明的测试过的ubuntu版本就可以。我使用的是ubuntu_20_04_x64。
3、进入控制台,运行安装脚本。不会的或者遇到困难,请留言给DeepSeek不要给我^ ^。
4、使用你ECS的公网IP地址访问你的网站。注意ECS的防火墙规则是否配置正确。
一般来说,使用安装脚本在已测试过的系统版本下进行安装不会出现什么问题。
另外,如果你不想大动干戈去搞什么Judge0,而只想使用DeepSeek,也不是不行咯,忽略下一步直接看下下步。
二、开始捯饬Judge0
先去到judge0.com,大体看看都有什么功能。它是一个传统判题机到目前为止不支持交互式和构造题,但是运行在沙盒里面,而且支持非常多的语言。
1、在OJ的云上再租一个服务器,但这个服务器的配置不低于2VCPU/4G内存。因为Judge0本身就会占用一定的内存,而2VCPU一般都是4线程,所以你最多一次评测4个测试点,若每个测试点限制内存为500Mb一下就可以正常工作。
2、安装Judge0服务器,并进行配置。不会的或者遇到困难,请留言给DeepSeek不要给我^ ^。
3、再云服务器上正确配置端口。
4、访问你Judge0所在ECS的works节点(其他官方文档上有的节点也可以),只要正常访问就可以,不必在意有没有返回数据或返回了什么数据,当你使用API调用了评测机之后它自然会有全格式的返回数据。
三、开始改造现有OJ
我用的OJ是轮询式的,所以只需要从ECS的后台检查一下数据库的内容而后参考OJ的评测机代码和守护进程(C语言)就可以知道它是怎么实现的评测。弄清楚流程之后,我们着手写自己的服务程序来调用Judge0服务器进行评测。在整个判题流程中插入了我们自己的代码之后,可想而知后面进行其他改造就会非常得心应手了。
当然,如果保持当前本地判题的方式,那么你只需要在OJ的判题机代码上增加几行代码,使之可以调用你的程序就可以了。例如根据不同的判题结果,调用不同的.py文件来与DeepSeek交互获得对学生代码的分析——这非常容易做,因为python的openai库是被DeepSeek直接支持的。最开始我也是这样做的,但随着需求增加,用一门达不到精通程度的语言来实现复杂任务实在是难受至极。所以,最后我还是回到了VB.NET的怀抱——估计这辈子也不可能精通python了。
言归正传,现在我们应该好好规划一下Judge0的多线程判题过程,至于判题结果如何发送给DeepSeek都应该在判题机集群正确工作之后再进行。一般来讲,当用户提交代码之后我们进行以下操作:
1、我们通过查询数据库,得到等待评测的提交。
2、题目对应的每个测试点对于Judge0来讲都是一个评测(虽然可以批量提交,但我们自己控制判题机集群的负载均衡)。
3、为每个测试点调用Judge0API,等待返回结果。
4、将全部测试结果进行汇总,写回数据库。
至此,完成了判题机的工作。
但我们需要考虑有很多个提交同时进行、有若干个Judge0服务器进行负载均衡的需求。所以,我们应该从判题服务的角度再来审视一下:
1、启动判题服务时,通过访问works节点检查Judge0服务器工作状况(判断是否在线、正在进行多少个任务、等待队列中有多少个任务)。
2、维持一个判题任务队列,其中保存构建Judge0API调用的信息。所有的提交的测试点都进入该队列。
3、使用Judge0Server类对判题任务队列进行轮询,并按照一定负载规则将任务摘取发送给制定的Judge0服务器。
4、维持一个各次提交的评测结果队列,其中保存题目对应的Judge0服务器返回的评测结果。每当一个提交的全部测试点均返回,我们对其进行汇总。而后写回数据库——PHP后台会自动更新前端页面。
所以,我们的评测机比原OJ的阻塞式的本地评测机要复杂一些,这里面有一些生产——消费模型需要实现,但它能够承受更大的负载也不会由于对某些代码的评测导致出错从而使大面积的评测陷入长时间的等待。
四、接入DeepSeek
当我们得到评测结果之后,就可以进行下一步操作:如果评测结果不为AC,那么将用户代码发送给DeepSeek来进行分析,将分析结果写入数据库,在前端设置等待和自动刷新功能即可。关于接入DeepSeek服务的代码可以参考上一篇。
需要样品请留言,测试时手下留情。