하루 15,000개 질문에 답하는 Cerebras의 사내 지식 베이스 설계 노하우 (feat. pgvector, RRF, MCP)

Cerebras 사내 지식 베이스 소개

Cerebras의 직원들은 사내 지식 베이스(Knowledge Base)에 매일 15,000개 이상의 질문 을 던집니다. 공개된 지 3개월 만에 회사에서 가장 널리 쓰이는 내부 도구 중 하나가 되었고, 사람뿐 아니라 자동화 스크립트와 에이전트도 이 시스템에 질문을 보냅니다. 이 글은 그 사내 지식 베이스인 Cerebras Knowledge, 즉 회사 곳곳에 흩어진 데이터를 하나로 모아 자연어로 답하는 검색 증강 시스템(RAG, Retrieval-Augmented Generation) 을 Cerebras 엔지니어링 팀이 어떻게 설계했는지 정리한 기술 해설입니다.

Cerebras는 대규모 AI 가속기(웨이퍼 스케일 엔진)를 만드는 회사로, 데이터센터 운영, 칩 설계, 하드웨어, 학습, 추론, 클라우드 플랫폼 등 서로 성격이 매우 다른 팀들이 함께 일합니다. 매년 수백 명의 새 직원이 합류하다 보니, 사내 커뮤니케이션 채널은 늘 똑같은 질문들로 채워졌습니다. 어디서 X를 찾을 수 있나요?, Y 전문가가 누구인가요?, Z가 뭔가요? 같은 것들입니다. 이런 질문에 매번 사람이 답하는 것은 비효율적이고, 답을 아는 사람이 자리를 비우면 정보는 곧바로 막혀 버립니다.

기업 내부 지식은 위키, Slack, 코드 저장소, 이슈 트래커 등 수십 개의 도구에 흩어져 있고, 각 도구는 서로 다른 형식과 접근 권한을 가집니다. 이 글이 흥미로운 이유는 단순히 "임베딩을 만들어 벡터 검색을 했다" 는 수준을 넘어, 실제 회사 데이터가 가진 지저분함(짧은 잡담과 긴 커널 설명이 같은 Slack 메시지로 섞여 있는 현실)을 정면으로 다루면서 여러 검색 기법을 융합해 실용적인 정확도를 끌어낸 설계 결정들을 구체적인 수치와 함께 공개했다는 점입니다. 사내 검색이나 코드베이스 검색, 에이전트용 지식 저장소를 만들려는 이들에게 좋은 참고 자료가 됩니다.

데이터가 있는 곳에서 데이터를 만난다: 단일 진실 공급원이라는 환상

조직 안에서 정보를 찾는 일은 근본적으로 어렵습니다. 데이터는 여러 도구에 흩어져 있고, 분기마다 누군가는 똑같은 "명쾌한 해법"을 제안합니다. 모든 것을 하나의 플랫폼에 기록해서 정보를 한 곳에 모으자. 그러나 Cerebras 팀은 이 접근을 정면으로 반박합니다.

단일 진실 공급원(single source of truth)이라는 꿈은, 당연하게도, 현실에서 제대로 작동하는 경우가 드뭅니다.

정보는 그것을 만들기에 가장 편하고 자연스러운 곳에서 생성됩니다. 문서의 제안 수정 사항은 Google Docs에, 논의는 Slack 스레드에, 코드 참조는 GitHub에, 상태 메타데이터는 Jira에 남습니다. 이런 플랫폼들은 각자의 영역에 최적화되어 수년간의 제품 엔지니어링과 분석을 거쳐 다듬어졌습니다. 풀 리퀘스트(pull request)에 대한 논의를 Google Docs에서 하는 것은 끔찍한 경험일 것입니다.

그래서 Cerebras 팀은 기존 행동을 최소한으로만 바꾸도록 시스템을 설계했습니다. 데이터 수집 측면에서 이것은 곧 각 플랫폼에서 데이터를 직접 추출한다는 의미입니다. 사람에게 "여기 말고 저기에 기록하라"고 요구하는 대신, 사람들이 이미 일하고 있는 곳으로 시스템이 찾아가는 것입니다.

지식 베이스의 해부학: 모든 것이 하나의 임베딩 테이블로

