Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 119 additions & 10 deletions include/kiwi/CoNgramModel.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
/**
* @file CoNgramModel.h
* @author bab2min (bab2min@gmail.com)
* @brief 문맥 기반 N-gram 언어 모델 (Contextual N-gram Model) 구현
* @version 0.22.1
* @date 2025-11-21
*
* 단어 임베딩과 문맥 정보를 활용한 신경망 기반 언어 모델입니다.
* 전통적인 N-gram 모델보다 더 풍부한 의미 정보를 포착할 수 있습니다.
*/

#pragma once

#include <array>
Expand All @@ -15,25 +26,49 @@ namespace kiwi
{
namespace lm
{
/**
* @brief 문맥 N-gram 모델의 헤더 정보
*/
struct CoNgramModelHeader
{
uint64_t vocabSize, contextSize;
uint16_t dim;
uint8_t contextType, outputType;
uint8_t keySize, windowSize, qbit, qgroup;
uint64_t numNodes;
uint64_t nodeOffset, keyOffset, valueOffset, embOffset;
uint64_t vocabSize; /**< 어휘 크기 */
uint64_t contextSize; /**< 문맥 크기 */
uint16_t dim; /**< 임베딩 차원 */
uint8_t contextType; /**< 문맥 타입 */
uint8_t outputType; /**< 출력 타입 */
uint8_t keySize; /**< 키 크기 */
uint8_t windowSize; /**< 윈도우 크기 */
uint8_t qbit; /**< 양자화 비트 수 */
uint8_t qgroup; /**< 양자화 그룹 크기 */
uint64_t numNodes; /**< 노드 개수 */
uint64_t nodeOffset; /**< 노드 데이터 오프셋 */
uint64_t keyOffset; /**< 키 데이터 오프셋 */
uint64_t valueOffset; /**< 값 데이터 오프셋 */
uint64_t embOffset; /**< 임베딩 데이터 오프셋 */
};

/**
* @brief 문맥 N-gram 모델의 노드 구조
*
* @tparam KeyType 키 타입
* @tparam ValueType 값 타입
* @tparam DiffType diff 타입
*/
template<class KeyType, class ValueType, class DiffType = int32_t>
struct Node
{
KeyType numNexts = 0;
ValueType value = 0;
DiffType lower = 0;
uint32_t nextOffset = 0;
KeyType numNexts = 0; /**< 다음 노드의 개수 */
ValueType value = 0; /**< 노드 값 */
DiffType lower = 0; /**< 하위 노드로의 오프셋 */
uint32_t nextOffset = 0; /**< 다음 노드들의 시작 오프셋 */
};

/**
* @brief 문맥 기반 N-gram 언어 모델의 기본 클래스
*
* 신경망 임베딩을 활용하여 문맥 정보를 효과적으로 활용하는 언어 모델입니다.
* 단어의 의미적 유사도와 문맥 유사도를 계산할 수 있습니다.
*/
class CoNgramModelBase : public ILangModel
{
protected:
Expand All @@ -49,20 +84,84 @@ namespace kiwi
size_t vocabSize() const override { return header.vocabSize; }
size_t getMemorySize() const override { return memorySize; }

/**
* @brief 모델 헤더 정보를 반환합니다.
* @return CoNgramModelHeader에 대한 const 참조
*/
const CoNgramModelHeader& getHeader() const { return header; }

/**
* @brief 주어진 단어와 가장 유사한 단어들을 찾습니다.
* @param vocabId 단어 ID
* @param topN 상위 N개
* @param output 결과를 저장할 배열 (단어 ID, 유사도)
* @return 찾은 단어의 개수
*/
virtual size_t mostSimilarWords(uint32_t vocabId, size_t topN, std::pair<uint32_t, float>* output) const = 0;

/**
* @brief 두 단어 간의 유사도를 계산합니다.
* @param vocabId1 첫 번째 단어 ID
* @param vocabId2 두 번째 단어 ID
* @return 유사도 점수
*/
virtual float wordSimilarity(uint32_t vocabId1, uint32_t vocabId2) const = 0;

/**
* @brief 주어진 문맥과 가장 유사한 문맥들을 찾습니다.
* @param contextId 문맥 ID
* @param topN 상위 N개
* @param output 결과를 저장할 배열
* @return 찾은 문맥의 개수
*/
virtual size_t mostSimilarContexts(uint32_t contextId, size_t topN, std::pair<uint32_t, float>* output) const = 0;

/**
* @brief 두 문맥 간의 유사도를 계산합니다.
* @param contextId1 첫 번째 문맥 ID
* @param contextId2 두 번째 문맥 ID
* @return 유사도 점수
*/
virtual float contextSimilarity(uint32_t contextId1, uint32_t contextId2) const = 0;

/**
* @brief 주어진 문맥에서 예측되는 단어들을 반환합니다.
* @param contextId 문맥 ID
* @param topN 상위 N개
* @param output 결과를 저장할 배열
* @return 예측된 단어의 개수
*/
virtual size_t predictWordsFromContext(uint32_t contextId, size_t topN, std::pair<uint32_t, float>* output) const = 0;

/**
* @brief 문맥 차이를 고려하여 단어를 예측합니다.
* @param contextId 문맥 ID
* @param bgContextId 배경 문맥 ID
* @param weight 가중치
* @param topN 상위 N개
* @param output 결과를 저장할 배열
* @return 예측된 단어의 개수
*/
virtual size_t predictWordsFromContextDiff(uint32_t contextId, uint32_t bgContextId, float weight, size_t topN, std::pair<uint32_t, float>* output) const = 0;

/**
* @brief 단어 ID 시퀀스를 문맥 ID로 변환합니다.
* @param vocabIds 단어 ID 배열
* @param size 배열 크기
* @return 문맥 ID
*/
virtual uint32_t toContextId(const uint32_t* vocabIds, size_t size) const = 0;

/**
* @brief 문맥과 단어의 매핑을 반환합니다.
* @return 문맥-단어 매핑 벡터
*/
virtual std::vector<std::vector<uint32_t>> getContextWordMap() const = 0;

/**
* @brief 캐시된 문맥-단어 매핑을 반환합니다.
* @return 캐시된 문맥-단어 매핑에 대한 const 참조
*/
const std::vector<std::vector<uint32_t>>& getContextWordMapCached() const
{
if (contextWordMapCache.empty())
Expand All @@ -72,6 +171,16 @@ namespace kiwi
return contextWordMapCache;
}

/**
* @brief 문맥 정의와 임베딩으로부터 모델을 빌드합니다.
* @param contextDefinition 문맥 정의 파일 경로
* @param embedding 임베딩 파일 경로
* @param maxContextLength 최대 문맥 길이
* @param useVLE VLE(Variable Length Encoding) 사용 여부
* @param reorderContextIdx 문맥 인덱스 재정렬 여부
* @param selectedEmbIdx 선택된 임베딩 인덱스
* @return 빌드된 모델의 메모리 객체
*/
static utils::MemoryObject build(const std::string& contextDefinition, const std::string& embedding,
size_t maxContextLength = -1,
bool useVLE = true,
Expand Down
65 changes: 60 additions & 5 deletions include/kiwi/FrozenTrie.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
#pragma once
/**
* @file FrozenTrie.h
* @author bab2min (bab2min@gmail.com)
* @brief 메모리 효율적인 불변(immutable) Trie 자료구조 정의
* @version 0.22.1
* @date 2025-11-21
*
* 읽기 전용 Trie 자료구조로, 빠른 문자열 검색과 패턴 매칭을 지원합니다.
* Aho-Corasick 알고리즘을 위한 실패 링크(fail link)를 포함합니다.
* 형태소 사전 검색 등에 사용됩니다.
*/

#pragma once

#include <array>
#include <vector>
Expand All @@ -15,6 +27,10 @@ namespace kiwi
{
namespace detail
{
/**
* @brief 값이 부분 매칭을 가지는지 확인하는 헬퍼 구조체
* @tparam Value 값 타입
*/
template<class Value, class = void>
struct HasSubmatch {};

Expand Down Expand Up @@ -66,6 +82,18 @@ namespace kiwi
};
}

/**
* @brief 메모리 효율적인 불변(frozen) Trie 자료구조
*
* 빌드 후 수정할 수 없는 Trie로, 메모리 사용량이 최적화되어 있습니다.
* Aho-Corasick 알고리즘을 위한 실패 함수(fail function)를 포함하여
* 다중 패턴 매칭을 효율적으로 수행할 수 있습니다.
*
* @tparam _Key 키(문자) 타입
* @tparam _Value 값 타입
* @tparam _Diff diff 값의 타입
* @tparam _HasSubmatch 부분 매칭 검사 헬퍼
*/
template<class _Key, class _Value, class _Diff = int32_t, class _HasSubmatch = detail::HasSubmatch<_Value>>
class FrozenTrie : public _HasSubmatch
{
Expand All @@ -74,19 +102,46 @@ namespace kiwi
using Value = _Value;
using Diff = _Diff;

/**
* @brief Trie의 노드 구조체
*/
struct Node
{
Key numNexts = 0;
Diff lower = 0;
uint32_t nextOffset = 0;

Key numNexts = 0; /**< 자식 노드의 개수 */
Diff lower = 0; /**< 하위 노드로의 오프셋 */
uint32_t nextOffset = 0; /**< 다음 노드들의 시작 오프셋 */

/**
* @brief 다음 문자에 해당하는 노드를 찾습니다.
* @tparam arch 아키텍처 타입 (최적화를 위한)
* @param ft FrozenTrie 참조
* @param c 다음 문자
* @return 찾은 노드 포인터, 없으면 nullptr
*/
template<ArchType arch>
const Node* nextOpt(const FrozenTrie& ft, Key c) const;

/**
* @brief 실패 링크를 따라 다음 노드를 찾습니다.
* @tparam arch 아키텍처 타입
* @param ft FrozenTrie 참조
* @param c 다음 문자
* @return 찾은 노드 포인터
*/
template<ArchType arch>
const Node* findFail(const FrozenTrie& ft, Key c) const;

/**
* @brief 실패 링크를 반환합니다.
* @return 실패 노드 포인터
*/
const Node* fail() const;

/**
* @brief 노드의 값을 반환합니다.
* @param ft FrozenTrie 참조
* @return 노드의 값에 대한 const 참조
*/
const Value& val(const FrozenTrie& ft) const;
};
private:
Expand Down
Loading
Loading