🌿 TrailMates: 스크롤은 줄이고, 방랑을 늘리는 오픈 웨이트 AI
요약
TrailMates는 사용자가 스크린에서 벗어나 야외 활동을 즐기도록 돕는 오픈 소스 AI 기반 앱입니다. 시간, 에너지 수준, 관심사 등을 고려하여 맞춤형 야외 모험 계획(활동 단계, 준비물, 질문 등)을 생성합니다. 단순한 일정표가 아닌 놀이 같은 자연 일지처럼 디자인되어 사용자 경험에 초점을 맞췄습니다.
핵심 포인트
- 스크린 중독 해소 및 아웃도어 활동 장려 앱입니다.
- 사용자의 상태(시간/에너지) 기반의 맞춤형 야외 계획을 제공합니다.
- 놀이와 같은 자연 일지 인터페이스로 사용자 경험을 개선했습니다.
- Python FastAPI 백엔드와 웹 기술 스택으로 구현되었습니다.
이 글은 Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass에 제출하는 내용입니다.
🌿 TrailMates — 스크롤은 줄이고, 방랑을 늘리다
만약 AI가 당신을 화면에 붙잡아 두려고 하는 대신, 당신이 그 화면에서 벗어나도록 도와준다면 어떨까요?
제가 만든 것 (What I Built)
TrailMates는 여가 시간을 작고 스크린 없는 모험으로 바꾸어 주는 오픈 소스 야외 활동 동반자입니다.
밖에 나가보고 싶지만 무엇을 해야 할지 전혀 모르겠다고 느낀 적이 있나요? TrailMates가 시작하는 것을 도와줍니다.
사용 가능한 시간, 에너지 수준, 선호하는 장소, 관심사를 선택하세요. 앱은 실용적인 활동 단계, 가져갈 물품, 안전 알림, 휴대폰 없는 도전 과제, 그리고 나중에 돌아보고 생각할 질문이 포함된 맞춤형 야외 계획을 생성합니다.
어쩌면 30분밖에 없고 에너지가 낮을 수도 있습니다. 어쩌면 근처 공원을 탐험하거나, 새들을 관찰하거나, 작은 디테일을 사진으로 찍거나, 아니면 단순히 마음챙김 산책을 하고 싶을 수도 있습니다.
복잡한 일정표가 필요하지 않을 때도 있습니다. 때로는 그저 약간의 자극이 필요할 뿐입니다.
저는 TrailMates를 마치 놀이 같은 자연 일지처럼 느끼도록 디자인했습니다. 흙빛 색상, 손으로 그린 낙서, 그리고 야외 활동을 매력적으로 느끼게 하는 친근한 인터페이스가 특징입니다.
진짜 목표는 무엇일까요? 앱이 충분히 유용하게 느껴져서 휴대폰을 내려놓고 모험을 즐길 수 있게 만드는 것입니다. 🌱
데모 (Demo)
🌿 실시간 앱: https://trailmates-89sz.onrender.com/
🔍 건강 점검: https://trailmates-89sz.onrender.com/health
📊 AI 상태: https://trailmates-89sz.onrender.com/api/status
이 애플리케이션은 Render에 호스팅되어 있으며, Python FastAPI 백엔드를 사용합니다.
AI 경험은 구성된 모델과 추론 제공업체(inference provider)에 따라 달라집니다. 만약 추론이 불가능하면, 앱은 모델이 생성한 것처럼 가장하는 대신 명확하게 표시된 규칙 기반 데모 계획으로 대체할 수 있습니다.
참고: 호스팅 서비스가 유휴 상태였을 경우 첫 번째 요청은 시간이 더 걸릴 수 있습니다.
코드
💻 GitHub 저장소: https://github.com/riyanshika7/TRAILMATES
이 프로젝트는 HTML, CSS, JavaScript, 그리고 Python FastAPI를 기반으로 구축된 경량 아키텍처를 사용합니다.
주요 파일들은 다음과 같습니다:
app/services/hf_service.py— 모델 추론(model inference) 및 AI 응답 처리.static/index.html— 랜딩 페이지 및 어드벤처 기획 인터페이스.static/app.js— 프론트엔드 상호작용 및 API 통신.render.yaml— Render 배포 설정.tests/test_api.py— 백엔드 API 테스트.
구축 과정 (How I Built It)
오픈 웨이트 모델 — Hugging Face Inference Providers
핵심 AI는 Qwen/Qwen2.5-7B-Instruct이며, 이는 HF Inference Providers 문서에서 추천하는 모델 중 하나입니다. 이 모델은 공식 OpenAI 호환 라우터 엔드포인트(router endpoint)를 통해 호출됩니다:
POST https://router.huggingface.co/v1/chat/completions
Authorization: Bearer $HF_TOKEN
시스템 프롬프트(system prompt)는 모델에게 엄격한 JSON 스키마(title, steps, items_to_bring, safety_tips, phone_free_challenge, reflection_question)를 반환하도록 지시합니다. hf_service.py의 _extract_ai_result() 메서드는 응답을 검증하며 — choices[0].message.content가 비어있지 않고(non-empty), 80자 이상이며(≥80 chars), JSON으로 파싱 가능하고, title과 steps를 포함하는지 확인한 후 is_ai_generated: true를 설정합니다. 이러한 검사 중 하나라도 실패하면 규칙 기반 폴백(rule-based fallback)이 실행되며 항상 명확하게 표시됩니다.
TabPFN (Prior Labs)
tabpfn 패키지는 requirements.txt에 포함되어 있습니다. Render에서 로드될 때, 적합성 스코어러는 "TabPFN (Prior Labs 테이블 모델)"로 표시됩니다. 로드가 되지 않을 경우(예: 로컬 CPU 전용 환경), "Heuristic rule-based scorer"라는 레이블의 휴리스틱 스코어러로 대체되며 — 이 레이블은 self.has_official_tabpfn에서 설정됩니다.
ElevenLabs
elevenlabs SDK는 elevenlabs_service.py에 연결되어 있습니다. API 키가 유효하면 플랜 브리핑을 위한 오디오 URL을 반환합니다. 401(만료된 키)을 반환하거나 구성되지 않은 경우, 프론트엔드는 window.speechSynthesis (브라우저 Web Speech API)로 대체되며 — 사용자는 여전히 오디오를 받지만 클라이언트 측에서 합성됩니다.
SerpApi
serpapi_service.py는 키와 위치가 제공될 때 로컬 공원 결과를 위해 Google Maps 엔진을 호출합니다. 결과에는 "source": "serpapi-live" 태그가 포함됩니다. 정적 기본값은 "source": "static-default"를 포함하여 프론트엔드가 어떤 데이터가 실제인지(그리고 실제로) 보여줄 수 있게 합니다.
Sentry
sentry_service.py는 모든 서비스 호출을 AgentSpan 컨텍스트 관리자로 감싸서 타이밍, 입력 및 출력을 인메모리 리스트에 기록합니다. 환경 변수에 SENTRY_DSN이 설정되면, 동일한 스팬이 Sentry의 추적 대시보드로 전달됩니다. 시작 로그는 어떤 모드가 활성화되었는지 정확하게 알려줍니다.
Render
앱은 render.yaml을 사용하여 Render에서 Python 웹 서비스로 배포됩니다:
빌드: pip install -r requirements.txt
시작: uvicorn app.main:app --host 0.0.0.0 --port $PORT
헬스 체크: /health가 {"status": "healthy"}를 반환합니다.
모든 API 키는 Render 환경 변수로 저장되며 — 클라이언트 브라우저로 절대 전송되지 않습니다.
이 구분은 중요합니다: 애플리케이션은 자신의 AI가 작동할 때에 대해 정직해야 합니다.
⚙️ 애플리케이션 스택
- 프론트엔드: HTML5, CSS3 및 바닐라 JavaScript.
- 백엔드: Python 및 FastAPI.
- 모델 추론: Hugging Face Inference Providers.
- 호스팅: Render Web Services.
- 버전 관리: Git 및 GitHub.
저는 프론트엔드와 백엔드를 이해하고 확장하기 쉽게 유지하는 경량 아키텍처를 선택했습니다.
🚀 Render를 사용하는 이유
Render는 TrailMates의 공개 호스팅 환경을 제공하며, 프론트엔드로부터 요청을 처리하는 FastAPI 애플리케이션을 실행합니다.
백엔드는 설정된 추론(inference) 제공업체와 통신하고, 응답을 처리하며, 사용자에게 구조화된 계획을 반환할 책임이 있습니다. API 자격 증명은 브라우저 코드에 포함되기보다는 서버 측 환경 변수에 남아 있습니다.
또한 이 애플리케이션은 배포 모니터링을 위한 상태 확인(health-check) 엔드포인트를 제공합니다.
단일 호스팅 애플리케이션을 사용함으로써 배포가 비교적 간단하게 유지되면서도 AI 통합을 발전시킬 여지를 남겨둡니다.
오픈 이노베이션이 중요한 이유
TrailMates에게 있어 오픈 이노베이션은 기술의 적응성을 유지하는 것입니다.
저는 이 프로젝트의 미래가 완전히 하나의 독점 모델 API에 의존하기를 원하지 않았습니다.
오픈 웨이트(open-weight) 모델은 개발자들에게 다양한 모델을 탐색하고, 그 출력을 비교하며, 프롬프트로 실험하고, 애플리케이션의 동작을 사용자 필요에 맞게 조정할 기회를 제공합니다.
이러한 유연성은 아웃도어 동반자에게 중요합니다. 15분밖에 없고 에너지가 낮은 사람과 활기찬 오후 시간을 보내고 싶은 사람이 필요로 하는 제안은 다릅니다. 저는 TrailMates가 전체 애플리케이션을 불필요하게 다시 작성하지 않고도 어떻게 그러한 경험들을 계획할 수 있는지 실험하고 싶습니다.
오픈 이노베이션은 또한 저에게 투명성에 대해 생각하도록 장려했습니다. 모델 추론이 사용할 수 없을 때, 규칙 기반 대체(rule-based fallback)는 여전히 유용한 데모 계획을 제공할 수 있습니다. 하지만 이는 절대 AI가 생성한 것으로 오인되어서는 안 됩니다.
트레이드오프(trade-offs)가 존재합니다. TrailMates는 현재 Hugging Face Inference Providers를 사용할 때 외부 추론 인프라에 의존합니다. 가용성, 지연 시간(latency), 비용은 구성된 제공업체와 모델에 따라 달라집니다. 저는 호스팅된 애플리케이션이 완전히 오프라인으로 실행되거나 추론이 대규모로 무료라고 주장하는 것이 아닙니다.
향후 버전에서는 호환 가능한 모델을 이용한 로컬 추론(local inference)을 지원하여, 사용자와 기여자들에게 플래너를 실행할 또 다른 방법을 제공하고 외부 추론 서비스에 대한 의존도를 줄일 수 있을 것입니다. 이는 또한 하드웨어 및 성능 고려 사항을 도입하게 됩니다.
저에게 오픈 혁신이란 오픈 모델이 모든 상황에서 자동으로 더 좋거나 저렴하다고 주장하는 것이 아닙니다. 그것은 대안을 탐구하고, 실험으로부터 배우고, 진화할 수 있는 무언가를 구축할 자유를 갖는 것입니다.
그리고 이것이 제가 이 프로젝트에서 가장 좋아하는 부분입니다: AI가 사람들을 AI와 계속 상호작용하도록 유지하기 위한 것이 아닙니다. 그것은 그들이 화면 너머의 무언가를 발견하는 것을 돕기 위한 것입니다.
나의 에이전트 세션 (My Agent Session)
Antigravity (AGY)로 구축되었으며, 전체 다중 세션 대화(multi-session conversation)를 통해 이 저장소에 포함된 코드(엔드포인트 수정, 정직한 출처 표기 로직, 그리고 이번 제출물 포함)가 생성되었습니다. 저는 구현의 주요 참고 자료로서 소스 코드를 공유합니다.
수상 부문 (Prize Categories)
-
Render 활용 최우수: TrailMates는 FastAPI 백엔드와 헬스 체크 엔드포인트를 갖춘 Render 호스팅 웹 애플리케이션으로 배포되었습니다.
-
Hugging Face 오픈 웨이트 모델 활용 최우수: https://router.huggingface.co/v1/chat/completions를 통한 Qwen/Qwen2.5-7B-Instruct 사용. 출처 표기는 응답 검증 후에만 표시됩니다.
-
최우수 TabPFN 활용: Prior Labs tabpfn 패키지가 설치되었으며, 적합성 스코어러가 어떤 것이 로드되었는지에 따라
🌼 마지막으로 전해드릴 이야기
기술이 항상 우리의 주의를 더 요구할 필요는 없습니다.
때로는, 우리가 그 주의를 주변 세상에 돌려주는 데 도움을 줄 수 있습니다.
TrailMates를 사용해보세요. 작은 모험을 생성하고, 휴대폰을 치우고, 바깥에서 무엇을 발견하는지 살펴보세요.
신선한 공기 한 모금. 약간의 호기심. 그리고 스크롤링은 조금 덜 하는 것.
아주 사소한 모험이라도 의미가 있습니다. 🌿
devchallenge #hf26challenge
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기