Cerebras의 지식 베이스는 세 가지를 제공합니다.

  1. 내부 데이터를 수집하고 저장하는 플랫폼.
  2. 그 데이터를 질의하는 플랫폼.
  3. 감사(auditing)와 분석을 갖춘 인증 및 권한 부여(authentication and authorization) 계층.

이 시스템의 핵심에는 여러 소스로부터 온 임베딩, 원본 요약(raw summaries), 메타데이터를 담는 단일 PostgreSQL 테이블 이 있습니다. 시스템은 회사 전반에서 데이터를 지속적으로 수집하며 질의에 바로 답할 수 있는 데이터스토어를 유지합니다.

팀은 단순하면서도 대부분의 데이터 형식과 함께 동작할 수 있는 데이터 인터페이스를 원했습니다. 또한 Cerebras의 다른 개발자들이 직접 커스텀 커넥터(connector)를 만들 수 있기를 바랐습니다. 그 결과는 의도적으로 단순합니다. Slack 스레드부터 넷리스트(netlist)까지, 모든 소스가 같은 임베딩 테이블에 안착하고, 그 테이블에 있는 것은 무엇이든 동일한 인터페이스로 즉시 질의할 수 있습니다.

각 데이터 소스는 데이터가 무엇인지, 어떻게 연결하는지, 얼마나 자주 가져와야 하는지 를 정의합니다. 그 결과로 만들어진 각 임베딩 행(row)은 Slack에서 왔든, 코드 저장소에서 왔든, 문서 시스템에서 왔든, 커스텀 데이터베이스에서 왔든 관계없이 동일한 인터페이스를 따릅니다. 임베딩 자체는 pgvector 확장을 사용해 3,072차원 벡터로 저장되며, HNSW(Hierarchical Navigable Small World) 인덱스로 근사 최근접 이웃 탐색을 수행합니다. 검색 상태와 임베딩 저장소가 같은 데이터베이스 안에 있다는 점은 뒤에서 살펴볼 여러 설계 결정을 훨씬 단순하게 만들어 줍니다.

Slack: 가장 중요하고 가장 까다로운 데이터 소스

Slack은 이 시스템에서 가장 중요하게 설계해야 했던 데이터 소스입니다. 회사 전반의 가장 최신 엔지니어링 논의가 벌어지는 곳이기 때문입니다. 문제는 Slack 데이터가 검색 관점에서 대단히 까다롭다는 데 있습니다.

비정형 Slack 대화를 처리하는 하이브리드 검색

팀은 처음에 원본 텍스트에 단순 임베딩을 적용하는 것만으로 충분한지 시험했습니다. 그러나 벡터 검색만으로는 관련된 모든 데이터를 매칭하기에 부족하다는 사실을 금방 깨달았습니다. Slack 메시지에는 몇 가지 고유한 어려움이 있습니다.

  • 정보 밀도(information density) 가 극단적으로 다릅니다. "응 그래 좋아 mike" 도 하나의 메시지이고, 상세한 커널 설명도 하나의 메시지입니다.
  • 메시지 길이 가 제각각이며, 짧은 메시지가 길고 상세한 메시지보다 코사인 유사도(cosine similarity)에서 더 높은 점수를 받는 일이 잦습니다.
  • 한 메시지의 의미는 종종 주변 대화의 맥락 에 의존합니다.

