Synaplan
기업을 위한 오픈소스 AI 플랫폼
지속적인 채용 탐색·요구사항별 이력서 매칭·알림·증거 기반 지원서 초안을 제공, 데이터·기후·지리·농업·개발 분야에 특화됩니다
Continuous job discovery, requirement-by-requirement matching against your verified CV, alerts, and evidence-checked application drafts. Built for data, climate, geospatial, agriculture and developmen
비즈니스Python · TypeScriptGitHub @YonSci가동 상태 재확인 필요운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Jobs-find-ai is a personal job-discovery and application assistant. It reads your CV, finds and scores relevant opportunities, and sends alerts by Telegram and email. When you ask, it helps draft applications based on your actual experience.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗A personal job discovery and application assistant for data science, AI, geospatial, climate, hydrology, agriculture and development-sector roles.
It collects postings from a shared catalog of public sources and from sources you add, screens them against your keywords, optionally pre-ranks them with JEV, asks an AI to explain requirement by requirement how each posting matches your verified CV evidence, alerts you (Telegram, email, in-app inbox), and, only when you click Prepare application, drafts a tailored CV, cover letter and screening answers grounded in that evidence for you to review, edit and export.
It never submits anything, never contacts employers on your behalf, and never invents facts about you. (Employers who buy a featured listing are emailed about their own listing.)
Version 0.4 serves many people on one server: each account has a private workspace, uses AI included in a sponsored seat or its own OpenAI key, connects its own mailbox for email alerts, and links its own Telegram chat in one tap. During the beta, a limited number of people can join each day without a code; others request an invitation. The first account created becomes the owner and gets the Cohort tab (invitations, plans, shared sources, activation metrics, the blind JEV benchmark). See docs/DEPLOYMENT.md for the Render deployment and docs/CATALOG_DESIGN.md for the shared catalog.
| Landing page | Opportunities | Match explanation |
|---|---|---|
| Applications | My evidence | Job sources |
|---|---|---|
More in docs/screenshots, including the full landing page and the phone layout. Captured from the live beta with a demo account.
CATALOG_SHARED=true each public source is read once for everyone. On a schedule (default every 6 hours) your own enabled sources are read too. Postings are de-duplicated, screened against your keywords by word stem (so "Data Scientist" matches "data science"), and the most promising unevaluated ones are sent to the AI, up to 50 per search. A few keyword-rejected postings a month are evaluated anyway, to measure what the keywords miss. Postings that have left their source are marked No longer listed.JEV_MODE=shadow) scores are stored and compared with the AI's; rank mode sends the AI the most promising postings first and holds confident low scores, while a random sample of held postings is still evaluated.Requirements: Python 3.11 or 3.12, Node 22+ (only to rebuild the dashboard), an OpenAI API key.
python deployment\setup.py # creates .env with random secrets (once)
python -m venv .venv
.venv\Scripts\pip install -r backend\requirements.lock
notepad .env # add OPENAI_API_KEY and any of the keys below
.\run.ps1 # starts API + dashboard + scheduler on http://127.0.0.1:8000
Open http://127.0.0.1:8000/app/ and create the first account, entering APP_TOKEN from .env as the setup code (or set OWNER_EMAIL to restrict the first account to your address). The root URL serves the public landing page from landing/. It becomes the owner, and any data created before accounts existed is attached to it. The owner account uses the server's OPENAI_API_KEY; other accounts add their own key under Account.
To keep it running in the background and start at logon:
.\deployment\register_windows_task.ps1 # -Remove to uninstall
The in-process scheduler runs while the server runs. Enable Scheduled searches in Preferences and set the interval there.
corepack pnpm install --frozen-lockfile
corepack pnpm exec vite build --config vite.client.config.ts
Remove-Item -Recurse -Force dashboard; Copy-Item -Recurse dist\dashboard dashboard
Add sources under Job sources. Use Test source before saving to see what a source returns. The Suggested list contains sources verified for this sector.
| Kind | Value | Notes |
|---|---|---|
| ReliefWeb | search query, e.g. climate OR GIS OR "data science" | Uses API v2 when RELIEFWEB_APPNAME is set (request one at https://apidoc.reliefweb.int/parameters#appname). Without it, falls back to the public RSS feed and reads each new job page. |
| Mailbox alerts (IMAP) | optional label/folder (default JobsFindAI) | Any account. Route LinkedIn, Devex, UNjobs, Impactpool, ReliefWeb or Indeed alert emails to a JobsFindAI label, then connect the mailbox under Account with an app password. Needs your AI key. |
| Gmail OAuth alerts | optional Gmail query | Owner account only; needs the Gmail authorization below. |
| RSS / Atom feed | feed URL | Any board that publishes a feed. Short entries are completed from the linked page. |
| Careers page | page URL | A public vacancies page. AI identifies the postings on it; each new posting page is read once. Needs AI. |
| Greenhouse / Lever / Workable / SmartRecruiters / Ashby | employer board identifier | The slug in the employer's board URL, e.g. cgiar in apply.workable.com/cgiar. |
| Remotive | categories, e.g. data,artificial-intelligence,research | Remote roles; check each posting's eligible regions. |
Page-reading connectors fetch only the specific public pages you configure, at most 60 per search with a one-second delay, and never log in anywhere. LinkedIn is not scraped; use its email alerts through Gmail.
Once, in Google Cloud console: create a project, enable the Gmail API, configure the OAuth consent screen (External, add your own address as a test user), and create an OAuth client ID of type Desktop app. Then:
.venv\Scripts\python deployment\gmail_setup.py path\to\client_secret_xxx.json
The browser opens, you approve read-only access, and GMAIL_REFRESH_TOKEN is written to .env. Restart the server, create the JobsFindAI label and a Gmail filter that applies it to alert emails, then add the Gmail source. Test-mode refresh tokens expire after 7 days unless the consent screen is published; rerun the script if imports start failing.
Notifications are off by default. In Preferences, enable alerts, tick channels, choose per-job or digest mode, and click Send test on each channel.
Telegram (recommended). Create a bot with BotFather and put its token in TELEGRAM_BOT_TOKEN. Restart, then under Account click Link Telegram and Open Telegram and press Start: the link carries a one-time code, and the dashboard notices the link within seconds. One bot serves every account on the server; each person links their own chat. The server long-polls Telegram, so no public URL is needed; Interested / Skip buttons work on a laptop. Only the linked chat can change job status. HTTPS deployments may instead register a webhook with python deployment/telegram_setup.py webhook.
Email. Set SMTP_HOST, SMTP_PORT=587, SMTP_USER, SMTP_PASSWORD, EMAIL_FROM, EMAIL_TO (STARTTLS; Gmail needs an app password).
WhatsApp. Twilio approved template; see .env.example. Sent per job even in digest mode.
Provider acceptance is not delivery confirmation. An alert is recorded before sending and never resent automatically.
INVITE_ONLY=true (default): new accounts need a code from the Cohort tab, except that up to OPEN_SEATS_PER_DAY (default 25) people a day can join without one. Set INVITE_ONLY=false to open sign-up.SECRET_KEY encrypts stored API keys and mailbox passwords (defaults to APP_TOKEN). Changing it invalidates them.backend/career/auth.py): Free, Beta (own OpenAI key), Beta with AI included (the first SPONSORED_SEATS members, on the server's key within SERVER_KEY_MONTHLY_CALLS), Pro and Pro Plus. The owner can change plans and sponsor seats in the Cohort tab.backend/career/billing.py): Chapa (ETB), Lemon Squeezy (cards, USD) or, when neither is configured, a manual request the owner confirms in the Cohort tab. Employers submit a vacancy for a featured listing; after the owner approves it, they pay and follow its views, Apply clicks and the members reached by matching keywords at /employers, signing in with an emailed link.Authorization: Bearer <APP_TOKEN>; that acts as the owner.Set OPENAI_API_KEY for the owner account. Members add their own key under Account; it is verified against the configured models and stored encrypted. Models are configurable (EXTRACT_MODEL, MATCH_MODEL, WRITE_MODEL). Costs are bounded: at most 50 evaluations per search (most promising first, failed ones retried at most three times then paused for a day), one drafting run per approved application with at most one revision, and descriptions trimmed to 30,000 characters before analysis. Changing your alert threshold or channels never discards evaluations; only changing verified evidence or the keyword, location or contract preferences does.
Without a key, CV text import, manual jobs, non-AI sources and keyword-overlap ranking still work.
Run on the server (on Render: Shell tab, from /app); all are read-only unless noted.
python -m career.catalog_report: catalog size, sources, shared sources, postings no longer listed, starter results.python -m career.jev_report: the whole funnel, JEV against the AI and members' decisions, confidence calibration, recall by field, cost per good match, cutoff sweep, and the owner's blind benchmark labels. --models lists dated JEV models to pin in JEV_MODEL.python -m career.business_report: revenue by month and product (ETB and USD apart), checkout conversion, paying members, the employer funnel with listing views and Apply clicks, institution enquiries, and monthly AI usage; also in the Cohort tab.python -m career.jev_backfill: rescores evaluated postings after a rubric or model change (uses JEV tokens).python -m career.schedule_reminder: lists members to remind about scheduled searches; a dry run unless --send.docker compose up --build -d starts API, worker, Celery Beat scheduler, PostgreSQL and Redis. In that mode the in-process scheduler is off and Beat runs searches every six hours. Note that Compose publishes port 8000; change the mapping if something else uses it.
cd backend
..\.venv\Scripts\python -m pytest tests -q
Tests use a temporary SQLite database and mocked providers. No network calls, model calls or messages are made.
backend/career/main.py: authenticated API and static dashboardbackend/career/sources.py: all connectors and the suggested-source listbackend/career/relevance.py: stem-based keyword and location screening, evaluation prioritybackend/career/service.py: ingestion, de-duplication, search run, alerts, archiving, application workflowbackend/career/catalog.py, collector.py: shared catalog, retention rule, shared collection of public sourcesbackend/career/jev.py, jev_report.py, benchmark.py: JEV pre-ranking, its validation report, the owner's blind benchmarkbackend/career/cv_versions.py: target roles over the verified evidence (search keywords, best fit per job, focus for drafting)backend/career/posting_facts.py, geo.py: posting details for filters, country lookup for the mapbackend/career/billing.py, public_jobs.py, public_site.py, employers.py: payments, the public job directory, employer listings and their self-service pagebackend/career/site_stats.py: public-site page views, search-engine arrivals and Apply clicks, without cookiesbackend/career/ai.py: extraction, matching, drafting with independent review and revisionbackend/career/notifications.py: in-app inbox, Telegram, email, WhatsApp, digests, test alertsbackend/career/telegram.py: long polling, chat linking, button handlingbackend/career/scheduler.py: in-process scheduler and stale-run repairbackend/career/documents.py: CV import and DOCX/PDF exportdeployment/: setup, Gmail and Telegram helpers, Windows task registrationapp/page.tsx, app/SwipeDeck.tsx, app/JobMap.tsx, app/CvVersions.tsx: dashboard source; dashboard/: compiled dashboard served by the APIdocs/PLAN.md: review findings and roadmap; docs/ARCHITECTURE.md: data flow and limits; docs/CATALOG_DESIGN.md: shared catalog