본문으로 바로 가기

지식 베이스와 지식 관리

지식 베이스는 관련 자료를 정리하고 청크, 벡터 모델, 검색 인덱스, Wiki와 지식 그래프를 일괄 설정하는 데 사용합니다. 파일, 웹페이지, 직접 작성한 Markdown과 FAQ 등의 콘텐츠를 지식 항목으로 관리하며, 수집 후 설정에 따라 파싱하고 인덱스를 생성합니다.

지식 베이스마다 독립적인 처리 설정을 사용할 수 있습니다. 질문할 때 검색 범위를 제한할 수 있으며, 멤버 접근과 조직 공유도 지식 베이스 단위로 권한을 부여합니다.

스크린샷 준비 중
지식 베이스 문서 목록: 파싱 상태, 태그와 일괄 작업

파싱 상태 열, 태그 열, 상단 필터와 문서 선택 후 나타나는 일괄 작업 표시줄이 포함된 문서 목록 페이지를 보여주세요.

website-docs/public/screenshots/kb-document-list.png
지식 베이스 문서 목록: 파싱 상태, 태그와 일괄 작업

관리 작업 진입점

작업UI 진입점
지식 베이스 생성, 청크 크기와 인덱스 스위치 변경지식 베이스 편집 팝업의 「청크」, 「인덱싱 전략」 탭
파일 업로드, 웹페이지 가져오기 또는 Markdown 작성문서 목록 페이지의 업로드 영역 또는 「새로 만들기」 드롭다운
폴더로 문서 정리문서 목록 왼쪽의 폴더 트리. 디렉터리 전체 업로드 시 디렉터리 구조 유지(폴더 트리 참조)
문서에 태그 추가(문서당 여러 개 가능)개별 문서는 상세 화면에서 변경. 여러 문서는 선택 후 일괄 작업 표시줄의 「태그」 사용(태그(KnowledgeTag) 참조)
파싱 결과 확인, 오타 수정문서 열기 → 청크 목록 → 청크 직접 편집(청크 편집과 버전 기록 참조)
부서, 보안 등급 등 사용자 지정 필드 추가문서 상세의 사용자 지정 메타데이터(모델 핵심 사항 참조)
작업 기록 조회지식 베이스 설정 → 활동(지식 베이스 활동 스트림(KB Activity) 참조)
지식 베이스 복사 또는 베이스 간 문서 이동지식 베이스 목록의 복사 또는 문서 일괄 작업의 이동(지식 베이스 복사와 지식 이동 참조)
스크린샷 준비 중
지식 베이스 설정: 청크 매개변수와 인덱싱 전략 스위치

청크 크기/겹침/부모·자식 청크 설정과 벡터, 키워드, Wiki, 그래프의 네 가지 인덱스 스위치를 보여주세요.

website-docs/public/screenshots/kb-settings.png
지식 베이스 설정: 청크 매개변수와 인덱싱 전략 스위치

지식 베이스 생성과 자료 가져오기

지식 베이스를 생성할 때 콘텐츠 유형, 모델과 인덱싱 방식을 선택한 뒤 파일 업로드, 웹페이지 가져오기 또는 Markdown 작성을 진행합니다. 일반 자료에는 문서 베이스를, 표준 질의응답에는 FAQ 베이스를 사용합니다. 벡터 스토리지는 생성 후 변경할 수 없으므로 지식 베이스 생성 전에 결정해야 합니다.

업로드 확인 페이지에서 태그와 이번 파일 묶음의 파싱 옵션을 설정할 수 있습니다. 일회성 처리 옵션은 지식 베이스 설정보다 우선하며, 지식 베이스 설정은 공간 기본값보다 우선합니다. 업로드 후 목록에서 파싱 진행 상황을 확인할 수 있습니다. 기존 문서에 변경된 청크 매개변수를 적용하려면 다시 파싱해야 합니다.

폴더와 태그 정리

폴더는 디렉터리별로 문서를 보관하는 데 사용하며, 문서 하나는 폴더 하나에만 속합니다. 디렉터리 전체를 업로드하면 계층 구조를 유지할 수 있습니다. 폴더 트리에서 이름을 바꾸거나 이동하면 하위 디렉터리 경로도 함께 갱신되며, 대상 디렉터리가 이미 있으면 콘텐츠를 병합합니다. 같은 지식 베이스 안에서 문서의 폴더를 이동하면 분류만 바뀌고 다시 파싱하지 않습니다.

태그는 교차 분류에 사용하며 문서 하나에 여러 태그를 연결할 수 있습니다. 업로드 시 태그를 미리 설정하거나 문서를 선택한 뒤 일괄 변경할 수 있습니다. 일괄 대화상자에서는 선택한 문서들의 공통 태그가 미리 선택됩니다. 여러 태그로 필터링할 때는 어느 하나와 일치하는 문서도 반환합니다.

자동 태그를 켜면 파싱 완료 시 기존 후보 태그 중 일치하는 항목을 선택합니다. 기본적으로 문서당 최대 3개를 연결하며, 기존 태그가 있으면 건너뜁니다. 설정은 이후 파싱에만 영향을 주며 과거 문서를 자동으로 보완하지 않습니다. 모델 실패도 문서 완료를 막지 않습니다.

