본문으로 건너뛰기

문제 해결

AI 스택은 docker compose 하나입니다. 그래서 문제 해결의 출발점도 하나입니다 — 어느 컨테이너가 이상한지 찾고, 그 컨테이너의 로그를 본다.

cd /opt/kopens/plantpulse-ai-docker/bin
./doctor.sh # 아무것도 바꾸지 않고 진찰만 합니다. 장애 중에 먼저 돌리십시오
./status.sh # 무엇이 떠 있나
./health.sh # 디스크 · 자원 · 서비스별 최근 로그까지

스택이 뜨지 않습니다​

형제 저장소 둘이 있는지부터​

ls /opt/kopens
# plantpulse-ai-docker
# plantpulse-ai-inference-server ← 없으면 compose 가 뜨지 않습니다
# plantpulse-timeseries-insight-server ← 없으면 compose 가 뜨지 않습니다

compose 가 이 둘의 파일을 상대 경로로 bind-mount 합니다(예: 게이트웨이 설정 litellm-config.yaml). 없으면 설치기가 기동을 거부하고 빠진 저장소 이름을 찍습니다 → 설치 개요.

설정 파일이 있는지​

sudo test -f /etc/kopens/plantpulse-ai.env && echo 있음 || echo 없음

없으면 bin/install.sh 를 다시 돌리거나 compose/env.gb10.example 을 그 경로로 복사합니다.

🔴 compose/.env 를 고치지 마십시오. 아무도 읽지 않습니다 — 정본은 /etc/kopens/plantpulse-ai.env 입니다.

기동 전 판정이 세웠는지​

bin/up.sh · restart.sh · update.sh 는 compose 를 올리기 전에 env 파일을 판정하고, 어긋나면 컨테이너를 하나도 만들지 않고 멈춥니다. 2026.10 에서 가장 흔한 것은 둘입니다.

cd /opt/kopens/plantpulse-ai-docker
sudo bash bin/lint-env.sh # 줄마다 제자리인지 — 바꾸지 않습니다
출력원인조치
lines that do not belong in … 와 줄마다 release · profile · redundant · derived · unknown2026.09 이하의 env 를 그대로 올렸다 — 이미지 참조 · GPU 몫 · 기본값과 같은 값 · PP_HOST · 옛 플랫폼 계정 줄이 남아 있다찍힌 sed 한 줄로 지웁니다. 지우기 전에 플랫폼 자격증명 두 값을 넣습니다 → 환경 변수 설정
renamed keys still use their old names옛 이름 CH_* 이 남았다지우지 말고 찍힌 sed(이름만 바꿈)를 실행합니다 → 아래 「CH_ 접두사」
PP_HW_PROFILE is not set하드웨어 모양 줄이 없다GB10 이면 PP_HW_PROFILE=gb10, AWS g7e 면 g7e 를 넣습니다
still has template placeholdersCHANGE_ME_* 가 남았다찍힌 키를 채웁니다. 공개 템플릿에 적힌 값으로는 띄우지 않습니다
[FATAL] [platform-credentials] …기동 전 DB 프로비저닝이 플랫폼 자격증명을 못 받았다아래 「컨테이너가 FATAL 로 멈춥니다」와 같은 원인입니다
PI_INBOUND_API_KEY is empty and PI_INBOUND_AUTH_DISABLED is not true인바운드 키가 비었다아래 「뒷단 서비스가 기동을 거부합니다」
PI_MEDIA_ENABLED=<값> — true 또는 false 만 받는다영상 · 음성 스위치에 다른 값을 적었다true 나 false 로 고칩니다 → 영상 · 음성 수집
줄 목록에 ASR_URL … media호스트 env 의 ASR_URL 이 영상 · 음성 스위치가 주는 값과 다르다그 줄을 지웁니다. 녹취를 켜는 것은 PI_MEDIA_ENABLED=true 한 줄입니다

[warn] 으로 찍히는 줄(lines to tidy — the stack starts as is)은 기동을 막지 않습니다 — 옛 이름 MEDIA_INGEST_ENABLED (이번 릴리즈 동안 별칭, alias), 스위치와 같은 값의 ASR_URL(media-same), 새 이름과 같은 값으로 남은 옛 줄(oldname)입니다. 함께 찍힌 sed 한 줄로 정리합니다. 별칭은 2026.11 에 걷어 내므로 그 전에 옮기십시오.

compose 자체가 요구하는 값(PP_DATALAKE_ADMIN_URL · PP_DATALAKE_ADMIN_API_KEY · PP_HW_PROFILE 등)이 비었는지는 이렇게 봅니다.

docker compose --env-file /etc/kopens/plantpulse-ai.env -f compose/docker-compose.yml config >/dev/null

컨테이너 하나가 계속 재시작합니다​

docker compose ps # 어느 것이 Restarting 인가
docker compose logs --tail=200 <컨테이너> # 왜 죽는가
자주 나오는 원인확인
GPU 를 못 잡음nvidia-smi · docker compose logs plantpulse-llm
플랫폼 DB 에 못 붙음아래 「플랫폼 DB」
메모리 부족docker stats · dmesg -T | grep -i oom
포트 충돌ss -ltnp | grep -E '80|443|4000|5959|5960|7115|8970' — 설치기가 이미 «남이 쥔 포트» 로 경고했을 수 있습니다 → 서비스 포트 맵
플랫폼 자격증명을 못 받음아래 「컨테이너가 FATAL 로 멈춥니다」
뒷단 서비스가 inbound · INBOUND_API_KEY is empty 로 멈춤아래 「뒷단 서비스가 기동을 거부합니다」
코파일럿만 기동 거부아래 「코파일럿만 뜨지 않습니다」

컨테이너가 FATAL 로 멈춥니다 — 플랫폼 자격증명​