그래서 팀은 하이브리드 접근이 필요했습니다. 모든 스레드가 여러 검색 기법을 통해 동시에 검색되도록 Slack 수집을 설계했으며, 각 기법은 다른 기법의 약점을 보완합니다.

  • 전문 검색(Full-text search): 임베딩이 뭉개 버리는 정확한 토큰을 잡아냅니다. 에러 문자열, 플래그 이름, 호스트 이름 같은 것들입니다. 엔지니어가 문자 그대로의 에러 메시지를 붙여 넣으면 정확한 어휘 매칭(lexical match)이 거의 언제나 최선의 증거이며, 어떤 의미적 유사도도 이를 앞질러서는 안 됩니다.
  • 임베딩 검색(Embedding search): 다른 표현(paraphrase)을 잡아냅니다. "복원이 매니페스트 로드 후 멈춥니다(restore hangs after manifest load)" 라고 묻는 사람과 "체크포인트가 NFS 마운트에서 정체됩니다(checkpoint stalls on the NFS mount)" 라고 답한 사람은 어휘를 전혀 공유하지 않을 수 있습니다. 서로 다른 단어로 쓰인 질문과 답을 연결하는 것이 바로 벡터 유사도입니다.
  • 역문서 빈도(Inverse Document Frequency, IDF): 신호와 잡음을 분리합니다. 잘 알려지지 않은 설정 플래그처럼 희귀한 토큰을 중심으로 한 짧은 메시지는 상위에 오를 자격이 있습니다. 반면 "좋아요, 감사합니다!" 는 임베딩 공간에서 많은 질의와 가깝게 위치하지만, 용어의 희소성을 고려하면 점수가 0에 수렴합니다.
  • 시간 감쇠(Age decay): Slack의 답변에는 유효 기간이 있다는 사실을 반영합니다. 두 스레드가 같은 질문에 답할 수 있고, 6개월 전의 것은 이제 존재하지 않는 인프라를 설명하고 있을 수 있습니다. 다른 조건이 같다면 더 최신 스레드가 이깁니다.

어떤 단일 채점자(scorer)도 홀로 신뢰받지 않습니다. 각 기법은 동일한 코퍼스(corpus)에 대해 자신만의 순위 뷰(ranked view)를 만들고, 그 뷰들은 질의 시점에 융합됩니다(뒤의 재순위 섹션 참고).

:books: 심화 학습: 임베딩에 맥락을 더하는 기법

Socket Mode로 실시간 데이터 수집

데이터를 실시간으로 수집하기 위해, 팀은 Slack 봇을 워크스페이스에 설치하고 소켓 모드(Socket Mode)로 실행했습니다. Slack은 모든 메시지 이벤트를 영속적인 웹소켓(WebSocket)으로 밀어 보내므로, Web API를 폴링(polling)하며 속도 제한(rate limit)을 소진하지 않고도 실시간 업데이트를 받을 수 있습니다.

이벤트가 도착하면 시스템은 즉시 이를 확인 응답(acknowledge)하고, 안정적인 이벤트 ID로 중복을 제거한 뒤, 수집 컨슈머(ingest consumer)가 처리하도록 메시지를 표시합니다.

수집 컨슈머는 새 메시지를 고립된 상태로 저장하지 않습니다. 메시지가 속한 스레드를 해석하고, 부모 메시지와 모든 답글을 포함한 전체 대화를 Slack API에서 다시 가져옵니다. 그런 다음 스레드 전체를 하나의 행으로 다시 씁니다. 따라서 기존 스레드에 달린 답글 하나는 부모와 모든 형제 메시지를 다시 끌어오게 되고, 저장된 콘텐츠, 참여자 목록, 마지막 활동 타임스탬프가 항상 완전한 대화 상태를 반영합니다. 시스템의 모든 Slack 채널은 각자의 데이터 소스를 가지므로, 예를 들어 바쁜 인시던트(incident) 채널은 더 자주 수집하도록 데이터 신선도를 세밀하게 조정할 수 있습니다.

스레드와 메시지: LLM 증류로 검색 신호 만들기

원본 Slack 텍스트는 시스템에 도착하는 즉시 키워드 검색이 가능합니다. Postgres의 전문 검색(GIN) 인덱스를 원본 콘텐츠 위에 유지하기 때문입니다. 그러나 유용한 벡터 검색을 가능하게 하려면 추가 처리가 필요합니다. Slack처럼 방대한 메시지 스트림을 검색 가능하게 만드는 엔지니어링의 어려움은 Slack AI가 대규모 메시지를 처리하는 방식을 다룬 Salesforce/Slack 엔지니어링 팀의 글에서도 엿볼 수 있습니다.

증류(distillation) 단계에서 LLM은 전체 스레드로부터 구조화된 데이터를 추출합니다.

  • 엔지니어가 실제로 검색할 법한 한 줄짜리 질문.
  • 짧은 요약.
  • 해결책(resolution).
  • 언급된 시스템과 코드 참조.