스크린샷 준비 중
문서 목록의 폴더 트리: 디렉터리별 탐색과 재분류

왼쪽 폴더 트리, 현재 디렉터리의 문서 목록과 폴더 이름 변경/이동 진입점을 보여주세요.

website-docs/public/screenshots/kb-folder-tree.png
문서 목록의 폴더 트리: 디렉터리별 탐색과 재분류
스크린샷 준비 중
일괄 태그 지정: 선택한 문서의 공통 태그 미리 선택

문서를 여러 개 선택한 뒤 연 태그 대화상자를 보여주세요. 선택된 태그 영역, 검색창과 선택 가능한 태그 목록을 포함해주세요.

website-docs/public/screenshots/kb-batch-tag.png
일괄 태그 지정: 선택한 문서의 공통 태그 미리 선택

청크 편집과 메타데이터 추가

문서 상세에서 텍스트 청크를 편집하여 파싱 오류를 수정하고 인덱스를 재생성할 수 있습니다. 편집하거나 롤백할 때마다 새 버전이 생성됩니다. 다른 사용자가 같은 청크를 이미 업데이트했다면 UI에서 새로고침 후 다시 시도하도록 안내합니다. 인덱스 업데이트에 실패하면 편집한 콘텐츠를 보존하고 실패 상태를 표시하며, 다시 제출하여 재시도할 수 있습니다.

사용자 지정 메타데이터는 부서, 보안 등급이나 버전 번호 등의 정보를 보완하는 데 사용하며 최대 20개 항목을 지원합니다. 메타데이터를 변경하면 요약 갱신을 트리거합니다. 필드 길이와 지원 유형의 자세한 내용은 참고 섹션을 확인하세요.

스크린샷 준비 중
청크 편집: 본문 수정, 버전 기록 조회와 롤백

청크 하나의 편집 상태, 버전 기록 목록(편집자와 시간 포함), 롤백 진입점을 보여주세요.

website-docs/public/screenshots/kb-chunk-edit.png
청크 편집: 본문 수정, 버전 기록 조회와 롤백

콘텐츠 복사와 이동

지식 베이스를 복사하면 기존 설정과 콘텐츠를 재사용할 수 있습니다. 베이스 간 이동 시 벡터 재사용 또는 재파싱을 선택할 수 있습니다. 재사용하려면 두 베이스가 같은 벡터 스토리지에 연결되어야 하며, 재파싱하면 대상 베이스의 스토리지와 처리 설정을 사용할 수 있습니다. 이동은 비동기 작업이며 진행 상황을 조회할 수 있습니다.

활동과 사용량 확인

지식 베이스 설정의 「활동」에는 설정, 문서, 청크, 공유와 Wiki 변경 사항이 기록됩니다. 이 진입점은 리소스 관리 권한을 충족하는 로그인 사용자용이며 API Key로는 접근할 수 없습니다.

스토리지 할당량은 작업 공간 단위로 계산하며 파일, 텍스트, 벡터와 인덱스를 포함합니다. 지식 베이스 생성과 업로드 전에 할당량을 확인하고, 콘텐츠 삭제 후 해당 사용량을 회수합니다.

스크린샷 준비 중
지식 베이스 활동 스트림: 시간 역순 작업 기록

활동 목록(작업자, 동작, 대상 문서, 시간)과 펼친 상세 드로어를 보여주세요.

website-docs/public/screenshots/kb-activity.png
지식 베이스 활동 스트림: 시간 역순 작업 기록

설정과 인터페이스 참고

지식 베이스 모델과 설정 항목

KB 유형

internal/types/knowledgebase.go:

go
const (
    KnowledgeBaseTypeDocument = "document" // 문서 유형
    KnowledgeBaseTypeFAQ      = "faq"      // FAQ 유형
    KnowledgeBaseTypeWiki     = "wiki"     // Wiki 유형
)

KB 업데이트 시 유형에 맞지 않는 설정을 제거합니다(예: FAQ가 아닌 베이스의 FAQConfig). VectorStoreID는 GORM <-:create 태그를 사용하므로 생성 후 변경할 수 없습니다(인덱스와 스토리지의 불일치 방지).

설정 구조 개요

ChunkingConfig(청크 설정)

