Files
CODE_ASSISTANT/docs/tech/abap-indexing-with-fabrix.md
T

7.4 KiB

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(윈도우)에서 돌릴 때 — -12 게이트웨이 경유

인덱싱은 고객사 PC 에서 돌리고, LLM 호출만 -12 의 CodeAssist 게이트웨이(바깥 포트 8914)로 보낸다. 헤더는 게이트웨이가 얹으니 코드 수정 없음. (-12 백엔드가 떠 있어야 함: curl http://10.196.81.34:8914/api/ito/models 에 모델 3개.)

# ABAP_INDEXING/.env  (고객사 PC)
LLM_BASE_URL=http://10.196.81.34:8914/api/ito
LLM_API_KEY=x                    # -12 .env 의 AAF_GATEWAY_KEY. 비어 있으면 아무 값
LLM_MODEL=339                    # GaussO Flash. Gemma(605/580) 금지 — 30~100배 느림
LLM_CONCURRENCY=2                # 429 안 나면 4
LLM_MAX_RETRIES=5
LLM_TIMEOUT_S=180
SUMMARIZE_BACKEND=api
cd ABAP_INDEXING
python -m venv .venv; .venv\Scripts\pip install -e ".[dev]"      # 고객사 PC 가 pip 되면. 안 되면 wheels 로
# data
aw\*.txt 배치 
$env:PYTHONUTF8="1"
.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    # 작게 먼저 → 아래 "확인할 것" 1번
.venv\Scripts\python -m summarize.jobs stats
.venv\Scripts\python -m summarize.runner --llm api                                     # 전량 (며칠 갈 수 있음)
.venv\Scripts\python -m index.loader --force

끝나면 data\index.db 를 -12 로 옮겨 거기서 query.api(:8100) 를 띄운다("끝나면" 절). PC 에서 8100 을 띄워도 -12 의 OpenCode 는 못 붙는다(컨테이너 → PC 방향 안 열림).

게이트웨이 없이 FabriX 직결하고 싶으면 (팀원 레포 수정)

summarize/llm_client.py _post_once 의 headers 를 이렇게 바꾸면 -12 없이도 됨. 값은 CodeAssist .envAAF_FABRIX_* 와 같음.

headers={
    "Content-Type": "application/json",
    "x-llm-model-id": self.model,                       # LLM_MODEL=339
    "x-generative-ai-client": os.environ["FABRIX_CLIENT_KEY"],
    "x-openapi-token": "Bearer " + os.environ["FABRIX_OPENAPI_TOKEN"],   # Bearer 접두 필수(실측)
    "x-generative-ai-user-email": os.environ.get("FABRIX_USER_EMAIL", ""),
}
# body["model"] 은 "/mnt/models" 로 고정 (FabriX 규격). LLM_BASE_URL 은 …/openapi/llm 까지.

-12 에서 준비

전제: CodeAssist 백엔드가 -12 에 떠 있고(curl :8080/api/ito/models 에 모델 3개), .envAAF_FABRIX_* 가 채워져 있음.

# 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 에 이렇게:

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)으로 간다.

돌리기

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 쪽은 .envABAP_INDEX_URL=http://127.0.0.1:8100 기본값 그대로라 OpenCode 재시작만 하면 앱이 "출처: 프로그램/unit" 붙은 코드를 답하기 시작함.