dev.to

I built an offline AI that knows your last frost date, no internet, no API

인터넷·API 없이 서리 날짜를 예측하는 오프라인 AI를 만들었습니다

FrostWise는 TabPFN-v2로 마지막 봄 서리 날짜를 예측하고 Gemma 3로 작물별 재배 조언을 작성하는 오프라인 도구입니다. CPU에서 실행하며 위치와 기후 정보를 외부 서버로 보내지 않습니다. 다만 기본 데이터셋은 실제 기후 통계를 바탕으로 만든 합성 데이터입니다.

AI 요약

FrostWise는 마지막 봄 서리 날짜와 작물별 파종 조언을 인터넷 연결 없이 제공하는 오픈소스 앱입니다. 텃밭에서 휴대전화 신호가 약해 서리 날짜를 확인하기 어려운 사용자를 위해 만들었습니다. 위치를 선택하거나 기후 수치를 직접 입력하고 작물을 고르면 예상 서리 날짜와 범위, 작물별 안내를 보여줍니다. 토마토나 바질처럼 추위에 약한 작물은 서리가 지난 뒤 심으라고 안내하고, 완두콩이나 케일처럼 추위에 강한 작물은 몇 주 일찍 파종하라고 알려줍니다.

두 모델이 맡은 역할

TabPFN-v2는 기후 특성을 바탕으로 서리 날짜를 예측합니다. 입력 특성은 위도와 고도, 2월·3월 평균 기온, 겨울철 최저 기온, 해당 겨울의 ENSO 지수입니다. 목표값은 마지막 서리 날짜를 연중 날짜(day-of-year)로 나타낸 수치입니다. 작성자는 학습 반복이나 하이퍼파라미터 탐색 없이 데이터를 문맥으로 넣고 한 번 추론하는 방식으로 사용합니다. 8코어 CPU에서는 예측에 약 3초가 걸립니다. 단일 날짜만 보여주는 대신 10~90 백분위수로 예상 범위도 제시합니다.

Gemma 3는 TabPFN이 낸 날짜와 선택한 작물을 받아 문장 형태의 재배 조언을 작성합니다. Ollama로 로컬에서 실행하며, 처음 시험한 gemma3:270m은 서리 날짜를 무시하고 대화를 이어가는 문제가 있었습니다. 약 815MB인 gemma3:1b는 지시를 더 잘 따랐고 CPU에서도 실행됐습니다. 날짜는 TabPFN의 예측값으로 고정하고 Gemma에는 조언만 맡깁니다. Ollama에 연결하지 못하면 강건한 작물과 추위에 약한 작물을 구분하는 규칙 기반 안내로 대체합니다.

실행과 데이터의 한계

FastAPI 서버가 두 모델과 단일 페이지 UI를 연결합니다. 모델 가중치를 처음 내려받아 캐시한 뒤에는 요청 처리 과정에서 외부로 통신하지 않습니다. 저장소를 복제하고 python run.py를 실행하면 localhost:8077에서 사용할 수 있습니다. 맞춤형 기후 데이터를 넣으려면 로컬 실행이 필요합니다. 공개 데모는 S3와 CloudFront로 제공하는 정적 사이트이며, 미리 계산한 TabPFN-v2와 Gemma 결과를 도시별로 보여줍니다. 데모의 모델 추론이 서버에서 실시간으로 이뤄지는 것은 아닙니다.

저장소에 포함한 데이터는 400행 규모의 합성 데이터입니다. 미국 내 실제 20개 지역의 공개된 마지막 서리 기후 기준을 바탕으로 만들었지만, 실시간 기상 관측 자료는 아닙니다. 작성자는 실제 기상 관측소 CSV를 넣어 같은 모델을 다시 사용할 수 있다고 설명합니다. 시카고와 비슷한 입력에서는 5월 20일, 범위는 5월 15~26일로 예측했고, 파고에서는 6월 19일을 제시했습니다. 이 결과가 실제 기후 기준과 맞았다는 점도 함께 언급하지만, 합성 데이터에 기반한 예시라는 한계가 있습니다.

특성 분석 결과

작성자는 각 특성을 실제 10~90 백분위 범위에서 바꾸며 예측 날짜가 며칠 움직이는지 분석했습니다. 2월 평균 기온 변화는 50일, 3월 평균 기온은 32일, 겨울철 최저 기온은 27일, 위도는 24일, 고도는 12일, ENSO 지수는 10일 차이를 냈습니다. 이 분석에서는 위도보다 2월 기온 변화가 더 큰 영향을 보였습니다. 다만 이는 저장소의 합성 데이터에서 얻은 결과입니다.

ENSO 영향은 지역에 따라 달랐습니다. 파고와 비슷한 기후에서는 라니냐와 엘니뇨 사이의 예측 차이가 약 0.1일이었고, 휴스턴과 비슷한 지역에서는 8일이었습니다. 위도 40도에서 해발 0m와 1,600m를 비교하면 고도가 높을 때 마지막 서리가 약 13일 늦어졌다고 설명합니다. 분석 스크립트는 python scripts/analyze.py로 실행할 수 있습니다.

오픈 모델 선택과 검증

작성자는 기본 TabPFN-3.5 가중치가 비상업적이며 브라우저 로그인을 요구해 TabPFN-v2를 골랐습니다. TabPFN-v2는 Prior Labs License를 따르며 Apache-2.0과 출처 표시 조건을 포함한다고 설명합니다. Gemma는 Ollama에서 실행하며 다른 오픈 웨이트 모델로 교체할 수 있습니다. 위치 정보가 외부 서버로 전송되지 않고 요청별 API 비용도 없다는 점이 오프라인 설계의 이유입니다.

개발 과정에서는 AI 코딩 에이전트를 사용했지만, 모델을 실제 CPU 환경에서 실행해 확인한 뒤 제품에 반영했다고 적었습니다. 초기 실행에서 정적 파일 경로 오류로 UI가 비어 보이는 문제와 작은 Gemma 모델이 날짜 지시를 따르지 않는 문제를 찾아 수정했습니다. 데이터가 합성이라는 사실도 검토 과정에서 드러나 게시글에 명시했다고 설명합니다.

원문: dev.to / 번역·요약: Trawling