필드유형기본값설명
chunk_sizeint필수청크 크기(문자 수)
chunk_overlapint-인접 청크의 겹침
separators[]string-구분자 목록
parser_engine_rules[]ParserEngineRule-파일 유형별 파싱 엔진 지정: {file_types, engine, xlsx_first_row_as_header?}
enable_parent_childboolfalse부모·자식 청크 전략 활성화
parent_chunk_sizeint4096부모 청크 크기(컨텍스트 반환용)
child_chunk_sizeint384자식 청크 크기(임베딩 검색용)
strategystring빈 값(= legacy청크 전략: legacy(기존 재귀 분할)/ auto(프로파일러가 계층 자동 선택)/ heading / heuristic / recursive(특정 계층 고정). 청크 메커니즘 참조
token_limitint0토큰 상한(0 = 제한 없음)
languages[]string자동 감지언어 힌트
table_metadata_instructionsstring-표 메타데이터 생성 지침

IndexingStrategy(인덱싱 파이프라인 스위치)

필드기본값설명
vector_enabledtrue의미 기반 벡터 검색
keyword_enabledtrue키워드(BM25) 검색
wiki_enabledfalseWiki 페이지 생성
graph_enabledfalse지식 그래프 추출

멀티모달 및 정보 보강 설정

VLMConfig(비전 언어 모델):

필드설명
enabled / model_id새 버전: 활성화 스위치 + 모델 ID
description_language이미지 설명 언어(빈 값 = 문서 언어 따름)
custom_instructionsKB 수준 이미지 해석 지침
model_name / base_url / api_key / interface_type이전 버전 호환 필드(ollama / openai)

활성화 판정: Enabled && ModelID != "" 또는 이전 버전의 ModelName != "" && BaseURL != "".

ASRConfig: enabled / model_id / language(언어 힌트, 선택 사항).

ImageProcessingConfig: model_id.

QuestionGenerationConfig(질문 생성): enabled; question_count는 청크당 생성할 질문 수(기본값 3, 상한 10); custom_instructions는 대상 독자 / 스타일 설명입니다.

ExtractConfig(지식 그래프): enabled, text, tags, nodes []*GraphNode{name, chunks, attributes}, relations []*GraphRelation{node1, node2, type}, custom_instructions(도메인 추출 지침).

FAQConfig(FAQ 베이스 전용): index_modequestion_only / question_answer, 기본값은 후자), question_index_modecombined / separate, 기본값 combined). 자세한 내용은 FAQ 문서를 참고하세요.

WikiConfig(indexing_strategy.wiki_enabled를 켠 지식 베이스)type = "wiki" 전용이 아니라는 점에 유의하세요. 일반 문서 베이스에서 Wiki 인덱스를 켜면 UpdateKnowledgeBase가 다음 조정 항목을 담을 빈 WikiConfig를 자동으로 생성합니다.

필드기본값설명
synthesis_model_id-Wiki 생성 LLM
max_pages_per_ingest0(제한 없음)단일 수집에서 생성/업데이트할 최대 페이지 수
extraction_granularitystandardfocused(주요 주제만)/ standard / exhaustive(모든 엔터티와 개념)
content_instructions / extraction_instructions-생성 및 추출 스타일 지침
ingest_batch_size / ingest_map_parallel / ingest_reduce_parallel / ingest_max_inflight5 / 10 / 10 / 4수집 동시성 매개변수

모든 custom_instructions 계열 필드는 업데이트 시 validateKnowledgeBasePromptInstructions로 길이와 유효성을 검증합니다(internal/handler/knowledgebase.go).

스토리지 설정

  • StorageProviderConfig(신규): provider ∈ {local, minio, cos, tos, s3, oss, ks3, obs};
  • StorageBackendID: 특정 스토리지 백엔드 인스턴스 연결;
  • StorageConfig(레거시 cos_config 열): secret_id / secret_key / region / bucket_name / app_id / path_prefix / provider / endpoint / use_ssl / force_path_style.

KB 계산 필드

목록 / 상세 응답에 포함되는 항목: knowledge_count, chunk_count, is_processing(FAQ 베이스), processing_count(문서 베이스에서 처리 중인 지식 수), share_count(공유한 조직 수), creator_name, is_pinned / pinned_at(현재 사용자의 상단 고정 상태).

저장 필드 is_temporary도 있습니다. 임시(ephemeral) 지식 베이스를 표시하며 일반 지식 베이스 목록에는 나타나지 않습니다. 시스템 내부에서 사용하며, 대표적으로 웹 검색으로 가져온 웹페이지를 검색 가능한 콘텐츠로 캐시할 때 사용합니다. 수동으로 지식 베이스를 생성하면 임시 베이스가 만들어지지 않습니다.

자동 태그

문서 지식 베이스의 태그 관련 설정에서 자동 태그를 켜고, 후보 태그를 먼저 준비한 뒤 채팅 모델을 선택합니다. 파싱 완료 후 시스템은 기존 태그에서 일치하는 항목을 비동기로 선택하며 새 태그를 생성하지 않습니다. auto_tag_config는 document 유형에만 적용됩니다.

필드기본값설명
enabledfalse자동 태그 활성화
model_id빈 값비어 있으면 지식 베이스의 summary_model_id 사용
max_tags3문서당 자동 연결 최대 개수, 상한 10
skip_if_taggedtrue수동 또는 데이터 소스에서 추가한 태그를 포함하여 기존 태그가 있으면 건너뜀. false이면 추가 방식으로 연결

설정은 이후 새로 파싱하거나 다시 파싱하는 문서에만 적용되며 과거 문서에 자동 소급 적용하지 않습니다. 모델 실패는 문서 완료를 막지 않으며 비동기 작업은 큐 정책에 따라 재시도합니다. 후보 태그는 지식 베이스 정렬 순서의 앞 500개를 가져옵니다. 자동 연결은 수동 태그를 삭제하지 않습니다. 데이터 소스가 출처 이름에 따라 태그를 추가하는 것은 별도 메커니즘입니다.