2026.10 부터 코파일럿 · 시계열 인사이트 API · LightRAG · RAG API · 디지털 스레드 · LiteLLM 은 기동할 때 플랫폼에서 계정 · 비밀번호를 받습니다. 받지 못하면 지난 값으로 뜨지 않고 FATAL 로 멈춥니다 — 그래서 이 여섯 중 여럿이 한꺼번에 재시작을 되풀이하면 여기부터 보십시오.

docker logs --tail=50 plantpulse-copilot-web 2>&1 | grep -iE 'credentials|fatal'
sudo grep -E '^PP_DATALAKE_ADMIN_(URL|API_KEY)=' /etc/kopens/plantpulse-ai.env
ls -l /etc/kopens/ca/root.crt /etc/kopens/ca/CA.crt
원인조치
PP_DATALAKE_ADMIN_URL · PP_DATALAKE_ADMIN_API_KEY 중 하나만 있음둘 다 넣습니다. 하나만 있으면 컨테이너가 거절합니다
/etc/kopens/ca/root.crt 가 없음플랫폼 신뢰 앵커를 둡니다(같은 내용을 CA.crt 로도). 인증서 검증을 끄는 길은 없습니다
키가 틀렸거나 AI 호스트 IP 가 플랫폼 허용목록에 없음(4xx)플랫폼 호스트 /etc/kopens/plantpulse-platform.env 의 PP_DATALAKE_ADMIN_API_KEY 를 그대로 옮기고, 허용목록에 AI 호스트 IP 를 넣습니다. 4xx 는 재시도 없이 바로 멈춥니다
플랫폼 :4950 에 안 닿음 · 5xx잠시 재시도한 뒤 멈춥니다. curl -sk https://<플랫폼 호스트>:4950 로 닿는지부터 봅니다

호스트 스크립트(기동 전 DB 프로비저닝 · install.sh START=1 의 사전 확인)도 같은 값으로 받습니다. 거기서 실패하면 컨테이너가 뜨기 전에 [FATAL] [platform-credentials] … 한 줄이 이유를 말하고 멈춥니다 — 조치는 위 표와 같습니다.

받기에 성공하면 로그에 credentials: 로 시작하는 줄이 키 이름과 개수만 찍습니다. 값을 고친 뒤에는 bin/restart.sh 로 다시 만듭니다 → 설치 개요


뒷단 서비스가 기동을 거부합니다 — 인바운드 키​

RAG · 시계열 인사이트 API · 문서 이해 · 비전 · 디지털 스레드는 인바운드 키가 비면 뜨지 않습니다(2026.10 재릴리즈 전에는 인증 없이 열린 채 healthy 로 떴습니다).

sudo grep -c '^PI_INBOUND_API_KEY=.' /etc/kopens/plantpulse-ai.env # 1 이면 값이 있습니다
docker logs --tail=50 plantpulse-rag-api 2>&1 | grep -iE 'inbound|fatal'
증상원인조치
bin/up.sh 가 컨테이너를 하나도 만들지 않고 [fail] PI_INBOUND_API_KEY is empty … 를 찍는다env 에 줄이 없거나 값이 비었다 — 기동 전 판정이 멈춥니다sudo bin/passwd.sh --generate PI_INBOUND_API_KEY 로 넣습니다(파일을 고친 뒤 스택을 다시 올립니다)
[fail] PI_INBOUND_AUTH_DISABLED=<값> — write true or false무인증 스위치에 다른 값을 적었다true · false 로 고치거나 줄을 지웁니다
로그에 FATAL: RAG_INBOUND_API_KEY is empty — refusing to start … 같은 줄컨테이너에 빈 키가 들어갔다 — compose 를 우회해 띄웠거나 이미지를 따로 돌렸다위와 같이 키를 넣고 bin/restart.sh 로 다시 만듭니다
스택은 뜨는데 관리 콘솔 · 채팅의 RAG · 시계열 호출이 401키를 바꾼 뒤 일부만 다시 만들었다bin/restart.sh 로 전체를 다시 만듭니다 — 아래 「관리 콘솔이 502 · upstream_auth」

인증 없이 띄우는 길은 개발용 스위치 PI_INBOUND_AUTH_DISABLED=true 하나이고, 키가 있으면 그 스위치는 무시됩니다 ([note] … is ignored — PI_INBOUND_API_KEY is set and the key wins). 운영 설치에서는 키를 넣는 것이 답입니다 → 환경 변수 설정


코파일럿만 뜨지 않습니다 — 저장 자격증명 암호화 키​

나머지 스택은 초록인데 plantpulse-copilot-web 만 기동을 거부한다면 PI_COPILOT_SECRET_KEY 를 봅니다.

docker logs --tail=50 plantpulse-copilot-web 2>&1 | grep -iE 'SECRET_KEY|secrets'
로그원인조치
PI_COPILOT_SECRET_KEY=… 한 줄을 넣으라고 찍음키가 없거나 모양이 틀림 — 2026.09 이하에서 올린 호스트는 줄이 없습니다(설치기가 기존 env 에 더하지 않습니다)openssl rand -base64 32 값으로 넣고 다시 만듭니다 → 환경 변수 설정
Stored secrets cannot be decrypted키가 바뀌었는데 옛 값을 주지 않음옛 값을 PI_COPILOT_SECRET_KEY_PREVIOUS 에 둡니다 → 교체 절차. 옛 값을 잃었다면 로그가 찍는 SQL 로 봉한 행을 비우고 그 자격증명을 화면에서 다시 넣습니다

디지털 스레드의 PI_DT_SECRET_KEY 가 비면 스택은 뜨고 커넥터 등록부만 config_error(503)로 답합니다. 기동 전 판정(bin/lint-env.sh)이 두 키가 빠졌는지 «저장 자격증명 암호화 키가 없다» 로 알려 줍니다.


