메뉴
BL
r/LocalLLaMA 5일 전

변호사의 로컬 AI 법률 문서 작성기: V100 클러스터 구축기

IMP
7/10
핵심 요약

한 변호사가 V100 12개와 RTX 3090 등 총 16개의 GPU를 활용해 법률 문서 초안을 자동 작성하는 로컬 AI 시스템을 완성했습니다. 실험 결과 V100 환경에서는 일반적인 Dense 모델보다 MoE(Mixture of Experts) 모델이 압도적인 처리 속도를 보여주어 시스템 전체를 MoE 중심으로 재구성했습니다. 여러 로컬 모델이 각자의 역할을 나누어 수행하는 오케스트레이터 구조를 통해 고수준의 법률 문서를 빠르고 정확하게 생성해 내는 것이 이 프로젝트의 핵심입니다.

번역된 본문

V100 서버를 구축한 변호사입니다. 몇몇 분들이 모든 설정이 끝난 후 실제로 무엇을 돌리고 있는지 물어보셨는데, 여기 공유합니다. 저는 여전히 변호사일 뿐이고, 여전히 Claude Code를 통해 이 모든 것을 구동하고 있으며, 내가 뭘 하고 있는지 완벽히 이해하지 못했습니다 — 하지만 적어도 지금은 작동합니다. 지난번보다는 훨씬 나아졌죠.

먼저, 하드웨어가 계획대로 완성되었습니다. 마지막 두 V100도 도착해서 제가 약속했던 "최종 형태"가 현실이 되었습니다. Threadripper Pro에 V100-SXM2 32GB 열두 장을 장착했습니다. 보드 A에 GPU {4,5,8,9}, 보드 B에 {6,7,10,11}, {0,1}에 NVLink 페어, 그리고 {2,3}에 한 카드가 16GB인 혼합 페어를 구성했습니다. 두 개의 다른 NVLink 보드에 걸쳐 모델을 분할하면 처리량이 급격히 떨어집니다 (보드 간 연결은 NVLink가 아니라 PCIe/NUMA를 거치기 때문입니다). 그래서 저는 모든 모델을 하나의 보드 안에서만 돌립니다. 이건 꽤 비싼 대가를 치르고 배운 교훈입니다.

그리고 네, 결국 두 번째 서버도 세팅했습니다. EPYC 7302P, 512GB RAM, RTX 3090 4장 + V100-PCIe 2장을 장착했습니다. 저의 중년 위기는 계획대로 진행 중입니다.

가장 큰 변화는 로컬 모델을 위해 vLLM을 포기했다는 점입니다. vLLM이 나쁘기 때문이 아니라 — 제가 원하는 모델이 MoE GGUF 형식인데, Volta 아키텍처에서 vLLM으로 이를 돌리는 건 막다른 길이기 때문입니다 (FP8/AWQ/Marlin 모두 SM75+ 이상을 요구하고, GPTQ 커널은 버전 7.0에서 버그가 있습니다). 그래서 llama.cpp로 전부 옮겼습니다 (최근 빌드에서 긴 프롬프트를 망치던 Gemma 채팅 파서 버그가 마침내 수정되었습니다).

제 첫 게시글에 암시했던 것과 정반대되는 부분이 있습니다: V100에서는 Dense(밀집) 모델이 함정입니다. MoE(전문가 혼합) 모델만이 쓸 만한 속도를 냅니다. 실제 법률 문서 작성 프롬프트(토큰 5개짜리 "안녕"이 아니라 수천 토큰의 컨텍스트)를 사용한 대략적인 디코딩 속도(Q8 GGUF, Q4 KV 캐시, flash-attn 활성화, 4카드 보드 하나 기준)는 다음과 같습니다:

모델 유형 tok/s (디코드)
Gemma-4-26B-A4B MoE ~113
Qwen3.6-35B-A3B MoE ~82
Qwen3.5-122B-A10B MoE ~50
모든 Dense 27-32B Dense ~20-28 (제 기준치인 40 미만이라 가치 없음)
Dense ~128B Dense ~9 (포기)

즉, 122B/10B-active 추론 모델이 V100 4장에서 약 50 tok/s로 돌아갑니다 — 첫 게시글에서 vLLM으로 돌렸던 Dense 32B 모델보다 빠릅니다 — 게다가 긴 컨텍스트에서도 이 속도가 유지됩니다 (Dense 모델들이 멈칫거릴 때, 저는 Gemma를 25k 토큰 이상으로 밀어붙여도 무너지지 않는 걸 확인했습니다). 이 사실이 모든 걸 바꿔놓았습니다: 저는 거대한 Dense 가중치 쫓기를 멈추고 MoE 기반으로 시스템을 구축했습니다.

실제로 돌아가고 있는 것 (여러분이 요청했던 스택): 이건 하나의 모델이 채팅에 답하는 것이 아닙니다 — 법률 작업을 여러 로컬 모델에 분배하는 오케스트레이터(Orchestrator)입니다. 각 모델은 자신만의 보드에 고정되어 GPU를 두고 경쟁하지 않습니다. 가장 무거운 작업(사실조서나 동의서 청원 등의 전체 문서 작성)을 돌릴 때는 두 서버에 있는 16개의 GPU가 모두 켜집니다:

  • 주력 문서 작성 — 보드 A {4,5,8,9}에서 Qwen3.6-35B-A3B
  • 복잡한 추론 및 중요 문서 작성 — 보드 B {6,7,10,11}에서 Qwen3.5-122B-A10B
  • {0,1} 페어에서 "사건에 승소 가능성이나 소송상 근거가 있는지" 판별하는 소형 게이트 모델
  • {2,3} 페어에서 제 초안을 공격(반박)하는 역할만 전담하는 적대적(Adversarial) 검토 모델
  • 3090들에서 재무/정보 추출용 Gemma-4-26B와 라우터 역할을 하는 소형 Qwen 모델
원문 보기
원문 보기 (영어)
Update from the lawyer with the V100 server. A few of you asked what I actually ended up running once the dust settled, so here it is. Still just a lawyer, still driving the whole thing through Claude Code, still not fully sure what I'm doing — but it works now, which is more than I could say last time. First, the hardware caught up to the plan. The last two V100s are in, so the "final form" I promised is real: twelve V100-SXM2 32GB on the Threadripper Pro. It's Board A on GPUs {4,5,8,9}, Board B on {6,7,10,11}, an NVLink pair on {0,1}, and a mixed pair on {2,3} where one card is a 16GB. Split a model across two different NVLink boards and throughput falls off a cliff (the cross-board hop is PCIe/NUMA, not NVLink), so I keep every model inside one board. Learned that one the expensive way. And yeah, I caved and built the second box. EPYC 7302P, 512gb RAM, 4x RTX 3090 + 2x V100-PCIe. The mid-life crisis remains on schedule. The bigger change: I gave up on vLLM for the local models. Not because vLLM is bad — because the models I actually want are MoE GGUFs, and vLLM on Volta is a dead end for those (FP8/AWQ/Marlin all want SM75+, the GPTQ kernels are broken on 7.0). I moved the whole thing to llama.cpp (mainline — a recent build finally fixed a Gemma chat-parser bug that had been mangling my long prompts). Here's the part that's the opposite of what my first post implied: on V100, dense models are a trap. Only MoE clears a usable speed. Rough decode numbers — Q8 GGUF, Q4 KV cache, flash-attn on, one 4-card board, on real drafting prompts (several thousand tokens of context, not a 5-token "hello"): | Model | Type | tok/s (decode) | |---|---|---| | Gemma-4-26B-A4B | MoE | \~113 | | Qwen3.6-35B-A3B | MoE | \~82 | | Qwen3.5-122B-A10B | MoE | \~50 | | any dense 27-32B | dense | \~20-28 (under my 40 floor, not worth it) | | dense \~128B | dense | \~9 (forget it) | So a 122B/10B-active reasoning model runs at \~50 tok/s on four V100s — faster than the dense 32B managed on vLLM in my first post — and it holds that at long context (I've pushed Gemma past 25k tokens without it falling apart, where the dense models choked). That reframed everything: I stopped chasing big dense weights and built the system around MoE. What's actually running (the stack you asked for): It isn't one model answering chat — it's an orchestrator that routes a legal task across several local models, each pinned to its own board so they don't fight over GPUs. When it runs the heaviest job (a full affidavit or motion, intake-to-document), it lights up 16 GPUs across both boxes: \- Workhorse drafting — Qwen3.6-35B-A3B on Board A {4,5,8,9} \- Heavy reasoning + high-stakes drafting — Qwen3.5-122B-A10B on Board B {6,7,10,11} \- A small "does this even have grounds" gate model on the {0,1} pair \- An adversarial reviewer whose entire job is to attack my own draft, on the {2,3} pair \- Gemma-4-26B for financial/extraction + a small Qwen as the router, on the 30
관련 소식