지식(Knowledge) 관리

모델 핵심 사항

internal/types/knowledge.go. 주요 필드: typemanual 수동 Markdown / faq / 파일 유형), source / channel(수집 채널), parse_status, summary_status, enable_status, file_name/type/size/hash/path, storage_size, metadata(JSON, 수동 지식은 ManualKnowledgeMetadata{content, format, status(draft/publish), version} 저장), custom_metadata(JSON, 사용자가 입력한 메타데이터), last_faq_import_result.

custom_metadata는 사용자가 관리하는 부서, 보안 등급, 버전 번호 등의 설명 필드를 저장합니다. metadata는 처리 흐름의 내부 상태와 ID를 저장합니다. 사용자 지정 메타데이터는 최대 20개 항목이며 키는 1–64자입니다. 값은 문자열, 숫자, 불리언 또는 null을 지원하며 길이는 1000자를 넘을 수 없습니다. 변경 후 요약을 자동으로 갱신합니다.

구현에서 Knowledge.CustomMetadataText()는 키 순서대로 정렬하여 키: 값 텍스트를 생성하고 요약 생성과 문서 수준 모델 컨텍스트에 사용합니다. 이 필드는 마이그레이션 000078에서 도입되었습니다.

수집 채널 상수: web, api, browser_extension, wechat, wecom, feishu, dingtalk, slack, im, notion, yuque, rss.

파싱 상태 머신:

요약의 독립 상태: summary_status ∈ {none, pending, processing, completed, failed}.

지식 라우트

메서드경로설명접근 제어
POST/knowledge-bases/:id/knowledge/file파일 업로드OwnedKBOrAdmin + KBAccessWrite
POST/knowledge-bases/:id/knowledge/urlURL 가져오기위와 동일
POST/knowledge-bases/:id/knowledge/manual수동 Markdown 지식위와 동일
GET/knowledge-bases/:id/knowledge목록(페이지네이션 + 필터)Viewer+ + KBAccessRead
DELETE/knowledge-bases/:id/knowledgeKB 콘텐츠 비우기Admin + KBAccessWrite
GET/knowledge/:id, /knowledge/batch상세 / 일괄 조회Viewer+
GET/knowledge/:id/stages, /knowledge/:id/spans처리 단계 / 스팬Viewer+
PUT / DELETE/knowledge/:id, /knowledge/manual/:id업데이트(custom_metadata 포함)/ 삭제OwnedKnowledgeKBOrAdmin + KBAccessWrite
POST/knowledge/:id/reparse, /knowledge/:id/cancel-parse재파싱 / 파싱 취소위와 동일
POST/knowledge/:id/regenerate-summary문서 요약 재생성위와 동일
GET/knowledge/:id/download원본 파일 다운로드Contributor+ + KBAccessWrite
GET/knowledge/:id/preview파일 미리 보기Viewer+ + KBAccessRead
PUT/knowledge/tags태그 일괄 업데이트Contributor+ / ingest
POST/knowledge/batch-reparse, /knowledge/batch-delete일괄 재파싱 / 삭제Contributor+ / ingest
POST/knowledge/move지식 이동Contributor+ / ingest
GET/knowledge/move/progress/:task_id이동 진행 상황Viewer+

목록 필터 매개변수

internal/types/knowledge.goKnowledgeListFilter + internal/handler/knowledge.go:

매개변수설명
page / page_size페이지네이션(기본 정렬 updated_at DESC
keyword파일 이름 / 제목 검색
file_type파일 유형 필터(pdf / manual / url …)
parse_status파싱 상태 필터
source수집 채널 필터(api / web / feishu …)
tag_id태그 필터, 여러 개는 쉼표로 구분(OR 의미
updated_from / updated_to업데이트 시간 범위(RFC3339)
folder_path폴더별 필터. 이 매개변수의 전달 여부가 목록 모드를 결정: 생략하면 전체 베이스의 평면 보기, 빈 문자열이면 지식 베이스 루트 디렉터리(하위 디렉터리 제외)
folder_recursivefolder_path와 함께 사용하며, true이면 하위 디렉터리의 문서도 반환

폴더 트리

폴더는 프로젝트, 출처 또는 디렉터리 계층별로 문서를 정리하는 데 사용합니다. 업로드 시 디렉터리 구조 유지와 수집 후 이름 변경 및 이동을 지원합니다.

폴더 작업:

  • 디렉터리 전체 업로드: 디렉터리 구조를 그대로 유지하므로 나중에 폴더를 수동으로 만들 필요가 없습니다;
  • 폴더 생성 / 이름 변경 / 이동: 문서 목록 왼쪽의 폴더 트리에서 실행합니다. 이름 변경 시 하위 디렉터리 경로도 함께 바뀝니다. 대상 경로가 이미 있으면 두 폴더를 병합합니다. 폴더를 자신의 하위 디렉터리로 이동할 수는 없습니다;
  • 문서 재분류: 문서를 선택한 뒤 지정 폴더로 이동합니다(루트 디렉터리로 돌아갈 수도 있음). 분류만 바뀌며 다시 파싱하지 않고 인덱스에도 영향을 주지 않습니다;
  • 디렉터리별 탐색: 목록 API의 folder_path가 보기 모드를 결정합니다. 생략하면 전체 베이스의 평면 목록, 빈 문자열이면 루트 디렉터리(하위 디렉터리 제외), folder_recursive=true를 함께 사용하면 하위 디렉터리도 나열합니다.

폴더와 태그는 서로 다른 문제를 해결하며 함께 사용할 수 있습니다. 폴더는 단일 소속입니다(문서는 한 디렉터리에만 존재하며 프로젝트/출처별 보관에 적합). 태그는 다대다 관계입니다(문서당 여러 태그가 가능하며 주제, 보안 등급, 상태별 교차 필터링에 적합). 검색 시 둘 다 범위 제한 조건으로 사용할 수 있습니다.

디렉터리 경로는 knowledges.folder_path에 저장하고 file_name에는 파일 이름만 저장합니다. 마이그레이션 000079에서 기존 파일 이름으로부터 디렉터리 경로를 소급 채웠습니다.

폴더 API는 GET/PUT /knowledge-bases/:id/knowledge/foldersPOST /knowledge/folder입니다. 자세한 내용은 지식 베이스 API를 참고하세요.

태그(KnowledgeTag)

internal/types/tag.go + internal/handler/tag.go:

go
type KnowledgeTag struct {
    ID              string // UUID
    SeqID           int64  // 자동 증가 정수 ID(API에서 사용)
    TenantID        uint64
    KnowledgeBaseID string
    Name            string // KB 내 고유
    Color           string
    SortOrder       int
}
type KnowledgeTagRelation struct { KnowledgeID, TagID string } // 다대다

문서 하나에 여러 태그를 지정할 수 있습니다. 초기에는 단일 태그(knowledges.tag_id 열 하나)였으나 migration 000063에서 연결 테이블 knowledge_tag_relations로 전환했습니다. 테이블 생성 시 기존 단일 태그 데이터를 이전한 뒤 knowledges.tag_id 열을 삭제했습니다. 따라서 현재 동작은 다음과 같습니다.

  • 읽기: Knowledge.Tags는 조회 시 knowledge_id 기준으로 일괄 JOIN하여 가져옵니다(gorm:"-", knowledges 테이블에는 저장하지 않음);
  • 쓰기: 전체 교체 방식입니다. PUT /knowledge/tags{knowledge_id: [tag_ids]}를 전달하면 먼저 해당 문서의 모든 연결을 삭제하고 새 집합을 기록합니다;
  • 필터: tag_idsOR 의미입니다(어느 태그든 일치하면 반환). SQL은 knowledges.id IN (SELECT knowledge_id FROM knowledge_tag_relations WHERE tag_id IN (...))를 사용합니다;
  • FAQ 항목은 별도 체계입니다. 항목 자체가 chunk이며 태그는 chunks.tag_id에 저장합니다(단일 태그). 문서의 다중 태그 연결 테이블과는 다른 경로입니다.

태그 자체의 관리 라우트: GET /knowledge-bases/:id/tags(Viewer+), POST(OwnedKBOrAdmin), PUT/DELETE /knowledge-bases/:id/tags/:tag_id(OwnedKBOrAdmin). tag_id 경로 매개변수는 UUID와 정수 seq_id를 모두 허용합니다.

프런트엔드의 두 진입점:

  • 일괄 태그 지정: 문서 목록에서 여러 문서를 선택한 뒤 일괄 작업 표시줄의 「태그」 버튼으로 BatchTagDialog.vue를 엽니다. 대화상자는 선택한 문서들의 공통 태그를 미리 선택하며, 검색과 태그 관리로 바로 이동을 지원합니다. 제출 후 목록을 새로고침합니다;
  • 업로드 시 태그 설정: 업로드 확인 대화상자(UploadConfirmDialog.vue)에서 파일 수집 전에 태그와 파싱 옵션을 직접 지정할 수 있어 업로드 후 다시 수정할 필요가 없습니다.

청크 편집과 버전 기록

문서 상세에서 청크 본문을 편집하여 OCR, 표 또는 수식의 파싱 오류를 수정할 수 있습니다. 저장 후 인덱스를 재생성하며 조회와 롤백을 위해 이전 버전을 보존합니다.

구현(internal/application/service/chunk.go, migration 000078):

데이터 모델:

필드 / 테이블용도
chunks.source_content파서 원본 출력, 불변. 기존 행은 최초 수동 편집 시 content에서 지연 방식으로 채움
chunks.content현재 적용되는 콘텐츠(검색과 인용 표시 모두 사용)
chunks.content_revision편집 또는 롤백마다 +1, 낙관적 잠금에 사용
chunks.index_statusready / processing / failed, 현재 콘텐츠가 검색 스토리지에 반영되었는지 표시
chunks.last_editor_id현재 버전을 만든 작업자
chunk_revisions 테이블덮어쓴 이전 버전 스냅샷(콘텐츠, 활성화 상태, 편집자, 출처, 시간)

동작 핵심 사항:

  • text 유형 청크만 편집할 수 있습니다. 공백 제거 후 콘텐츠가 비어 있으면 안 되며 상한은 200000바이트입니다;
  • 낙관적 동시성: 요청에 expected_revision을 포함할 수 있습니다. 현재 버전과 다르면 409를 반환하며 프런트엔드는 새로고침 후 재시도를 안내합니다;
  • 이미지 추가 불가: 원본 콘텐츠에 없던 이미지 URL이 편집 콘텐츠에 있으면 거부합니다. 특정 이미지의 Markdown 참조를 삭제하면 해당 OCR / caption 하위 청크는 영구 삭제하지 않고 비활성화합니다. 따라서 이전 버전으로 롤백하면 다시 활성화할 수 있습니다;
  • 부모·자식 청크 일관성: 자식 청크 편집 후 오프셋에 따라 변경 사항을 부모 청크에 반영합니다(부모의 source_content는 불변으로 유지. 교체는 역순으로 적용하여 길이가 바뀌어도 좌표 체계가 어긋나지 않음);
  • 인덱스 실패 처리: 인덱스 재생성에 실패해도 행은 정상 저장하지만 index_status = failed로 설정하고 UI에서 이를 안내합니다. 같은 콘텐츠를 다시 제출하면 재시도합니다;
  • 생성된 질문 유지: 콘텐츠를 편집해도 기존 검색 질문은 유지하며 「현재 본문 버전과 일치하지 않음」으로 표시만 합니다. 개별 수정(PUT /chunks/by-id/:id/questions)또는 전체 재생성(POST /chunks/by-id/:id/questions/regenerate)이 가능합니다;
  • 요약 연동: 콘텐츠 또는 활성화 상태가 바뀌면 문서 요약 갱신을 큐에 등록하고 summary_statuspending으로 변경합니다. POST /knowledge/:id/regenerate-summary로 수동 트리거할 수도 있습니다.

롤백(POST /chunks/:knowledge_id/:id/revert)자체도 새로운 편집입니다. 대상 이전 버전의 콘텐츠를 현재 콘텐츠로 기록하고 버전 번호는 계속 증가하며, 원래 콘텐츠는 기록 목록에 들어갑니다. 따라서 「롤백의 롤백」도 가능합니다.

API 목록은 API 참고: 청크와 태그를 확인하세요.

요약 수동 편집과 청크 탐색

문서 콘텐츠 미리 보기에서 요약을 편집하고 저장하여 자동 요약을 수정할 수 있습니다. PUT /knowledge/:id에서 description을 생략하면 기존 요약을 유지하고, 명시적인 빈 문자열이면 지웁니다. 요약 업데이트는 원본 문서 콘텐츠 수정과 같지 않습니다. 다시 생성하려면 「요약 다시 생성」을 사용합니다. 콘텐츠/메타데이터 변경으로도 요약 갱신이 트리거될 수 있습니다.

문서 청크는 페이지 단위로 로드하며 문서 전환과 검색 결과 이동 시 페이지 상태를 갱신합니다. 전체 필드는 지식 API청크 API를 참고하세요.

다운로드와 미리 보기 보안

GET /knowledge/:id/preview의 보안 메커니즘은 internal/handler/knowledge_preview_security_test.go로 검증하여 보장합니다.

제어구현목적
Content-Type: application/octet-stream 강제응답 헤더 고정브라우저가 HTML/SVG를 페이지로 실행하지 못하게 함(저장형 XSS 방지)
X-Content-Type-Options: nosniff응답 헤더MIME 스니핑 우회 방지
Content-Disposition: attachment; filename=...응답 헤더인라인 렌더링 대신 다운로드 강제
경로 검증ValidateKBScopedStoragePath()파일 경로가 해당 KB의 허가된 스토리지 범위 내에 있어야 함(경로 순회 / 무단 읽기 방지)
크기 제한GetFile 응답 본문 제한초대형 파일로 인한 미리 보기 장애 방지

테스트는 파일 콘텐츠가 <script>alert(1)</script>여도 바이너리 첨부 파일로만 전송됨을 명시적으로 검증합니다. 다운로드 엔드포인트(/knowledge/:id/download)는 더 높은 Contributor+ 권한이 필요하며 KBAccessWrite 접근 제어를 거칩니다.

지식 베이스 복사와 지식 이동

복사(Copy / Duplicate)와 Preflight

internal/application/service/knowledge_clone_move.go. preflight 규칙은 internal/handler/knowledgebase_copy_preflight_test.go로 보장합니다.

  • POST /knowledge-bases/copy: 전체 베이스 복사(설정 + 콘텐츠). body에 source_id를 전달합니다. 비동기 작업이며 진행 상황은 GET /knowledge-bases/copy/progress/:task_id로 조회합니다(활동 스트림에 kb.clone_started / kb.clone_completed / kb.clone_failed 기록).
  • POST /knowledge-bases/:id/duplicate: 설정만 복사합니다(콘텐츠 / 인덱스 / 공유 기록 제외). 활동 스트림에 kb.duplicated를 기록합니다.

Preflight(복사 전 검증, 즉시 동기적으로 거부):

  1. 원본 / 대상 KB의 테넌트 격리(테넌트 간 요청 거부);
  2. 원본 KB 존재 여부;
  3. VectorStore 호환성: reuse_vectors 모드는 서로 다른 벡터 저장소에 있는 KB를 지원하지 않습니다(벡터를 직접 옮길 수 없음);
  4. StorageBackend 호환성: 서로 다른 스토리지 백엔드 간 복사는 지원하지 않습니다;
  5. API Key로 호출할 때는 원본 / 대상 KB가 모두 allow-list에 있어야 합니다.

지식 이동 접근 제어(move gate)

POST /knowledge/move는 두 모드를 지원하며 제약 조건을 handler와 service 두 계층에서 검증합니다(internal/handler/knowledge_move_gate_test.gointernal/application/service/knowledge_move_gate_test.go에서 이중 확인).

  • reuse_vectors 모드: 기존 벡터를 직접 재사용하며 원본 KB와 대상 KB가 같은 VectorStore에 연결되어야 합니다;
  • reparse 모드: 대상 베이스에서 다시 파싱하여 벡터를 생성하므로 벡터 저장소 간 이동을 허용합니다.

같은 저장소인지 판정하는 SharesStoreWith()의 정규화 의미(빈 문자열은 nil로 정규화하며 nil은 환경 기본 store를 의미):

text
nil & nil               → true   (둘 다 env-store)
"" & nil                → true   (빈 문자열을 nil로 정규화)
"store-a" & "store-a"   → true
"store-a" & "store-b"   → false
"store-a" & nil         → false  (명시적 연결과 env-store는 같은 저장소로 보지 않음)

GET /knowledge-bases/:id/move-targets는 접근 제어 조건을 충족하는 대상 베이스 후보를 반환합니다. 이동은 비동기 작업이며 진행 상황은 GET /knowledge/move/progress/:task_id로 조회합니다.

스토리지 할당량과 사용량

할당량은 테넌트에 속합니다(internal/types/tenant.go).

필드기본값설명
storage_quota10737418240(10GB)테넌트 전체 할당량
storage_used0사용량(원본 파일, 텍스트, 벡터와 인덱스 점유량 포함)

KB 생성과 지식 업로드 전에 모두 할당량을 확인하며(internal/handler/knowledgebase.go 생성 검증 흐름), 초과하면 쓰기를 거부합니다. 각 지식은 자신의 file_sizestorage_size를 기록하고 삭제 시 사용량을 회수합니다.

KB 라우트와 권한

(접근 제어 의미는 「테넌트, 사용자와 인증·인가」 문서를 참고하세요. KBAccessRead/Write는 조직 공유 경로를 해석합니다.)

메서드경로Handler접근 제어
POST/knowledge-basesCreateKnowledgeBaseContributor+ / API Key manage_kbs
GET/knowledge-basesListKnowledgeBasesViewer+ / retrieve
GET/knowledge-bases/:idGetKnowledgeBaseViewer+ + KBAccessRead
PUT/knowledge-bases/:idUpdateKnowledgeBaseOwnedKBOrAdmin + KBAccessWrite
DELETE/knowledge-bases/:idDeleteKnowledgeBaseOwnedKBOrAdmin + KBAccessWrite
PUT/knowledge-bases/:id/pinTogglePinKnowledgeBaseViewer+ + KBAccessRead
POST/GET/knowledge-bases/:id/hybrid-searchHybridSearchViewer+ + KBAccessRead
POST/knowledge-bases/copyCopyKnowledgeBaseContributor+ / manage_kbs
POST/knowledge-bases/:id/duplicateDuplicateKnowledgeBaseContributor+ / manage_kbs + KBAccessRead
GET/knowledge-bases/copy/progress/:task_idGetKBCloneProgressViewer+ / retrieve 또는 manage_kbs
GET/knowledge-bases/:id/move-targetsListMoveTargetsViewer+ + KBAccessRead
GET/knowledge-bases/:id/activityListKnowledgeBaseActivityOwnedKBOrAdmin + KBAccessRead(JWT 전용)

생성 흐름internal/handler/knowledgebase.go): Contributor 검증 → 테넌트 스토리지 할당량 확인 → EmbeddingModelID 검증 → VectorStoreID 연결 검증 → 생성 → KB + vector_store_display 반환.

연쇄 삭제: KB 아래의 모든 Knowledge → Chunk → 벡터 인덱스 → 키워드 인덱스 → Wiki 페이지 → 태그 → 저장 파일 삭제 → KB 자체 소프트 삭제. 공유 측 editor는 원본 KB를 삭제할 수 없습니다(삭제에는 owner 테넌트와 Admin 측 권한 필요).

POST /knowledge-bases/:id/hybrid-searchinternal/handler/knowledgebase.go + internal/application/service/knowledgebase_search*.go)는 KB의 IndexingStrategy에 따라 후보 검색을 조합합니다. 벡터(vector_enabled)+ 키워드 BM25(keyword_enabled)를 rank fusion으로 융합하고 리랭킹(rerank)하며, 지식 그래프 보강(graph_enabled)을 추가할 수 있습니다. 다중 KB에서는 knowledgebase_search_fanout.go가 동시 분산 실행하고 knowledgebase_search_fusion.go가 융합합니다. 공유 KB 검색 경로는 knowledgebase_search_shared.go를 참고하세요. FAQ 베이스 검색에는 별도의 매칭 전략(부정 예시 필터링 / 반복 후보 검색)이 있습니다. FAQ 문서를 참고하세요.