설정을 바꿨는데 코파일럿이 무시합니다 — CH_ 접두사​

2026.10 에서 코파일럿 환경 변수의 접두사가 CH_ → CO_ 로 바뀌었고 폴백이 없습니다. 예전 env 의 CH_API_V1_KEY · CH_LLM_MAX_COMPLETION_TOKENS · CH_OTEL_GENAI_CONTENT 같은 줄은 코파일럿이 읽지 않습니다. 줄을 지우기만 하면 값이 기본값으로 돌아갑니다 — 예컨대 CH_API_V1_KEY 로 부르던 외부 연동은 그 키로 더는 들어오지 못합니다.

기동 전 판정은 이 줄들을 renamed 로 잡아 기동을 세우고, 줄마다 이름만 바꾸는 sed 한 줄을 찍습니다(값은 그대로, 백업을 남김). 그것을 실행하고 bin/restart.sh plantpulse-copilot-web 으로 다시 만듭니다.

cd /opt/kopens/plantpulse-ai-docker
sudo bash bin/lint-env.sh 2>&1 | grep -A2 'renamed'

옛 이름과 새 이름이 둘 다 있고 값이 다르면 새 이름이 이깁니다 — 어느 값이 맞는지 확인한 뒤 옛 줄을 지웁니다 → 환경 변수 설정


올린 뒤 로그가 안 남거나 쓰기가 실패합니다 — 볼륨 소유권​

2026.10 부터 컨테이너는 plantpulse-dcgm 하나를 빼고 전부 비root 로 돕니다(우리 이미지는 uid 10001, gid 0). 옛 설치에서 root 로 만들어진 쓰기 볼륨(앱 로그 · 시계열 파인튜닝 가중치 · LightRAG · Qdrant · Neo4j · Phoenix 저장소, vLLM 캐시, 프록시 인증서)에는 그대로 쓰지 못합니다. 그 실패는 대개 조용하고(로그 파일 대신 콘솔에만 남는 식), Qdrant 는 바로 죽고, 프록시는 인증서 키를 못 읽어 처방을 찍고 멈춥니다.

bin/up.sh · restart.sh · update.sh 는 올리기 전에 bin/volumes-nonroot.sh 로 소유권을 한 번 맞춥니다. docker compose up 을 맨손으로 불렀다면 이 단계를 건너뛴 것입니다.

cd /opt/kopens/plantpulse-ai-docker/bin
./volumes-nonroot.sh # 이미 맞으면 아무것도 바꾸지 않습니다
./restart.sh

맞추지 못하면 볼륨 소유권을 <uid:gid> 로 맞추지 못했다 를 찍고 기동을 멈춥니다 → 서비스 운영


플랫폼 DB 에 못 붙습니다​

🔴 AI 스택은 PostgreSQL · Aster TSDB · Redis · RustFS 를 띄우지 않습니다. 플랫폼 설치본을 공용으로 씁니다. 이 넷이 죽으면 AI 도 함께 멈춥니다.

# 플랫폼 호스트는 이 URL 의 호스트입니다 (PP_HOST 는 따로 적지 않습니다)
sudo grep -E '^PP_DATALAKE_ADMIN_URL=' /etc/kopens/plantpulse-ai.env

# 실제로 닿는가
nc -zv <플랫폼 호스트> 5432 # PostgreSQL
nc -zv <플랫폼 호스트> 9042 # Cassandra

안 닿으면 플랫폼 쪽 문제입니다 → 서비스 포트 맵.

플랫폼 계정은 env 에 없습니다 (2026.10)

PG · Aster TSDB · Redis · RustFS 의 계정 · 비밀번호 · 포트는 컨테이너도 호스트 스크립트도 시작할 때 플랫폼에서 받습니다. 인증이 거절되면 env 가 아니라 플랫폼의 값과 위 「컨테이너가 FATAL 로 멈춥니다」를 보십시오. 플랫폼에서 비밀번호를 바꿨다면 AI 컨테이너를 다시 시작해야 새 값을 받습니다.


관리 콘솔이 502 · upstream_auth 를 띄웁니다​

콘솔 화면의 한 메뉴가 … rejected the console's inbound API key (401) - check <변수> 로 실패한다면, 콘솔 뒤의 서비스가 콘솔의 인바운드 키를 거절한 것입니다 — 콘솔 세션 만료가 아닙니다. 예전 판은 이 401 을 세션 만료로 읽어 로그인 화면으로만 되돌려 보냈습니다(다시 로그인해도 같았습니다).

뒷단과 콘솔이 같은 PI_INBOUND_API_KEY 로 떠 있는지가 원인입니다. 한쪽만 다시 만들었거나 키를 바꾼 뒤 일부만 재기동한 경우가 대부분이므로, 스택 전체를 다시 만듭니다.

cd /opt/kopens/plantpulse-ai-docker && bin/restart.sh

관리 콘솔 주소는 2026.10 부터 http://<AI 서버>:5959 · https://<AI 서버>:5960 입니다(종전 9080).

LLM 화면이 502 · llm_upstream 을 띄웁니다​

콘솔의 LLM 읽기 화면(API 키 · 로그 · 모델 등록 목록 · 업스트림 상태 등)이 502 와 사유 llm_upstream 으로 실패한다면, 게이트웨이(LiteLLM)나 그 DB 가 5xx 를 낸 것입니다 — 콘솔 백엔드가 터진 것이 아닙니다. 응답의 upstream_status 가 게이트웨이가 낸 상태 코드입니다. 예전 판은 이것을 500 으로 그대로 흘려 콘솔 고장처럼 보였습니다.

docker compose logs --tail=100 plantpulse-litellm # 게이트웨이가 왜 5xx 를 냈나 (DB 접속 등)