이 데이터 포인트들을 임베딩해 공유 임베딩 테이블에 씁니다. 원본 대화록(transcript)은 직접 임베딩하지 않습니다. 실험에서 스레드를 일관된 형식으로 정규화했을 때 정확도가 크게 올랐고, 추가 메타데이터는 의미적 매칭에 더 유용한 신호를 주었습니다. LLM이 어떤 데이터 형식을 가장 잘 이해하는지 11가지 형식을 비교한 실험에서도 잘 구조화된 형식이 유리하다는 결과가 나온 바 있습니다. 이렇게 비정형 대화를 구조화된 문서로 바꾸는 접근은 Anthropic의 프롬프트 엔지니어링 가이드가 권장하는 XML 태그 구조화와도 통하는 부분이 있습니다.

버스팅: 긴 스레드에 묻힌 신호를 살리기

여기까지 오자 Slack 검색은 꽤 좋아졌지만, 팀은 같은 문제를 계속 마주쳤습니다. 긴 스레드 안의 중요한 메시지가 스레드 수준 요약에는 항상 담기지 않는다는 것입니다.

개별 메시지의 신호를 끌어올리기 위해 팀은 버스팅(bursting) 을 사용합니다. 버스트(burst)는 동일 작성자가 연속으로 남긴 메시지의 묶음입니다. 스레드 주제를 맥락으로 앞에 붙여 개별 버스트를 임베딩하는데, 때로는 정답이 스레드 요약에는 결코 담기지 않는 어휘를 가진 한 개의 곁가지 메시지에 들어 있기 때문입니다. 버스트 임베딩은 그런 메시지를 그 자체로 찾을 수 있게 만듭니다.

저신호 데이터가 데이터베이스에 도달하지 못하도록, 각 버스트는 가중 신호 조합에 대해 채점되고 임베딩되기 전에 임계값을 통과해야 합니다.

  • 코퍼스 전반에서 상대적으로 희귀한 토큰을 포함할 것(IDF 최소 4.0 이상).
  • 결합된 버스트가 최소 200자 이상일 것.
  • 버스트 안의 하나 이상의 메시지가 리액션(reaction)을 포함할 것(사회적 가중치 부여).

증류가 끝나면, 조건을 통과한 버스트가 임베딩되어 스레드 수준 레코드와 나란히 임베딩 테이블에 저장됩니다.

코드 저장소: grep이면 충분하다는 통념을 넘어

처음에 팀은 코드 저장소를 임베딩하는 것이 정말 필요한지 논쟁했습니다. Claude Code를 비롯한 명령줄 도구가 부상하면서, "grep이면 충분하다(grep is all you need)" 라는 인상이 강했기에 코드 임베딩을 만드는 것이 오히려 직관에 어긋나 보였습니다. 그러나 업계의 다른 이들과 이야기하고 대규모 코드베이스의 시맨틱 검색에 관한 Cursor의 실험 결과를 읽은 뒤, 팀은 시도해 보기로 결정했습니다.

Cerebras에는 40GB가 넘는 것을 포함해 수많은 내부 저장소가 있습니다. 팀의 주된 고민은 이 저장소들을 어떻게 효율적으로 최신 상태로 유지하느냐였습니다.

CocoIndex로 코드 임베딩 유지하기

여러 실험 끝에 팀은 코드베이스 벡터화에 특화된 오픈소스 문서 임베딩 프레임워크 CocoIndex에 안착했습니다.

각 저장소에 대해, 팀은 굵은 단위에서 미세한 단위로 정렬된 언어별 정규식(regex) 경계를 사용해 코드를 분할(split)합니다. 분할기(splitter)는 클래스 같은 상위 수준 경계를 먼저 시도합니다. 그렇게 나온 청크가 여전히 너무 크면 메서드 경계로, 다시 더 작은 블록으로 물러납니다. 이렇게 만들어진 청크를 임베딩해 벡터를 Postgres에 씁니다. 하나의 파일이 파일 수준과 함수 수준처럼 서로 다른 구체성 수준에서 여러 임베딩을 만들어 낼 수 있습니다.

CocoIndex는 동기화 메타데이터를 Postgres에 추적합니다. 커밋마다 저장소 전체를 다시 계산하는 대신 변경된 코드 청크만 다시 임베딩하고 다시 내보냅니다. 동기화 상태와 임베딩 저장소가 같은 데이터베이스에 있기에 이 방식은 특히 잘 맞았습니다. 코드베이스 수가 늘어나면서, 팀은 저장소 온보딩을 파일 경로 수준의 허용 목록(allowlist)과 차단 목록(denylist)을 포함한 설정 파일로 옮겨 각 팀이 직접 제출할 수 있게 했습니다.

