CareNote๋ AgentDVR์์ ๋ นํ๋ ์์์ RunPod ์๋ฒ๋ก ๋ณด๋ด๊ณ , ์๋ฒ์์ ์์์ ๋ถ์ํ ๋ค ๋์ ์ฌ๋ถ๋ฅผ ํ๋จํ๊ณ ์์ฝ๋ณด๊ณ ์๋ฅผ ์์ฑํ๋ ํ๋ก์ ํธ์ ๋๋ค.
README์์๋ ๋ค์ ๋ด์ฉ์ ํ์ธํ์ค ์ ์์ต๋๋ค.
- ์ด๋ค ํ์ผ์ ์คํํด์ผ ํ๋์ง
- AgentDVR, RunPod, ์์ฝ ์ค์ผ์ค๋ฌ๊ฐ ๊ฐ๊ฐ ์ด๋ค ์ญํ ์ธ์ง
- ์์ ๋ถ์ ๊ฒฐ๊ณผ๊ฐ ์ด๋์ ์ ์ฅ๋๋์ง
- ํด๋ ํ์ ๋๋ฌธ์ ๋๋ ค์ง๋ ๋ฌธ์ ๋ฅผ ์ด๋ป๊ฒ ํด๊ฒฐํ๋์ง
- ํ ์คํธ์ ๋ฌธ์ ํด๊ฒฐ์ ์ด๋ค ์์๋ก ํ๋ฉด ๋๋์ง
๋ก์ปฌ PC์ AgentDVR๊ฐ ์์์ ๋
นํํ๋ฉด send_video.py๊ฐ RunPod ์๋ฒ์ server.py๋ก ์์์ ๋ณด๋ด๊ณ , ์๋ฒ๋ Qwen ๋ชจ๋ธ๋ก ์์ ์ค๋ช
ํ
์คํธ๋ฅผ ๋ง๋ ๋ค ๋์ ๊ฐ์ง, ์ด๋ฉ์ผ ์๋ฆผ, ์์ฝ๋ณด๊ณ ์ ์์ฑ์ ์ฒ๋ฆฌํฉ๋๋ค.
AgentDVR ๋
นํ ์๋ฃ
-> send_video.py ์คํ
-> RunPod ์๋ฒ /health ํ์ธ
-> RunPod ์๋ฒ /analyze-video/๋ก ์์ ์
๋ก๋
-> ์๋ฒ๊ฐ ์์์ ์์ ์ ์ฅ
-> Qwen3-VL ๋ชจ๋ธ์ด ์์ ๋ด์ฉ์ ํ
์คํธ๋ก ๋ถ์
-> ๋ถ์ ํ
์คํธ ํ์ผ ์ ์ฅ
-> ๊ฐ์ ํ
์คํธ๋ฅผ ๋ฐ๋ก ๋์ ๊ฐ์ง ํจ์๋ก ์ ๋ฌ
-> 1์ฐจ ๋์ ๊ฐ์ง
-> ํ์ํ๋ฉด Claude 2์ฐจ ํ๋จ
-> ๋์์ผ๋ก ํ๋จ๋๋ฉด ์ด๋ฉ์ผ ์๋ฆผ
-> ์ ํด์ง ์ฃผ๊ธฐ๋ง๋ค ์์ฝ๋ณด๊ณ ์ ์์ฑ ๋ฐ ์ด๋ฉ์ผ ๋ฐ์ก
์ค์ํ ์ ์ ๋์ ๊ฐ์ง์์ ํด๋๋ฅผ ๋ค์ ๋ค์ ธ์ ์ต์ ํ์ผ์ ์ฐพ์ง ์๋๋ค๋ ๊ฒ์ ๋๋ค. ์๋ฒ๊ฐ ๋ฐฉ๊ธ ๋ง๋ ๋ถ์ ํ ์คํธ๋ฅผ ๋ฐ๋ก ํจ์์ ๋๊ธฐ๊ธฐ ๋๋ฌธ์ ์ค์๊ฐ ๊ฐ์ง ์ง์ฐ์ด ์ค์ด๋ญ๋๋ค.
์ด ํ๋ก์ ํธ๋ ํฌ๊ฒ ๋ ์์น์์ ๋์ํฉ๋๋ค.
| ์์น | ์คํ ํ์ผ | ์ญํ |
|---|---|---|
| RunPod ์๋ฒ | server.py |
์์์ ๋ฐ๊ณ , ๋ชจ๋ธ ๋ถ์, ๋์ ๊ฐ์ง, ์์ฝ ์ค์ผ์ค๋ฌ๋ฅผ ์คํ |
| ๋ก์ปฌ Windows PC | send_video.py |
AgentDVR๊ฐ ๋ง๋ ๋ นํ ์์์ RunPod ์๋ฒ๋ก ์ ์ก |
RunPod์์๋ ์๋ฒ๋ฅผ ์คํํ๊ณ , ๋ก์ปฌ PC์์๋ AgentDVR ์ด๋ฒคํธ์ send_video.py๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
carenote_modular/
server.py RunPod์์ ์คํํ๋ ์๋ฒ ์ง์
์
send_video.py AgentDVR ์์ ์ ์ก ์ง์
์
trigger.example.bat AgentDVR ์ฐ๊ฒฐ์ฉ Windows ๋ฐฐ์นํ์ผ ์์
.env.example GitHub์ ์ฌ๋ฆฌ๋ ํ๊ฒฝ ๋ณ์ ์์ ํ์ผ
.gitignore ๊ฐ์ธ ์ค์ /๋ก๊ทธ/์บ์ ์ ์ธ ๊ท์น
main_scheduler.py 3๋ถ ์ฃผ๊ธฐ ์์ฝ ์ค์ผ์ค๋ฌ
chunked_scheduler.py 60๋ถ ์ฃผ๊ธฐ ์์ฝ ์ค์ผ์ค๋ฌ
summary_worker.py ์์ฝ ์์ฑ ํจ์ ํธํ์ฉ ์ง์
์
fall_alert_checker.py ์ ์ฅ๋ ํ
์คํธ ํ์ผ ๋์ ์ฌ๊ฒ์ฌ์ฉ ์ง์
์
carenote_dashboard.py ๊ธฐ์กด ์ฝ๋ ํธํ์ฉ ๋์๋ณด๋ ์ง์
์
utils.py ๊ธฐ์กด ์ฝ๋ ํธํ์ฉ ์ ํธ ์ง์
์
app/ FastAPI ์๋ฒ, ๋ชจ๋ธ ๋ก๋ฉ, ์์ ๋ถ์ ์์
client/ RunPod๋ก ์์์ ๋ณด๋ด๋ ํด๋ผ์ด์ธํธ ์ฝ๋
core/ ํ์ผ ์ ์ฅ, ์ธ๋ฑ์ค, ๊ณตํต ๋ก๊น
์ค์
dashboard/ ๋์๋ณด๋ ์ํ์ ์ค์ ์ ์ฅ
detection/ ๋์ ๊ฐ์ง, Claude 2์ฐจ ํ๋จ, ๋์ ์ด๋ฉ์ผ
training_data.py 1์ฐจ ๋์ ๊ฐ์ง ์ฌํ์ต์ฉ ๋ฌธ์ฅ ๋ฐ์ดํฐ
train_classifier.py fall_classifier.pkl ์ฌํ์ต ์คํฌ๋ฆฝํธ
summary/ ์์ฝ ์์ฑ, ์์ฝ ์ด๋ฉ์ผ, ์์ฝ ์ค์ผ์ค๋ฌ
web/ ๋์๋ณด๋ HTML
models/ ๋์ 1์ฐจ ๊ฐ์ง ๋ชจ๋ธ ํ์ผ
| ํ์ผ | ์ค๋ช |
|---|---|
server.py |
์๋ฒ ์คํ ํ์ผ์
๋๋ค. ๋ด๋ถ์ ์ผ๋ก app.main:app์ ๋ถ๋ฌ์ต๋๋ค. |
send_video.py |
AgentDVR๊ฐ ๋
นํ ์๋ฃ ํ ์คํํ ํ์ผ์
๋๋ค. ๋ด๋ถ์ ์ผ๋ก client.send_video๋ฅผ ์คํํฉ๋๋ค. |
trigger.example.bat |
AgentDVR์ send_video.py๋ฅผ ์ฐ๊ฒฐํ ๋ ์ฐธ๊ณ ํ๋ Windows ๋ฐฐ์นํ์ผ ์์์
๋๋ค. |
.env.example |
GitHub์ ์ฌ๋ ค๋ ๋๋ ํ๊ฒฝ ๋ณ์ ์์์
๋๋ค. ์ค์ ๋น๋ฐ๊ฐ์ .env์ ๋ฃ์ต๋๋ค. |
.gitignore |
.env, ๋ก๊ทธ, ์บ์, ์์ ํ์ผ์ด GitHub์ ์ฌ๋ผ๊ฐ์ง ์๋๋ก ๋ง์ต๋๋ค. |
main_scheduler.py |
3๋ถ๋ง๋ค ์์ฝ๋ณด๊ณ ์๋ฅผ ์์ฑํ๋ ์ค์ผ์ค๋ฌ์ ๋๋ค. |
chunked_scheduler.py |
60๋ถ๋ง๋ค ์์ฝ๋ณด๊ณ ์๋ฅผ ์์ฑํฉ๋๋ค. ๋ด๋ถ์ ์ผ๋ก 10๋ถ ๋จ์ ์กฐ๊ฐ์ ๋ง๋ค์ด ๊ธด ์๊ฐ๋๋ฅผ ์์ ์ ์ผ๋ก ์์ฝํฉ๋๋ค. |
summary_worker.py |
์์ฝ ์์ฑ ํจ์๋ฅผ ์ง์ importํด์ ์ฐ๋ ๊ธฐ์กด ์ฝ๋์ ํธํ๋๋๋ก ๋จ๊ฒจ๋ ํ์ผ์ ๋๋ค. |
fall_alert_checker.py |
์ด๋ฏธ ์ ์ฅ๋ ํ ์คํธ ํ์ผ ํ๋๋ฅผ ๋ค์ ๋์ ๊ฒ์ฌํ ๋ ์ฌ์ฉํฉ๋๋ค. |
models/fall_classifier.pkl |
1์ฐจ ๋์ ๊ฐ์ง์ ์ฐ๋ ๋ถ๋ฅ ๋ชจ๋ธ์ ๋๋ค. |
detection/training_data.py |
fall_classifier.pkl์ ๋ค์ ํ์ตํ ๋ ์ฐ๋ ๋ฌธ์ฅ ๋ฐ์ดํฐ์
๋๋ค. |
detection/train_classifier.py |
training_data.py๋ฅผ ์ด์ฉํด fall_classifier.pkl์ ์๋ก ๋ง๋๋ ์คํฌ๋ฆฝํธ์
๋๋ค. |
web/dashboard.html |
๋ธ๋ผ์ฐ์ ์์ ๋ณด๋ ๋์๋ณด๋ ํ๋ฉด์ ๋๋ค. |
RunPod ์๋ฒ ์ชฝ์๋ ๋ค์์ด ์ค๋น๋์ด ์์ด์ผ ํฉ๋๋ค.
- Python ์คํ ํ๊ฒฝ
- Qwen3-VL ๋ชจ๋ธ ํ์ผ
- GPU ์ฌ์ฉ ๊ฐ๋ฅํ RunPod Pod
- ํ์ํ Python ๋ผ์ด๋ธ๋ฌ๋ฆฌ
- Anthropic API ํค
- ์ด๋ฉ์ผ ๋ฐ์ก ๊ณ์ ์ ๋ณด
๋ก์ปฌ Windows PC ์ชฝ์๋ ๋ค์์ด ํ์ํฉ๋๋ค.
- AgentDVR
- Python ์คํ ํ๊ฒฝ
send_video.py๊ฐ ์๋ ํ๋ก์ ํธ ํด๋- RunPod ์๋ฒ ์ฃผ์
ํ๊ฒฝ์ ๋ฐ๋ผ ์ด๋ฏธ ์ค์น๋์ด ์์ ์ ์์ต๋๋ค. ์๋ค๋ฉด ๋ค์ ๊ณ์ด์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ํ์ํฉ๋๋ค.
fastapi
uvicorn
python-dotenv
requests
anthropic
numpy
scikit-learn
pytz
pydantic
sentence-transformers
transformers
vllm
qwen-vl-utils
RunPod์ GPU, CUDA, vLLM, Transformers ๋ฒ์ ์ ์ฌ์ฉํ๋ ์ด๋ฏธ์ง์ ๋ชจ๋ธ์ ๋ฐ๋ผ ๋ง์ถฐ์ผ ํฉ๋๋ค.
ํ๊ฒฝ ๋ณ์๋ .env ํ์ผ์ ๋ฃ๊ฑฐ๋ RunPod ํ๊ฒฝ ๋ณ์๋ก ์ค์ ํ ์ ์์ต๋๋ค.
GitHub์๋ ์ค์ .env๋ฅผ ์ฌ๋ฆฌ์ง ๋ง๊ณ .env.example๋ง ์ฌ๋ฆฝ๋๋ค. ์ฒ์ ์คํํ๋ ์ฌ๋์ .env.example์ ๋ณต์ฌํด์ ์๊ธฐ ํ๊ฒฝ์ ๋ง๋ .env๋ฅผ ๋ง๋ค๋ฉด ๋ฉ๋๋ค.
๊ฐ์ฅ ์ค์ํ ๊ฐ:
ANTHROPIC_API_KEY=your_anthropic_api_key
SENDER_EMAIL=sender@example.com
SENDER_PASSWORD=your_email_app_password
JANG_EMAIL=receiver@example.com
CARENOTE_SERVER_URL=https://your-runpod-id-9000.proxy.runpod.net๋ชจ๋ธ๊ณผ ์ ์ฅ ์์น:
CHECKPOINT_PATH=/workspace/models/qwen3-vl-8b-instruct-fp8
BASE_RESULT_DIR=/workspace/development/generated_data์๋ฒ ๋ชจ๋ธ ์ต์ :
GPU_MEMORY_UTILIZATION=0.8
MAX_MODEL_LEN=32768
TENSOR_PARALLEL_SIZE=1
ENFORCE_EAGER=true
MODEL_TIMEOUT_SEC=60
MAX_UPLOAD_BYTES=1073741824์์ฝ ์ค์ผ์ค๋ฌ:
ENABLE_SUMMARY_SCHEDULER=true๋์ ๊ฐ์ง:
EMAIL_ALERT_ENABLED=true
FALL_CLASSIFIER_THRESHOLD=0.65
FALL_CLASSIFIER_PATH=models/fall_classifier.pkl
EMBEDDING_MODEL_NAME=all-MiniLM-L6-v2
CLAUDE_MODEL=claude-sonnet-4-6๋ก๊ทธ:
LOG_LEVEL=INFO
CARENOTE_LOG_FILE=/workspace/development/generated_data/logs/carenote.log
CARENOTE_CLIENT_LOG_FILE=logs/send_video.logAgentDVR ๋์๋ณด๋ ํ์์ฉ:
AGENT_DVR_BASE_URL=http://localhost:8090
AGENT_DVR_OBJECT_ID=1
AGENT_DVR_STREAM_URL=
AGENT_DVR_IFRAME_URL=AGENT_DVR_OBJECT_ID๋ AgentDVR์์ ์นด๋ฉ๋ผ/์ฅ์น๋ง๋ค ๋ถ์ฌ๋๋ ID์
๋๋ค. ํ์ฌ ์นด๋ฉ๋ผ ID๊ฐ 1์ด๋ฉด ์์ฒ๋ผ 1๋ก ๋ก๋๋ค.
RunPod์์ ํ๋ก์ ํธ ํด๋๋ก ์ด๋ํ ๋ค ์๋ฒ๋ฅผ ์คํํฉ๋๋ค.
uvicorn server:app --host 0.0.0.0 --port 9000๊ฐ์ํ๊ฒฝ์ ๋จผ์ ํ์ฑํํ๊ณ AgentDVR ํ๋ฉด ํ์ ์ค์ ๊น์ง ๊ฐ์ด ๋ฃ๋๋ค๋ฉด ๋ค์์ฒ๋ผ ์คํํฉ๋๋ค. ๊ฐ์ํ๊ฒฝ ๊ฒฝ๋ก๋ ์ฌ์ฉํ๋ RunPod ์ด๋ฏธ์ง์ ๋ง๊ฒ ๋ฐ๊ฟ๋๋ค.
source /path/to/your/venv/bin/activate
export AGENT_DVR_BASE_URL="http://localhost:8090/"
export AGENT_DVR_OBJECT_ID="1"
uvicorn server:app --host 0.0.0.0 --port 9000์ฝ๋์์๋ AGENT_DVR_BASE_URL ๋ค์ /๋ฅผ ์๋์ผ๋ก ์ ๋ฆฌํ๋ฏ๋ก http://localhost:8090/์ http://localhost:8090 ๋ ๋ค ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋์๋ณด๋์ AgentDVR ์์ ์ฃผ์๋ ์๋ฒ๊ฐ ๋ง๋ ๋ค ๋ธ๋ผ์ฐ์ ์ ์ ๋ฌํฉ๋๋ค. ๊ทธ๋์ localhost:8090์ ๋์๋ณด๋๋ฅผ ์ด๊ณ ์๋ PC์์ AgentDVR์ ์ ๊ทผ ๊ฐ๋ฅํ ์ฃผ์์ฌ์ผ ํฉ๋๋ค.
์ ์์ ์ผ๋ก ์ผ์ก๋์ง ํ์ธํฉ๋๋ค.
curl http://127.0.0.1:9000/health์ ์ ์๋ต ์์:
{
"status": "ok",
"model_loaded": true
}์ธ๋ถ PC์์๋ RunPod ํ๋ก์ ์ฃผ์๋ก ํ์ธํฉ๋๋ค.
https://your-runpod-id-9000.proxy.runpod.net/health
๋์๋ณด๋๋ ๋ค์ ์ฃผ์์์ ํ์ธํฉ๋๋ค.
https://your-runpod-id-9000.proxy.runpod.net/dashboard
3๋ถ ์ฃผ๊ธฐ ์์ฝ์ main_scheduler.py๊ฐ ๋ด๋นํฉ๋๋ค.
์๋ฒ์ ๋ถ์ด ์๋ ๊ธฐ๋ณธ 60๋ถ ์์ฝ๊ณผ ์ค๋ณต๋์ง ์๊ฒ ํ๋ ค๋ฉด ๋จผ์ ์๋ ์์ฝ์ ๋๋๋ค.
.env:
ENABLE_SUMMARY_SCHEDULER=falseํฐ๋ฏธ๋ 1์์ ์๋ฒ ์คํ:
uvicorn server:app --host 0.0.0.0 --port 9000ํฐ๋ฏธ๋ 2์์ 3๋ถ ์์ฝ ์ค์ผ์ค๋ฌ ์คํ:
python main_scheduler.py์ด๋ ๊ฒ ํ๋ฉด ์์ ๋ถ์ ์๋ฒ๋ ๊ณ์ ์ผ์ ธ ์๊ณ , ์์ฝ๋ณด๊ณ ์๋ 3๋ถ๋ง๋ค ๋ณ๋ ํ๋ก์ธ์ค์์ ์์ฑ๋ฉ๋๋ค.
์๋ฒ์ ๋ถ๋ฆฌํด์ 60๋ถ ์์ฝ ์ค์ผ์ค๋ฌ๋ง ์คํํ๋ ค๋ฉด ๋ค์ ๋ช ๋ น์ ์ฌ์ฉํฉ๋๋ค.
python chunked_scheduler.py์ด ๊ฒฝ์ฐ์๋ ์๋ฒ ์๋ ์์ฝ์ด ์ผ์ ธ ์์ผ๋ฉด ์ค๋ณต ์คํ๋ ์ ์์ผ๋ฏ๋ก, ๋ถ๋ฆฌ ์ด์ํ ๋๋ ENABLE_SUMMARY_SCHEDULER=false๋ฅผ ๊ถ์ฅํฉ๋๋ค.
AgentDVR๋ ๋ นํ๊ฐ ๋๋ฌ์ ๋ ํน์ ์คํฌ๋ฆฝํธ๋ฅผ ์คํํ ์ ์์ต๋๋ค.
์ด ํ๋ก์ ํธ์์๋ ๋ก์ปฌ Windows PC์ send_video.py๋ฅผ AgentDVR ์ด๋ฒคํธ์ ์ฐ๊ฒฐํฉ๋๋ค.
GitHub์๋ ๊ฐ์ธ PC ๊ฒฝ๋ก๊ฐ ๋ค์ด๊ฐ ์ค์ ๋ฐฐ์นํ์ผ ๋์ trigger.example.bat๋ฅผ ์ฌ๋ฆฝ๋๋ค. ์ค์ PC์์๋ ์ด ํ์ผ์ ๋ณต์ฌํด์ AgentDVR๊ฐ ์คํํ๋ trigger.bat๋ก ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
๋ฐฐ์นํ์ผ์์ ์ฌ์ฉํ ์ ์๋ ํ๊ฒฝ ๋ณ์:
CARENOTE_PYTHON_EXE=C:\path\to\python.exe
CARENOTE_SEND_VIDEO_SCRIPT=C:\path\to\carenote_modular\send_video.py
CARENOTE_TRIGGER_LOG_FILE=C:\path\to\logs\trigger.log
์ด ๊ฐ์ ๋ฐ๋ก ์ค์ ํ์ง ์์ผ๋ฉด trigger.example.bat๋ ๊ธฐ๋ณธ์ ์ผ๋ก python ๋ช
๋ น๊ณผ ๋ฐฐ์นํ์ผ์ด ์๋ ํด๋์ send_video.py๋ฅผ ์ฌ์ฉํฉ๋๋ค.
AgentDVR๊ฐ ์์ ํ์ผ ๊ฒฝ๋ก๋ฅผ ์ธ์๋ก ๋๊ธฐ๋ฉด send_video.py๋ ๋ค์ ์์๋ก ๋์ํฉ๋๋ค.
- ์ ๋ฌ๋ฐ์ ์์ ํ์ผ์ด ์ค์ ๋ก ์๋์ง ํ์ธํฉ๋๋ค.
- ํ์ผ ํฌ๊ธฐ๊ฐ ์์ ๋ ๋๊น์ง ์ ์ ๊ธฐ๋ค๋ฆฝ๋๋ค.
- RunPod ์๋ฒ์
/health๋ฅผ ํ์ธํฉ๋๋ค. - ์๋ฒ์ ๋ชจ๋ธ์ด ์ค๋น๋์ด ์์ผ๋ฉด
/analyze-video/๋ก ์ ๋ก๋ํฉ๋๋ค. - ์๋ฒ๊ฐ ์ ์ํ๋ฉด ๋ก์ปฌ ์์ ํ์ผ์ ์ญ์ ํฉ๋๋ค.
๋ก์ปฌ ์์์ ์ญ์ ํ์ง ์์ผ๋ ค๋ฉด ๋ค์ ๊ฐ์ ์ค์ ํฉ๋๋ค.
DELETE_LOCAL_VIDEO_AFTER_SEND=false์๋ ํ ์คํธ:
python send_video.py C:\path\to\test.mp4| ์ฃผ์ | ๋ฐฉ์ | ์ค๋ช |
|---|---|---|
/health |
GET | ์๋ฒ์ ๋ชจ๋ธ ์ค๋น ์ํ ํ์ธ |
/analyze-video/ |
POST | ์์ ์ ๋ก๋ ๋ฐ ๋ถ์ ์์ฒญ |
/dashboard |
GET | ๋์๋ณด๋ ํ๋ฉด |
/api/dashboard/status |
GET | ๋์๋ณด๋ ์ํ JSON |
/api/dashboard/settings |
GET | ์์ ์ด๋ฉ์ผ ์ค์ ํ์ธ |
/api/dashboard/settings |
POST | ์์ ์ด๋ฉ์ผ ์ค์ ๋ณ๊ฒฝ |
/api/dashboard/settings/reset |
POST | ์์ ์ด๋ฉ์ผ ์ค์ ์ด๊ธฐํ |
์์ ์
๋ก๋๋ ๋ฐ๋ก ๋ถ์ ๊ฒฐ๊ณผ๋ฅผ ๊ธฐ๋ค๋ฆฌ์ง ์๊ณ 202 Accepted๋ก ์ ์๋ฉ๋๋ค.
์๋ต ์์:
{
"status": "queued",
"id": "test_abcdef12",
"message": "์์ ์
๋ก๋ ์๋ฃ. ๋ถ์์ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์งํํฉ๋๋ค."
}๋ถ์์ ์๋ฒ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ์งํ๋๋ฉฐ, ๊ฒฐ๊ณผ๋ ํ ์คํธ ํ์ผ๊ณผ ๋์๋ณด๋ ์ํ๋ก ํ์ธํฉ๋๋ค.
๊ธฐ๋ณธ ์ ์ฅ ๋ฃจํธ:
/workspace/development/generated_data
ํ์ ํด๋:
generated_data/
videos/ ์
๋ก๋๋ ์์ ์์ ์ ์ฅ
texts/ Qwen ๋ถ์ ํ
์คํธ ์ ์ฅ
summaries/ ์์ฝ๋ณด๊ณ ์ ์ ์ฅ
status/ ๋์๋ณด๋ ์ํ์ ์ค์ ์ ์ฅ
logs/ ์ค์ ํ ๊ฒฝ์ฐ ๋ก๊ทธ ํ์ผ ์ ์ฅ
ํ ์คํธ ์ ์ฅ ์์:
texts/
camera_2026-06-17_10-00-00.txt
_text_index_2026-06-17.jsonl
_latest_text.json
์์ฝ ์ ์ฅ ์์:
summaries/
summary_2026-06-17_10-00-00_to_2026-06-17_11-00-00.txt
_summary_index.jsonl
_latest_summary.json
์ด์ ๋ฐฉ์์ ํต์ฌ ๋ฌธ์ ๋ ํ ์คํธ ํ์ผ์ด ๋ง์์ง์๋ก ์ต์ ํ์ผ์ ์ฐพ๊ธฐ ์ํด ํด๋ ์ ์ฒด๋ฅผ ํ์ํด์ผ ํ๋ค๋ ์ ์ด์์ต๋๋ค.
ํ์ผ ์๊ฐ ์ ์ ๋๋ ๋ฌธ์ ๊ฐ ์ ๋ณด์ด์ง ์์ง๋ง, ์ฅ๊ธฐ๊ฐ ์ด์ํ๋ฉด texts ํด๋ ์์ ํ์ผ์ด ๊ณ์ ๋์ด๋ฉ๋๋ค. ๊ทธ๋ฌ๋ฉด ์ต์ ํ์ผ ํ๋๋ฅผ ์ฐพ๊ธฐ ์ํด ๋ง์ ํ์ผ ์ด๋ฆ๊ณผ ์์ ์๊ฐ์ ํ์ธํด์ผ ํ๊ณ , ์ ์ฅ์๊ฐ ๋๋ฆฐ ํ๊ฒฝ์์๋ ๋์๋ณด๋๋ ๋์ ๊ฐ์ง๊ฐ ์ง์ฐ๋ ์ ์์ต๋๋ค.
ํ์ฌ ๊ตฌ์กฐ๋ ๋ ๊ฐ์ง๋ก ๋๋ ํด๊ฒฐํฉ๋๋ค.
์ฒซ ๋ฒ์งธ, ์ค์๊ฐ ๋์ ๊ฐ์ง๋ ํ์ผ ํ์์ ํ์ง ์์ต๋๋ค.
์๋ฒ๋ Qwen ๋ถ์์ด ๋๋๋ฉด ๋ถ์ ํ ์คํธ๋ฅผ ํ์ผ๋ก ์ ์ฅํฉ๋๋ค. ๋์์ ๊ทธ ํ ์คํธ ๋ฌธ์์ด์ ๋์ ๊ฐ์ง ํจ์์ ๋ฐ๋ก ๋๊น๋๋ค. ์ฆ, ๋์ ๊ฐ์ง๋ "๋ฐฉ๊ธ ์ ์ฅํ ํ์ผ์ ๋ค์ ํด๋์์ ์ฐพ๋ ๋ฐฉ์"์ด ์๋๋ผ "๋ฐฉ๊ธ ์์ฑ๋ ํ ์คํธ๋ฅผ ๋ฐ๋ก ๊ฒ์ฌํ๋ ๋ฐฉ์"์ ๋๋ค.
๋ ๋ฒ์งธ, ์ฅ๊ธฐ ๋ณด๊ด๊ณผ ์์ฝ ์ฒ๋ฆฌ๋ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ถ์ ํ ์คํธ ํ์ผ์ ๊ทธ๋๋ก ์ ์ฅํฉ๋๋ค. ๋์ ์ ํ ์คํธ๊ฐ ์ ์ฅ๋ ๋๋ง๋ค ์๋ ์ธ๋ฑ์ค ํ์ผ์ ๊ฐ์ด ๊ฐฑ์ ํฉ๋๋ค.
_text_index_YYYY-MM-DD.jsonl
_latest_text.json
์์ฝ๋ณด๊ณ ์๋ ๋ง์ฐฌ๊ฐ์ง๋ก ์ต์ ์์ฝ ํ์ผ ์ ๋ณด๋ฅผ ๋ณ๋ ํ์ผ์ ๊ธฐ๋กํฉ๋๋ค.
_summary_index.jsonl
_latest_summary.json
๊ทธ๋์ ๋์๋ณด๋๋ ์์ฝ ๋ก์ง์ ๋งค๋ฒ ํด๋ ์ ์ฒด๋ฅผ ํ์ง ์๊ณ , ํ์ํ ์ธ๋ฑ์ค๋ง ์ฝ์ต๋๋ค.
์ ๋ฆฌํ๋ฉด ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
| ๋ชฉ์ | ์ด์ ๋ฐฉ์ | ํ์ฌ ๋ฐฉ์ |
|---|---|---|
| ์ค์๊ฐ ๋์ ๊ฐ์ง | ์ ์ฅ๋ ํ์ผ์ ๋ค์ ์ฐพ์ ์ฝ์ | ์์ฑ๋ ํ ์คํธ๋ฅผ ๋ฐ๋ก ํจ์์ ์ ๋ฌ |
| ์ต์ ํ ์คํธ ํ์ | ํด๋ ์ ์ฒด ํ์ | _latest_text.json ์ฝ๊ธฐ |
| ์์ฝ ๋์ ์ฐพ๊ธฐ | ํด๋ ์ ์ฒด ํ์ | ๋ ์ง๋ณ ์ธ๋ฑ์ค ํ์ผ ์ฝ๊ธฐ |
| ์ฅ๊ธฐ ๋ณด๊ด | ํ ์คํธ ํ์ผ ์ ์ฅ | ํ ์คํธ ํ์ผ ์ ์ฅ ์ ์ง |
๋์ ๊ฐ์ง๋ 2๋จ๊ณ๋ก ๊ตฌ์ฑ๋์ด ์์ต๋๋ค.
1์ฐจ ๊ฐ์ง:
models/fall_classifier.pkl๋ชจ๋ธ ์ฌ์ฉ- Qwen์ด ์์ฑํ ํ ์คํธ๋ฅผ ์๋ฒ ๋ฉ์ผ๋ก ๋ณํ
- ๋์ ๊ฐ๋ฅ์ฑ์ด ๊ธฐ์ค๊ฐ ์ด์์ด๋ฉด ์์ฌ ์ํฉ์ผ๋ก ํ๋จ
2์ฐจ ํ๋จ:
- 1์ฐจ ๊ฐ์ง์์ ์์ฌ๋๋ฉด Claude๊ฐ ํ ์คํธ๋ฅผ ๋ค์ ์ฝ๊ณ ํ๋จ
- ์ค์ ๋์์ผ๋ก ํ๋จ๋๋ฉด ์ด๋ฉ์ผ ์๋ฆผ ๋ฐ์ก
๋์์ธ๋ฐ ์ ์์ผ๋ก ์ฒ๋ฆฌ๋๋ ๊ฒฝ์ฐ์๋ ๋จผ์ ๊ธฐ์ค๊ฐ์ ๋ฎ์ถฐ ํ ์คํธํฉ๋๋ค.
FALL_CLASSIFIER_THRESHOLD=0.45๊ฐ์ ๋ฎ์ถ๋ฉด ๋์์ ๋ ์ ์ก์ ์ ์์ง๋ง, ์ ์ ์ํฉ์ ๋์์ผ๋ก ์คํํ ๊ฐ๋ฅ์ฑ๋ ๋์ด๋ฉ๋๋ค. ์ฅ๊ธฐ์ ์ผ๋ก๋ ์ค์ Qwen ์ถ๋ ฅ ๋ฌธ์ฅ์ ๋ชจ์์ fall_classifier.pkl์ ๋ค์ ํ์ตํ๋ ๊ฒ์ด ๊ฐ์ฅ ์ข์ต๋๋ค.
models/fall_classifier.pkl์ 1์ฐจ ๋์ ๊ฐ์ง์ ์ฌ์ฉํ๋ ํ์ต ์๋ฃ ๋ชจ๋ธ์
๋๋ค.
์ฃผ์ํ ์ ์ .pkl ์์ ์๋ณธ ๋ฌธ์ฅ ๋ฐ์ดํฐ๊ฐ ๊ทธ๋๋ก ๋ค์ด ์๋ ๊ฒ์ด ์๋๋ผ๋ ์ ์
๋๋ค. ์๋ณธ ๋ฌธ์ฅ๋ค์ detection/training_data.py์ ๋ณด๊ดํ๊ณ , .pkl์๋ ๊ทธ ๋ฌธ์ฅ๋ค๋ก ํ์ต๋ Logistic Regression ๋ชจ๋ธ์ ๊ฐ์ค์น๊ฐ ์ ์ฅ๋ฉ๋๋ค.
์ ํ๋๋ฅผ ์ฌ๋ฆฌ๊ณ ์ถ์ ๋๋ ๋ค์ ์์๋ก ์์ ํฉ๋๋ค.
detection/training_data.py์ ์ค์ Qwen ์ถ๋ ฅ ๋ฌธ์ฅ์ ์ถ๊ฐํฉ๋๋ค.- ๋์/์ฃผ์ ์ํฉ์ด๋ฉด ๋ผ๋ฒจ์
1๋ก ๋ก๋๋ค. - ์ ์ ์ํฉ์ด๋ฉด ๋ผ๋ฒจ์
0์ผ๋ก ๋ก๋๋ค. - ์ฌํ์ต ๋ช ๋ น์ ์คํํฉ๋๋ค.
- ์๋ก ์์ฑ๋
models/fall_classifier.pkl๋ก ์๋ฒ๋ฅผ ๋ค์ ์คํํฉ๋๋ค.
์ฌํ์ต ๋ช ๋ น:
python -m detection.train_classifier๊ธฐ๋ณธ ๋์:
- ๊ธฐ์กด
models/fall_classifier.pkl์ด ์์ผ๋ฉด.bak๋ฐฑ์ ํ์ผ์ ๋จผ์ ๋ง๋ญ๋๋ค. detection/training_data.py์TRAINING_DATA๋ฅผ ์๋ฒ ๋ฉํฉ๋๋ค.- Logistic Regression ๋ชจ๋ธ์ ๋ค์ ํ์ตํฉ๋๋ค.
- ์ ๋ชจ๋ธ์
models/fall_classifier.pkl์ ์ ์ฅํฉ๋๋ค.
๋ฐฑ์ ์์ด ๋ฐ๋ก ๋ฎ์ด์ฐ๊ณ ์ถ์ ๋:
python -m detection.train_classifier --no-backup๋ค๋ฅธ ์์น์ ์ ์ฅํ๊ณ ์ถ์ ๋:
python -m detection.train_classifier --output /workspace/development/generated_data/models/fall_classifier.pklํ์ต๋ง ํ ์คํธํ๊ณ ํ์ผ์ ์ ์ฅํ์ง ์์ผ๋ ค๋ฉด:
python -m detection.train_classifier --dry-run์ฌํ์ต ํ ์๋ฒ์์ ์ ๋ชจ๋ธ์ ์ฐ๊ฒ ํ๋ ค๋ฉด ์๋ฒ๋ฅผ ์ฌ์์ํ๋ ๊ฒ์ด ๊ฐ์ฅ ํ์คํฉ๋๋ค.
์ด๋ฉ์ผ์ ๋ ์ข ๋ฅ๊ฐ ์์ต๋๋ค.
| ์์น | ์ญํ |
|---|---|
detection/emailer.py |
๋์ ๋ฐ์ ์ ๊ธด๊ธ ์๋ฆผ ์ด๋ฉ์ผ ๋ฐ์ก |
summary/emailer.py |
์ ๊ธฐ ์์ฝ๋ณด๊ณ ์ ์ด๋ฉ์ผ ๋ฐ์ก |
๋ ํ์ผ ๋ชจ๋ ๋ฐ์ ๊ณ์ ์ SENDER_EMAIL, SENDER_PASSWORD๋ฅผ ์ฌ์ฉํฉ๋๋ค.
์์ ์๋ ๊ธฐ๋ณธ์ ์ผ๋ก JANG_EMAIL์ ์ฌ์ฉํ๋ฉฐ, ๋์๋ณด๋์์ ์์ ์ด๋ฉ์ผ์ ๋ฐ๊พธ๋ฉด ๋์ ์๋ฆผ์ ๋์๋ณด๋ ์ค์ ์ ์ฐ์ ์ฌ์ฉํฉ๋๋ค.
์๋ฒ์ ์ค์ผ์ค๋ฌ๋ Python logging์ ์ฌ์ฉํฉ๋๋ค.
๊ธฐ๋ณธ ๋ก๊ทธ ๋ ๋ฒจ:
LOG_LEVEL=INFO๋ ์์ธํ ๋ณด๊ณ ์ถ์ ๋:
LOG_LEVEL=DEBUGํ์ผ์๋ ์ ์ฅํ๊ณ ์ถ์ ๋:
CARENOTE_LOG_FILE=/workspace/development/generated_data/logs/carenote.log๋ก์ปฌ PC์์ send_video.py๊ฐ ๋จ๊ธฐ๋ ์ ์ก ๋ก๊ทธ๋ ๋ณ๋ ํ์ผ์ ์ฌ์ฉํฉ๋๋ค.
CARENOTE_CLIENT_LOG_FILE=logs/send_video.loguvicorn server:app --host 0.0.0.0 --port 9000curl http://127.0.0.1:9000/healthmodel_loaded๊ฐ true๊ฐ ๋ ๋๊น์ง ๊ธฐ๋ค๋ฆฝ๋๋ค.
๋ก์ปฌ PC ๋ธ๋ผ์ฐ์ ์์ ์๋ ์ฃผ์๋ฅผ ์ฝ๋๋ค.
https://your-runpod-id-9000.proxy.runpod.net/health
https://your-runpod-id-9000.proxy.runpod.net/dashboard
RunPod ๋๋ ๋ก์ปฌ PC์์ ํ ์คํธ ์์์ ํ๋ ๋ณด๋ ๋๋ค.
curl -X POST -F "file=@test.mp4" https://your-runpod-id-9000.proxy.runpod.net/analyze-video/ls /workspace/development/generated_data/texts์๋ ํ์ผ์ด ์๊ฒผ๋์ง ํ์ธํฉ๋๋ค.
๋ถ์๊ฒฐ๊ณผ.txt
_text_index_YYYY-MM-DD.jsonl
_latest_text.json
60๋ถ ์์ฝ์ ์๊ฐ์ด ์ง๋์ผ ์์ฑ๋ฉ๋๋ค. ๋ฐ๋ก ํ ์คํธํ๊ณ ์ถ๋ค๋ฉด 3๋ถ ์ค์ผ์ค๋ฌ๋ฅผ ๋ฐ๋ก ์คํํฉ๋๋ค.
python main_scheduler.py์์ฝ ํ์ผ ํ์ธ:
ls /workspace/development/generated_data/summaries์ง์ ์
๋ก๋ ํ
์คํธ๊ฐ ์ฑ๊ณตํ ๋ค AgentDVR ์ด๋ฒคํธ์ send_video.py๋ฅผ ์ฐ๊ฒฐํฉ๋๋ค.
502๋ ๋๋ถ๋ถ RunPod ํ๋ก์๊ฐ ์๋ฒ ์ฑ์ ์ฐ๊ฒฐํ์ง ๋ชปํ๋ค๋ ๋ป์ ๋๋ค.
ํ์ธํ ๊ฒ:
- Pod๊ฐ Running ์ํ์ธ์ง
- ์๋ฒ๋ฅผ
--host 0.0.0.0 --port 9000์ผ๋ก ์คํํ๋์ง - RunPod ํ๋ก์ ์ฃผ์์ ํฌํธ๊ฐ 9000์ธ์ง
- ์๋ฒ๊ฐ ์คํ ์ค์ ์๋ฌ๋ก ์ข ๋ฃ๋์ง ์์๋์ง
- ๋ชจ๋ธ ๋ก๋ฉ ์ค ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ์ด ๋ฐ์ํ์ง ์์๋์ง
FastAPI ์๋ฒ๋ ์ผ์ก์ง๋ง Qwen ๋ชจ๋ธ์ด ์์ง ์ค๋น๋์ง ์์ ์ํ์ ๋๋ค.
ํ์ธํ ๊ฒ:
- ๋ชจ๋ธ ๊ฒฝ๋ก
CHECKPOINT_PATH๊ฐ ๋ง๋์ง - RunPod GPU ๋ฉ๋ชจ๋ฆฌ๊ฐ ์ถฉ๋ถํ์ง
GPU_MEMORY_UTILIZATION,MAX_MODEL_LEN๊ฐ์ ๋๋ฌด ํฌ๊ฒ ์ก์ง ์์๋์ง- ์๋ฒ ๋ก๊ทธ์ ๋ชจ๋ธ ๋ก๋ฉ ์ค๋ฅ๊ฐ ์๋์ง
๋ชจ๋ธ ๋ก๋ฉ์ด ๋๋๊ธฐ ์ ์ ์์์ ๋ณด๋ธ ์ํ์ ๋๋ค.
/health์์ model_loaded=true๊ฐ ๋์จ ๋ค ๋ค์ ํ
์คํธํฉ๋๋ค.
์๋ฒ๊ฐ ์ด๋ฏธ ๋ค๋ฅธ ์์์ ๋ถ์ ์ค์ด๋ผ๋ ๋ป์ ๋๋ค.
ํ์ฌ ๊ตฌ์กฐ๋ ํ ๋ฒ์ ํ๋์ ์์๋ง ๋ถ์ํ๋๋ก ์ ๊ธ์ด ๊ฑธ๋ ค ์์ต๋๋ค. ์ด์ ์์ ๋ถ์์ด ๋๋ ๋ค ๋ค์ ์์์ ์ฒ๋ฆฌํฉ๋๋ค.
์์ฝ ๋์ ์๊ฐ ๊ตฌ๊ฐ์ ๋ถ์ ํ ์คํธ๊ฐ ์์ผ๋ฉด ์์ฝ๋ณด๊ณ ์๋ฅผ ๋ง๋ค์ง ์์ต๋๋ค.
ํ์ธํ ๊ฒ:
/workspace/development/generated_data/texts์ ๋ถ์ ํ ์คํธ๊ฐ ์๋์ง_text_index_YYYY-MM-DD.jsonlํ์ผ์ด ์๋์งANTHROPIC_API_KEY๊ฐ ์ค์ ๋์ด ์๋์ง- ์ค์ผ์ค๋ฌ๊ฐ ์ค์ ๋ก ์คํ ์ค์ธ์ง
ํ์ธํ ๊ฒ:
SENDER_EMAIL์ด ๋ง๋์งSENDER_PASSWORD๊ฐ ์ผ๋ฐ ๋น๋ฐ๋ฒํธ๊ฐ ์๋๋ผ ์ฑ ๋น๋ฐ๋ฒํธ์ธ์งJANG_EMAIL๋๋ ๋์๋ณด๋ ์์ ์ด๋ฉ์ผ์ด ๋ง๋์ง- Gmail ๋ณด์ ์ค์ ์์ SMTP ๋ก๊ทธ์ธ์ด ํ์ฉ๋๋์ง
send_video.py๋ ์์์ ๋ณด๋ด๊ธฐ ์ ์ /health๋ฅผ ํ์ธํฉ๋๋ค.
๋ค์ ์ค ํ๋์ผ ๊ฐ๋ฅ์ฑ์ด ํฝ๋๋ค.
- RunPod ์๋ฒ๊ฐ ์์ง ์ผ์ง์ง ์์
- ์๋ฒ๋ ์ผ์ก์ง๋ง ๋ชจ๋ธ ๋ก๋ฉ์ด ๋๋์ง ์์
- RunPod ํ๋ก์ ์ฃผ์๊ฐ ํ๋ฆผ
- ํฌํธ๊ฐ 9000์ด ์๋
- ์๋ฒ๊ฐ ์ค๊ฐ์ ์๋ฌ๋ก ์ข ๋ฃ๋จ
๋จผ์ ๋ธ๋ผ์ฐ์ ์์ ์๋ ์ฃผ์๋ฅผ ์ง์ ์ด์ด ํ์ธํฉ๋๋ค.
https://your-runpod-id-9000.proxy.runpod.net/health
์๋ฒ ์คํ:
uvicorn server:app --host 0.0.0.0 --port 9000์๋ฒ ์ํ ํ์ธ:
curl http://127.0.0.1:9000/healthํ ์คํธ ์์ ์ ๋ก๋:
curl -X POST -F "file=@test.mp4" http://127.0.0.1:9000/analyze-video/3๋ถ ์์ฝ ์ค์ผ์ค๋ฌ:
python main_scheduler.py60๋ถ ์์ฝ ์ค์ผ์ค๋ฌ:
python chunked_scheduler.pyํ ์คํธ ํ์ผ ๋์ ์ฌ๊ฒ์ฌ:
python fall_alert_checker.py /workspace/development/generated_data/texts/example.txtAgentDVR ์ ์ก ์๋ ํ ์คํธ:
python send_video.py C:\path\to\test.mp41์ฐจ ๋์ ๊ฐ์ง ๋ชจ๋ธ ์ฌํ์ต:
python -m detection.train_classifier- RunPod์์ ๊ธฐ๋ณธ์ผ๋ก ์คํํ ๊ฒ์
server.py์ ๋๋ค. - ๋ก์ปฌ AgentDVR์์ ์คํํ ๊ฒ์
send_video.py์ ๋๋ค. - ์๋ฒ๋ฅผ ์ผ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก 60๋ถ ์์ฝ ์ค์ผ์ค๋ฌ๋ ๊ฐ์ด ์คํ๋ฉ๋๋ค.
- 3๋ถ ์์ฝ์ ์ฐ๋ ค๋ฉด
main_scheduler.py๋ฅผ ๋ฐ๋ก ์คํํฉ๋๋ค. - ์ค์๊ฐ ๋์ ๊ฐ์ง๋ ํ ์คํธ ๋ด์ฉ์ ๋ฐ๋ก ์ ๋ฌ๋ฐ๊ธฐ ๋๋ฌธ์ ํด๋ ์ ์ฒด ํ์ ์ง์ฐ์ ํผํฉ๋๋ค.
- ํ ์คํธ์ ์์ฝ ํ์ผ์ ์ฅ๊ธฐ ๋ณด๊ด์ ์ํด ๊ณ์ ์ ์ฅ๋ฉ๋๋ค.
- ๋์๋ณด๋์ ์์ฝ ๋ก์ง์ ์ต์ ์ ๋ณด ํ์ผ๊ณผ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- 1์ฐจ ๋์ ๊ฐ์ง ์ ํ๋๋ฅผ ๊ฐ์ ํ๋ ค๋ฉด
detection/training_data.py๋ฅผ ์์ ํ๊ณpython -m detection.train_classifier๋ก.pkl์ ๋ค์ ๋ง๋ญ๋๋ค.