게이트웨이에 아예 닿지 못하면 같은 502 에 사유가 llm_unreachable 입니다. 4xx(입력 오류)는 게이트웨이의 사유가 그대로 화면에 나옵니다.


답이 안 나옵니다​

순서대로 좁힙니다 — 게이트웨이 → 모델 → 화면.

docker compose logs --tail=100 plantpulse-litellm # 게이트웨이가 요청을 받았나
docker compose logs --tail=100 plantpulse-llm # 모델이 답했나
docker compose logs --tail=100 plantpulse-copilot-web
증상흔한 원인
게이트웨이 로그에 요청이 없다화면에서 게이트웨이 주소·키가 틀림
게이트웨이가 401PI_LLM_API_KEY 불일치
외부 연동만 모델 이름 오류로 실패옛 이름(aura-35b · gpt-4o · text-embedding-3-large 등)을 부름 — 지금은 aura-lite · aura-embedding-4b 입니다 → API 연동 가이드
모델이 오래 걸리다 끊김GPU 메모리 부족 — nvidia-smi
「답을 만들지 못했습니다 … 모델이 빈 응답을 돌려줬습니다」다시 시도해도 모델이 빈 답을 냈습니다(API 로는 502). 반복되면 사고 모드와 생성 상한을 봅니다 → 환경 변수 설정
「⚠ 같은 내용이 반복되어 답변 생성을 중단했습니다」모델이 같은 말을 되풀이해 코파일럿이 끊었습니다. 질문을 좁혀 다시 묻습니다

「연결이 끊겼습니다. 서버는 답을 계속 만들고 있어…」​

묻기 도중 연결만 끊긴 것입니다(네트워크 전환 · 프록시 절단 등). 새 화면의 문구는 「연결이 끊겼습니다. 서버가 답을 마저 만들고 있어, 끝나는 대로 여기에 불러옵니다」 입니다. 서버는 답을 끝까지 만들어 저장하므로, 화면은 이 안내를 띄운 채 5초마다, 최대 5분 동안 그 대화의 답을 다시 조회해 도착하면 불러옵니다. 기다리면 됩니다 — 폰에서도 같습니다. 5분 안에 못 찾으면 오류 안내로 바뀌고 다시 시도 단추가 남습니다 — 이때는 대화를 다시 열어 답이 저장됐는지 먼저 보십시오.


문서를 못 찾습니다 (RAG)​

docker compose logs --tail=100 plantpulse-rag-api
docker compose logs --tail=100 plantpulse-lightrag
curl -s http://127.0.0.1:6333/healthz # Qdrant(벡터 색인)
증상볼 곳
채팅이 「문서 검색을 지금 쓸 수 없습니다(MCP 게이트웨이 응답 없음) …」 라고만 하고 답하지 않는다채팅의 문서 검색은 MCP 게이트웨이로만 갑니다. 게이트웨이가 떠 있는지 — docker compose logs --tail=100 plantpulse-mcp-gateway-api, 코파일럿 로그의 [MCP_GATEWAY] unreachable · [DOC_SEARCH_GUARD]. 같은 때 다른 질문의 답 앞머리에는 「도구 게이트웨이에 닿지 않습니다 …」 가 붙습니다
채팅이 「문서 검색 도구가 꺼져 있거나 이 계정에 허용되지 않았습니다 …」 라고만 하고 답하지 않는다게이트웨이는 응답하는데 rag_search 가 모델에 오지 않습니다. AI 관리 콘솔 › MCP 게이트웨이 에서 서버의 RAG Gateway 와 도구의 rag_search 가 켜져 있는지 봅니다(둘 다 처음부터 켜져 있으니 누가 끈 것입니다). 켜져 있으면 그 사람의 채팅 도구 권한(tool:mcp)과 게이트웨이 «권한» 탭을 봅니다 → RAG — 채팅의 문서 검색
넣은 문서가 검색에 안 걸린다색인 작업이 끝났는지 — plantpulse-rag-api 로그 · Sync History 의 건너뛴 이유 → RAG
문서 업로드가 실패한다plantpulse-docling-serve · plantpulse-document-understanding-api
답이 엉뚱한 문서를 인용한다색인이 낡음 — 다시 넣고 색인
AI 가 「문서에서 찾지 못했다」고만 한다정상 동작일 수 있습니다 — 검색이 빈손이면 답을 짓지 않고 retrieved: false 로 돌려줍니다. rag_list_documents 로 그 문서가 색인돼 있는지부터 봅니다
RAG /health 가 degraded응답의 ingest · neo4j · qdrant 중 ok 가 아닌 것

큰 PDF 가 색인 도중 실패합니다​

LightRAG 는 문서 조각마다 LLM 으로 엔티티를 뽑습니다. 한 조각이 시간 안에 못 끝나면 문서 전체가 실패로 남고, 남은 조각은 시도도 하지 않습니다.

docker compose logs plantpulse-lightrag | grep -E 'Worker execution timeout|workers initialized'
로그뜻
extract LLM func: Worker execution timeout after 480s예전 기본값(호출당 240초)으로 도는 설치입니다
(Timeouts: Func: 3600s, Worker: 7200s, …)지금 기본값입니다

시간 예산은 /etc/kopens/plantpulse-ai.env 의 LIGHTRAG_LLM_TIMEOUT(기본 3600초)이고, 실제 한도는 그 두 배입니다. 채팅과 질의가 몰려 모델이 느린 시간대에 색인이 잘리면 이 값을 봅니다. 바꾼 뒤에는 재시작이 아니라 재생성(bin/restart.sh)이 필요합니다.

타임아웃만 늘리지 마십시오