지식 처리 파이프라인

internal/application/service/knowledge_create.go / knowledge_process.go / knowledge_process_config.go:

text
업로드 (file/url/manual)
  → Knowledge 생성 (parse_status=pending) → Asynq 큐 등록
  → Worker: DocReader 파싱 → 청크 분할 (ChunkingConfig)
      → 벡터 임베딩      (indexing_strategy.vector_enabled)
      → 키워드 인덱스     (keyword_enabled)
      → 그래프 추출      (graph_enabled + ExtractConfig)
      → Wiki 생성       (wiki_enabled + WikiConfig)
      → 질문 생성        (QuestionGenerationConfig.enabled)
  → parse_status=finalizing, pending_subtasks_count=N
  → 보강 하위 작업마다 완료 후 원자적으로 감소; 0 도달 → parse_status=completed

설정 병합 우선순위EffectiveProcessConfig): Knowledge.ProcessOverrides(단일 업로드 재정의. 지식 metadata의 KnowledgeProcessOverrides에 저장하며 parser 규칙 / 청크 / VLM / ASR / 질문 생성 / 그래프 스위치 등을 재정의 가능)> KB 설정 > 테넌트 기본값.

Chunk 유형(internal/types/chunk.go): text, parent_text, image_ocr, image_caption, summary, entity, relationship, faq, web_search, table_summary, table_column, wiki_page. chunk는 is_enabled 스위치와 flags 비트 플래그(bit0 = 추천 가능)를 지원합니다.