커스텀 데이터 소스: 플러그인 스크립트로 확장

일부 팀은 이미 자체 데이터베이스를 가지고 있었고, 지식 베이스에 참여하기 위해 데이터를 Slack이나 문서 시스템으로 옮기고 싶어 하지 않았습니다. 이들은 기존 테이블 위에서 동일한 질의 표면(query surface)을 원했습니다.

이를 지원하기 위해 팀은 커스텀 소스를 플러그인 스크립트 로 다룹니다. 한 팀이 자기 시스템에서 데이터를 읽어 우리 임베딩 테이블 형태의 행을 내보내는 방법을 아는 작은 Python 모듈과, 그에 대응하는 데이터 소스 항목을 담아 풀 리퀘스트를 엽니다. 스크립트가 다른 모든 임베딩 행과 동일한 스키마로 공유 데이터베이스에 쓰기만 하면, 나머지 스택은 변경 없이 동작합니다. 그 데이터는 시스템의 다른 어느 곳에서도 특별한 처리 없이 Slack, 코드, 문서와 나란히 질의 가능해집니다.

질의 처리: 계획 수립과 도구 팬아웃

모든 질의에 대해, 시스템은 먼저 짧은 계획 수립(planning) 과정을 실행합니다. 여기서 LLM은 어떤 도구와 데이터 소스가 중요할지를 결정합니다. 주요 도구는 다음과 같습니다.

  • subsystem_index: 파일별 LLM 요약.
  • search: Slack, 위키, 코드 및 기타 인덱싱된 소스를 아우르는 통합 벡터 파이프라인으로, 내부적으로 병합 및 재순위됩니다.
  • search_slack: Slack 직접 검색.
  • search_code: 소스 저장소에 대한 ripgrep 검색.
  • recent_prs: 질문과 관련된 최근 풀 리퀘스트.
  • who_knows: 특정 주제에 대해 입증된 전문성을 가진 사람들.

특히 who_knows 는 글 첫머리에서 언급한 "Y 전문가가 누구인가요?" 라는 질문에 직접 답합니다. 이 지식 베이스가 문서만 검색하는 것이 아니라 사람(전문가)까지 찾아 연결한다는 점은, 단순히 흩어진 정보를 모으는 것을 넘어서는 이 시스템의 차별점입니다.

계획기(planner)는 우리가 인덱싱한 것에 대한 압축된 설명 위에서 동작합니다. 어떤 프로젝트가 존재하는지, 각 프로젝트에서 어떤 소스를 사용할 수 있는지, 각 소스가 어떤 질문에 잘 답하는지를 봅니다. 사용자의 질의와 활성 범위(scope)가 주어지면, 계획기는 도구 선택을 내놓고, 실행기(executor)가 이를 병렬로 팬아웃(fan-out)하여 공통 증거 형식으로 정규화한 뒤 최종 종합(synthesis) LLM에 넘깁니다. 이렇게 LLM이 도구 사용을 스스로 계획하고 병렬로 실행하는 구조는 Search-o1 같은 에이전트형 검색 연구와 같은 흐름에 있습니다.

재순위: RRF로 서로 다른 검색 결과를 융합하기

한 문서는 질의와 어휘를 공유한다는 이유만으로, 정작 다른 질문에 답하면서도 상위에 떠오를 수 있습니다. 재순위(reranking) 전에, 팀은 검색기(retriever)들의 호환되지 않는 결과 목록을 상호 순위 융합(Reciprocal Rank Fusion, RRF) 으로 결합합니다. 모든 문서에 대해, 그 문서가 등장하는 각 목록마다 가중치를 더합니다. 기본 가중치는 1.0이고 평활화 상수(smoothing constant)는 60입니다.

\text{score}(d) = \sum_{L} \frac{w}{k + \text{rank}_L(d)} \quad (w = 1.0,\ k = 60)

평활화 상수는 하나의 강한 표를 던지는 것보다 합의(consensus)를 더 중요하게 만듭니다. 여러 검색기에서 상위에 등장하는 문서가, 단 하나의 검색기에서만 1위를 한 문서를 이길 수 있는 것입니다. 그다음 팀은 중복 청크를 하나의 소스로 다시 병합하고, 각 파일이 기여할 수 있는 결과 수에 상한을 두어 더 다양한 상위 20개를 얻습니다.

