인터넷 연결이나 API 없이 마지막 서리 날짜를 알려주는 오프라인 AI를 만들었습니다
요약
본 글은 인터넷 연결이나 API 의존 없이 마지막 서리 날짜를 예측하는 오프라인 AI 프로그램 'FrostWise' 개발 과정을 소개합니다. 이 프로그램은 오픈 웨이트 모델을 사용하여 기기 외부로 데이터를 전송할 필요가 없으며, 신호가 불안정한 텃밭 환경에서도 작물 재배에 필요한 정확한 정보를 제공합니다.
핵심 포인트
- Wi-Fi나 API 없이 작동하는 오프라인 AI 솔루션 제시
- 오픈 웨이트 모델을 활용하여 데이터 보안 및 독립성 확보
- 사용자에게 예측된 서리 날짜 범위와 구체적인 작물 재배 조언 제공
- 신호가 불안정한 커뮤니티 텃밭 등 다양한 환경에 최적화
이것은 Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass에 제출하는 글입니다.
채소밭에서 가장 유용한 숫자는 마지막 봄 서리 날짜입니다. 이 날짜를 일주일만 잘못 예측해도, 차가운 밤 한 번이 토마토 모종을 짓무르게 만듭니다.
그 숫자를 알려주는 모든 도구는 같은 결함을 가지고 있습니다. 바로 서버에 의존한다는 것입니다. 신호가 잡히는 텃밭 구석에서 휴대폰으로 찾아보며, 비가 오기 전에 페이지가 로드되기를 바라는 식입니다.
그래서 저는 FrostWise를 만들었습니다. 이 프로그램은 마지막 서리 날짜를 예측하고 무엇을 심어야 하는지 알려주는데, 모든 과정을 Wi-Fi가 꺼진 상태의 노트북에서 처리합니다. 오픈 웨이트 모델 두 개를 사용하며, API 키도, 계정도 필요 없고, 아무것도 기기 외부로 전송되지 않습니다.
저는 특정 사람을 위해 이 프로그램을 만들었습니다. 언덕 위의 커뮤니티 텃밭에 구획을 가진 제 친구가 있습니다. 그곳은 신호가 완전히 끊기는 곳입니다. 매년 봄 그녀는 "지금 심어도 안전한지"라고 저에게 문자를 보내는데, 텃밭 자체에서 서리 날짜 사이트를 로드할 수 없기 때문입니다. FrostWise는 그녀가 배터리가 없는 상태에서도 자신의 휴대폰으로 열어볼 수 있는 해결책입니다.
내가 만든 것
FrostWise는 단 하나의 질문에 정직하게 답합니다. "당신이 있는 곳에서 추위가 언제 물러갈지, 그리고 무엇을 해야 하는지."
사용자는 위치를 선택하거나(또는 직접 기후 데이터를 입력) 작물을 고르면 세 가지 정보를 받게 됩니다:
- 날짜. 예측된 마지막 봄 서리 날짜와 함께, 가짜 단일 일자 약속이 아닌 정직한 범위가 제시됩니다.
- 조언. 선택한 작물에 대한 평이한 언어로 된 조언입니다. 토마토나 바질 같은 연약한 작물은 서리가 지난 후에 심으세요. 완두콩이나 케일 같은 강건한 작물은 몇 주 일찍 파종하세요.
- 신뢰할 근거. 이 숫자는 사용자가 검사하고 재훈련할 수 있는 모델에서 나온 것이며, 범위는 위험도를 알려줍니다.
이 프로그램은 사람들을 가장 문자 그대로 화면 밖으로 내보냅니다. 그 '화면'이란 씨앗을 땅에 심기 위해 밖에 나가서 행동하기 직전의 10초를 의미합니다. 핵심 목표는 바로 이 순간을 짧게 만드는 것입니다.
누구에게 적합한가: 작은 텃밭이나 신호가 불안정한 곳에 있는 사람이라면 누구나. 커뮤니티 텃밭, 언덕 경사지 채소밭, 산책로 초소의 허브 화분 등. 클라우드 API가 쓸모없는 장소가 바로 사람들이 정원을 가꾸는 곳입니다.
데모 (Demo)
지금 사용해 보기: d2damz5gbd2rbh.cloudfront.net
이 호스팅 링크는 정적 웹사이트(S3 및 CloudFront를 이용, 비용 거의 없음)로, 미리 계산된 TabPFN-v2와 Gemma 결과를 설정된 도시들에 대해 제공하므로 실제 모델 출력을 클릭해 볼 수 있습니다. 라이브 모델 자체는 사용자의 기기에서 실행됩니다. 사용자 지정 기후 입력을 위해 완전히 오프라인으로 하려면, 레포지토리를 복제(clone)하여 python run.py를 실행하세요.
매우 다른 세 가지 기후 조건에 걸친 전체 흐름을 소개합니다: 마이애미(사실상 서리 없음), 시카고(실제 5월 서리), 그리고 파고(여름까지 지속되는 서리). 동일한 코드로, 세 가지 솔직한 답변을 얻었습니다.
하나의 답변은 다음과 같은 모습을 합니다: 예측된 마지막 서리 날짜, 그 주변의 정확한 범위, 그리고 특정 작물에 대해 Gemma가 현지에서 작성한 식재 조언입니다.
서리 날짜가 애니메이션으로 나타난 후, 로컬 Gemma 모델이 실시간으로 식재 조언을 작성합니다. 이 비디오에서 인터넷에 연결하는 부분은 전혀 없습니다.
코드 (Code)
GitHub logo simplynadaf / frostwise
서리가 물러나는 시기를 아세요. 오프라인 우선 식재 계획가: TabPFN-v2가 마지막 봄 서리를 예측하고 Gemma 3이 조언을 작성합니다. 완전히 로컬에서, 인터넷 연결 없이, API 없이 작동합니다. Hacktoberfest 오픈소스 AI 챌린지 주간 1일차: 잔디 밟기(Touch Grass)를 위해 제작되었습니다.
🌱 FrostWise: 서리가 물러나는 시기를 아세요 (2026)
오프라인 우선 식재 계획 도구. 오픈 웨이트 모델이 인터넷 연결 없이, 계정 없이, API 비용 걱정 없이 사용자의 노트북에서 마지막 봄 서리 날짜를 예측하고 무엇을 심어야 할지 알려줍니다. 서리 날짜는 테이블 기반 파운데이션 모델(tabular foundation model)로 예측하며, 조언은 로컬 언어 모델(local language model)이 작성합니다. 그리고 사용자가 입력하는 어떤 내용도 기기를 벗어나지 않습니다.
Hacktoberfest 오픈 소스 AI 챌린지 · 주차 1: Touch Grass
🔗 라이브 데모: d2damz5gbd2rbh.cloudfront.net · 💻 실시간 실행: Getting Started (전체 오프라인 모델이 로컬에서 실행됨) · 🎬 유튜브 데모: 곧 공개
참고 사항
라이브 데모에 대하여. 호스팅 미리 보기는 정적 사이트(S3 + CloudFront)로, 설정된 도시의 실제, 사전에 계산된 TabPFN-v2 + Gemma 결과를 제공하므로 실제 모델 출력을 클릭하여 확인할 수 있습니다. 반면, 라이브 모델 자체는 서버나 인터넷 연결 없이 사용자의 기기에서 실행됩니다. 사용자 지정에 대해서는...
클론(Clone)한 후, python run.py를 실행하면 localhost:8077에서 작동합니다. 첫 번째 예측을 할 때 모델 가중치(model weights)가 한 번 캐싱되며, 그 이후에는 네트워크 케이블을 뽑아도 여전히 작동합니다.
제가 이것을 만든 방법
이 모든 것은 두 개의 오픈 웨이트 모델이 각각 로컬에서 하나의 정직한 작업을 수행하는 것입니다.
예측: TabPFN-v2
TabPFN은 Prior Labs에서 개발한 테이블형 파운데이션 모델(tabular foundation model)입니다. 이 부분이 흥미롭고 놀라운 지점입니다. 제가 만든 서리 데이터로 모델을 학습시키는 대신, 데이터를 컨텍스트(context)로 제공하면 단 한 번의 순전파(forward pass)만으로 예측합니다. 별도의 학습 루프(training loop), 하이퍼파라미터 검색(hyperparameter search), GPU가 필요 없습니다.
from tabpfn import TabPFNRegressor
from tabpfn.constants import ModelVersion
...
저는 v2 가중치(weights)를 의도적으로 사용했습니다. 기본 TabPFN-3.5 가중치는 상업적이지 않으며 브라우저 로그인을 요구합니다. 반면 v2 가중치는 Prior Labs 라이선스(Apache-2.0 plus attribution)를 따르기 때문에 전체 스택이 진정으로 오픈되어 있고 헤드리스(headless)로 실행될 수 있습니다. '오픈 혁신' 프로젝트에서 이러한 구별점은 부가 설명이 아니라 핵심입니다.
특징(features)은 실제로 서리 시기를 결정하는 요소들입니다: 위도, 고도, 2월과 3월의 평균 기온, 가장 추웠던 겨울밤, 그리고 해당 겨울의 ENSO 지수입니다. 목표 변수(target)는 연중 마지막 서리가 오는 날짜(last-frost day-of-year)입니다. 일반적인 8코어 CPU에서도 약 3초 만에 예측하며, 저는 범위에 대한 10%에서 90% 분위수(quantiles)를 읽습니다.
시카고 같은 입력값의 경우 5월 20일로 나오며, 범위는 5월 15일에서 26일입니다. 파고(Fargo)의 경우 6월 19일이라고 예측합니다. 이 수치들은 실제 기후 규범과 일치하며, 모델이 노이즈를 암기하는 것이 아니라 물리적 원리를 학습하고 있다는 것을 보여주었습니다.
데이터에 대한 솔직한 언급을 드리자면, 저장소의 400개 행 데이터셋은 근거가 있지만 합성(synthetic)입니다. 저는 20개의 실제 미국 지역에 대해 기록된 마지막 서리 규범을 바탕으로 이를 생성했기 때문에 관계 자체는 실재하지만, 이는 라이브 날씨 피드가 아닌 교육용 데이터셋입니다. 이것은 결함이 아니라 특징입니다. 사용자의 자체 기상 관측소 CSV 파일로 fit 포인트를 지정하면 동일한 모델이 실제 뒷마당을 예측합니다. 오픈 스택 덕분에 이 교체 작업이 지원 티켓(support ticket) 대신 한 줄의 코드 변경으로 가능해집니다.
조언: Ollama를 통한 로컬 Gemma 3 사용
날짜는 숫자입니다. 하지만 정원사는 문장을 원합니다. 그래서 Ollama가 제공하는 로컬 Gemma 3 모델이 예측된 날짜와 작물 정보를 결합하여 가이드라인을 만들어줍니다.
payload = {
"model": "gemma3:1b",
"prompt": f"{SYSTEM}\n\nLocation: {station}. Last frost: {date}. Plant: {crop}.",
...
저는 크기가 작아서 gemma3:270m으로 시작했습니다. 하지만 너무 작았습니다. 서리 날짜를 무시하고 잡담을 했습니다. gemma3:1b(약 815 MB)는 지침을 깔끔하게 따르면서도 CPU에서 여전히 편안하게 실행됩니다. 설계에 대한 솔직한 한 줄은 이렇습니다. 모델에게 날짜가 주어지면, 절대로 임의로 만들어내지 않습니다. 그 숫자는 항상 TabPFN의 것입니다.
백업 계획: 모델이 없을 때
'오프라인에서 작동한다'고 약속하는 도구는 모델에 접근할 수 없는 상황에서도 살아남아야 합니다. 만약 Ollama가 다운되면, 결정론적인 내한성(tender-vs-hardy) 규칙이 같은 날짜로부터 정확한 조언을 작성합니다. 이 앱은 끝나지 않는 불안한 스피너를 절대 보여주지 않습니다.
def advise(plant, forecast):
try:
return {"text": call_gemma(plant, forecast), "source": "gemma"}
...
셸(Shell)
작은 FastAPI 서버가 두 모델을 연결하고 단일 페이지 UI를 제공합니다 (조용한 밤하늘 배경에는 Three.js 사용, 빌드 단계 없음). 이 서버는 요청 경로에서 항상 localhost와만 통신합니다. 가중치(weights)가 캐시되면 어떠한 아웃바운드 호출도 없습니다.
데이터가 실제로 말하는 것
모델이 깔끔하게 작동하도록 만든 후, 저는 예측 도구가 거의 하지 않는 일을 했습니다. 즉, 모델에게 무엇을 배웠는지 물어본 것입니다. 각 특징(feature)을 실제 10번째-90번째 백분위수 범위에 걸쳐 스윕하고, 예측된 마지막 서리 날짜가 얼마나 이동했는지 측정했습니다. 여기에 있는 모든 숫자는 python scripts/analyze.py로 재현 가능합니다.
그 결과는 저를 놀라게 했습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


