Scholia: 코스 지식 기반에서 답변하는 AI 학습 파트너
요약
Scholia는 코스 자료에 특화된 학습 파트너 AI입니다. 사용자의 질문에 강의 녹화본, 슬라이드, 교과서 등 구조화된 자체 콘텐츠를 기반으로 답변하며, 모든 주장에 출처 '칩'을 첨부합니다. 특히 채점 피드백이나 복잡한 개념 비교와 같이 단순 키워드 검색으로는 어려운 영역에서 체인 이동 및 재귀적 추론 능력을 보여줍니다.
핵심 포인트
- 구조화된 코스 자료 기반의 답변 제공
- 모든 주장에 출처(칩)를 첨부하여 신뢰성 확보
- 단순 검색을 넘어선 체인 이동 및 재귀적 추론 가능
- 채점 피드백 분석 등 복잡한 학습 패턴 지원
이 글은 Sanity Challenge: Path One, Ship an Agent That Queries Real Content에 제출하는 내용입니다.
제가 만든 것 (What I Built)
Scholia는 하나의 코스를 위한 학습 파트너입니다. 사용자에게 질문을 하면, 해당 코스의 자체 자료(강의 녹화본, 슬라이드 덱, 교과서, 문제 세트 및 루브릭, 그리고 사용자의 성적 받은 과제)를 기반으로 답변합니다. 모든 주장에는 클릭할 수 있는 '칩'이 첨부됩니다. 강의 칩은 특정 시점의 YouTube 녹화본을 열어줍니다. 슬라이드 칩은 덱 이름과 슬라이드 번호를 명시합니다. 책 칩은 장(chapter)과 페이지를 명시합니다.
Scholia는 다섯 가지 모드를 가지고 있으며, 각 모드가 작동하는 이유는 콘텐츠가 구조화되어 있기 때문입니다:
| Mode | 얻을 수 있는 것 (What you get) | 스키마에서 가능하게 하는 부분 (What in the schema makes it possible) |
|---|---|---|
| Study | 코스 자체 용어로 설명과 다시 볼 위치 안내 | lecture.segments[]는 startSec을 가지고 있습니다; slideDeck.slides[]는 number를 가지고 있습니다; bookChapter.sections[]는 pageStart를 가지고 있습니다 |
| ... |
코스에서 다루지 않는 내용에 대해서는 Scholia가 신뢰할 수 있는 짧은 허용 목록의 사이트(docs.python.org, ocw.mit.edu, Wikipedia 및 몇몇 대학)를 검색합니다. 이러한 결과는 코스의 인용 자료와 섞이지 않습니다. 이들은 황갈색의
키워드 검색이 할 수 없는 답변
"제가 어디서 점수를 잃었고, 무엇을 다시 봐야 하나요?" 이 단어들은 코스 자료에 전혀 등장하지 않습니다. 이에 답하기 위해 에이전트는 체인을 따라 이동해야 합니다. 각 채점 피드백 조각은 키로 루브릭 기준(rubric criterion)의 이름을 지정하고, 각 기준은 토픽으로 태그되며, 각 토픽은 특정 강의 세그먼트, 슬라이드 및 책 섹션에 의해 참조됩니다. Scholia는 GROQ에서 이 이동을 결정론적으로 수행한 다음 정확한 위치 정보(locators)를 요청합니다:
재귀 (Recursion) (3점 손실, 주요 오류 1건). 재귀적 순열에서의 기본 사례 처리. 다시 보기: 기본 사례와 재귀 해제 과정 이해
강의 6 · 13:17; 재귀 곱셈 및 팩토리얼에 대한 슬라이드강의 6 · 슬라이드 9.딕셔너리, 튜플, 리스트 및 가변성 (Dictionaries, tuples, lists and mutability) (각 2점 손실). 클로닝(cloning) 대신 입력 핸들(input hand)을 변경하는 경우. 다시 보기: 별칭 효과(aliasing side effects)를 피하기 위한 리스트 클로닝
강의 5 · 35:08; 슬라이싱을 사용한 리스트 클로닝강의 5 · 슬라이드 20.
사이드 패널의 막대 그래프(모든 네 가지 제출물에 걸친 토픽별 손실 점수)는 모델에서 온 것이 아니라 동일한 질의에서 나온 것입니다.
"bisect_search1의 복잡도는 무엇인가요?" 키워드 검색은 강의 11의 슬라이드 14를 찾고, 그 슬라이드는 두 가지 내용을 담고 있습니다. 첫째는 O(log n) 호출에 O(n) 복사본을 곱하여 O(n log n)이라고 작성합니다. 몇 줄 뒤에는 "만약 우리가 정말 조심한다면"이라는 내용과 함께 복사된 길이가 매번 절반으로 줄어들어 총합은 O(n)이 된다고 합니다. 지식 기반 구축 과정에서 이 내용은 항목 간의 충돌로 플래그 지정되었습니다. Scholia는 반감 계열 논거(halving-series argument)를 사용하여 O(n)이라고 답변하고 해당 슬라이드를 인용했습니다. 저는 아래에서 이 내용을 다룰 것이며, 왜냐하면 이 내용에는 충돌에 대한 언급이 없었기 때문입니다.
"월러스 연산자(walrus operator)는 무엇이며, 이 코스에서 다루나요?" 이 코스는 Python 3.8 이전의 자료를 기반으로 합니다. Scholia는 한 문장으로 그렇게 말한 다음, docs.python.org에서 "코스 자료 외(Outside course material)" 섹션 아래에 보여주며 답변합니다.
데모
실시간 사용: https://scholia.mol.la (로그인 불필요). 스튜디오는 https://scholia.mol.la/studio에 임베드되어 있습니다.
다음 기능을 사용해 보세요:
- 학습(Study): 재귀가 왜 기본 사례(base case)를 필요로 하나요?
- 개선(Improve): 어디서 점수를 잃고 있나요, 그리고 무엇을 다시 봐야 할까요?
- 과제(Assignment): 답변을 주지 않으면서 문제 세트 3을 시작하는 것을 도와주세요.
- 모의 시험(Mock exam): 모의 시험을 시작하세요. 그런 다음 첫 번째 질문에 답합니다.
- 학습(Study): 와일러스 연산자(walrus operator)란 무엇인가요? (강좌를 떠나는 것을 지켜보세요)
코드
GitHub logo SumonMSelim / scholia
Scholia
강좌 콘텐츠가 구조화되어 있기 때문에 작동하는 학습 파트너.
Scholia는 학생이 받는 모든 것(강의 녹화본, 슬라이드 덱, 교과서 과제, 채점된 제출물)을 타이핑된 Sanity 문서로 변환하고, 그 위에 Sanity 지식 기반(Knowledge Base)을 구축한 다음, 에이전트(agent)를 배치합니다. 모든 답변은 정확한 강의 초, 슬라이드 번호 또는 책 페이지를 인용합니다.
DEV x Sanity Challenge (Path One)을 위해 제작되었습니다. MIT OpenCourseWare(CC BY-NC-SA 4.0)의 데모 코스 3개와 각각 오픈 라이선스 교과서가 페어링되어 있습니다:
- 6.0001 Introduction to Computer Science and Programming in Python, Think Python 2e (CC BY-NC 3.0) 포함
- 6.0002 Introduction to Computational Thinking and Data Science, Think Stats 2e (CC BY-NC-SA 4.0) 포함
- 6.006 Introduction to Algorithms, Open Data Structures (CC BY 2.5 CA) 포함
학생의 제출물과 채점자 피드백은 가상의 내용입니다.
- Sanity 프로젝트
dqd1lxzm, 데이터셋production(공개) - 실시간 데모: https://scholia.mol.la
모드(Modes)
| 모드 | 내용 |
|---|
…
Next.js 16에 임베디드된 Sanity Studio 6, MCP 클라이언트가 포함된 Vercel AI SDK 7, Amazon Bedrock (Nova 2 Lite), 웹 폴백을 위한 Tavily, 배포를 위한 AWS CDK로 구성되었습니다. CDK 배포와 헤드리스 브라우저 검사를 포함한 모든 것이 Docker에서 실행됩니다.
Sanity 사용 방법
콘텐츠 모델
총 18개의 스키마 유형이 있습니다. 문서에는 course, topic, learningObjective, lecture, slideDeck, book, bookChapter, assignment, submission, examScope 및 webReference가 포함됩니다. 이들 안에 있는 객체는 segment, slide, bookSection, rubricCriterion, feedbackItem, scopedTopic 및 sourceInfo입니다.
이 모든 것을 결정한 두 가지 결정 사항이 있습니다.
로케이터(Locators)가 문서 내에 존재합니다. 강의는 세그먼트 배열을 가진 하나의 문서입니다. 각 세그먼트는 startSec, endSec, 텍스트 및 주제 참조를 포함하며, 길이 2~4분의 자막 트랙으로 구성됩니다. 슬라이드와 책 섹션도 각각 number와 pageStart로 동일하게 작동합니다. 따라서 지식 기반은 전체 강의를 요약할 수 있으며, 정확한 초(second) 단위 정보는 여전히 GROQ 프로젝션을 통해 얻을 수 있습니다.
주제(Topics)는 연결고리입니다. 세그먼트, 슬라이드, 책 섹션, 루브릭 기준, 시험 범위 항목 등 모든 것은 동일한 열두 개의 topic 문서를 참조합니다. 피드백은 _key를 통해 루브릭 기준을 참조합니다. 이것이 "입력을 변형했습니다(you mutated the input)"라는 메시지를 "강의 5를 35:08에서 다시 시청하세요(rewatch lecture 5 at 35:08)"로 바꾸는 것입니다.
데이터 수집 파이프라인(ingest pipeline)은 순수한 TypeScript로 작성되었습니다. 이 파이프라인은 OCW 캡션 파일(VTT)을 시간 창으로 구문 분석하고, unpdf를 사용하여 PDF에서 페이지별 슬라이드 및 책 텍스트를 추출하며, 수기로 작성된 메타데이터(주제, 루브릭, 시험 가중치, 허구의 제출물)를 병합한 다음, 각 과정의 문서들(77, 74, 81)을 결정론적 ID와 함께 하나의 트랜잭션으로 작성합니다. 과정 하나는 수작업 구조의 시드 파일입니다. 6.0002와 6.006를 추가했다는 것은 파이프라인 자체를 변경한 것이 아니라 두 개의 시드 파일을 작성했다는 의미이며, 단지 책의 페이지 헤더나 노트가 없는 강의에 대한 선택적 설정만 제외하고 말입니다. 문서들이 서로 참조하기 때문에 하나의 트랜잭션이 중요했으며, Sanity는 아직 존재하지 않는 문서에 대한 참조를 거부합니다.
지식 기반 및 Context MCP
하나의 Knowledge Base가 세 가지 과정 모두에게 단일 Context MCP 엔드포인트를 통해 서비스를 제공합니다. 제가 사용 중인 계획은 조직당 최대 150개의 문서를 인덱싱하며, 세 과정에는 232개의 문서가 있으므로, 지식 기반은 다음을 설명하는 140개의 문서를 받습니다: 과정, 주제, 학습 목표, 전체 스크립트가 포함된 강의, 루브릭이 있는 과제, 채점된 제출물 및 시험 범위. 슬라이드 덱과 책 장은 이 범위를 벗어나며, 에이전트는 이를 lookup_source를 통해 직접 데이터셋을 조회하여 접근합니다. 답변을 선택된 과정 내에 유지하는 두 가지 요소가 있습니다. 에이전트에게 해당 과정에 대한 지식 기반 항목만 사용하도록 지시하며, 모든 소스 조회가 GROQ에서 과정별로 필터링되므로 인용이 다른 과정으로 향할 수 없습니다.
에이전트는 조직 토큰을 사용하여 @ai-sdk/mcp를 통해 Knowledge Base 모드의 Context MCP 엔드포인트에 연결합니다. 이 엔드포인트가 노출하는 세 가지 도구를 사용합니다:
initial_context는 대화당 한 번만 사용되며, Knowledge Base ID와 개요를 위해 사용됩니다.- 두세 개의 키워드를 사용하는
knowledge_base_search. - 가장 적합한 항목에 대한
knowledge_base_read.
Knowledge Base가 설명합니다. 이 지식 기반은 신뢰성 있게 초(second)나 페이지 번호를 제공하지 않기 때문에, 저는 agent에게 MCP 도구들 옆에 자체적인 네 가지 도구를 부여했습니다:
lookup_source: typed arrays를 대상으로 GROQ를 실행합니다. 키워드와 선택적 강의 번호 또는 토픽 슬러그를 입력받아[lecture 6 @ 4:53]과 같은 준비된 인용 문자열(cite strings)을 가진 세그먼트, 슬라이드 및 책 섹션을 반환합니다. GROQ의match는 접두사 기반(prefix based)이므로, 저는 키워드를 어간 추출(stemming)하여("aliasing"은 "alias"가 됨) 각 항목이 몇 개의 키워드를 포함하는지 기준으로 결과를 순위화합니다.weak_topics: 피드백을 루브릭 기준에 연결하여 토픽으로 만들고 감점된 점수를 합산합니다. 모델은 이 총점을 읽기만 할 뿐, 직접 계산하지는 않습니다.exam_plan: 시험 가중치별로, 비복원(without replacement) 방식으로 시드를 사용하여 주제를 샘플링하고 학습 목표를 첨부합니다.- **
web_search**와 **save_web_reference**는 폴백(fallback)을 처리합니다. Context MCP는 읽기 전용이므로, 저장 작업은 쓰기 토큰(write token)과 함께@sanity/client를 통해 진행되며status: pending으로 기록됩니다.
UI가 확인할 수 있는 인용구 (Citations the UI can check)
agent는 고정된 구문([lecture 6 @ 12:40], [slides 4 #5], [book ch.11 p.106], [assignment 3: hands], [submission ps3])으로 인용구를 작성합니다. UI는 이를 구문 분석(parses)하여 코스 소스(비디오 URL에 &t= 초 추가, 슬라이드 덱 링크, 책 링크)와 비교하고 해결합니다. 또한 해당 턴에서 도구들이 반환한 모든 인용 문자열을 수집합니다. 모델이 작성했지만 어떤 도구도 반환하지 않은 인용구에는 "unverified" 배지가 붙습니다. [lecture 12 @ ?]와 같이 형식이 잘못된(malformed) 인용구는 아예 구문 분석되지 않고 일반 텍스트로 남아있기 때문에, 잘못된 장소의 링크가 되는 일은 없습니다.
배포 (Deploy)
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