지식 베이스 활동 스트림(KB Activity)

지식 베이스 설정의 「활동」 탭은 설정 변경, 문서 업로드와 삭제, 청크 편집, 공유 변경과 Wiki 업데이트를 기록하며 작업자, 시간과 결과를 포함합니다.

internal/application/service/kb_activity.go는 감사 로그 체계(AuditLog, scope는 knowledge_base)를 재사용하며 recordKBActivity(ctx, audit, tenantID, kbID, action, targetType, targetID, outcome, details)로 기록합니다.

  • 활동 동작internal/types/audit_log.go): kb.created / kb.updated / kb.deleted / kb.duplicated / kb.clone_started / kb.clone_completed / kb.clone_failed, kb.share_added / kb.share_permission_changed / kb.share_removed와 지식 / chunk 수준의 추가·삭제·수정 동작;
  • 트리거 출처: context의 kbActivityTaskMetadata{TaskID, Trigger}user 사용자 작업 / system 백그라운드 작업)를 details에 자동 병합합니다. outcome에 따라 processing_status를 자동 보완합니다(accepted→pending, success→completed, partial→partial, failed/denied→failed, canceled→canceled);
  • 일괄 작업의 표본 제목: kbActivityAppendSampleTitles는 일괄 작업에 중복 제거된 제목을 최대 5개 포함합니다(첫 번째는 title, 나머지는 titles 배열). 활동 스트림의 가독성을 유지하고 크기를 제한합니다;
  • 억제 메커니즘: withKBActivitySuppressed(ctx)를 사용하면 내부 연쇄 작업에서 중복 활동 기록을 생성하지 않습니다.

조회 엔드포인트: GET /knowledge-bases/:id/activity(OwnedKBOrAdmin, JWT 사용자 전용, API Key 접근 불가).

구현 참고

아래 경로는 모두 저장소 루트 디렉터리 기준입니다.

계층파일
KB 모델과 설정 구조internal/types/knowledgebase.go, indexing_strategy.go
지식 / Chunk / 태그 모델internal/types/knowledge.go, chunk.go, tag.go
처리 설정 재정의internal/types/knowledge_process.go
KB Handlerinternal/handler/knowledgebase.go
지식 Handlerinternal/handler/knowledge.go
태그 Handlerinternal/handler/tag.go
KB 서비스internal/application/service/knowledgebase.go
지식 생성 / 처리 파이프라인internal/application/service/knowledge_create.go, knowledge_process.go, knowledge_process_config.go
복사와 이동internal/application/service/knowledge_clone_move.go
활동 스트림internal/application/service/kb_activity.go
라우트와 접근 제어internal/router/router.go, internal/router/rbac.go
주요 검증 테스트internal/handler/knowledge_preview_security_test.go, knowledge_move_gate_test.go, knowledgebase_copy_preflight_test.go

WeKnora v0.8.0 소스 코드 기반 한국어 번역 · MIT License