# ABAP_INDEXING 을 고객사 사내 LLM(FabriX/Gauss) 으로 돌리기 — 팀원용 가이드 2026-09-21. ABAP_INDEXING 레포(팀원 소유)의 Stage 3(로직 조각 추출)을 고객사 -12 컨테이너에서 FabriX 로 돌리는 절차. 결과(`data/index.db`)는 CodeAssist 의 `abap_index_*` 툴이 씀 → `5_django_backend/README.md` "ABAP 소스 인덱스 붙이기". ## 핵심: FabriX 에 직접 붙이지 말고 CodeAssist 게이트웨이를 거친다 ABAP_INDEXING 의 LLM 클라이언트(`summarize/llm_client.py`)는 `Authorization: Bearer <키>` 하나만 보낸다. FabriX 는 그걸 안 받고 `x-openapi-token` / `x-generative-ai-client` / `x-llm-model-id` 세 헤더를 요구한다 → 직접 붙이면 **401**. CodeAssist 백엔드의 `/api/ito/chat/completions` 는 OpenAI 호환 입구고, 저 헤더를 알아서 얹어 FabriX 로 넘긴다(401 시 형식 재시도 포함). 그러니 **`LLM_BASE_URL` 을 게이트웨이로** 주면 인덱싱 코드는 한 줄도 안 고쳐도 된다. ``` summarize.runner ──OpenAI 호환(Bearer)──▶ Django :8080/api/ito ──FabriX 헤더──▶ FabriX (x-llm-model-id=339) ``` ## 로컬(내 PC)에서 먼저 돌릴 때 — OpenRouter 직결 고객사 전이라 로컬에서 돌리면 게이트웨이 필요 없음. 인덱싱 클라이언트가 OpenRouter 를 그대로 지원함(`usage.include` 까지 붙임). ```ini # ABAP_INDEXING/.env LLM_BASE_URL=https://openrouter.ai/api/v1 LLM_API_KEY=sk-or-... # CodeAssist 개발에 쓰는 OpenRouter 키 그대로 LLM_MODEL=z-ai/glm-5.2 # 텍스트 요약. CodeAssist 로컬 기본 모델과 같음 LLM_CONCURRENCY=4 SUMMARIZE_BACKEND=api ``` ```bash cd ABAP_INDEXING python -m venv .venv && .venv/Scripts/pip install -e ".[dev]" # data/raw/*.txt 배치 후 .venv/Scripts/python -m ingest.normalize && .venv/Scripts/python -m parser.run && .venv/Scripts/python -m index.loader .venv/Scripts/python -m summarize.runner --llm api --program <프로그램명> --limit 3 # 작게 먼저 .venv/Scripts/python -m summarize.jobs stats .venv/Scripts/python -m summarize.runner --llm api # 전량 .venv/Scripts/python -m index.loader --force .venv/Scripts/python -m query.api # 127.0.0.1:8100 ``` - 무료 티어(`:free`)는 429 로 굳는 이력 있음(`ASSUMPTIONS.md` 3). 유료 키로. - 비용: `run-record.md` "GLM 5.2 비용 실측" 참고. 55본 기준 수치가 있음. - 끝나면 CodeAssist 로컬은 `.env` 의 `ABAP_INDEX_URL` 기본값(127.0.0.1:8100)이라 OpenCode 재시작만 하면 `[출처: 프로그램/unit]` 붙은 답이 나옴. - 고객사로 옮길 땐 `data/index.db` 파일 하나만(소스 원문까지 안에 있음) — 위 "-12 에서 준비" 절의 FabriX 재인덱싱은 안 해도 됨. 단 조각 설명이 GLM 산출이라 모델 표기(`PROMPT_VERSION`·모델명)를 같이 적어둘 것. ## -12 에서 준비 전제: CodeAssist 백엔드가 -12 에 떠 있고(`curl :8080/api/ito/models` 에 모델 3개), `.env` 의 `AAF_FABRIX_*` 가 채워져 있음. ```bash # 1) 레포 올리기 (인터넷 없음 — PC 거쳐 scp) scp -P 8912 -r ABAP_INDEXING root@10.196.81.34:/www/ # 2) 파이썬 — CodeAssist 가 쓰던 offline wheels 에 fastapi·uvicorn·pydantic 은 있음. pydantic-settings 는 없을 수 있음 cd /www/ABAP_INDEXING && python3 -m venv .venv .venv/bin/pip install --no-index --find-links /www/wheels fastapi "uvicorn[standard]" pydantic pydantic-settings # pydantic-settings 없다고 하면: PC 에서 `pip download pydantic-settings --platform manylinux2014_x86_64 --python-version 3.12 --only-binary=:all: -d wheels` 받아서 /www/wheels 에 추가 .venv/bin/pip install --no-index --no-deps -e . # 3) .env cp .env.example .env && vi .env ``` `.env` 에 이렇게: ```ini LLM_BASE_URL=http://127.0.0.1:8080/api/ito # CodeAssist 게이트웨이. 뒤에 /chat/completions 를 클라이언트가 붙임 LLM_API_KEY=x # CodeAssist .env 의 AAF_GATEWAY_KEY 값. 비어 있으면 아무 값(x) LLM_MODEL=339 # x-llm-model-id. 텍스트 요약이라 GaussO Flash(339). 581(Think) 은 4배 느림, Gemma 는 쓰지 말 것 LLM_CONCURRENCY=2 # FabriX 가 429 를 어떻게 주는지 모름 — 2 로 시작해서 429 안 나면 4 LLM_MAX_RETRIES=5 LLM_TIMEOUT_S=180 SUMMARIZE_BACKEND=api ``` `LLM_MODEL` 이 곧 `x-llm-model-id` 다 — 게이트웨이는 body 의 `model` 이 허용 목록(`AAF_FABRIX_MODELS`)에 있으면 그 id 로 보낸다. 목록에 없는 이름이면 기본(`AAF_FABRIX_MODEL_ID`)으로 간다. ## 돌리기 ```bash cd /www/ABAP_INDEXING && set -a; . ./.env; set +a # 소스 수집 파일을 data/raw/*.txt 로 넣은 뒤 .venv/bin/python -m ingest.normalize # Stage 1 — LLM 없음 .venv/bin/python -m parser.run # Stage 2 — LLM 없음 .venv/bin/python -m index.loader # Stage 4 # Stage 3 — 먼저 작게. 프로그램 하나 unit 3개로 게이트웨이·JSON 응답이 되는지 .venv/bin/python -m summarize.runner --llm api --program <프로그램명> --limit 3 .venv/bin/python -m summarize.jobs stats # failed 없는지 # 되면 전량 (nohup 으로, 며칠 걸릴 수 있음) nohup .venv/bin/python -m summarize.runner --llm api > logs/summarize.log 2>&1 & .venv/bin/python -m index.loader --force # 조각 반영 nohup .venv/bin/python -m query.api > logs/query.log 2>&1 & # :8100 — CodeAssist 툴이 붙음 curl -s http://127.0.0.1:8100/health ``` ## 먼저 확인할 것 3개 (안 되면 여기서 걸림) 1. **`response_format: json_object` 를 FabriX 가 받는가.** 클라이언트가 이걸 항상 보낸다. FabriX 가 400 을 주면 `_post_once` 에서 그 줄을 빼고 `_extract_json` 이 본문에서 JSON 을 파싱하게 둬야 함(파서는 이미 관대함). 확인: 위 `--limit 3` 실행에서 400 나오는지. 2. **속도·한도.** 55본에 조각 3,212개였음 → 1만 본이면 LLM 호출 수십만 번. 339 가 1.9s/호출이면 순차로 며칠. 이금관 팀에 일일 토큰 한도·동시 호출 제한 미리 물어볼 것. 3. **한글 출력.** 컨테이너 로케일이 ASCII 라 파이썬이 한글 찍다 죽는다 → 모든 실행 앞에 `PYTHONUTF8=1` (CodeAssist 도 그렇게 띄움). ## 하지 말 것 - `LLM_BASE_URL` 에 FabriX 주소 직접 넣기 — 401. - `LLM_MODEL` 에 Gemma(605/580) — 텍스트 요약에 이미지 모델 쓸 이유 없고 30~100배 느림. - -13 의 게이트웨이(8918) 로 붙기 — 컨테이너 간 통신 금지. -12 안의 8080 만. ## 끝나면 `data/index.db` 가 커지고(55본에 43MB) `:8100/health` 에 적재 통계가 나오면, CodeAssist 쪽은 `.env` 의 `ABAP_INDEX_URL=http://127.0.0.1:8100` 기본값 그대로라 OpenCode 재시작만 하면 앱이 "출처: 프로그램/unit" 붙은 코드를 답하기 시작함.