序
? ? ? ? 各大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服務的代碼可以參考上一篇。
? ? ? ?
? ? ? ? 需要樣品請留言,測試時手下留情。