- Slack/코드 저장소/문서/내부 데이터베이스를 기존 위치에서 직접 수집하는 Cerebras Knowledge를 구축해 출시 3개월 만에 직원/자동화/에이전트로부터 하루 15,000건 이상의 질문을 처리함
- 모든 데이터를 하나의 도구로 옮기는 대신 공통 스키마의 Postgres 임베딩 테이블에 연결하고, 수집/질의/인증·권한·감사·분석 계층을 분리해 새로운 데이터 소스를 쉽게 추가하도록 설계함
- Slack 검색은 원문 임베딩만으로 부족해 전문 검색/임베딩 검색/역문서 빈도/시간 감쇠를 함께 사용하고, 스레드 요약과 중요한 개별 발화 묶음을 별도로 임베딩함
- 질의마다 LLM이 사용할 검색 도구를 먼저 계획하고 결과를 병렬 수집한 뒤 RRF와 재순위화 모델로 통합하며, MCP에서는 동일한 검색 기능을 작고 안정적인 원시 도구로 직접 공개함
- 조직 전체를 무조건 검색하지 않고 Slack 채널/저장소/문서 공간 등을 묶은 프로젝트 단위 검색 범위를 기본값으로 지정해 팀별로 관련성 높은 결과를 제공함
정보가 생성되는 곳에서 직접 수집
- Cerebras의 데이터센터 운영/칩 설계/하드웨어/학습/추론/클라우드 플랫폼 팀에서는 매년 수백 명이 새로 합류하면서 “X는 어디에 있는가”, “Y의 전문가는 누구인가”, “Z는 무엇인가” 같은 질문이 반복됨
- 모든 정보를 단일 플랫폼에 기록하는 방식은 실제 업무에서 잘 작동하지 않는다고 판단함
- 문서의 제안 수정, Slack 스레드, GitHub 코드 참조, Jira 상태 메타데이터처럼 정보는 각 작업에 적합한 도구에서 생성됨
- 각 플랫폼은 오랜 제품 개발과 분석을 통해 특정 분야에 맞게 최적화돼 있어 사용 방식을 바꾸도록 강제하지 않기로 함
- 수집 단계에서 각 플랫폼에 직접 연결해 기존 업무 행동의 변화를 최소화함
공통 임베딩 테이블 중심의 구조
- 지식 베이스는 세 계층으로 구성됨
- 내부 데이터를 수집하고 저장하는 플랫폼
- 저장된 데이터를 질의하는 플랫폼
- 인증/권한 부여/감사/분석을 적용하는 계층
- 중심에는 여러 출처의 임베딩/원문 요약/메타데이터를 저장하는 단일 Postgres 테이블이 있음
- Slack 스레드, 코드 저장소, 문서 시스템, 넷리스트, 맞춤형 데이터베이스가 동일한 임베딩 행 인터페이스를 사용함
- 각 데이터 소스는 데이터의 정의, 연결 방법, 수집 주기를 지정하며 공통 테이블에 기록되는 즉시 동일한 질의 인터페이스에서 검색 가능해짐
- Cerebras 개발자가 별도의 연결기를 만들 수 있도록 데이터 인터페이스를 의도적으로 단순하게 유지함
Slack에 필요한 혼합 검색
- Slack은 최신 엔지니어링 논의가 이루어지는 가장 중요한 데이터 소스였음
- 원문에 단순 임베딩을 적용한 벡터 검색만으로는 관련 정보를 모두 찾기 어려웠음
- “응, 좋아” 같은 짧은 메시지와 자세한 커널 설명이 같은 메시지 단위로 저장됨
- 짧은 메시지가 더 길고 상세한 메시지보다 코사인 유사도에서 앞서는 경우가 많음
- 개별 메시지의 뜻이 주변 대화에 의존함
- 각 Slack 스레드를 네 가지 방식으로 동시에 검색함
- 전문 검색은 오류 문자열/플래그 이름/호스트 이름처럼 임베딩에서 흐려지는 정확한 토큰을 찾음
- 임베딩 검색은 “manifest 이후 복원이 멈춤”과 “NFS 마운트에서 체크포인트가 정지함”처럼 다른 어휘로 표현된 질문과 답변을 연결함
- 역문서 빈도(IDF) 는 희귀한 설정 플래그가 포함된 짧은 메시지의 순위를 높이고 흔한 반응성 문구의 점수를 낮춤
- 시간 감쇠는 동일한 관련성을 가진 답변 중 오래된 인프라를 설명할 수 있는 과거 스레드보다 최신 스레드를 우선함
- 한 가지 점수만 신뢰하지 않고 각 검색기가 만든 순위 목록을 질의 시점에 결합함
Socket Mode 기반 실시간 수집
- Slack 봇을 워크스페이스에 설치하고 Socket Mode의 지속적인 WebSocket 연결로 모든 메시지 이벤트를 수신함
- Web API를 반복 호출하지 않아도 실시간으로 갱신하며 요청 속도 제한 소비를 줄임
- 이벤트가 도착하면 즉시 응답하고 안정적인 이벤트 ID로 중복을 제거한 뒤 수집 소비자가 처리하도록 표시함
- 새 메시지를 독립적으로 저장하지 않고 해당 메시지가 속한 전체 스레드를 다시 가져옴
- 부모 메시지와 모든 답글을 한 행으로 저장함
- 기존 스레드에 답글이 추가되면 부모/형제 답글/참여자 목록/마지막 활동 시각이 모두 최신 상태로 갱신됨
- Slack 채널마다 별도 데이터 소스를 두어 사고 대응 채널처럼 변경이 잦은 채널의 수집 주기를 더 짧게 설정할 수 있음
스레드 증류와 구조화
- 원문 Slack 텍스트는 Postgres GIN 전문 인덱스를 통해 저장 직후 키워드 검색이 가능함
- 벡터 검색용 데이터는 LLM이 전체 스레드에서 다음 항목을 추출함
- 엔지니어가 실제 검색할 법한 한 줄 질문
- 짧은 요약
- 해결 방법
- 관련 시스템과 코드 참조
- 추출된 항목을 임베딩해 공통 테이블에 저장하며 원본 대화문 자체는 직접 임베딩하지 않음
- 실험에서는 스레드를 일관된 형식으로 정규화했을 때 정확도가 크게 높아졌고, 추가 메타데이터도 의미 검색에 더 유용한 신호를 제공함
긴 스레드의 개별 메시지를 살리는 Bursting
- 스레드 수준 요약만으로는 긴 대화 속 중요한 메시지가 누락되는 문제가 남음
- 같은 작성자가 연속해서 보낸 메시지를 연속 발화 묶음(burst) 으로 결합하고, 스레드 주제를 문맥으로 앞에 붙여 별도로 임베딩함
- 스레드 요약에 포함되지 않은 곁가지 대화의 답변도 독립적으로 검색 가능해짐
- 낮은 신호의 발화가 데이터베이스에 들어가지 않도록 가중 신호를 계산하고 임계값을 통과한 묶음만 저장함
- 전체 말뭉치에서 IDF가 4.0 이상인 희귀 토큰을 포함함
- 결합된 발화 길이가 최소 200자임
- 하나 이상의 메시지에 반응 이모지가 있어 사회적 가중치를 얻음
- 조건을 충족한 묶음은 스레드 수준 레코드와 함께 공통 임베딩 테이블에 저장됨
대규모 코드 저장소의 증분 임베딩
- Claude Code 같은 명령줄 도구가 확산되면서 코드에는
grep만으로 충분할 수 있다고 보았지만, 업계 관계자와 Cursor의 대규모 코드베이스 의미 검색 결과를 검토한 뒤 코드 임베딩을 도입함 - 일부 내부 저장소는 40GB를 넘어 전체를 지속적으로 다시 임베딩하는 비용이 주요 과제였음
- 여러 실험 뒤 코드베이스 벡터화에 특화된 오픈소스 문서 임베딩 프레임워크 CocoIndex를 선택함
- 언어별 정규식 경계를 큰 단위부터 작은 단위 순으로 적용해 코드를 분할함
- 먼저 클래스 같은 상위 경계를 사용함
- 청크가 너무 크면 메서드와 더 작은 블록 경계로 내려감
- 하나의 파일에서 파일 수준/함수 수준처럼 서로 다른 세분도의 임베딩이 여러 개 생성될 수 있음
- CocoIndex가 Postgres에 동기화 메타데이터를 유지해 커밋마다 변경된 코드 청크만 다시 임베딩하고 내보냄
- 저장소가 늘어난 뒤에는 팀이 직접 제출할 수 있는 설정 파일로 온보딩을 전환하고 파일 경로별 허용 목록/차단 목록을 지원함
맞춤형 데이터 소스 연결
- 일부 팀은 기존 데이터베이스의 정보를 Slack이나 문서 시스템으로 옮기지 않고 동일한 검색 인터페이스를 사용하기를 원함
- 맞춤형 소스를 플러그인 스크립트로 취급함
- 팀이 기존 시스템을 읽어 공통 임베딩 테이블 형태의 행을 내보내는 작은 Python 모듈을 풀 리퀘스트로 제출함
- 이에 대응하는 데이터 소스 설정도 함께 추가함
- 공통 스키마로 공유 데이터베이스에 기록하기만 하면 Slack/코드/문서와 함께 검색되며 나머지 시스템에는 별도 처리가 필요하지 않음
질의 계획과 도구 병렬 실행
- 모든 질문에 대해 LLM이 먼저 짧은 계획 단계를 실행해 사용할 도구와 데이터 소스를 결정함
- 주요 도구는 다음과 같음
subsystem_index: 파일별 LLM 요약search: Slack/위키/코드/기타 인덱스를 통합하고 내부에서 병합·재순위화하는 벡터 검색search_slack: Slack 직접 검색search_code: 소스 저장소에 대한ripgreprecent_prs: 질문과 관련된 최근 풀 리퀘스트who_knows: 특정 주제의 전문성을 실제로 보여준 사람 검색
- 계획기는 프로젝트 목록/프로젝트별 데이터 소스/각 소스가 답하기 좋은 질문을 압축한 설명을 사용함
- 실행기는 선택된 도구를 병렬 호출하고 결과를 공통 근거 형식으로 정규화한 뒤 최종 합성 LLM에 전달함
RRF와 재순위화
- 질의와 어휘만 공유하고 실제로는 다른 질문에 답하는 문서가 상위에 나타날 수 있어 별도 재순위화 단계를 둠
- 서로 다른 검색기의 순위 목록을 상호 순위 융합(RRF) 으로 결합함
- 각 문서가 등장한 목록마다
weight / (60 + rank)를 더함 - 기본 가중치는 1.0, 평활 상수는 60임
- 여러 검색기에서 고르게 상위에 등장한 문서가 단일 검색기에서만 1위를 차지한 문서를 앞설 수 있음
- 각 문서가 등장한 목록마다
- 중복 청크를 원본 단위로 합치고 파일별 결과 수를 제한해 다양한 상위 20개 후보를 만듦
- 작은 재순위화 모델이 원래 질문을 기준으로 각 문서에 0~10점을 부여하고 상위 10개를 남김
- 최종 결과에는 주변 문맥을 다시 추가함
- 위키 섹션이 일치하면 인접한 두 섹션을 함께 가져와 제목/사전 조건/주의사항이 청크 분할로 사라지지 않게 함
- 검색 결과는 여러 검색기의 결합/원본 단위 중복 제거/질문 기반 재순위화/주변 문맥 확장을 거친 근거 묶음으로 반환됨
MCP와 웹 UI의 역할 분담
- MCP에서는 하나의 “질문에 답하기” 엔드포인트 대신
search_slack,search_code,search,who_knows같은 검색 기본 기능을 각각의 도구로 공개함 - 도구를 빠르고 저렴하게 호출할 수 있도록 가능한 한 LLM 의존성을 제거함
- 입력과 출력 범위를 좁고 구조적이며 안정적으로 유지함
- 벡터 검색/어휘 검색/
ripgrep같은 단일 파이프라인에 가벼운 점수 규칙을 적용해 원시 근거 행을 반환함
- Claude Code를 비롯한 MCP 호환 에이전트가 호출할 도구/순서/결과 조합 방식을 결정하는 오케스트레이션 엔진이 됨
- 웹 UI에서는 같은 도구를 하나의 완전한 질의 파이프라인으로 연결함
- 계획기가 질문과 활성 프로젝트를 살펴 호출할 검색 도구를 선택함
- 실행기가 호출을 병렬 처리하고 점수/최신성/출처 힌트를 포함한 공통 근거 스키마로 변환함
- 합성기가 질문과 근거 묶음으로 인용/주의사항/출처 간 통합을 포함한 답변을 생성함
- 사용자는 단순히 질문하고 답을 받지만 내부에서는 계획기 → 실행기 → 합성기 흐름이 실행됨
프로젝트 단위의 검색 범위
- 말뭉치가 커지자 조직 전체를 항상 검색하는 방식의 관련성이 급격히 낮아짐
- 컴파일러 팀은 인프라 운영 절차가 검색 결과에 나타나는 것을 원하지 않았으며 반대 상황도 동일했음
- 프로젝트를 질의가 실행될 기본 작업 공간으로 도입함
- 특정 Slack 채널/코드 저장소/내부 데이터베이스/문서 공간을 팀이나 과제별로 묶음
- 공유 사고 채널이나 중앙 플랫폼 저장소 하나를 여러 프로젝트에서 참조할 수 있으며 데이터는 복제하지 않음
- 온보딩 과정에서 ML 학습 인프라/Compiler/Data Center Operations처럼 업무에 맞는 기본 프로젝트를 선택하거나 만들도록 함
- 기본 프로젝트를 사용자 프로필에 저장하고 모든 질의 범위를 자동 제한해 신규 엔지니어도 관련 채널과 저장소를 먼저 익히지 않고 검색을 시작할 수 있음
기존 도구를 유지하는 지식 베이스
- 지식 베이스의 작동 원칙은 정보를 하나의 경직된 시스템으로 옮기지 않고 이미 생성되는 위치에서 수집하는 것임
- 여러 검색 방식을 결합해 근거를 빠르게 찾으면서도 실제 기업 데이터의 다양성을 수용하고, 조직이 성장해도 유용성을 유지할 수 있는 구조를 만듦