한 조각의 출력 상한(LIGHTRAG_LLM_MAX_TOKENS, 기본 32768)이 함께 걸려 있어 긴 예산이 안전합니다. 상한을 지우고 예산만 늘리면 폭주한 요청 하나가 GPU 슬롯을 한 시간 붙잡습니다.

문서·사진 도구가 refused to fetch 로 실패합니다​

문서 이해 · 비전 도구는 받은 URL 이 사내 주소(루프백 · 사설망 · 링크로컬) 로 풀리면 거절합니다. 사유에 resolves to a non-public address 가 보이면 이 경우입니다.

사내 파일 서버를 일부러 열어 주려면 그 호스트 이름을 FETCH_ALLOWED_HOSTS 에 적고 두 서비스를 다시 만듭니다. URL 에 쓰는 이름 그대로(포트를 붙이면 그 포트만) 적어야 맞습니다.

echo 'FETCH_ALLOWED_HOSTS=files.example.local' | sudo tee -a /etc/kopens/plantpulse-ai.env >/dev/null
cd /opt/kopens/plantpulse-ai-docker
bin/restart.sh plantpulse-document-understanding-api plantpulse-vision-api

→ 환경 변수 설정 · MCP 도구 지도

도면이 일반 문서로 색인되거나 도면 화면이 안 나옵니다​

도면 수집은 기본으로 꺼져 있습니다(DRAWING_INGEST_ENABLED=false). 꺼져 있으면 rag-api 에 도면 API 자체가 없고, DXF · PDF 도면은 도면으로 읽히지 않습니다.

docker exec plantpulse-rag-api printenv DRAWING_INGEST_ENABLED

false 면 호스트 env 에 DRAWING_INGEST_ENABLED=true 를 적고 bin/restart.sh plantpulse-rag-api 로 다시 만든 뒤, 도면을 다시 올립니다 — 켜기 전에 올린 파일은 도면으로 다시 읽히지 않습니다. PDF 는 올릴 때 종류를 «도면» 으로 줘야 도면으로 읽힙니다 → 환경 변수 설정

콘솔이 내는 말뜻
drawing is platform-managed — update it in the platform, not here (409)플랫폼 자산 문서로 들어온 도면을 콘솔에서 덮어 올리려 했습니다(2026.10 재릴리즈 3). 고치는 것은 플랫폼에서 합니다
drawing is platform-managed — delete it in the platform ledger, or exclude it from RAG (POST …/exclude) (409)플랫폼 원장 도면을 콘솔에서 지우려 했습니다. 지우는 것은 플랫폼 원장에서 하고, 검색에서만 빼려면 «코퍼스에서 제외» 합니다
manually uploaded drawings cannot be excluded — delete the drawing or re-index it instead (platform-ledger drawings can be excluded) (409)콘솔에서 직접 올린 도면은 «검색 제외» 를 할 수 없습니다. 지우거나 다시 색인합니다. 플랫폼 원장 도면은 제외할 수 있습니다
extension not allowed (400)DWG 입니다. DXF 나 PDF 로 내보내 올립니다

채팅에 넣은 파일을 읽지 못합니다​

묻기 입력칸의 파일 넣기로 넣은 파일은 코파일럿이 받아 객체 저장소에 두고, 문서 이해 서비스(plantpulse-document-understanding-api)에 읽게 합니다 — 문서는 docling 으로, 도면은 도면 판독으로, 영상 · 음성은 녹취(/api/v1/transcribe → plantpulse-asr)로. 쓰는 법은 AI 채팅 — 파일 넣기에 있습니다.

docker logs --tail=200 plantpulse-copilot-web 2>&1 | grep -E '\[CHAT_ATTACH|\[attach\]|\[CHAT_MEDIA' # 올림 · 판독 · 녹취 · 실패 사유
docker compose logs --tail=100 plantpulse-document-understanding-api
docker compose logs --tail=100 plantpulse-docling-serve
docker compose logs --tail=100 plantpulse-asr # 영상 · 음성 — PI_MEDIA_ENABLED=true 일 때만 뜹니다

올릴 때 거절되는 것 — 칩에 아래 문장이 그대로 뜨고, 그 파일은 보내지 않습니다.

칩에 뜨는 말원인 · 할 일
「이 파일 형식은 올릴 수 없습니다. 오피스(xlsx·xls·csv·docx·pptx)·PDF·도면(DXF·PDF)·영상(mp4·mov·mkv·webm)·음성(m4a·mp3·wav) 파일을 올려 주세요」받는 형식이 아닙니다. 형식은 내용으로 판정하므로 확장자만 바꿔서는 들어가지 않습니다
「영상·음성 파일의 이름과 내용이 맞지 않습니다 …」확장자는 영상 · 음성인데 파일 머리가 그 형식이 아닙니다. 변환기에서 확장자만 바꾼 파일이면 원래 형식으로 다시 내보냅니다
「영상·음성 파일이 너무 큽니다(최대 1GB)」영상 · 음성은 1GB 까지입니다. 나누거나 해상도를 낮춰 넣습니다
「영상·음성이 너무 깁니다(최대 60분). 잘라서 올려 주세요」60분이 넘습니다. 앞부분만 받지 않습니다 — 잘라서 나눠 넣습니다
「지금은 녹취를 기다리는 파일이 많습니다. 잠시 뒤 다시 올려 주세요」설치 전체에서 녹취를 기다리거나 올리는 중인 영상 · 음성이 4개입니다. 앞의 것이 처리되면 다시 넣습니다
「DWG 는 읽지 못합니다. DXF 나 PDF 로 내보내 올려 주세요」CAD 에서 DXF 나 PDF 로 내보내 넣습니다
「사진은 이미지로 붙여 주세요(입력칸에 놓으면 이미지로 붙습니다)」사진 파일이 첨부 길로 왔습니다. 입력칸에 다시 넣으면 사진으로 붙습니다
「파일이 너무 큽니다(최대 50MB)」파일 하나는 50MB 까지입니다. 나눠서 넣습니다
「한 대화에는 파일을 20개까지 올릴 수 있습니다」이 대화에 이미 20개가 있습니다. 새 대화에서 넣습니다
「파일이 비어 있습니다」0바이트 파일입니다
「이 파일을 읽지 못했습니다: 손상됐거나 끝까지 받지 못했습니다」파일이 깨졌거나 올리는 중에 끊겼습니다. 원본을 열어 본 뒤 다시 넣습니다
「파일 구조가 너무 커서 받지 않았습니다(압축을 푼 크기·항목 수 상한)」오피스 파일 안의 항목이 2만 개를 넘거나 풀린 크기가 500MB 를 넘습니다
「파일을 저장하지 못했습니다. 잠시 뒤 다시 올려 주세요」객체 저장소에 쓰지 못했습니다. 코파일럿 로그와 객체 저장소 상태를 봅니다