이 후보들과 원래 질의를 작은 재순위 모델(reranker)에 보냅니다. 이 모델은 각 문서에 0에서 10까지의 점수를 매기고, 팀은 상위 10개를 남깁니다. 순위가 확정되면 승자에게 맥락을 다시 더합니다. 예를 들어 위키 섹션을 매칭하면 인접한 두 섹션을 함께 끌어와, 청킹(chunking)이 갈라놓은 제목, 전제 조건, 주의 사항이 사라지지 않게 합니다. 긴 컨텍스트의 중간에 있는 정보가 무시되기 쉽다는 Lost in the Middle 연구의 문제의식을 떠올리면, 이렇게 맥락을 복원해 완전한 스니펫을 만드는 일의 중요성이 분명해집니다. 즉, search의 출력은 서로 다른 검색기에서 융합되고, 소스 수준에서 중복 제거되며, 실제 질문에 대해 재순위된 뒤, 비로소 주변 맥락으로 확장된 풍부한 증거 묶음입니다.

MCP: 검색 기본기를 도구로 노출하기

MCP(Model Context Protocol) 통합에서, 팀은 검색 구성 요소들을 하나의 "이 질문에 답하라" 는 엔드포인트 뒤에 숨기는 대신 직접 호출 가능한 도구로 노출합니다. 이 도구들은 의도적으로 단순하고 가능한 한 LLM에 의존하지 않도록(LLM-free) 만들어져, 클라이언트가 빠르고 저렴하게 질의할 수 있습니다.

각 MCP 도구는 search_slack, search_code, search, who_knows처럼 하나의 검색 기본기(retrieval primitive)에 대응합니다. 도구 입출력은 좁고, 구조화되어 있으며, 안정적이라서, 도구 안에 별도의 오케스트레이션 로직을 심지 않고도 어떤 클라이언트나 에이전트에서든 쉽게 호출할 수 있습니다. 대부분의 도구는 벡터 검색, 어휘 검색, ripgrep 같은 하나의 질의 파이프라인을 실행하고, 가벼운 채점 휴리스틱을 적용한 뒤 원본 증거 행을 반환합니다.

이렇게 하면 Claude Code나 MCP 호환 에이전트가 오케스트레이션 엔진이 됩니다. 어떤 도구를, 어떤 순서로 호출하고, 결과를 어떻게 최종 답변이나 코드 수정으로 조립할지 에이전트가 결정합니다. 검색 계층 자체는 요청을 처리하기 위해 그런 LLM 결정에 의존하지 않습니다. 도구를 얇게 유지하고 오케스트레이션을 클라이언트로 넘기는 이 설계 철학은 Anthropic이 정리한 코드 실행 기반 MCP 활용법과도 맞닿아 있습니다.

Web UI: planner에서 executor, synthesis로 이어지는 파이프라인

웹 UI에서는 동일한 도구들이 존재하지만, 모든 사용자 질문에 대해 처음부터 끝까지 실행되는 완전한 질의 파이프라인에 연결되어 있습니다. UI 에이전트가 계획기와 실행기 단계를 소유합니다.

계획기 (Planner): 가벼운 LLM 과정이 질의와 활성 프로젝트를 검사한 뒤, search, search_slack, subsystem_index 같은 어떤 검색 도구를 호출할지 고릅니다.

실행기 (Executor): 시스템이 그 도구 호출들을 병렬로 팬아웃하고, 결과를 모아, 점수와 최신성(recency), 소스 힌트를 담은 공유 증거 스키마로 정규화합니다.

종합 (Synthesis): 최종 LLM 과정이 타입이 지정된 증거 묶음과 원래 질문을 받아, 인용, 주의 사항, 소스 간 종합을 포함해 UI에 표시되는 답변을 만들어 냅니다.

사용자 관점에서 웹 UI는 그저 "질문하면 답을 주는" 것입니다. 그러나 그 이면에서는 MCP 클라이언트가 명시적으로 재현할 수 있는 동일한 계획기 → 실행기 → 종합 패턴이 돌아갑니다.

