尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证正在加载完整 README。 以下为已保存的摘录。
JobAgent — AI 기반 채용 공고 분석 멀티 에이전트 시스템 채용 공고 URL을 입력하면 5개의 전문 AI 에이전트가 협력하여 이력서와의 갭을 분석하고, 맞춤형 자기소개서 초안을 자동 생성하는 풀스택 AI 에이전트 프로젝트입니다. typescript waitUntil( runOrchestrator(jobUrl, userId, onEvent) .then(state => setJobState(jobId, state)) ); return NextResponse.json({ jobId }); // 즉시 반환 typescript feedback.passed = feedback.score >= 70; // LLM 판단 결정론적 override查看完整 README ↗
채용 공고 URL을 입력하면 5개의 전문 AI 에이전트가 협력하여 이력서와의 갭을 분석하고, 맞춤형 자기소개서 초안을 자동 생성하는 풀스택 AI 에이전트 프로젝트입니다.
사용자 (URL + 이력서)
↓
[오케스트레이터]
↓
[스크래핑 에이전트] → Jina Reader API
↓
[분석 에이전트] → 공고 구조화 파싱
↓
[매칭 에이전트] → RAG + 갭 분석
↓
[작성 에이전트] → 자기소개서 초안
↓
[검토 에이전트] → 품질 점수 평가
↓ (score < 70, 최대 2회 재루프)
[최종 결과 반환]
SSE(Server-Sent Events)로 각 에이전트의 실행 과정을 실시간으로 화면에 스트리밍합니다.
| 역할 | 기술 | 비고 |
|---|---|---|
| 프레임워크 | Next.js 16 + TypeScript + Tailwind CSS | App Router |
| LLM | Google Gemini 1.5 Flash | Google AI Studio 무료 |
| 임베딩 | Google text-embedding-004 (768차원) | Gemini API 포함 |
| 벡터 DB | Supabase pgvector | Seoul 리전 |
| DB | Supabase (PostgreSQL) | 무료 500MB |
| 스크래핑 | Jina Reader API | 무료 |
| 배포 | Vercel Hobby | 무료 |
| 에이전트 | 역할 | 핵심 구현 |
|---|---|---|
| Scraper | 공고 텍스트 추출 | Jina API 우선, 실패 시 fetch fallback, 200자 미만 오류처리 |
| Analyzer | 공고 구조화 | generateJSON<StructuredJob>, 7개 필드 강제 추출 |
| Matcher | 갭 분석 | RAG 검색(position+skills 쿼리) + fit score 계산 |
| Writer | 자기소개서 생성 | 부족 스킬→성장 의지 전환 프롬프트, 800~1000자 제한 |
| Reviewer | 품질 검증 | score >= 70 코드 재계산, 미달 시 Writer 재루프 |
| Orchestrator | 파이프라인 제어 | withRetry(2회), writer-reviewer 루프, SSE 이벤트 발행 |
에이전트 파이프라인은 여러 LLM 호출로 수십 초가 소요됩니다. API Route가 응답을 반환하면 서버리스 함수가 즉시 프리즈되어 파이프라인이 중단됩니다.
해결: @vercel/functions의 waitUntil()로 응답 반환 후에도 백그라운드 작업을 완료까지 유지합니다.
waitUntil(
runOrchestrator(jobUrl, userId, onEvent)
.then(state => setJobState(jobId, state))
);
return NextResponse.json({ jobId }); // 즉시 반환
Reviewer가 passed 필드를 잘못 반환하는 경우(LLM 환각)를 방어하기 위해, API 응답과 무관하게 score >= 70 조건을 코드에서 재계산합니다.
feedback.passed = feedback.score >= 70; // LLM 판단 결정론적 override
해외 리전만 제공하는 Qdrant Cloud 대신 **Supabase pgvector(서울 리전)**을 선택해 임베딩 저장/검색 지연을 최소화했습니다.
.env.local 파일 생성:
GEMINI_API_KEY= # https://aistudio.google.com/apikey
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY= # Supabase > Project Settings > API > service_role
NEXT_PUBLIC_APP_URL=http://localhost:3000
# (선택) 텍스트 생성을 Claude로 전환 — 미설정 또는 Claude 호출 실패 시 Groq 사용, 임베딩은 항상 Gemini
LLM_PROVIDER=anthropic
ANTHROPIC_API_KEY= # https://console.anthropic.com/settings/keys
ANTHROPIC_MODEL= # 기본 claude-haiku-5-5
ANTHROPIC_EFFORT= # 기본 low (low | medium | high | xhigh | max)
Supabase SQL Editor에서 아래 쿼리를 실행하세요:
create extension if not exists vector;
create table if not exists resume_chunks (
id uuid primary key default gen_random_uuid(),
user_id text not null,
content text not null,
embedding vector(768) not null,
created_at timestamptz not null default now()
);
create index if not exists resume_chunks_user_id_idx on resume_chunks (user_id);
create or replace function search_resume_chunks(
p_user_id text,
query_embedding vector(768),
match_count int
)
returns table (id uuid, content text, similarity float)
language sql stable as $$
select id, content, 1 - (embedding <=> query_embedding) as similarity
from resume_chunks
where user_id = p_user_id
order by embedding <=> query_embedding
limit match_count;
$$;
npm install
npm run dev
2001056/job-agent) 연결.env.local 값 동일하게 입력