| 과업 | 시니어 자격증 접수 서비스 제작 실습 - 8/19(수)~8/20(목) 이틀 |
|---|---|
| 학생 공지 | 오늘 8/18(화) 오전 발표 및 안내문 배포 완료 |
| 제작 범위 | 자격증 8종 중 1개 선택, 화면 3개 - 접수 사이트 / FAQ 챗봇 / 관리자 페이지 |
| 완료 조건 | 학생당 공개 URL 3개 - 접수 사이트 / 챗봇 / GitHub |
| 현재 상태 | 배포용 시작 코드 빈 껍데기 - 챗봇 파일 내용 "# D22에서 완성합니다" 1줄 |
| 필요 조치 | 오늘 밤 내용물 전량 제작 - 아래 결정 6건 회신 필요 |
완료조건이 "URL 3개 공개"인데 챗봇 URL이 걸립니다. 지난주 화요일 택배 사이트 실습에서 9명 전원이 Vercel 배포에 성공했고, 오늘 저녁 그 9개 사이트를 다시 확인하니 전부 정상입니다.
멀티캠퍼스 공식 커리큘럼에는 이 이틀이 "바른말 챗봇, LLM 파인튜닝, RAG"로 등록되어 있습니다. 실제로는 자격증 접수 서비스로 진행하기로 했고, "커리큘럼 문구를 그대로 이행하지 않아도 된다, RAG는 장난감 수준이면 충분"은 이미 결정된 사안입니다. 남은 것은 AI 호출을 조금이라도 넣을지 하나입니다.
접수 폼에서 신청하면 Supabase(무료 온라인 DB)에 한 줄씩 쌓이는 구조입니다.
챗봇은 문서를 읽고 답합니다. 오늘 안내문의 "문서 3-5개" 칸이 지금 비어 있습니다.
"미니 프로젝트 수행일지가 필요하다"는 말씀이 DM에는 없어서 관리카드 시트를 직접 확인했습니다. "수행일지 URL" 탭이 실제로 있습니다 - 1조/2조/3조 x 주차별로 일지 링크를 적는 빈칸. 조별로 일지를 쓰고 링크를 제출하는 구조입니다.
아래 코드의 붉은 칸이 학생이 채울 곳입니다. 접수 코드 3개 + 챗봇 2개. 이 위치가 둘째 날 튜닝 수업(비슷한말 사전, 기준값 조정)으로 그대로 이어집니다.
| # | 산출물 | 대기 중인 결정 |
|---|---|---|
| 1 | 접수 사이트 시작 코드 (자격증 카드 8개 + 폼, 빈칸 3) | 1, 3 |
| 2 | 챗봇 (빈칸 2 + 테스트 질문 5 + 정답 + 문서 폴더) | 1, 2 |
| 3 | 관리자 페이지 (접수 내역 표) | - |
| 4 | 자격증 8종 문서 24개 | 4 |
| 5 | 수행일지 구글독스 양식 | 5 |
| 6 | 수요일 진행표 (시간대별 할 일) | - |
| 7 | 완료 자동 채점 (질문 5개를 챗봇에 넣어 정답 대조) | - |
const SUPABASE_URL = "빈칸1: 내 DB 주소"; const SUPABASE_KEY = "빈칸1: 내 접속 키"; const db = supabase.createClient(SUPABASE_URL, SUPABASE_KEY); async function submitApplication(form) { const { error } = await db.from("applications").insert({ name: form.name.value, phone: form.phone.value, cert: 빈칸2: 고른 자격증 값 연결, exam_round: form.round.value }); if (error) { alert("접수 실패: " + error.message); return; } location.href = "done.html"; } async function loadApplications() { // 관리자 페이지용 const { data } = await db.from("applications") .select("*") .빈칸3: 최신순 정렬; renderTable(data); }
def score(question, doc_text): # 질문과 문서가 얼마나 겹치나
words = set(re.findall(r"[가-힣a-zA-Z0-9]+", question))
hits = 빈칸1: 문서에 있는 단어 개수 세기
return hits / max(len(words), 1)
THRESHOLD = 빈칸2: 이 값 아래면 "모르겠습니다"
def answer(question, docs):
best = max(docs, key=lambda d: score(question, d["text"]))
if score(question, best["text"]) < THRESHOLD:
return "죄송합니다, 제가 가진 문서로는 답할 수 없습니다."
return f"[근거: {best['file']}]\n" + summarize(best["text"], question)
미니 프로젝트 1 수행일지 - ___조 (조원: ___, ___, ___) [8/19 수] 1. 오늘 목표 2. 한 것 (조원별 1줄) 3. 막힌 것과 푼 방법 (에러 / 시도 / 결과) 4. 되는지 확인 (접수하면 DB에 쌓이나, 챗봇이 답하나, 모르는 건 모른다고 하나) 5. 내일 할 것 [8/20 목] 같은 5개 + 발표 주소 3개 (사이트 / 챗봇 / GitHub)