올린 뒤 판독이 실패한 것 — 칩에 「이 파일을 읽지 못했습니다: 사유」 가 뜹니다. 사유는 서버가 남긴 영어 문장입니다. 이 파일은 보낼 수 있고, AI 는 «읽지 못한 파일» 로 압니다.

사유원인 · 할 일
document reader unreachable · drawing reader unreachable문서 이해 서비스에 닿지 못했습니다. plantpulse-document-understanding-api 가 떠 있는지 봅니다
document reader is not configured코파일럿에 문서 이해 서비스 주소가 없습니다. 기본 compose 에서는 생기지 않습니다 — 설정을 손으로 바꿨는지 봅니다
reading took longer than 10 min판독이 10분을 넘었습니다. 큰 PDF 이거나 색인 작업과 겹친 때입니다. 파일을 빼고 한산할 때 다시 넣거나, 필요한 쪽만 잘라 넣습니다
too many files are being read — remove it and add it again동시에 읽는 파일이 너무 많습니다. 칩을 빼고 잠시 뒤 다시 넣습니다
reading was interrupted — remove the file and add it again판독 중에 코파일럿이 다시 시작했습니다(15분 넘게 진행이 없으면 이렇게 접습니다). 빼고 다시 넣습니다
document reader answered 503 등 숫자문서 이해 서비스가 바쁘거나 키가 맞지 않습니다. 문서 이해 로그를 봅니다
그 밖의 문장문서 이해 서비스가 준 사유 그대로입니다(예: 열리지 않는 옛 오피스 파일). 원본을 PDF 나 새 형식(xlsx · docx · pptx)으로 다시 저장해 넣습니다

영상 · 음성의 녹취가 실패한 것 — 칩에 「녹취하지 못했습니다: 사유」 또는 「받지 않았습니다: 사유」 가 뜹니다. 사유는 문서 이해 서비스가 준 영어 문장 그대로입니다. 연결 · 혼잡 같은 일시 실패는 1 · 5 · 30초 뒤 세 번 다시 해 본 뒤에 실패로 접고, 설정 · 입력 문제는 바로 실패로 접습니다. 실패한 파일도 보낼 수 있고 원본도 재생되지만, AI 는 «받아 적지 못한 파일» 로 압니다.