결국 같은 검색 계층을 두 가지 방식으로 노출하는 셈입니다. MCP는 오케스트레이션을 클라이언트에 맡기고, 웹 UI는 오케스트레이션까지 내장합니다. 두 접근의 차이를 정리하면 다음과 같습니다.

측면 MCP 웹 UI
오케스트레이션 주체 클라이언트나 에이전트(Claude Code 등) 내장 UI 에이전트
도구의 성격 얇은 검색 기본기, 가능한 한 LLM 비의존 계획기, 실행기, 종합을 갖춘 완전한 파이프라인
반환값 원본 증거 행 인용과 주의 사항을 포함한 최종 답변
계획기와 실행기 클라이언트가 명시적으로 재현 UI 에이전트가 소유

:books: 심화 학습: MCP와 에이전트 검색

조직화: 프로젝트와 범위 지정 검색

코퍼스가 커지면서 "모든 것을 모든 곳에서 검색" 하는 방식은 빠르게 쓸모를 잃었습니다. 컴파일러 팀 엔지니어는 결과에 인프라 런북(runbook)이 섞이는 것을 원하지 않았고, 그 반대도 마찬가지였습니다. 프로젝트(project) 는 검색을 기본적으로 관련성 있게 만드는 방법입니다.

팀은 질의가 실행되는 작업 공간을 조직하는 주된 방법으로 프로젝트를 도입했습니다. 프로젝트는 특정 Slack 채널, 코드 저장소, 내부 데이터베이스, 문서 공간처럼 한 팀이나 이니셔티브에 관련된 데이터 소스들의 이름 붙은 묶음입니다. 프로젝트는 의도적으로 가볍습니다. 공유 인시던트 채널이나 중앙 플랫폼 저장소 같은 동일한 데이터 소스는 복제되는 대신 여러 프로젝트에서 참조될 수 있습니다.

온보딩 과정에서 사용자는 자신의 업무 방식에 맞는 기본 프로젝트를 선택하거나 생성하도록 안내받습니다. ML 학습 인프라, 컴파일러, 데이터센터 운영 같은 것들입니다. 그 기본 프로젝트는 사용자 프로필에 저장되어 질의 범위를 자동으로 지정합니다. 새 엔지니어는 어떤 Slack 채널, 저장소, 문서 공간이 중요한지 먼저 배우지 않고도 신호가 높은 답을 얻습니다.

마치며: 시스템에 데이터를 맞추지 않고, 데이터가 있는 곳으로 간다

결국 이 지식 베이스가 작동하는 이유는, 모든 것을 하나의 경직된 시스템에 밀어 넣는 대신 정보가 이미 존재하는 곳에서 사람을 만나기 때문입니다. 여러 검색 기법을 결합함으로써 증거를 빠르게 표면화할 수 있고, 그 결과는 실제 회사 데이터를 다룰 만큼 유연하면서도 Cerebras가 계속 성장해도 유용함을 유지할 만큼 구조화된 검색 경험입니다.

이 글의 설계에서 사내 검색이나 코드베이스 검색을 만들려는 개발자가 가져갈 만한 교훈은 분명합니다. 첫째, 벡터 검색은 만능이 아니며 전문 검색, IDF, 시간 감쇠 같은 고전적 정보 검색 기법과 융합할 때 비로소 실용적 정확도에 도달합니다. 둘째, 원본 텍스트를 그대로 임베딩하기보다 LLM으로 구조화된 형태로 증류한 뒤 임베딩하는 것이 정확도를 크게 끌어올립니다. 셋째, 임베딩 저장소와 검색 상태를 같은 데이터베이스(여기서는 Postgres와 pgvector)에 두는 단순한 선택이 증분 동기화 같은 운영을 훨씬 쉽게 만듭니다. 넷째, 검색 기본기를 MCP 도구로 얇게 노출하면 오케스트레이션을 에이전트에 맡겨 시스템을 유연하게 확장할 수 있습니다. 화려한 단일 모델보다, 여러 신호를 정직하게 융합하는 파이프라인이 실제 조직의 지저분한 데이터 위에서 더 잘 작동한다는 점이 이 사례의 핵심입니다.

:scroll: How Cerebras Built Its Enterprise Knowledge Base 소개 블로그

https://www.cerebras.ai/blog/how-we-built-our-knowledge-base

더 읽어보기




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다! 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다. :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: