fftext: API 키 없이 노트북에서 모든 텍스트를 요약, 번역 및 팩트 체크하기
요약
API 키와 GPU 없이 로컬 CPU만으로 텍스트 요약, 번역, 팩트 체크를 수행하는 Python CLI 도구인 fftext를 소개합니다. 개인정보 보호, 비용 절감, 오프라인 사용성을 극대화한 경량화된 로컬 AI 워크플로우를 제공합니다.
핵심 포인트
- API 키 없이 로컬 CPU 환경에서 작동하는 경량 Python CLI
- Qwen3.5-0.8B 모델을 활용한 요약, 설명, 팩트 체크 기능
- 개인정보 보호 및 오프라인 환경에서의 높은 사용성
- llama-cpp-python 기반의 효율적인 토큰 스트리밍 구현
위키피디아(Wikipedia) 문서 하나를 요약하기 위해 프런티어(Frontier) API 비용을 지불하는 것에 지쳤습니다.
그래서 이번 주에 fftext를 만들었습니다. 기본적으로 네 가지 기능을 수행하는 작은 Python CLI(Command Line Interface)로, API 키 없이, 누구의 서버로도 데이터를 보내지 않고, CPU를 사용하여 로컬에서 작동합니다:
fftext s "https://en.wikipedia.org/wiki/Llama.cpp"
세 개의 불렛 포인트가 터미널로 스트리밍됩니다. 약 500MB의 모델 가중치(model weights), 명령어 하나면 끝입니다. GPU는 필요 없습니다! (제 노트북에는 GPU가 없습니다)
네 가지 동사
fftext s notes.txt # 요약 (summarize)
fftext e https://example.com/article # 쉽게 설명하기 (explain like I'm five)
fftext c "The Eiffel Tower was built in 1822." # 팩트 체크 (fact-check)
...
모든 명령어는 동일한 세 가지 입력 형태를 받습니다: 파일, URL, 또는 원문 문자열(raw string)이며, 해당 순서대로 처리됩니다. URL은 readability-lxml을 통해 가져와서 처리되므로, 모델이 내비게이션 바나 쿠키 배너가 아닌 깔끔한 기사 본문을 볼 수 있게 합니다.
GPT-4가 있는데 왜 굳이 사용해야 할까
제가 계속해서 마주했던 세 가지 이유입니다:
개인정보 보호 (Privacy). 제가 요약하는 텍스트는 종종 초안, 개인 문서, 또는 동료가 보낸 내용인 경우가 많습니다. 이는 제 노트북을 벗어나서는 안 됩니다.
비용과 번거로움 (Cost and friction). "이 기사의 내용을 세 줄로 요약하면 뭐야" 같은 작업에 프런티어 모델을 사용하는 것은 과합니다. API 호출을 시작하고, 키를 관리하고, 토큰 사용량을 모니터링하는 것은 작은 모델이 충분히 처리할 수 있는 작업에 있어 모두 번거로운 과정입니다.
오프라인 (Offline). 비행기, 기차, 약한 호텔 와이파이, 혹은 그 어느 카페에서도 사용할 수 있습니다. 첫 실행 이후에는 check 기능을 제외한 모든 기능이 네트워크 없이도 작동합니다.
모델은 llama-cpp-python을 통해 실행되는 unsloth/Qwen3.5-0.8B-GGUF (Q4_K_M 양자화)입니다. PyTorch, CUDA, LangChain은 사용하지 않습니다. 토큰은 생성되는 대로 스트리밍되는데, 이는 CPU 환경에서 사람들이 생각하는 것보다 더 중요합니다. 첫 번째 토큰이 1초 이내에 나타나면 체감 지연 시간(perceived latency)이 크게 줄어듭니다.
팩트 체크(fact-check) 명령어가 흥미로운 부분입니다
summarize, explain, translate는 각각 정교한 시스템 프롬프트(system prompt)를 가진 단일 LLM 호출입니다. 지루할 수 있지만 잘 작동합니다.
check는 작은 파이프라인(pipeline)입니다:
- 주장 추출 (Extract claims): LLM이 입력값으로부터 사실 관계를 담은 문장들을 JSON 배열 형태로 출력합니다.
- 순위 매기기 (Rank): LLM이 사실 확인이 가장 용이한 상위 3개의 주장을 선정합니다. 살아남은 각 주장마다 약 4회의 추가 LLM 호출 비용이 발생하므로, 순위 매기기는 비용 폭발을 막아주는 핵심 단계입니다.
- 키워드 쿼리로 재작성 (Rewrite as keyword queries):
"James Talarico is a Presbyterian seminarian."는"James Talarico" Presbyterian seminarian으로 변환됩니다. 검색 엔진은 희귀 토큰(rare tokens)에 가중치를 두며, 불용어(stopwords)가 포함된 전체 문장은 재현율(recall)을 떨어뜨립니다. - 검색 (Search): Mojeek와 Startpage를 사용하며, 주장 인덱스에 따라 교차 사용하고, 지터링(jittered)된 대기 시간(sleeps)과 일반적인 데스크톱 사용자 에이전트(UA)를 적용합니다. 향후 Brave API를 추가할 예정입니다.
- 증거 요약 (Summarize evidence): 각 스니펫(snippet)이 해당 주장을 뒷받침하는지에 대해 한 문장으로 요약합니다.
- 종합 및 라벨링 (Synthesize and label): 소스 URL과 함께
SUPPORTED(지지됨),REFUTED(반박됨),CONFLICTING(상충됨), 또는INSUFFICIENT(불충분함)로 분류합니다.
출력 결과는 다음과 같습니다:
SUPPORTED 에펠탑은 1889년에 완공되었습니다. [https://en.wikipedia.org/wiki/Eiffel_Tower]
REFUTED 토마스 에디슨에 의해 건설되었습니다. [https://www.britannica.com/biography/Gustave-Eiffel]
INSUFFICIENT 현재 파리에서 가장 높은 구조물입니다. [-]
0.8B 모델 단독으로는 이 내용의 절반을 환각(hallucinate)할 것입니다. 하지만 주장을 *제안(proposes)*하고 실시간 웹이 이를 *판단(disposes)*하게 만드는 0.8B 모델은 놀라울 정도로 잘 작동한다는 것이 증명되었습니다. 모델은 예언자(oracle)가 아니라 오케스트레이터(orchestrator)입니다.
할 수 없는 것!
이것은 0.8B 모델입니다. GPT-5.6이나 Opus 4.7이 아닙니다. 긴 문서는 4,096 토큰 컨텍스트(context)에 맞추기 위해 약 10,000자 지점에서 앞뒤가 잘립니다(head-and-tail clipped). 규모가 작은 언어에서는 번역 품질이 저하됩니다. 팩트 체커는 스크래핑(scraping)에 의존하므로, 만약 Mojeek와 Startpage가 동시에 캡차(captcha)를 띄우면 상황이 진정될 때까지 INSUFFICIENT 판정이 나옵니다.
하지만 노트북에서, 오프라인 상태로(대부분), 단일 바이너리(binary)만으로 "이 기사를 요약해줘", "이 개념을 설명해줘", "이 이메일을 번역해줘", 그리고 "이 내용 중 어떤 주장이 틀렸는지 알려줘"와 같은 작업을 수행하기에는 솔직히 매우 유용했습니다.
사용해보기
pip install .
fftext s "https://en.wikipedia.org/wiki/Photosynthesis"
첫 실행 시 가중치(weights, 약 500 MB)를 Hugging Face (HF) 캐시로 가져옵니다. 그 이후의 모든 실행은 오프라인으로 진행됩니다.
코드, 전체 README, 그리고 데모 영상은 repo에서 확인할 수 있습니다. 이슈(Issues)와 풀 리퀘스트(PRs)는 언제나 환영합니다!! 특히 가장 개선의 여지가 많은 부분인 check 파이프라인(pipeline)에 대한 기여를 적극 환영합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기