사유원인 · 할 일
media transcription is disabled: ASR_URL is not set영상 · 음성이 꺼진 설치입니다. 관리자가 호스트 env 에 PI_MEDIA_ENABLED=true 를 넣고 녹취 모델을 받아 다시 띄웁니다 → 영상 · 음성 수집
media transcription is misconfigured: …녹취 설정이 맞지 않습니다(서빙 이름 등). 문서 이해의 /health 와 로그를 봅니다
transcription service unreachable · transcription service answered 503 등문서 이해 서비스나 녹취 서빙(plantpulse-asr)에 닿지 못했거나 바빴습니다. 둘이 떠 있는지 보고 빼고 다시 넣습니다
transcription service is not configured코파일럿에 문서 이해 서비스 주소가 없습니다. 기본 compose 에서는 생기지 않습니다
「받지 않았습니다: …」(길이 초과)머리에서 길이를 읽지 못해 받은 파일이 받아 적는 중에 60분을 넘었습니다. 잘라서 넣습니다
다른 증상원인
보내기가 눌리지 않고 「파일을 읽는 중입니다 — 다 읽으면 보낼 수 있습니다」 가 남아 있다판독이 끝나지 않았습니다. 다 읽거나 실패하면 풀립니다. 읽는 중인 파일을 빼도 풀립니다
「첨부 파일을 아직 읽는 중입니다. 다 읽은 뒤 보내 주세요」보내는 순간 서버에서 아직 읽는 중인 파일이 있었습니다. 칩이 «읽음» 이 된 뒤 다시 보냅니다
칩을 눌렀더니 「이 파일을 찾을 수 없습니다. 지워졌거나 볼 수 없는 파일입니다」파일이 지워졌거나 남의 대화의 파일입니다. 첨부는 대화의 주인만 엽니다(관리자도 같습니다)
칩을 눌렀더니 「파일을 불러오지 못했습니다. 잠시 뒤 다시 열어 주세요」객체 저장소에서 원본이나 읽은 글을 가져오지 못했습니다
파일은 «읽음» 인데 AI 가 파일 내용을 모른다고 한다그 사람에게 채팅 도구 권한 tool:builtin 이 없으면 AI 가 첨부를 읽는 도구를 받지 못합니다 → 권한
긴 문서의 뒷부분을 AI 가 모른다앞 100쪽(시트 · 슬라이드는 하나를 한 쪽으로)만 읽습니다. 필요한 부분을 잘라 넣습니다
PDF 도면의 치수 · 부품표를 엉뚱하게 읽는다문서로 읽힌 것입니다. 칩의 도면 단추를 눌러 도면으로 다시 읽힌 뒤 보냅니다
영상을 넣고 물었는데 AI 가 「아직 받아 적는 중」 이라고 한다녹취가 끝나지 않았습니다. 5분 · 200MB 이하는 질문이 20초까지 기다리고, 그보다 긴 파일은 뒤에서 받아 적습니다. 「녹취 준비됨」 이 된 뒤 다시 묻습니다
칩이 오래 「녹취 대기 중」 에 머문다받아 적기는 설치 전체에서 한 번에 하나씩, 넣은 순서대로 합니다(짧은 파일 먼저). 앞의 파일이 끝나기를 기다립니다. 계속 그대로면 [CHAT_MEDIA 로그를 봅니다
「말·자막을 찾지 못했습니다」말소리도 내장 자막도 없습니다. 화면 글자 · 입힌 자막은 읽지 않습니다
영상이 재생되지 않는다브라우저가 못 여는 코덱(예: H.265)입니다. 받아 적기와 답은 그대로 됩니다
큰 영상을 올리다 HTML 413 이 뜬다프록시의 채팅 첨부 경로는 1040MB 로 열려 있습니다(호스트의 MEDIA_MAX_FILE_MB 를 따르지 않습니다). 프록시 이미지를 손으로 바꿨거나 앞에 다른 프록시가 있는지 봅니다

음성으로 묻기가 「지금 음성 입력을 쓸 수 없습니다」로 끝납니다​

채팅의 음성으로 묻기는 녹음을 문서 이해 서비스의 녹취 입구로 보내고, 문서 이해가 녹취 서빙(plantpulse-asr)을 부릅니다. 이 안내(「…녹취 서비스가 꺼져 있거나 바쁩니다」)는 그 길 어딘가가 닫혀 있다는 뜻입니다. 코파일럿 로그에 문서 이해가 낸 상태 코드가 남습니다.

docker logs --tail=100 plantpulse-copilot-web 2>&1 | grep '\[voice\]' # 예: [voice] doc-und answered 503: …
docker exec plantpulse-document-understanding-api printenv ASR_URL # 비었으면 영상 · 음성이 꺼진 설치
cd /opt/kopens/plantpulse-ai-docker && bin/status.sh # plantpulse-asr · plantpulse-asr-audio
원인보이는 것조치
영상 · 음성이 꺼져 있다(기본)문서 이해의 ASR_URL 이 비어 있고, 녹취 입구가 503(media transcription is disabled: ASR_URL is not set)호스트 env 에 PI_MEDIA_ENABLED=true 를 넣고 녹취 모델을 받은 뒤 bin/restart.sh → 영상 · 음성 수집
켰는데 문서 이해가 옛 값으로 떠 있다ASR_URL 이 여전히 비어 있음스위치를 바꾼 뒤 docker restart 가 아니라 bin/restart.sh 로 다시 만듭니다
plantpulse-asr 가 unhealthy · 재시작 반복문서 이해 /health 의 components.asr.status 가 down, 전체 status 가 degradeddocker logs plantpulse-asr — 모델(/opt/kopens/models/Aura-ASR-Turbo)이 없으면 bin/fetch-models.sh 로 받습니다. 첫 기동은 컴파일 때문에 오래 걸릴 수 있습니다
plantpulse-asr-audio 가 0 이 아닌 코드로 끝났다bin/status.sh 에서 «Exited (0)» 이 아님. 이것에 기대는 plantpulse-asr 도 뜨지 않습니다docker logs plantpulse-asr-audio 를 보고, 이미지가 받아졌는지 확인한 뒤 bin/restart.sh
녹취 서빙이 바쁘다영상 처리와 겹친 시간잠시 뒤 다시 합니다

plantpulse-asr-audio 가 «Exited (0)» 으로 남아 있는 것은 정상입니다 — 오디오 라이브러리를 볼륨에 옮기고 끝나는 일회성 서비스이고, bin/status.sh 도 정상으로 셉니다.

다른 안내원인
「음성 입력은 HTTPS 주소에서만 됩니다」브라우저가 평문 주소에서는 마이크를 주지 않습니다. https:// 로 접속합니다
「마이크 권한이 거부됐습니다」주소창의 자물쇠 → 마이크 «허용»
「녹음이 너무 깁니다(최대 60초)」 · 「녹음이 너무 큽니다(최대 4MB)」질문 한 번은 60초 · 4MB 까지입니다
「말소리를 알아듣지 못했습니다」녹취가 빈 결과였습니다. 마이크에 가까이 대고 다시 말합니다

MCP 도구가 안 보입니다​

PP_API_URL · PP_API_TOKEN 은 비어 있으면 스택이 뜨지 않지만, 토큰이 틀리면 스택은 정상으로 뜨고 채팅의 플랫폼 MCP 도구만 0개가 됩니다. 그래서 「고장」처럼 안 보입니다.

sudo grep -E '^PP_API_(URL|TOKEN)' /etc/kopens/plantpulse-ai.env

값을 채운 뒤에는 재시작이 아니라 재생성이 필요합니다 — docker restart 는 env 를 다시 읽지 않습니다.

cd /opt/kopens/plantpulse-ai-docker && bin/restart.sh

시계열 분석이 안 됩니다​

docker compose logs --tail=100 plantpulse-timeseries-insight-api # :8970
docker compose logs --tail=100 plantpulse-timeseries-insight-server # :8980 (호스트에는 안 열립니다)

이 둘은 플랫폼 Aster TSDB 에서 값을 읽습니다. 위 「플랫폼 DB」를 먼저 확인하십시오.

예측이 500 이거나, 전부 NAIVE 로 옵니다​

설정 오류는 서버를 죽이지 않습니다 — 같은 프로세스가 이상탐지도 서비스하므로 무관한 기능까지 멈추지는 않습니다. 먼저 추론 서버의 /health 를 봅니다.

# 이 이미지에는 curl 이 없습니다 — python 으로 찌릅니다
docker compose exec plantpulse-timeseries-insight-server \
python -c "import urllib.request; print(urllib.request.urlopen('http://localhost:8980/health').read().decode())"

models.ttm.loaded: false 에 status: "degraded" 면 예측 모델이 못 올라온 것이고, error 에 이유가 있습니다. models 항목이 아예 없으면 이전 판이라 헬스체크로는 안 보입니다 — 아래 로그로 가리십시오.

docker compose logs plantpulse-timeseries-insight-server | grep -E 'MODEL_LOAD|WARMUP|INFER_FORECAST|fallback naive'
로그뜻할 일
[MODEL_WARMUP_FAIL] TTM ch=… 설정이 체크포인트와 맞지 않는다체크포인트 세대와 로더 클래스가 어긋났습니다. 예측은 500 입니다TS_TTM_MODEL_CLASS 를 비워 두거나(체크포인트가 고름) 세대에 맞춥니다 → 설명
[MODEL_LOAD_FAIL] … 무작위 초기화 모델로 대체하지 «않는다»같은 원인입니다. 적재를 거부한 자리입니다위와 같습니다
[MODEL_WARMUP_SKIP] TTM ch=…2026-09-21 이전 판의 같은 원인입니다. 그 판에서는 예측이 200 에 model_used="NAIVE" 로 나옵니다위와 같습니다
TTM 을 돌릴 데이터가 모자라다 -> fallback naive. reason=…데이터 부족. 200 에 NAIVE 입니다 — 지금 판은 이것만 단순 외삽으로 흡수합니다reason 을 읽습니다
TTM failed -> fallback naive. reason='<태그>_prediction_q0.1'모든 예측이 NAIVE 로 옵니다. R3 가중치는 실렸는데 분위수 열 이름 수정이 빠진 이미지입니다(예: 2026.09-20260924-1004)수정이 들어간 이미지로 다시 받습니다(./update.sh)
TTM failed -> fallback naive. reason=… (그 밖)이전 판의 폴백입니다 — 그 판은 데이터 부족 외의 실패도 200 NAIVE 로 삼켰습니다reason 을 읽습니다

NAIVE 로 답한 경우에는 응답의 fallback_reason 에도 같은 이유가 담겨 옵니다 — 로그에 못 들어가는 자리에서는 그쪽을 보십시오.

「전부 NAIVE」와 「500」은 같은 병의 두 판입니다

설정 오류가 단순 외삽으로 둔갑하던 것을 2026-09-21 에 고쳤습니다. 예전 판은 /health 정상 · 예측 200 · 모든 답이 조용히 단순 외삽인 채로 돌 수 있었습니다. 어느 판이든 볼 곳은 같습니다 — 위 로그와 TS_TTM_MODEL_CLASS 입니다.

판 번호로 가리지 마십시오 — 이 달의 이미지는 2026.09-<날짜>-<시각> 으로 여러 번 다시 구워집니다. 위 로그 줄이 가장 확실한 구분입니다.

설정을 바꿨는데 수치가 한 자리도 안 변했습니다​

그러면 그 설정은 안 먹은 것입니다. 모델 라이브러리의 파라미터는 모르는 이름을 조용히 삼키는 경우가 있어, 잘못 준 값이 오류 없이 무시됩니다. 실제로 이상탐지의 집계·평활 파라미터(aggr_win_size · smoothing_window_size)가 라이브러리 인자 개명 이후 전부 무시된 채로 돌고 있었고(2026-07-24 감사), 그동안 오류도 경고도 없었습니다.

설정을 바꿨으면 «수치가 변했는지» 로 확인하십시오

「오류가 안 났다」는 확인이 아닙니다. 바꾸기 전후의 점수 분포나 탐지 건수를 비교해서, 한 자리도 안 변했으면 설정이 닿지 않은 것으로 보십시오.

극단값으로 한 번 시험해 보는 것이 가장 빠릅니다 — 값을 크게 바꿨는데 결과가 똑같다면 그 설정은 닿고 있지 않습니다.


디스크가 찹니다​

docker system df
df -h /data1

컨테이너 로그는 도커가 회전시키므로 손으로 지울 것이 없습니다. 대개 이미지와 볼륨입니다.

docker image prune -f # 태그 없는 옛 이미지
docker volume prune 을 함부로 돌리지 마십시오

Neo4j · Qdrant · LightRAG 저장소가 볼륨에 있습니다. 컨테이너가 내려간 사이에 돌리면 지식 그래프와 벡터 색인이 사라집니다.


긴급 복구​

cd /opt/kopens/plantpulse-ai-docker/bin
./restart.sh # 스택 전체. 0 이면 «쓸 수 있다» 는 뜻입니다
docker compose restart plantpulse-lightrag # 하나만

이미지를 새로 받아 올리려면:

./update.sh
데이터가 있는 곳

LightRAG 원본 문서 · 색인 · 지식 그래프는 이름 붙은 도커 볼륨에 있습니다 (pi-lightrag-inputs · pi-lightrag-storage · pi-qdrant-data · pi-neo4j-data, 2026.10 부터 공장 그래프 거울의 pi-digital-thread-neo4j-data 와 시계열 파인튜닝 가중치 pi-ttm-tuned-models). 호스트 디렉토리가 아니므로 rm -rf 로는 지워지지 않고, 반대로 docker volume prune 한 번에 같이 날아갑니다. 지우기 전에 반드시 백업하십시오 — bin/backup.sh 가 compose 볼륨(로그 · 캐시 제외)을 받습니다.


함께 보기​