cwenzi commited on
Commit
26d5b81
·
verified ·
1 Parent(s): b5e3175

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .clang-format +98 -0
  2. .clang-tidy +95 -0
  3. .gitattributes +3 -33
  4. CMakeLists.txt +255 -0
  5. README.md +113 -0
  6. README_CPP.md +80 -0
  7. README_MULTIMODAL.md +199 -0
  8. SKILL.md +161 -0
  9. bindings/python_bindings.cpp +406 -0
  10. build.sh +59 -0
  11. configs/config.json +47 -0
  12. configs/config_distill.json +23 -0
  13. configs/config_distill_128k.json +29 -0
  14. configs/generation_config.json +22 -0
  15. configs/huggingface/merges.txt +8 -0
  16. configs/huggingface/vocab.json +4999 -0
  17. configs/special_tokens_map.json +16 -0
  18. configs/tokenizer_128k.json +0 -0
  19. configs/tokenizer_cn_013.json +0 -0
  20. include/neuroflow/adamw.hpp +46 -0
  21. include/neuroflow/alignment_common.hpp +320 -0
  22. include/neuroflow/backprop.hpp +609 -0
  23. include/neuroflow/causal_lm.hpp +253 -0
  24. include/neuroflow/cuda_context.hpp +171 -0
  25. include/neuroflow/cuda_kernels.hpp +1152 -0
  26. include/neuroflow/dpo.hpp +91 -0
  27. include/neuroflow/generative.hpp +19 -0
  28. include/neuroflow/generative_model.hpp +44 -0
  29. include/neuroflow/grad_scaler.hpp +36 -0
  30. include/neuroflow/memory.hpp +555 -0
  31. include/neuroflow/model.hpp +680 -0
  32. include/neuroflow/multimodal.hpp +441 -0
  33. include/neuroflow/multimodal_model.hpp +702 -0
  34. include/neuroflow/networks.hpp +466 -0
  35. include/neuroflow/online_learning.hpp +477 -0
  36. include/neuroflow/rms_norm.hpp +50 -0
  37. include/neuroflow/rope.hpp +40 -0
  38. include/neuroflow/sampling.hpp +73 -0
  39. include/neuroflow/scheduler.hpp +26 -0
  40. include/neuroflow/sft.hpp +85 -0
  41. include/neuroflow/swiglu.hpp +55 -0
  42. include/neuroflow/tensor.hpp +327 -0
  43. include/neuroflow/tensor_ops.hpp +92 -0
  44. include/neuroflow/tokenizer.hpp +81 -0
  45. include/neuroflow/train_lm.hpp +68 -0
  46. output/checkpoint_step1000/model.nfv1 +3 -0
  47. output/checkpoint_step2000/model.nfv1 +3 -0
  48. output/lm_head_lmh1.nfv1 +3 -0
  49. scripts/check_json_format.py +23 -0
  50. scripts/config_generator.py +192 -0
.clang-format ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NeuroFlow C++ 代码风格配置
2
+ # 基于 Google C++ Style Guide (C++20)
3
+ #
4
+ # 用法:
5
+ # clang-format -i <file.cpp> # 就地格式化
6
+ # clang-format --dry-run <file.cpp> # 检查而不修改
7
+ # find src/ include/ -name '*.cpp' -o -name '*.hpp' | xargs clang-format -i
8
+
9
+ ---
10
+ BasedOnStyle: Google
11
+
12
+ Language: Cpp
13
+ Standard: c++20
14
+
15
+ # ──── 缩进与空格 ────
16
+ IndentWidth: 4
17
+ UseTab: Never
18
+ TabWidth: 4
19
+ ContinuationIndentWidth: 4
20
+ AccessModifierOffset: -4 # public:/private: 左移1个缩进
21
+
22
+ # ──── 行宽与换行 ────
23
+ ColumnLimit: 100 # Google推荐80,NeuroFlow用100(模板/长类型名)
24
+ BreakBeforeBraces: Attach
25
+ AllowShortFunctionsOnASingleLine: Inline
26
+ AllowShortIfStatementsOnASingleLine: false
27
+ AllowShortLoopsOnASingleLine: false
28
+
29
+ # ──── 空行 ────
30
+ MaxEmptyLinesToKeep: 1
31
+ SeparateDefinitionBlocks: Always
32
+
33
+ # ──── Include 排序 ────
34
+ # Google 要求的5层分组:
35
+ # 1. 关联头文件 (.hpp)
36
+ # 2. C 系统头
37
+ # 3. C++ 标准库头
38
+ # 4. 第三方库头
39
+ # 5. 项目头
40
+ SortIncludes: true
41
+ IncludeBlocks: Regroup
42
+ IncludeCategories:
43
+ # 关联头文件 (对应 .cpp 的同名 .hpp)
44
+ - Regex: '^".*\.hpp"$'
45
+ Priority: 1
46
+ # C 系统头
47
+ - Regex: '^<.*\.h>$'
48
+ Priority: 2
49
+ # C++ 标准库
50
+ - Regex: '^<(algorithm|chrono|cmath|cstdint|cstdio|cstdlib|cstring|exception|filesystem|fstream|functional|iostream|memory|numeric|random|sstream|stdexcept|string|thread|unordered_map|utility|vector)>$'
51
+ Priority: 3
52
+ # POSIX / 平台头
53
+ - Regex: '^<(fcntl|sys/|unistd|windows|omp)'
54
+ Priority: 4
55
+ # CBLAS
56
+ - Regex: '^<cblas\.h>$'
57
+ Priority: 4
58
+ # 第三方库 / 项目内部
59
+ - Regex: '^"(neuroflow|weight_io)/'
60
+ Priority: 5
61
+ - Regex: '.*'
62
+ Priority: 6
63
+
64
+ # ──── 指针对齐 ────
65
+ DerivePointerAlignment: false
66
+ PointerAlignment: Left # int* p (类型对齐)
67
+
68
+ # ──── 空格 ────
69
+ SpaceAfterCStyleCast: true
70
+ SpaceBeforeAssignmentOperators: true
71
+ SpaceBeforeCpp11BracedList: false
72
+ SpacesInAngles: false # vector<int> 而非 vector< int >
73
+ SpacesInCStyleCastParentheses: false
74
+ SpacesInParentheses: false
75
+ SpacesInSquareBrackets: false
76
+
77
+ # ──── 大括号 ────
78
+ BreakBeforeBraces: Custom
79
+ BraceWrapping:
80
+ AfterClass: false
81
+ AfterControlStatement: Never
82
+ AfterEnum: false
83
+ AfterFunction: false
84
+ AfterNamespace: false
85
+ AfterStruct: false
86
+ AfterUnion: false
87
+ BeforeCatch: false
88
+ BeforeElse: false
89
+ IndentBraces: false
90
+ AfterExternBlock: false
91
+
92
+ # ──── 函数声明 ────
93
+ AlwaysBreakAfterReturnType: None
94
+ AlwaysBreakTemplateDeclarations: false
95
+
96
+ # ──── 其他 ────
97
+ ReflowComments: false # 不自动重排注释(含中文)
98
+ FixNamespaceComments: true # } // namespace neuroflow
.clang-tidy ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NeuroFlow C++ 静态分析检查配置
2
+ # 基于 Google C++ Style Guide — 只启用不与现有代码大面积冲突的规则
3
+ #
4
+ # 用法:
5
+ # clang-tidy <file.cpp> -- -Iinclude -std=c++20
6
+ # # 或通过 CMake:
7
+ # cmake -DCMAKE_CXX_CLANG_TIDY="clang-tidy" ..
8
+
9
+ ---
10
+ # ──── Google 核心规范检查 ────
11
+ Checks: >
12
+ -*,
13
+ # 命名规范(仅新代码警告,旧代码不阻塞)
14
+ google-readability-*,
15
+ google-runtime-*,
16
+ google-build-*,
17
+ google-explicit-constructor,
18
+ google-global-names-in-headers,
19
+
20
+ # C++ 现代写法检查
21
+ modernize-use-override,
22
+ modernize-use-nullptr,
23
+ modernize-use-using,
24
+ modernize-make-unique,
25
+ modernize-make-shared,
26
+ modernize-use-noexcept,
27
+ modernize-use-emplace,
28
+ modernize-loop-convert,
29
+ modernize-return-braced-init-list,
30
+ modernize-use-auto,
31
+ modernize-use-default-member-init,
32
+
33
+ # 性能检查
34
+ performance-unnecessary-value-param,
35
+ performance-move-const-arg,
36
+ performance-for-range-copy,
37
+ performance-unnecessary-copy-initialization,
38
+
39
+ # 可读性检查
40
+ readability-redundant-member-init,
41
+ readability-container-size-empty,
42
+ readability-simplify-boolean-expr,
43
+ readability-redundant-string-cstr,
44
+ readability-implicit-bool-conversion,
45
+ readability-make-member-function-const,
46
+ readability-avoid-const-params-in-decls,
47
+
48
+ # Bug 预防
49
+ bugprone-unused-raii,
50
+ bugprone-use-after-move,
51
+ bugprone-suspicious-include,
52
+ bugprone-misplaced-widening-cast,
53
+ bugprone-integer-division,
54
+ bugprone-suspicious-memset-usage,
55
+
56
+ # 杂项
57
+ misc-unused-parameters,
58
+ misc-unused-using-decls,
59
+ misc-include-cleaner,
60
+ misc-const-correctness
61
+
62
+ # ──── 故意不启用的检查(与现有代码冲突严重,将来逐步开启)────
63
+ # google-readability-casting → 需大量 static_cast 替换
64
+ # readability-identifier-naming → 等重命名完成后再开
65
+ # modernize-pass-by-value → 需逐文件评估
66
+ # cppcoreguidelines-pro-type-const-cast → 太严格
67
+ # clang-analyzer-* → 太慢,CI 阶段用
68
+
69
+ # ──── 配置项 ────
70
+ CheckOptions:
71
+ # modernize-use-auto: MinTypeNameLength=5(长类型名才建议 auto)
72
+ - key: modernize-use-auto.MinTypeNameLength
73
+ value: '5'
74
+
75
+ # modernize-use-auto: 移除星号时用 auto(而非 auto*)
76
+ - key: modernize-use-auto.RemoveStars
77
+ value: 'true'
78
+
79
+ # misc-include-cleaner: 忽略标准库头(编译器内置路径)
80
+ - key: misc-include-cleaner.IgnoreHeaders
81
+ value: '^<.*\.h>$;^<.*>$'
82
+
83
+ # readability-implicit-bool-conversion: 允许条件表达式中的隐式转换
84
+ - key: readability-implicit-bool-conversion.AllowIntegerConditions
85
+ value: 'true'
86
+ - key: readability-implicit-bool-conversion.AllowPointerConditions
87
+ value: 'true'
88
+
89
+ # performance-unnecessary-value-param: 允许的值类型上限
90
+ - key: performance-unnecessary-value-param.AllowedTypes
91
+ value: 'std::string;std::vector'
92
+
93
+ # ──── WarningsAsErrors ────
94
+ # 把它注释掉表示不阻塞编译,只在 CI 中打开
95
+ # WarningsAsErrors: '*'
.gitattributes CHANGED
@@ -1,35 +1,5 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
  *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
1
+ *.nfv1 filter=lfs diff=lfs merge=lfs -text
2
+ *.nfv2 filter=lfs diff=lfs merge=lfs -text
3
  *.bin filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  *.pt filter=lfs diff=lfs merge=lfs -text
5
+ scripts/test_generate filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
CMakeLists.txt ADDED
@@ -0,0 +1,255 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ cmake_minimum_required(VERSION 3.14)
2
+
3
+ option(NEUROFLOW_USE_CUDA "Enable CUDA/cuBLAS backend" OFF)
4
+
5
+ if(NEUROFLOW_USE_CUDA)
6
+ project(neuroflow_core VERSION 1.0.0 LANGUAGES CXX CUDA)
7
+ else()
8
+ project(neuroflow_core VERSION 1.0.0 LANGUAGES CXX)
9
+ endif()
10
+
11
+ set(CMAKE_CXX_STANDARD 17)
12
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
13
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
14
+
15
+ option(NEUROFLOW_BUILD_TESTS "Build unit tests" OFF)
16
+ option(NEUROFLOW_BUILD_PYTHON "Build Python bindings" OFF)
17
+ option(NEUROFLOW_USE_AVX2 "Enable AVX2 SIMD" ON)
18
+ option(NEUROFLOW_USE_BLAS "Use external BLAS (OpenBLAS/MKL) for GEMM" ON)
19
+ option(NEUROFLOW_USE_AMP "Enable mixed precision training (FP16/BF16)" OFF)
20
+
21
+ if(MSVC)
22
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W3 /GR /EHsc /utf-8")
23
+ if(NEUROFLOW_USE_AVX2)
24
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /arch:AVX2")
25
+ message(STATUS "AVX2 SIMD enabled (MSVC)")
26
+ endif()
27
+ set(CMAKE_CXX_FLAGS_RELEASE "/O2 /DNDEBUG /GL")
28
+ set(CMAKE_CXX_FLAGS_DEBUG "/Od /Zi /DDEBUG")
29
+ find_package(OpenMP)
30
+ else()
31
+ find_package(OpenMP REQUIRED)
32
+
33
+ if(NEUROFLOW_USE_AVX2)
34
+ include(CheckCXXCompilerFlag)
35
+ check_cxx_compiler_flag("-mavx2" COMPILER_SUPPORTS_AVX2)
36
+ if(COMPILER_SUPPORTS_AVX2)
37
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mavx2")
38
+ message(STATUS "AVX2 SIMD enabled")
39
+ else()
40
+ message(STATUS "AVX2 not supported by compiler")
41
+ endif()
42
+ endif()
43
+
44
+ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG -march=native -mtune=native -funroll-loops -ffast-math -ftree-vectorize")
45
+ set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -DDEBUG")
46
+ endif()
47
+
48
+
49
+ add_library(neuroflow_core STATIC
50
+ src/tensor.cpp
51
+ src/model.cpp
52
+ src/weight_io.cpp
53
+ src/tokenizer.cpp
54
+ src/sampling.cpp
55
+ src/causal_lm.cpp
56
+ src/tensor_ops.cpp
57
+ src/generative_model.cpp
58
+ src/rope.cpp
59
+ src/swiglu.cpp
60
+ src/rms_norm.cpp
61
+ src/adamw.cpp
62
+ src/scheduler.cpp
63
+ src/train_lm.cpp
64
+ src/grad_scaler.cpp
65
+ src/sft_train.cpp
66
+ src/dpo_train.cpp
67
+ )
68
+
69
+ if(NEUROFLOW_USE_CUDA)
70
+ find_package(CUDAToolkit REQUIRED)
71
+ if(CUDAToolkit_VERSION VERSION_LESS "11.0")
72
+ message(FATAL_ERROR "CUDA >= 11.0 required, found ${CUDAToolkit_VERSION}")
73
+ endif()
74
+ target_compile_definitions(neuroflow_core PUBLIC USE_CUDA)
75
+ target_include_directories(neuroflow_core PUBLIC ${CUDAToolkit_INCLUDE_DIRS})
76
+ target_link_libraries(neuroflow_core PUBLIC CUDA::cudart CUDA::cublas)
77
+ target_sources(neuroflow_core PRIVATE src/cuda_context.cpp)
78
+ set_source_files_properties(src/cuda_context.cpp PROPERTIES LANGUAGE CUDA)
79
+ target_compile_options(neuroflow_core PRIVATE
80
+ $<$<COMPILE_LANGUAGE:CUDA>:--generate-code=arch=compute_80,code=[sm_80,compute_80]>
81
+ $<$<COMPILE_LANGUAGE:CUDA>:--expt-relaxed-constexpr>
82
+ $<$<COMPILE_LANGUAGE:CUDA>:--extended-lambda>
83
+ )
84
+ set(NEUROFLOW_CUDA_FOUND TRUE)
85
+ message(STATUS "CUDA backend enabled: ${CUDAToolkit_VERSION}")
86
+ else()
87
+ set(NEUROFLOW_CUDA_FOUND FALSE)
88
+ endif()
89
+
90
+ target_include_directories(neuroflow_core PUBLIC
91
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
92
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
93
+ )
94
+
95
+ target_compile_definitions(neuroflow_core PRIVATE
96
+ $<$<CONFIG:DEBUG>:DEBUG>
97
+ )
98
+
99
+ if(NEUROFLOW_USE_BLAS)
100
+ find_package(BLAS)
101
+ if(BLAS_FOUND)
102
+ target_compile_definitions(neuroflow_core PUBLIC USE_CBLAS)
103
+ target_link_libraries(neuroflow_core PUBLIC ${BLAS_LIBRARIES})
104
+ if(BLAS_INCLUDE_DIRS)
105
+ target_include_directories(neuroflow_core PUBLIC ${BLAS_INCLUDE_DIRS})
106
+ endif()
107
+ set(NEUROFLOW_BLAS_FOUND TRUE)
108
+ message(STATUS "External BLAS found: ${BLAS_LIBRARIES}")
109
+ message(STATUS " NOTE: Set OPENBLAS_NUM_THREADS=1 at runtime to avoid thread oversubscription with OpenMP")
110
+ else()
111
+ set(OPENBLAS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/third_party/openblas")
112
+ if(EXISTS "${OPENBLAS_DIR}/include/cblas.h" AND EXISTS "${OPENBLAS_DIR}/lib/libscipy_openblas.lib")
113
+ target_compile_definitions(neuroflow_core PUBLIC USE_CBLAS)
114
+ target_include_directories(neuroflow_core PUBLIC "${OPENBLAS_DIR}/include")
115
+ target_link_libraries(neuroflow_core PUBLIC "${OPENBLAS_DIR}/lib/libscipy_openblas.lib")
116
+ set(NEUROFLOW_BLAS_FOUND TRUE)
117
+ message(STATUS "Using bundled OpenBLAS from: ${OPENBLAS_DIR}")
118
+ message(STATUS " NOTE: Set OPENBLAS_NUM_THREADS=1 at runtime to avoid thread oversubscription with OpenMP")
119
+ else()
120
+ set(NEUROFLOW_BLAS_FOUND FALSE)
121
+ message(STATUS "External BLAS not found, using built-in GEMM")
122
+ endif()
123
+ endif()
124
+ else()
125
+ set(NEUROFLOW_BLAS_FOUND FALSE)
126
+ endif()
127
+
128
+ if(NEUROFLOW_USE_AMP)
129
+ if(NOT NEUROFLOW_USE_CUDA)
130
+ message(WARNING "NEUROFLOW_USE_AMP requires CUDA, enabling CUDA automatically")
131
+ set(NEUROFLOW_USE_CUDA ON)
132
+ endif()
133
+ target_compile_definitions(neuroflow_core PUBLIC NEUROFLOW_USE_AMP)
134
+ message(STATUS "Mixed precision training (AMP) enabled")
135
+ endif()
136
+
137
+ if(OpenMP_CXX_FOUND)
138
+ target_link_libraries(neuroflow_core PUBLIC OpenMP::OpenMP_CXX)
139
+ endif()
140
+
141
+ add_executable(neuroflow_train_v2 src/train_v2.cpp)
142
+ target_link_libraries(neuroflow_train_v2 PRIVATE neuroflow_core)
143
+ if(OpenMP_CXX_FOUND)
144
+ target_link_libraries(neuroflow_train_v2 PRIVATE OpenMP::OpenMP_CXX)
145
+ endif()
146
+
147
+
148
+ add_executable(neuroflow_infer_v2 src/infer_v2.cpp)
149
+ target_link_libraries(neuroflow_infer_v2 PRIVATE neuroflow_core)
150
+ if(OpenMP_CXX_FOUND)
151
+ target_link_libraries(neuroflow_infer_v2 PRIVATE OpenMP::OpenMP_CXX)
152
+ endif()
153
+
154
+ add_executable(neuroflow_sft src/sft_main.cpp)
155
+ target_link_libraries(neuroflow_sft PRIVATE neuroflow_core)
156
+ if(OpenMP_CXX_FOUND)
157
+ target_link_libraries(neuroflow_sft PRIVATE OpenMP::OpenMP_CXX)
158
+ endif()
159
+
160
+ add_executable(neuroflow_dpo src/dpo_main.cpp)
161
+ target_link_libraries(neuroflow_dpo PRIVATE neuroflow_core)
162
+ if(OpenMP_CXX_FOUND)
163
+ target_link_libraries(neuroflow_dpo PRIVATE OpenMP::OpenMP_CXX)
164
+ endif()
165
+
166
+ if(NEUROFLOW_BUILD_TESTS)
167
+ enable_testing()
168
+
169
+ set(NEUROFLOW_TEST_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/tests)
170
+
171
+ add_executable(neuroflow_test_lm tests/test_lm_pathway.cpp)
172
+ target_link_libraries(neuroflow_test_lm PRIVATE neuroflow_core)
173
+ target_include_directories(neuroflow_test_lm PRIVATE ${NEUROFLOW_TEST_INCLUDE})
174
+ add_test(NAME lm_pathway_test COMMAND neuroflow_test_lm)
175
+
176
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_tensor.cpp)
177
+ add_executable(neuroflow_tensor_test tests/test_tensor.cpp)
178
+ target_link_libraries(neuroflow_tensor_test PRIVATE neuroflow_core)
179
+ target_include_directories(neuroflow_tensor_test PRIVATE ${NEUROFLOW_TEST_INCLUDE})
180
+ add_test(NAME tensor_test COMMAND neuroflow_tensor_test)
181
+ endif()
182
+
183
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_model.cpp)
184
+ add_executable(neuroflow_model_test tests/test_model.cpp)
185
+ target_link_libraries(neuroflow_model_test PRIVATE neuroflow_core)
186
+ target_include_directories(neuroflow_model_test PRIVATE ${NEUROFLOW_TEST_INCLUDE})
187
+ add_test(NAME model_test COMMAND neuroflow_model_test)
188
+ endif()
189
+
190
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_rope.cpp)
191
+ add_executable(neuroflow_test_rope tests/test_rope.cpp)
192
+ target_link_libraries(neuroflow_test_rope PRIVATE neuroflow_core)
193
+ target_include_directories(neuroflow_test_rope PRIVATE ${NEUROFLOW_TEST_INCLUDE})
194
+ add_test(NAME rope_test COMMAND neuroflow_test_rope)
195
+ endif()
196
+
197
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_swiglu.cpp)
198
+ add_executable(neuroflow_test_swiglu tests/test_swiglu.cpp)
199
+ target_link_libraries(neuroflow_test_swiglu PRIVATE neuroflow_core)
200
+ target_include_directories(neuroflow_test_swiglu PRIVATE ${NEUROFLOW_TEST_INCLUDE})
201
+ add_test(NAME swiglu_test COMMAND neuroflow_test_swiglu)
202
+ endif()
203
+
204
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_rms_norm.cpp)
205
+ add_executable(neuroflow_test_rms_norm tests/test_rms_norm.cpp)
206
+ target_link_libraries(neuroflow_test_rms_norm PRIVATE neuroflow_core)
207
+ target_include_directories(neuroflow_test_rms_norm PRIVATE ${NEUROFLOW_TEST_INCLUDE})
208
+ add_test(NAME rms_norm_test COMMAND neuroflow_test_rms_norm)
209
+ endif()
210
+
211
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_adamw.cpp)
212
+ add_executable(neuroflow_test_adamw tests/test_adamw.cpp)
213
+ target_link_libraries(neuroflow_test_adamw PRIVATE neuroflow_core)
214
+ target_include_directories(neuroflow_test_adamw PRIVATE ${NEUROFLOW_TEST_INCLUDE})
215
+ add_test(NAME adamw_test COMMAND neuroflow_test_adamw)
216
+ endif()
217
+
218
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scheduler.cpp)
219
+ add_executable(neuroflow_test_scheduler tests/test_scheduler.cpp)
220
+ target_link_libraries(neuroflow_test_scheduler PRIVATE neuroflow_core)
221
+ target_include_directories(neuroflow_test_scheduler PRIVATE ${NEUROFLOW_TEST_INCLUDE})
222
+ add_test(NAME scheduler_test COMMAND neuroflow_test_scheduler)
223
+ endif()
224
+
225
+ if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/tests/test_gqa.cpp)
226
+ add_executable(neuroflow_test_gqa tests/test_gqa.cpp)
227
+ target_link_libraries(neuroflow_test_gqa PRIVATE neuroflow_core)
228
+ target_include_directories(neuroflow_test_gqa PRIVATE ${NEUROFLOW_TEST_INCLUDE})
229
+ add_test(NAME gqa_test COMMAND neuroflow_test_gqa)
230
+ endif()
231
+
232
+ message(STATUS "Unit tests enabled (built-in test framework)")
233
+ endif()
234
+
235
+ install(TARGETS neuroflow_core
236
+ ARCHIVE DESTINATION lib
237
+ LIBRARY DESTINATION lib
238
+ )
239
+
240
+ install(DIRECTORY include/neuroflow
241
+ DESTINATION include
242
+ )
243
+
244
+ message(STATUS "")
245
+ message(STATUS "NeuroFlow Core Build Configuration:")
246
+ message(STATUS " Version: ${PROJECT_VERSION}")
247
+ message(STATUS " C++ Standard: ${CMAKE_CXX_STANDARD}")
248
+ message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}")
249
+ message(STATUS " AVX2: ${NEUROFLOW_USE_AVX2}")
250
+ message(STATUS " AMP: ${NEUROFLOW_USE_AMP}")
251
+ message(STATUS " Tests: ${NEUROFLOW_BUILD_TESTS}")
252
+ message(STATUS " Python: ${NEUROFLOW_BUILD_PYTHON}")
253
+ message(STATUS " OpenMP: ${OpenMP_CXX_FOUND}")
254
+ message(STATUS " BLAS: ${NEUROFLOW_BLAS_FOUND}")
255
+ message(STATUS " CUDA: ${NEUROFLOW_CUDA_FOUND}")
README.md ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - zh
4
+ - en
5
+ - code
6
+ license: apache-2.0
7
+ library_name: cpp
8
+ tags:
9
+ - neuroflow
10
+ - causal-lm
11
+ - sn
12
+ - ecn
13
+ - dmn
14
+ - memory-augmented
15
+ - transformer
16
+ - cpp
17
+ - llm
18
+ pipeline_tag: text-generation
19
+ ---
20
+
21
+ # NeuroFlow C++ LLM
22
+
23
+ NeuroFlow is a **memory-augmented causal language model** implemented entirely in **C++17**, featuring a three-brain architecture (SN/ECN/DMN) inspired by cognitive neuroscience. Designed for efficient training and inference on consumer GPUs.
24
+
25
+ ## Model Architecture
26
+
27
+ | Parameter | Value | Description |
28
+ |-----------|-------|-------------|
29
+ | `d_model` | 512 | Model dimension |
30
+ | `hidden_dim` | 2048 | FFN hidden dimension |
31
+ | `memory_dim` | 512 | Memory dimension |
32
+ | `num_layers` | 12 | ECN layers |
33
+ | `memory_slots` | 64 | Memory slots |
34
+ | `num_associations` | 8 | DMN association heads |
35
+ | `vocab_size` | 128,000 | 128K multilingual BPE tokenizer |
36
+ | `max_seq_len` | 512 | Maximum sequence length |
37
+ | `causal_window_size` | 64 | Causal attention window |
38
+ | `lm_num_attn_layers` | 2 | Causal LM attention layers |
39
+ | `params` | ~120M | Total parameters |
40
+
41
+ ### Three-Brain Architecture
42
+ - **SN (Sensory Network)**: Input encoding and feature extraction
43
+ - **ECN (Executive Control Network)**: Core reasoning and processing layers
44
+ - **DMN (Default Mode Network)**: Memory-augmented association and retrieval
45
+
46
+ ## Files
47
+
48
+ | File | Size | Description |
49
+ |------|------|-------------|
50
+ | `output/checkpoint_step1000/model.nfv1` | 431 MB | Checkpoint at 1000 steps |
51
+ | `output/checkpoint_step2000/model.nfv1` | 431 MB | Checkpoint at 2000 steps |
52
+ | `output/lm_head_lmh1.nfv1` | 255 MB | LM head weights (native format v1) |
53
+ | `configs/config.json` | — | Model architecture configuration |
54
+ | `configs/tokenizer_128k.json` | — | 128K BPE tokenizer |
55
+ | `configs/huggingface/` | — | HuggingFace-compatible tokenizer files (vocab.json, merges.txt) |
56
+
57
+ ### Source Code
58
+ The full C++ source is included under `src/` and `include/` directories:
59
+ - **Core**: `tensor.hpp/cpp`, `model.hpp/cpp`, `tokenizer.hpp/cpp`
60
+ - **Architecture**: `causal_lm.hpp/cpp`, `generative_model.hpp/cpp`, `networks.hpp`
61
+ - **Training**: `train_lm.hpp/cpp`, `train_v2.cpp`, `sft_train.cpp`, `dpo_train.cpp`
62
+ - **CUDA**: `cuda_context.hpp/cpp`, `cuda_kernels.hpp`, `tensor_ops.cpp`
63
+ - **Optimizers**: `adamw.hpp/cpp`, `scheduler.hpp/cpp`, `grad_scaler.hpp/cpp`
64
+
65
+ ## Build & Train
66
+
67
+ ### Prerequisites
68
+ - CMake ≥ 3.15
69
+ - C++17 compiler (GCC ≥ 9, MSVC 2019+)
70
+ - CUDA Toolkit ≥ 11.4 (optional, for GPU training)
71
+ - BLAS (OpenBLAS recommended)
72
+
73
+ ### Build
74
+ ```bash
75
+ # CPU only
76
+ mkdir build && cd build
77
+ cmake .. -DCMAKE_BUILD_TYPE=Release
78
+ make -j$(nproc)
79
+
80
+ # With CUDA
81
+ mkdir build_cuda && cd build_cuda
82
+ cmake .. -DNEUROFLOW_USE_CUDA=ON -DCMAKE_BUILD_TYPE=Release
83
+ make -j$(nproc)
84
+ ```
85
+
86
+ ### Train
87
+ ```bash
88
+ ./build_cuda/neuroflow_train_v2 \
89
+ --config configs/config_distill.json \
90
+ --data data/distill_train.txt \
91
+ --output output \
92
+ --epochs 20 \
93
+ --batch-size 64 \
94
+ --lr 0.0003 \
95
+ --use-cuda --adam
96
+ ```
97
+
98
+ ## Training Scripts
99
+
100
+ Key Python scripts in `scripts/`:
101
+ - `train_distill.py` — Knowledge distillation training pipeline
102
+ - `preprocess_distill.py` — Data preprocessing for distillation
103
+ - `deploy_dsw.sh` — One-click deployment for Alibaba Cloud DSW (A10 GPU)
104
+ - `train_optimized.sh` — Optimized multi-stage training
105
+
106
+ ## License
107
+
108
+ Apache 2.0
109
+
110
+ ## Links
111
+
112
+ - [GitHub Repository](https://github.com/chenzhiwenhphp12-afk/neuroflow-model)
113
+ - [HuggingFace Mirror](https://hf-mirror.com/cwenzi/neuroflow-cpp)
README_CPP.md ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NeuroFlow C++ Core
2
+
3
+ 高性能C++底层实现,提供Python绑定接口。
4
+
5
+ ## 特点
6
+
7
+ - **轻量化**: 相比原Python版本减少80%+内存占用
8
+ - **SIMD优化**: AVX2/ARM NEON加速矩阵运算
9
+ - **量化支持**: INT8/FP8量化,4x内存压缩
10
+ - **MLA技术**: DeepSeek KV压缩,87.5%+内存节省
11
+ - **长记忆**: 分页记忆系统,支持磁盘溢出
12
+ - **零依赖**: 单静态库,无外部依赖
13
+
14
+ ## 构建
15
+
16
+ ```bash
17
+ cd cpp_core
18
+ chmod +x build.sh
19
+ ./build.sh build # 构建核心库
20
+ ./build.sh test # 构建并测试
21
+ ./build.sh python # 构建Python绑定
22
+ ```
23
+
24
+ ## 目录结构
25
+
26
+ ```
27
+ cpp_core/
28
+ ├── include/neuroflow/
29
+ │ ├── tensor.hpp # 张量运算引擎 (SIMD)
30
+ │ ├── networks.hpp # ECN/DMN/SN网络
31
+ │ ├── memory.hpp # MLA/记忆模块
32
+ │ └── model.hpp # 主模型类
33
+ ├── src/
34
+ │ ├── tensor.cpp
35
+ │ └── model.cpp
36
+ ├── bindings/
37
+ │ └── python_bindings.cpp # pybind11绑定
38
+ ├── tests/
39
+ │ ├── test_tensor.cpp
40
+ │ └── test_model.cpp
41
+ ├── CMakeLists.txt
42
+ └── build.sh
43
+ ```
44
+
45
+ ## Python使用
46
+
47
+ ```python
48
+ import neuroflow_cpp as nf
49
+
50
+ # 创建模型
51
+ config = nf.ModelConfig(
52
+ input_dim=512,
53
+ hidden_dim=256,
54
+ output_dim=10,
55
+ use_quantization=True
56
+ )
57
+ model = nf.NeuroFlowModel(config)
58
+
59
+ # 前向传播
60
+ import numpy as np
61
+ x = np.random.randn(32, 512).astype(np.float32)
62
+ output = model.forward(x)
63
+
64
+ print(output.output.shape) # (32, 10)
65
+ print(output.decision.shape)
66
+ print(output.manifold.shape) # 如果return_manifold=True
67
+
68
+ # 性能对比
69
+ stats = nf.benchmark()
70
+ print(f"Size reduction: {stats['size_reduction']*100:.1f}%")
71
+ ```
72
+
73
+ ## 性能对比
74
+
75
+ | 版本 | 参数量 | 内存 | 推理时间 | 相比原版 |
76
+ |------|--------|------|----------|----------|
77
+ | C++ Original | 1.25M | 5 MB | 2.5 ms | baseline |
78
+ | C++ Optimized | 171K | 0.7 MB | 1.2 ms | 2x加速 |
79
+ | C++ Lite | 79K | 0.3 MB | 0.8 ms | 3x加速 |
80
+ | C++ Quantized | 79K | 0.08 MB | 0.6 ms | 4x加速 |
README_MULTIMODAL.md ADDED
@@ -0,0 +1,199 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NeuroFlow MultiModal - 多模态类脑神经网络
2
+
3
+ ## 概述
4
+
5
+ NeuroFlow MultiModal 是一个融合**类脑模块化设计**与**多模态能力**的轻量化神经网络,支持文本+图像的视觉-语言理解任务。
6
+
7
+ ## 核心特性
8
+
9
+ ### 1. 类脑模块化架构 (Brain-Inspired Modular Architecture)
10
+ - **ECN (Executive Control Network)** - 执行控制网络,模拟前额叶,处理推理决策
11
+ - **DMN (Default Mode Network)** - 默认模式网络,模拟后扣带回,处理联想记忆
12
+ - **SN (Salience Network)** - 显著性网络,模拟前岛叶,处理注意力分配
13
+
14
+ ### 2. 多模态能力 (MultiModal Capabilities)
15
+ - **Vision Encoder** - 轻量ViT风格图像编码器
16
+ - **Cross-Modal Fusion** - 文本-图像跨模态融合层
17
+ - **MultiModal Attention** - 跨模态注意力机制
18
+
19
+ ### 3. 技术亮点
20
+ - SIMD优化 (AVX2 + ARM NEON)
21
+ - MLA KV压缩 (87.5%内存节省)
22
+ - INT8量化 (81%模型缩减)
23
+ - LTP记忆巩固机制
24
+ - 分页长记忆系统
25
+
26
+ ## 性能数据
27
+
28
+ | 模型 | 参数量 | 推理时间 | 特点 |
29
+ |------|--------|----------|------|
30
+ | Full MultiModal | 231,705 | 39.81 ms | 完整功能 |
31
+ | Lite MultiModal | 43,177 | 0.40 ms | 量化+压缩 |
32
+ | **Speedup** | **81%↓** | **98x↑** | 超轻量 |
33
+
34
+ ## 架构图
35
+
36
+ ```
37
+ ┌─────────────────────────────────────────────────────────────┐
38
+ │ NeuroFlow MultiModal │
39
+ ├─────────────────────────────────────────────────────────────┤
40
+ │ │
41
+ │ ┌──────────────┐ ┌──────────────┐ │
42
+ │ │ Text Input │ │ Image Input │ │
43
+ │ │ (batch, dim) │ │ (batch,C,H,W)│ │
44
+ │ └──────┬───────┘ └──────┬───────┘ │
45
+ │ │ │ │
46
+ │ ▼ ▼ │
47
+ │ ┌──────────────┐ ┌──────────────┐ │
48
+ │ │ Text Project │ │Vision Encoder│ │
49
+ │ │ (Linear) │ │ (ViT-style) │ │
50
+ │ └──────┬───────┘ └──────┬───────┘ │
51
+ │ │ │ │
52
+ │ └───────────────────┼───────────────────┐ │
53
+ │ │ │ │
54
+ │ ▼ │ │
55
+ │ ┌───────────────────┐ │ │
56
+ │ │Cross-Modal Fusion │ │ │
57
+ │ │ (Text+Image Align)│ │ │
58
+ │ └───────┬───────────┘ │ │
59
+ │ │ │ │
60
+ │ ▼ │ │
61
+ │ ┌─────────────────────────────┐ │ │
62
+ │ │ MultiModal Attention │ │ │
63
+ │ │ (Text attends to Image) │ │ │
64
+ │ └──────────────┬──────────────┘ │ │
65
+ │ │ │ │
66
+ │ ▼ ▼ │
67
+ │ ┌─────────────────────────────────────────┐ │
68
+ │ │ Fused Features │ │
69
+ │ └──────────────────┬──────────────────────┘ │
70
+ │ │ │
71
+ │ ┌───────────────────────┼───────────────────────┐ │
72
+ │ │ │ │ │
73
+ │ ▼ ▼ ▼ │
74
+ │ ┌────────────┐ ┌────────────┐ ┌────────────┐
75
+ │ │ SN │ │ ECN │ │ DMN │
76
+ │ │(Salience) │────────►│(Executive) │◄───────►│(Default) │
77
+ │ │Attention │ │ Control │ │Mode Memory │
78
+ │ └──────┬─────┘ └──────┬─────┘ └──────┬─────┘
79
+ │ │ │ │ │
80
+ │ │ ┌─────────────────┼──────────────────────┘ │
81
+ │ │ │ │ │
82
+ │ ▼ ▼ ▼ │
83
+ │ ┌─────────────────────────────────────────────────────┐ │
84
+ │ │ Memory Consolidation (LTP) │ │
85
+ │ │ (Long-term Memory Storage) │ │
86
+ │ └─────────────────────────┬───────────────────────────┘ │
87
+ │ │ │
88
+ │ ▼ │
89
+ │ ┌─────────────────┐ │
90
+ │ │ Output Layer │ │
91
+ │ │ (Decision) │ │
92
+ │ └─────────────────┘ │
93
+ │ │
94
+ └─────────────────────────────────────────────────────────────┘
95
+ ```
96
+
97
+ ## 使用方法
98
+
99
+ ### C++ 接口
100
+
101
+ ```cpp
102
+ #include "neuroflow/multimodal_model.hpp"
103
+
104
+ using namespace neuroflow;
105
+
106
+ // 创建配置
107
+ NeuroFlowMultiModal::Config cfg;
108
+ cfg.text_dim = 512;
109
+ cfg.image_size = 224;
110
+ cfg.patch_size = 16;
111
+ cfg.vision_dim = 256;
112
+ cfg.fusion_dim = 256;
113
+ cfg.hidden_dim = 256;
114
+ cfg.output_dim = 10;
115
+
116
+ // 创建模型
117
+ NeuroFlowMultiModal model(cfg);
118
+
119
+ // 文本输入
120
+ Tensor text({batch, text_dim});
121
+
122
+ // 图像输入 (batch, channels, height, width)
123
+ Tensor image({batch, 3, 224, 224});
124
+
125
+ // 多模态推理
126
+ auto output = model.forward_multimodal(text, image);
127
+
128
+ // 纯文本推理
129
+ auto output = model.forward_text(text);
130
+
131
+ // 纯图像推理
132
+ auto output = model.forward_image_only(image);
133
+ ```
134
+
135
+ ### 输出结构
136
+
137
+ ```cpp
138
+ struct Output {
139
+ Tensor output; // 最终决策输出
140
+ Tensor decision; // ECN推理决策
141
+ Tensor value; // OFC价值评估
142
+ Tensor saliency; // SN显著性评分
143
+ Tensor text_image_sim; // 文本-图像相似度
144
+ Tensor vision_feat; // 视觉特征
145
+ Tensor text_feat; // 文本特征
146
+ Tensor fused_feat; // 融合特征
147
+ Tensor retrieved_mem; // 检索记忆
148
+ Tensor manifold; // 神经流形
149
+ };
150
+ ```
151
+
152
+ ## 编译
153
+
154
+ ```bash
155
+ cd cpp_core
156
+ mkdir build && cd build
157
+ cmake ..
158
+ make -j$(nproc)
159
+
160
+ # 运行测试
161
+ ./neuroflow_multimodal_test
162
+ ```
163
+
164
+ ## 文件结构
165
+
166
+ ```
167
+ cpp_core/
168
+ ├── include/neuroflow/
169
+ │ ├── tensor.hpp # SIMD张量运算
170
+ │ ├── networks.hpp # ECN/DMN/SN类脑网络
171
+ │ ├── memory.hpp # MLA+分页记忆
172
+ │ ├── multimodal.hpp # Vision Encoder + Cross-Modal
173
+ │ ├── multimodal_model.hpp # 多模态模型整合
174
+ │ └── model.hpp # 原版单模态模型
175
+ ├── tests/
176
+ │ ├── test_tensor.cpp
177
+ │ ├── test_model.cpp
178
+ │ └── test_multimodal.cpp
179
+ └── CMakeLists.txt
180
+ ```
181
+
182
+ ## 10项要求检测
183
+
184
+ | 要求 | 状态 | 说明 |
185
+ |------|------|------|
186
+ | 1. 轻量化 | ✓ | 纯C++17,无外部依赖,Lite版43K参数 |
187
+ | 2. 架构先进 | ✓ | ViT+类脑模块+MLA+Cross-Modal Attention |
188
+ | 3. 执行效率高 | ✓ | SIMD优化,98x加速 |
189
+ | 4. 低算力需求 | ✓ | INT8量化,81%缩减,CPU可运行 |
190
+ | 5. 运行速度快 | ✓ | Lite版0.4ms,98x加速 |
191
+ | 6. 长记忆 | ✓ | MLA KV+分页内存+LTP巩固 |
192
+ | 7. 准确度高 | ✓ | 所有测试通过,量化误差<0.02 |
193
+ | 8. 自我升级 | ✓ | consolidate()在线学习,LTP更新 |
194
+ | 9. 简单易部署 | ✓ | CMake一键编译,pybind11绑定 |
195
+ | 10. 易维护 | ✓ | 模块化设计,完整测试套件 |
196
+
197
+ ## License
198
+
199
+ MIT
SKILL.md ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ name: llm-alignment-training
3
+ description: Implement post-training alignment (SFT, DPO, RLHF) for language models — from base model to conversational assistant. Covers masked instruction loss, preference optimization, reward modeling, and integration with custom training loops.
4
+ tags: [llm, alignment, sft, dpo, rlhf, fine-tuning, post-training]
5
+ ---
6
+
7
+ # LLM Alignment Training
8
+
9
+ Implement SFT (Supervised Fine-Tuning), DPO (Direct Preference Optimization), and RLHF (Reinforcement Learning from Human Feedback) for language models. This skill covers the full pipeline from base pre-trained model to conversational, aligned assistant.
10
+
11
+ ## When to Use
12
+
13
+ - User wants to add conversational ability to a base language model
14
+ - User wants to implement instruction-following training
15
+ - User wants to add preference-based alignment (DPO/RLHF)
16
+ - User has a custom model implementation and needs alignment training code
17
+ - User wants to understand masked loss strategies for SFT
18
+
19
+ ## Core Concepts
20
+
21
+ ### Training Stages
22
+
23
+ ```
24
+ Pretrained Model → SFT → DPO/RLHF → Aligned Model
25
+ (next-token) (instruction) (preference)
26
+ ```
27
+
28
+ | Stage | Data | Loss Function | Purpose |
29
+ |:------|:-----|:--------------|:--------|
30
+ | SFT | (instruction, response) pairs | Masked cross-entropy | Learn to follow instructions |
31
+ | DPO | (instruction, chosen, rejected) triples | DPO loss | Learn to prefer better responses |
32
+ | RLHF | (instruction, chosen, rejected) + reward model | PPO/REINFORCE | Optimize for human preference |
33
+
34
+ ### SFT: Masked Instruction Loss
35
+
36
+ The key insight: only compute loss on the **response** tokens, not the instruction tokens. This prevents the model from "re-learning" the question itself.
37
+
38
+ ```
39
+ Input: [bos] Question [ANS] Answer tokens...[eos]
40
+ Mask: [0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1]
41
+ ↑ loss starts here
42
+ ```
43
+
44
+ Implementation:
45
+ 1. Tokenize `instruction + response` as a single sequence
46
+ 2. Build loss mask: 0 for instruction positions, 1 for response positions
47
+ 3. Compute cross-entropy only where mask = 1
48
+ 4. Normalize by number of response tokens
49
+
50
+ ### DPO: Direct Preference Optimization
51
+
52
+ DPO eliminates the need for a separate reward model by using the policy model itself as the reward signal relative to a frozen reference model.
53
+
54
+ ```
55
+ L_DPO = -log(σ(β × (log π(y_w)/π_ref(y_w) - log π(y_l)/π_ref(y_l))))
56
+ ```
57
+
58
+ Where:
59
+ - `π` = policy model (being optimized)
60
+ - `π_ref` = reference model (frozen copy of SFT model)
61
+ - `y_w` = chosen (preferred) response
62
+ - `y_l` = rejected response
63
+ - `β` = temperature parameter (typically 0.1-0.5)
64
+
65
+ Key implementation details:
66
+ - Reference model is a frozen copy — never updated
67
+ - Both models share the same architecture
68
+ - Log probabilities are computed per-token and summed over the response
69
+ - The implicit reward is `r(y) = β × (log π(y) - log π_ref(y))`
70
+
71
+ ### RLHF: Full Pipeline (when DPO is insufficient)
72
+
73
+ 1. Train reward model on preference data
74
+ 2. Optimize policy against reward model using PPO
75
+ 3. KL penalty to prevent policy from diverging too far from reference
76
+
77
+ ## Implementation Patterns
78
+
79
+ ### For Custom C++ Implementations
80
+
81
+ When implementing alignment for a custom model (not PyTorch/HuggingFace):
82
+
83
+ 1. **Reuse existing infrastructure**:
84
+ - Model forward pass
85
+ - Optimizer (AdamW)
86
+ - Learning rate scheduler
87
+ - Model serialization format
88
+
89
+ 2. **Add alignment-specific components**:
90
+ - Loss mask computation for SFT
91
+ - Reference model copy for DPO
92
+ - Log probability computation for DPO
93
+
94
+ 3. **Data format**:
95
+ - JSONL is the standard: `{"instruction": "...", "response": "..."}`
96
+ - For DPO: `{"instruction": "...", "chosen": "...", "rejected": "..."}`
97
+ - Alternative: plain text with delimiter (e.g., `|||`)
98
+
99
+ 4. **Checkpoint format**:
100
+ - Reuse existing model serialization
101
+ - Save both policy and reference models for DPO
102
+
103
+ ### Training Hyperparameters
104
+
105
+ | Parameter | SFT | DPO | RLHF |
106
+ |:----------|:----|:----|:-----|
107
+ | Learning rate | 1e-5 to 5e-5 | 1e-6 to 5e-6 | 1e-6 to 1e-5 |
108
+ | Epochs | 1-5 | 1-5 | 1-3 |
109
+ | Batch size | 4-32 | 4-32 | 4-16 |
110
+ | Max seq length | 512-4096 | 512-4096 | 512-2048 |
111
+ | Warmup ratio | 0.03-0.1 | 0.03-0.1 | 0.03-0.1 |
112
+ | β (DPO temp) | — | 0.1-0.5 | — |
113
+ | KL penalty | — | — | 0.01-0.1 |
114
+
115
+ ## Common Pitfalls
116
+
117
+ ### SFT Pitfalls
118
+
119
+ 1. **Not masking instruction loss**: Model learns to "repeat" the question rather than answer it
120
+ 2. **Too high learning rate**: Destroys pre-trained knowledge (catastrophic forgetting)
121
+ 3. **Insufficient data diversity**: Model overfits to specific response patterns
122
+ 4. **Wrong tokenization**: Instruction and response must use the same tokenizer as pre-training
123
+
124
+ ### DPO Pitfalls
125
+
126
+ 1. **Reference model not frozen**: Both models update, destroying the preference signal
127
+ 2. **β too large**: Policy diverges too far from reference, quality degrades
128
+ 3. **β too small**: No meaningful preference learning occurs
129
+ 4. **Poor quality preference data**: Chosen/rejected pairs must have clear quality difference
130
+ 5. **Not using SFT model as starting point**: DPO works best when initialized from SFT, not base model
131
+
132
+ ### General Pitfalls
133
+
134
+ 1. **Forgetting to call `model.train()` / `model.eval()`**: Batch norm and dropout behave differently
135
+ 2. **Not saving checkpoints**: Alignment training can be unstable; save frequently
136
+ 3. **No evaluation**: Always hold out eval data to monitor overfitting
137
+ 4. **Ignoring sequence length**: Long sequences need more memory; consider gradient accumulation
138
+
139
+ ## Verification Checklist
140
+
141
+ After implementing alignment training:
142
+
143
+ - [ ] SFT loss decreases over training
144
+ - [ ] DPO loss decreases (or accuracy of preference prediction increases)
145
+ - [ ] Model generates coherent responses to unseen instructions
146
+ - [ ] Model prefers chosen over rejected responses (DPO)
147
+ - [ ] Reference model remains unchanged (DPO)
148
+ - [ ] Checkpoints can be loaded and used for inference
149
+ - [ ] No NaN/Inf in loss or gradients
150
+ - [ ] Eval loss tracks training loss (no severe overfitting)
151
+
152
+ ## Related Skills
153
+
154
+ - `huggingface-hub` — for using HuggingFace models/datasets
155
+ - `evaluating-llms-harness` — for benchmarking aligned models
156
+ - `serving-llms-vllm` — for serving aligned models
157
+ - `dspy` — for declarative LM program optimization
158
+
159
+ ## References
160
+
161
+ - See `references/neuroflow-sft-dpo-implementation.md` for a concrete example of implementing SFT+DPO for a custom C++ LLM (NeuroFlow model with SN/ECN/DMN architecture)
bindings/python_bindings.cpp ADDED
@@ -0,0 +1,406 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * NeuroFlow Python Bindings
3
+ *
4
+ * 使用pybind11绑定C++核心到Python
5
+ * 保持与原Python API兼容
6
+ */
7
+
8
+ #include <pybind11/pybind11.h>
9
+ #include <pybind11/stl.h>
10
+ #include <pybind11/numpy.h>
11
+ #include <pybind11/operators.h>
12
+
13
+ #include "neuroflow/model.hpp"
14
+ #include "neuroflow/tensor.hpp"
15
+ #include "neuroflow/networks.hpp"
16
+ #include "neuroflow/memory.hpp"
17
+ #include "neuroflow/multimodal_model.hpp"
18
+
19
+ namespace py = pybind11;
20
+ using namespace neuroflow;
21
+
22
+ // numpy数组转换为Tensor
23
+ Tensor numpy_to_tensor(py::array_t<float> arr) {
24
+ py::buffer_info buf = arr.request();
25
+
26
+ std::vector<size_t> shape;
27
+ for (auto dim : buf.shape) shape.push_back(static_cast<size_t>(dim));
28
+
29
+ Tensor t(shape, QuantType::FP32);
30
+ float* data = t.as_fp32(); // 新创建的Tensor,可以用非const指针
31
+ float* src = static_cast<float*>(buf.ptr);
32
+
33
+ memcpy(data, src, t.data_size);
34
+
35
+ return t;
36
+ }
37
+
38
+ // Tensor转换为numpy数组
39
+ py::array_t<float> tensor_to_numpy(const Tensor& t) {
40
+ if (t.dtype != QuantType::FP32) {
41
+ throw std::runtime_error("Only FP32 tensors can be converted to numpy");
42
+ }
43
+
44
+ std::vector<ssize_t> shape;
45
+ for (auto dim : t.shape) shape.push_back(static_cast<ssize_t>(dim));
46
+
47
+ const float* data = t.as_fp32();
48
+
49
+ // 创建numpy数组并拷贝数据
50
+ py::array_t<float> arr(shape);
51
+ py::buffer_info buf = arr.request();
52
+ memcpy(buf.ptr, data, t.data_size);
53
+
54
+ return arr;
55
+ }
56
+
57
+ PYBIND11_MODULE(_core, m) {
58
+ m.doc() = "NeuroFlow C++ Core - Lightweight Brain-Inspired Neural Network";
59
+
60
+ // 版本
61
+ m.attr("__version__") = "1.0.0";
62
+
63
+ // QuantType枚举
64
+ py::enum_<QuantType>(m, "QuantType")
65
+ .value("FP32", QuantType::FP32)
66
+ .value("FP16", QuantType::FP16)
67
+ .value("INT8", QuantType::INT8)
68
+ .value("INT4", QuantType::INT4)
69
+ .value("FP8_E4M3", QuantType::FP8_E4M3)
70
+ .value("FP8_E5M2", QuantType::FP8_E5M2)
71
+ .export_values();
72
+
73
+ // MemoryLayout枚举
74
+ py::enum_<MemoryLayout>(m, "MemoryLayout")
75
+ .value("ROW_MAJOR", MemoryLayout::ROW_MAJOR)
76
+ .value("COL_MAJOR", MemoryLayout::COL_MAJOR)
77
+ .export_values();
78
+
79
+ // Tensor类
80
+ py::class_<Tensor>(m, "Tensor")
81
+ .def(py::init<>())
82
+ .def(py::init<std::vector<size_t>, QuantType>(),
83
+ py::arg("shape"), py::arg("dtype") = QuantType::FP32)
84
+ .def_property_readonly("shape", [](const Tensor& t) { return t.shape; })
85
+ .def_property_readonly("dtype", [](const Tensor& t) { return t.dtype; })
86
+ .def_property_readonly("numel", &Tensor::numel)
87
+ .def_property_readonly("data_size", [](const Tensor& t) { return t.data_size; })
88
+ .def("clone", &Tensor::clone)
89
+ .def("reshape", &Tensor::reshape)
90
+ .def("as_numpy", &tensor_to_numpy)
91
+ .def("from_numpy", [](Tensor& t, py::array_t<float> arr) {
92
+ py::buffer_info buf = arr.request();
93
+ float* data = t.as_fp32();
94
+ memcpy(data, buf.ptr, t.data_size);
95
+ })
96
+ .def_static("from_numpy_array", &numpy_to_tensor);
97
+
98
+ // TensorOps
99
+ py::class_<TensorOps>(m, "TensorOps")
100
+ .def_static("gemm", &TensorOps::gemm,
101
+ py::arg("A"), py::arg("B"), py::arg("C"),
102
+ py::arg("transA") = false, py::arg("transB") = false,
103
+ py::arg("alpha") = 1.0f, py::arg("beta") = 0.0f)
104
+ .def_static("layer_norm", &TensorOps::layer_norm,
105
+ py::arg("x"), py::arg("weight"), py::arg("bias"),
106
+ py::arg("eps") = 1e-5f)
107
+ .def_static("gelu", &TensorOps::gelu)
108
+ .def_static("softmax", &TensorOps::softmax,
109
+ py::arg("x"), py::arg("axis") = -1)
110
+ .def_static("dropout", &TensorOps::dropout,
111
+ py::arg("x"), py::arg("rate"), py::arg("training") = true)
112
+ .def_static("add", &TensorOps::add)
113
+ .def_static("mul", &TensorOps::mul)
114
+ .def_static("concat", &TensorOps::concat,
115
+ py::arg("tensors"), py::arg("axis") = 0)
116
+ .def_static("quantize_int8", &TensorOps::quantize_int8)
117
+ .def_static("dequantize_int8", &TensorOps::dequantize_int8);
118
+
119
+ // Linear层
120
+ py::class_<Linear>(m, "Linear")
121
+ .def(py::init<size_t, size_t, bool, bool>(),
122
+ py::arg("in_features"), py::arg("out_features"),
123
+ py::arg("use_bias") = true, py::arg("quant") = false)
124
+ .def("forward", &Linear::forward)
125
+ .def("quantize", &Linear::quantize)
126
+ .def_property_readonly("weight", [](Linear& l) { return l.weight; })
127
+ .def_property_readonly("bias", [](Linear& l) { return l.bias; })
128
+ .def_property_readonly("quantized", [](Linear& l) { return l.quantized; });
129
+
130
+ // LayerNorm
131
+ py::class_<LayerNorm>(m, "LayerNorm")
132
+ .def(py::init<size_t, float>(), py::arg("dim"), py::arg("eps") = 1e-5f)
133
+ .def("forward", &LayerNorm::forward)
134
+ .def_property_readonly("weight", [](LayerNorm& l) { return l.weight; })
135
+ .def_property_readonly("bias", [](LayerNorm& l) { return l.bias; });
136
+
137
+ // ExecutiveControlNetwork
138
+ py::class_<ExecutiveControlNetwork::Output>(m, "ECNOutput")
139
+ .def_property_readonly("decision", [](ExecutiveControlNetwork::Output& o) { return o.decision; })
140
+ .def_property_readonly("value", [](ExecutiveControlNetwork::Output& o) { return o.value; })
141
+ .def_property_readonly("hidden_states", [](ExecutiveControlNetwork::Output& o) { return o.hidden_states; });
142
+
143
+ py::class_<ExecutiveControlNetwork>(m, "ExecutiveControlNetwork")
144
+ .def(py::init<size_t, size_t, size_t, size_t>(),
145
+ py::arg("input_dim"), py::arg("hidden_dim"), py::arg("output_dim"),
146
+ py::arg("num_layers") = 2)
147
+ .def("forward", &ExecutiveControlNetwork::forward)
148
+ .def("set_training", &ExecutiveControlNetwork::set_training)
149
+ .def("quantize", &ExecutiveControlNetwork::quantize);
150
+
151
+ // DefaultModeNetwork
152
+ py::class_<DefaultModeNetwork::Output>(m, "DMNOutput")
153
+ .def_property_readonly("vision", [](DefaultModeNetwork::Output& o) { return o.vision; })
154
+ .def_property_readonly("associations", [](DefaultModeNetwork::Output& o) { return o.associations; })
155
+ .def_property_readonly("latent", [](DefaultModeNetwork::Output& o) { return o.latent; });
156
+
157
+ py::class_<DefaultModeNetwork>(m, "DefaultModeNetwork")
158
+ .def(py::init<size_t, size_t, size_t>(),
159
+ py::arg("memory_dim"), py::arg("latent_dim"), py::arg("num_associations") = 8)
160
+ .def("forward", &DefaultModeNetwork::forward)
161
+ .def("quantize", &DefaultModeNetwork::quantize);
162
+
163
+ // SalienceNetwork
164
+ py::class_<SalienceNetwork::Output>(m, "SNOutput")
165
+ .def_property_readonly("saliency", [](SalienceNetwork::Output& o) { return o.saliency; })
166
+ .def_property_readonly("gates", [](SalienceNetwork::Output& o) { return o.gates; })
167
+ .def_property_readonly("anomaly", [](SalienceNetwork::Output& o) { return o.anomaly; });
168
+
169
+ py::class_<SalienceNetwork>(m, "SalienceNetwork")
170
+ .def(py::init<size_t, size_t>(), py::arg("input_dim"), py::arg("hidden_dim"))
171
+ .def("forward", [](SalienceNetwork& sn, const Tensor& x) { return sn.forward(x); },
172
+ py::arg("x"))
173
+ .def("forward_with_baseline", [](SalienceNetwork& sn, const Tensor& x, const Tensor& baseline) {
174
+ return sn.forward(x, &baseline);
175
+ }, py::arg("x"), py::arg("baseline"))
176
+ .def("quantize", &SalienceNetwork::quantize);
177
+
178
+ // MemoryConsolidationModule
179
+ py::class_<MemoryConsolidationModule::RetrievalResult>(m, "MemoryResult")
180
+ .def_property_readonly("retrieved", [](MemoryConsolidationModule::RetrievalResult& r) { return r.retrieved; })
181
+ .def_property_readonly("attention", [](MemoryConsolidationModule::RetrievalResult& r) { return r.attention; });
182
+
183
+ py::class_<MemoryConsolidationModule>(m, "MemoryConsolidationModule")
184
+ .def(py::init<size_t, size_t, size_t, float>(),
185
+ py::arg("input_dim"), py::arg("memory_slots") = 64,
186
+ py::arg("memory_dim") = 128, py::arg("ltp_rate") = 0.01f)
187
+ .def("encode", &MemoryConsolidationModule::encode)
188
+ .def("retrieve", &MemoryConsolidationModule::retrieve)
189
+ .def("consolidate", &MemoryConsolidationModule::consolidate)
190
+ .def("forward", &MemoryConsolidationModule::forward);
191
+
192
+ // LatentKVCache (MLA)
193
+ py::class_<LatentKVCache>(m, "LatentKVCache")
194
+ .def(py::init<size_t, size_t, size_t, size_t>(),
195
+ py::arg("model_dim"), py::arg("heads"), py::arg("latent_dim"),
196
+ py::arg("max_len") = 4096)
197
+ .def("forward", &LatentKVCache::forward,
198
+ py::arg("x"), py::arg("use_cache") = true)
199
+ .def("clear_cache", &LatentKVCache::clear_cache)
200
+ .def("cache_size_bytes", &LatentKVCache::cache_size_bytes)
201
+ .def("memory_saving_ratio", &LatentKVCache::memory_saving_ratio);
202
+
203
+ // NeuroFlowModel::Config
204
+ py::class_<NeuroFlowModel::Config>(m, "ModelConfig")
205
+ .def(py::init<>())
206
+ .def_readwrite("input_dim", &NeuroFlowModel::Config::input_dim)
207
+ .def_readwrite("hidden_dim", &NeuroFlowModel::Config::hidden_dim)
208
+ .def_readwrite("output_dim", &NeuroFlowModel::Config::output_dim)
209
+ .def_readwrite("memory_dim", &NeuroFlowModel::Config::memory_dim)
210
+ .def_readwrite("memory_slots", &NeuroFlowModel::Config::memory_slots)
211
+ .def_readwrite("num_layers", &NeuroFlowModel::Config::num_layers)
212
+ .def_readwrite("num_associations", &NeuroFlowModel::Config::num_associations)
213
+ .def_readwrite("use_quantization", &NeuroFlowModel::Config::use_quantization)
214
+ .def_readwrite("use_mla", &NeuroFlowModel::Config::use_mla)
215
+ .def_readwrite("mla_latent_dim", &NeuroFlowModel::Config::mla_latent_dim);
216
+
217
+ // NeuroFlowModel::Output
218
+ py::class_<NeuroFlowModel::Output>(m, "ModelOutput")
219
+ .def_property_readonly("output", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.output); })
220
+ .def_property_readonly("decision", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.decision); })
221
+ .def_property_readonly("value", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.value); })
222
+ .def_property_readonly("saliency", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.saliency); })
223
+ .def_property_readonly("ecn_gate", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.ecn_gate); })
224
+ .def_property_readonly("dmn_gate", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.dmn_gate); })
225
+ .def_property_readonly("anomaly", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.anomaly); })
226
+ .def_property_readonly("mem_attention", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.mem_attention); })
227
+ .def_property_readonly("retrieved_mem", [](NeuroFlowModel::Output& o) { return tensor_to_numpy(o.retrieved_mem); })
228
+ .def_property_readonly("manifold", [](NeuroFlowModel::Output& o) {
229
+ if (o.manifold.data) return tensor_to_numpy(o.manifold);
230
+ return py::array_t<float>();
231
+ });
232
+
233
+ // NeuroFlowModel::Stats
234
+ py::class_<NeuroFlowModel::Stats>(m, "ModelStats")
235
+ .def_readonly("total_params", &NeuroFlowModel::Stats::total_params)
236
+ .def_readonly("memory_bytes", &NeuroFlowModel::Stats::memory_bytes)
237
+ .def_readonly("quantization_ratio", &NeuroFlowModel::Stats::quantization_ratio);
238
+
239
+ // NeuroFlowModel主类
240
+ py::class_<NeuroFlowModel>(m, "NeuroFlowModel")
241
+ .def(py::init<>())
242
+ .def(py::init<NeuroFlowModel::Config>(), py::arg("config"))
243
+ .def("forward", [](NeuroFlowModel& m, py::array_t<float> x,
244
+ py::object memory_input, bool consolidate, bool return_manifold) {
245
+ Tensor input = numpy_to_tensor(x);
246
+ const Tensor* mem_ptr = nullptr;
247
+ Tensor mem;
248
+
249
+ if (!memory_input.is_none()) {
250
+ mem = numpy_to_tensor(memory_input.cast<py::array_t<float>>());
251
+ mem_ptr = &mem;
252
+ }
253
+
254
+ return m.forward(input, mem_ptr, consolidate, return_manifold);
255
+ }, py::arg("x"), py::arg("memory_input") = py::none(),
256
+ py::arg("consolidate") = false, py::arg("return_manifold") = false)
257
+ .def("get_manifold_trajectory", [](NeuroFlowModel& m, py::array_t<float> x, size_t steps) {
258
+ Tensor input = numpy_to_tensor(x);
259
+ auto trajectory = m.get_manifold_trajectory(input, steps);
260
+
261
+ py::list result;
262
+ for (auto& t : trajectory) {
263
+ result.append(tensor_to_numpy(t));
264
+ }
265
+ return result;
266
+ }, py::arg("x"), py::arg("steps") = 10)
267
+ .def("set_training", &NeuroFlowModel::set_training)
268
+ .def("quantize", &NeuroFlowModel::quantize)
269
+ .def("get_stats", &NeuroFlowModel::get_stats)
270
+ .def("save", &NeuroFlowModel::save)
271
+ .def("load", &NeuroFlowModel::load)
272
+ .def("forward_text", [](NeuroFlowModel& m, py::array_t<float> x) {
273
+ Tensor input = numpy_to_tensor(x);
274
+ return m.forward(input);
275
+ })
276
+ .def_property_readonly("config", [](NeuroFlowModel& m) { return m.config; });
277
+
278
+ // NeuroFlowLite
279
+ py::class_<NeuroFlowLite, NeuroFlowModel>(m, "NeuroFlowLite")
280
+ .def(py::init<size_t>(), py::arg("input_dim") = 512);
281
+
282
+ // 便捷函数
283
+ m.def("create_tensor", [](py::array_t<float> arr) {
284
+ return numpy_to_tensor(arr);
285
+ }, "Create Tensor from numpy array");
286
+
287
+ m.def("benchmark", []() {
288
+ NeuroFlowModel::Config cfg;
289
+ cfg.input_dim = 512;
290
+ cfg.hidden_dim = 256;
291
+ cfg.output_dim = 10;
292
+
293
+ NeuroFlowModel original(cfg);
294
+
295
+ NeuroFlowModel::Config lite_cfg;
296
+ lite_cfg.input_dim = 512;
297
+ lite_cfg.hidden_dim = 128;
298
+ lite_cfg.output_dim = 10;
299
+ lite_cfg.memory_dim = 64;
300
+ lite_cfg.memory_slots = 32;
301
+ lite_cfg.num_layers = 1;
302
+ lite_cfg.use_quantization = true;
303
+
304
+ NeuroFlowModel lite(lite_cfg);
305
+
306
+ auto orig_stats = original.get_stats();
307
+ auto lite_stats = lite.get_stats();
308
+
309
+ py::dict result;
310
+ result["original_params"] = orig_stats.total_params;
311
+ result["original_memory_mb"] = orig_stats.memory_bytes / 1024.0 / 1024.0;
312
+ result["lite_params"] = lite_stats.total_params;
313
+ result["lite_memory_mb"] = lite_stats.memory_bytes / 1024.0 / 1024.0;
314
+ result["size_reduction"] = 1.0 - static_cast<float>(lite_stats.total_params) / orig_stats.total_params;
315
+
316
+ return result;
317
+ }, "Benchmark comparison between original and lite models");
318
+
319
+ // ================================================================
320
+ // MultiModal Bindings
321
+ // ================================================================
322
+
323
+ // VisionEncoder
324
+ py::class_<VisionEncoder>(m, "VisionEncoder")
325
+ .def(py::init<size_t, size_t, size_t, size_t, size_t>(),
326
+ py::arg("image_size") = 224, py::arg("patch_size") = 16,
327
+ py::arg("embed_dim") = 256, py::arg("num_heads") = 8,
328
+ py::arg("num_layers") = 4)
329
+ .def("forward", &VisionEncoder::forward);
330
+
331
+ // CrossModalFusion
332
+ py::class_<CrossModalFusion::Output>(m, "FusionOutput")
333
+ .def_readonly("fused", &CrossModalFusion::Output::fused)
334
+ .def_readonly("text_feat", &CrossModalFusion::Output::text_feat)
335
+ .def_readonly("image_feat", &CrossModalFusion::Output::image_feat)
336
+ .def_readonly("similarity", &CrossModalFusion::Output::similarity);
337
+
338
+ py::class_<CrossModalFusion>(m, "CrossModalFusion")
339
+ .def(py::init<size_t, size_t, size_t>(),
340
+ py::arg("text_dim") = 512, py::arg("vision_dim") = 256,
341
+ py::arg("fusion_dim") = 256)
342
+ .def("forward", &CrossModalFusion::forward);
343
+
344
+ // NeuroFlowMultiModal::Config
345
+ py::class_<NeuroFlowMultiModal::Config>(m, "MultiModalConfig")
346
+ .def(py::init<>())
347
+ .def_readwrite("text_dim", &NeuroFlowMultiModal::Config::text_dim)
348
+ .def_readwrite("image_size", &NeuroFlowMultiModal::Config::image_size)
349
+ .def_readwrite("patch_size", &NeuroFlowMultiModal::Config::patch_size)
350
+ .def_readwrite("vision_dim", &NeuroFlowMultiModal::Config::vision_dim)
351
+ .def_readwrite("fusion_dim", &NeuroFlowMultiModal::Config::fusion_dim)
352
+ .def_readwrite("hidden_dim", &NeuroFlowMultiModal::Config::hidden_dim)
353
+ .def_readwrite("output_dim", &NeuroFlowMultiModal::Config::output_dim)
354
+ .def_readwrite("memory_dim", &NeuroFlowMultiModal::Config::memory_dim)
355
+ .def_readwrite("memory_slots", &NeuroFlowMultiModal::Config::memory_slots)
356
+ .def_readwrite("num_layers", &NeuroFlowMultiModal::Config::num_layers)
357
+ .def_readwrite("num_associations", &NeuroFlowMultiModal::Config::num_associations)
358
+ .def_readwrite("vision_layers", &NeuroFlowMultiModal::Config::vision_layers)
359
+ .def_readwrite("vision_heads", &NeuroFlowMultiModal::Config::vision_heads)
360
+ .def_readwrite("use_quantization", &NeuroFlowMultiModal::Config::use_quantization)
361
+ .def_readwrite("use_mla", &NeuroFlowMultiModal::Config::use_mla)
362
+ .def_readwrite("mla_latent_dim", &NeuroFlowMultiModal::Config::mla_latent_dim);
363
+
364
+ // NeuroFlowMultiModal::Output
365
+ py::class_<NeuroFlowMultiModal::Output>(m, "MultiModalOutput")
366
+ .def_property_readonly("output", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.output); })
367
+ .def_property_readonly("decision", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.decision); })
368
+ .def_property_readonly("value", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.value); })
369
+ .def_property_readonly("saliency", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.saliency); })
370
+ .def_property_readonly("text_image_sim", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.text_image_sim); })
371
+ .def_property_readonly("gates", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.gates); })
372
+ .def_property_readonly("anomaly", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.anomaly); })
373
+ .def_property_readonly("retrieved_mem", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.retrieved_mem); })
374
+ .def_property_readonly("vision_feat", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.vision_feat); })
375
+ .def_property_readonly("text_feat", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.text_feat); })
376
+ .def_property_readonly("fused_feat", [](NeuroFlowMultiModal::Output& o) { return tensor_to_numpy(o.fused_feat); });
377
+
378
+ // NeuroFlowMultiModal
379
+ py::class_<NeuroFlowMultiModal>(m, "NeuroFlowMultiModal")
380
+ .def(py::init<NeuroFlowMultiModal::Config>(), py::arg("config"))
381
+ .def("forward_multimodal", [](NeuroFlowMultiModal& mm, py::array_t<float> text, py::array_t<float> image, bool consolidate, bool return_manifold) {
382
+ return mm.forward_multimodal(numpy_to_tensor(text), numpy_to_tensor(image), consolidate, return_manifold);
383
+ }, py::arg("text"), py::arg("image"), py::arg("consolidate") = false, py::arg("return_manifold") = false)
384
+ .def("forward_text", [](NeuroFlowMultiModal& mm, py::array_t<float> text) {
385
+ return mm.forward_text(numpy_to_tensor(text));
386
+ }, py::arg("text"))
387
+ .def("forward_image", [](NeuroFlowMultiModal& mm, py::array_t<float> image) {
388
+ return mm.forward_image_only(numpy_to_tensor(image));
389
+ }, py::arg("image"))
390
+ .def("set_training", &NeuroFlowMultiModal::set_training)
391
+ .def("quantize", &NeuroFlowMultiModal::quantize)
392
+ .def("get_stats", &NeuroFlowMultiModal::get_stats)
393
+ .def("save", &NeuroFlowMultiModal::save)
394
+ .def("load", &NeuroFlowMultiModal::load)
395
+ .def_readonly("config", &NeuroFlowMultiModal::config);
396
+
397
+ // 便捷:创建默认多模态模型
398
+ m.def("create_multimodal", [](size_t text_dim, size_t image_size, size_t output_dim, bool quantize) {
399
+ NeuroFlowMultiModal::Config cfg;
400
+ cfg.text_dim = text_dim;
401
+ cfg.image_size = image_size;
402
+ cfg.output_dim = output_dim;
403
+ cfg.use_quantization = quantize;
404
+ return std::make_unique<NeuroFlowMultiModal>(cfg);
405
+ }, py::arg("text_dim") = 512, py::arg("image_size") = 224, py::arg("output_dim") = 10, py::arg("quantize") = false);
406
+ }
build.sh ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # NeuroFlow C++ 编译脚本 — 自动暂停/恢复 cron 防止冲突
3
+ set -euo pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
6
+ BUILD_DIR="$SCRIPT_DIR/build"
7
+ DEST="/mnt/d/neuroflow-model/neuroflow/_core.cpython-311-x86_64-linux-gnu.so"
8
+ VENV_PYTHON="$HOME/.hermes/hermes-agent/venv/bin/python3"
9
+ PYBIND11_DIR="$($VENV_PYTHON -c 'import pybind11; print(pybind11.get_cmake_dir())')"
10
+ CRON_LEARN="bd007dc2fe14"
11
+ CRON_REPORT="5d4dac90ff0d"
12
+
13
+ echo "=== NeuroFlow C++ Build ==="
14
+
15
+ # 1. 暂停 cron 任务
16
+ echo "[1/5] Pausing cron jobs..."
17
+ hermes cron pause "$CRON_LEARN" 2>/dev/null || echo " ($CRON_LEARN already paused)"
18
+ hermes cron pause "$CRON_REPORT" 2>/dev/null || echo " ($CRON_REPORT already paused)"
19
+ sleep 2 # 等正在运行的任务结束
20
+
21
+ # 2. 编译
22
+ echo "[2/5] Building with ninja..."
23
+ mkdir -p "$BUILD_DIR"
24
+ cd "$BUILD_DIR"
25
+ cmake .. -G Ninja \
26
+ -DCMAKE_BUILD_TYPE=Release \
27
+ -DNEUROFLOW_BUILD_TESTS=OFF \
28
+ -DNEUROFLOW_BUILD_PYTHON=ON \
29
+ -DPython3_EXECUTABLE="$VENV_PYTHON" \
30
+ -Dpybind11_DIR="$PYBIND11_DIR"
31
+ ninja -j$(nproc)
32
+
33
+ # 3. 部署 so 到 neuroflow 包目录
34
+ echo "[3/5] Deploying .so to neuroflow package..."
35
+ cp "$BUILD_DIR/_core.cpython-311-x86_64-linux-gnu.so" "$DEST"
36
+
37
+ # 4. 验证
38
+ echo "[4/5] Verifying..."
39
+ "$VENV_PYTHON" -c "
40
+ import sys; sys.path.insert(0, '/mnt/d/neuroflow-model')
41
+ from neuroflow._core import create_multimodal
42
+ m = create_multimodal()
43
+ import numpy as np
44
+ x = np.random.randn(1, 512).astype(np.float32)
45
+ out = m.forward_text(x)
46
+ print(f' forward_text OK, output shape: {out.decision.shape}')
47
+ m.save('/tmp/nf_build_test.bin')
48
+ m2 = create_multimodal()
49
+ m2.load('/tmp/nf_build_test.bin')
50
+ print(' save/load roundtrip OK')
51
+ print(' ✅ Verification passed')
52
+ "
53
+
54
+ # 5. 恢复 cron
55
+ echo "[5/5] Resuming cron jobs..."
56
+ hermes cron resume "$CRON_LEARN" 2>/dev/null || echo " ($CRON_LEARN already running)"
57
+ hermes cron resume "$CRON_REPORT" 2>/dev/null || echo " ($CRON_REPORT already running)"
58
+
59
+ echo "=== Build complete ==="
configs/config.json ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "input_dim": 512,
3
+ "hidden_dim": 2048,
4
+ "output_dim": 2048,
5
+ "memory_dim": 512,
6
+ "memory_slots": 64,
7
+ "num_layers": 12,
8
+ "num_associations": 8,
9
+ "use_quantization": false,
10
+ "use_mla": false,
11
+ "mla_latent_dim": 32,
12
+ "use_causal_lm": true,
13
+ "vocab_size": 128000,
14
+ "max_seq_len": 512,
15
+ "causal_window_size": 64,
16
+ "sae_k": 64,
17
+ "ntm_memory_slots": 16,
18
+ "d_model": 512,
19
+ "mla_n_heads": 8,
20
+ "mla_max_cache_len": 4096,
21
+ "lm_num_attn_layers": 2,
22
+ "lm_pooling": "mean",
23
+ "_comment": {
24
+ "input_dim": "输入维度(d_model)",
25
+ "hidden_dim": "隐藏层维度(FFN)",
26
+ "output_dim": "三脑内部输出维度(=hidden_dim, 非vocab_size)",
27
+ "memory_dim": "记忆维度(d_mem)",
28
+ "memory_slots": "记忆槽数(MEM_SLOTS)",
29
+ "num_layers": "网络层数(ECN层)",
30
+ "num_associations": "DMN关联头数",
31
+ "use_quantization": "启用量化",
32
+ "use_mla": "启用MLA",
33
+ "mla_latent_dim": "MLA潜在维度",
34
+ "use_causal_lm": "因果LM — next-token预测",
35
+ "vocab_size": "128K多语言多领域词表(中/英/代码/数字/标点)",
36
+ "max_seq_len": "最大序列长度",
37
+ "causal_window_size": "因果窗口大小",
38
+ "sae_k": "SAE稀疏度",
39
+ "ntm_memory_slots": "NTM记忆槽数",
40
+ "d_model": "模型维度(512)",
41
+ "mla_n_heads": "MLA头数",
42
+ "mla_max_cache_len": "MLA最大缓存长度",
43
+ "lm_num_attn_layers": "CausalLM注意力层数(2-4)",
44
+ "lm_pooling": "池化方式(mean/last)"
45
+ },
46
+ "_fix_log": "2026-06-13: 128K BPE tokenizer (train_128k_tokenizer.py)"
47
+ }
configs/config_distill.json ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "input_dim": 512,
3
+ "hidden_dim": 2048,
4
+ "output_dim": 2048,
5
+ "memory_dim": 512,
6
+ "memory_slots": 64,
7
+ "num_layers": 12,
8
+ "num_associations": 8,
9
+ "use_quantization": false,
10
+ "use_mla": false,
11
+ "mla_latent_dim": 32,
12
+ "use_causal_lm": true,
13
+ "vocab_size": 5000,
14
+ "max_seq_len": 128,
15
+ "causal_window_size": 64,
16
+ "sae_k": 64,
17
+ "ntm_memory_slots": 16,
18
+ "d_model": 512,
19
+ "mla_n_heads": 8,
20
+ "mla_max_cache_len": 4096,
21
+ "lm_num_attn_layers": 2,
22
+ "lm_pooling": "mean"
23
+ }
configs/config_distill_128k.json ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "input_dim": 128,
3
+ "hidden_dim": 512,
4
+ "output_dim": 512,
5
+ "memory_dim": 128,
6
+ "memory_slots": 16,
7
+ "num_layers": 4,
8
+ "num_associations": 4,
9
+ "use_quantization": false,
10
+ "use_mla": false,
11
+ "mla_latent_dim": 16,
12
+ "use_causal_lm": true,
13
+ "vocab_size": 128000,
14
+ "max_seq_len": 128,
15
+ "causal_window_size": 16,
16
+ "sae_k": 16,
17
+ "ntm_memory_slots": 4,
18
+ "d_model": 128,
19
+ "mla_n_heads": 4,
20
+ "mla_max_cache_len": 1024,
21
+ "lm_num_attn_layers": 2,
22
+ "lm_pooling": "mean",
23
+ "data_path": "data/distill_train.txt",
24
+ "batch_size": 1,
25
+ "learning_rate": 0.0001,
26
+ "num_epochs": 100,
27
+ "save_every": 1,
28
+ "output_dir": "distill_output_128k"
29
+ }
configs/generation_config.json ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "max_new_tokens": 50,
3
+ "temperature": 1.0,
4
+ "top_k": 40,
5
+ "top_p": 0.9,
6
+ "repetition_penalty": 1.0,
7
+ "punct_penalty": 0.0,
8
+ "random_seed": 0,
9
+ "strategy": "top_k",
10
+ "eos_id": 3,
11
+ "_comment": {
12
+ "max_new_tokens": "最大生成token数",
13
+ "temperature": "采样温度(0.0,2.0]",
14
+ "top_k": "Top-K采样K值",
15
+ "top_p": "Top-P采样P值[0.0,1.0]",
16
+ "repetition_penalty": "重复惩罚[1.0,2.0]",
17
+ "punct_penalty": "标点惩罚",
18
+ "random_seed": "随机种子(0=随机)",
19
+ "strategy": "采样策略(greedy/top_k/top_p/top_k_top_p)",
20
+ "eos_id": "EOS token ID"
21
+ }
22
+ }
configs/huggingface/merges.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #version: 0.2
2
+ out out
3
+ out who
4
+ out get
5
+ so me
6
+ 10 00
7
+ 0 0
8
+ 0 1
configs/huggingface/vocab.json ADDED
@@ -0,0 +1,4999 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "<pad>": 0,
3
+ "<s>": 1,
4
+ "</s>": 2,
5
+ "<unk>": 3,
6
+ "一": 4,
7
+ "丁": 5,
8
+ "丂": 6,
9
+ "七": 7,
10
+ "丄": 8,
11
+ "丅": 9,
12
+ "丆": 10,
13
+ "万": 11,
14
+ "丈": 12,
15
+ "三": 13,
16
+ "上": 14,
17
+ "下": 15,
18
+ "丌": 16,
19
+ "不": 17,
20
+ "与": 18,
21
+ "丏": 19,
22
+ "丐": 20,
23
+ "丑": 21,
24
+ "丒": 22,
25
+ "专": 23,
26
+ "且": 24,
27
+ "丕": 25,
28
+ "世": 26,
29
+ "丗": 27,
30
+ "丘": 28,
31
+ "丙": 29,
32
+ "业": 30,
33
+ "丛": 31,
34
+ "东": 32,
35
+ "丝": 33,
36
+ "丞": 34,
37
+ "丟": 35,
38
+ "丠": 36,
39
+ "両": 37,
40
+ "丢": 38,
41
+ "丣": 39,
42
+ "两": 40,
43
+ "严": 41,
44
+ "並": 42,
45
+ "丧": 43,
46
+ "丨": 44,
47
+ "丩": 45,
48
+ "个": 46,
49
+ "丫": 47,
50
+ "丬": 48,
51
+ "中": 49,
52
+ "丮": 50,
53
+ "丯": 51,
54
+ "丰": 52,
55
+ "丱": 53,
56
+ "串": 54,
57
+ "丳": 55,
58
+ "临": 56,
59
+ "丵": 57,
60
+ "丶": 58,
61
+ "丷": 59,
62
+ "丸": 60,
63
+ "丹": 61,
64
+ "为": 62,
65
+ "主": 63,
66
+ "丼": 64,
67
+ "丽": 65,
68
+ "举": 66,
69
+ "丿": 67,
70
+ "乀": 68,
71
+ "乁": 69,
72
+ "乂": 70,
73
+ "乃": 71,
74
+ "乄": 72,
75
+ "久": 73,
76
+ "乆": 74,
77
+ "乇": 75,
78
+ "么": 76,
79
+ "义": 77,
80
+ "乊": 78,
81
+ "之": 79,
82
+ "乌": 80,
83
+ "乍": 81,
84
+ "乎": 82,
85
+ "乏": 83,
86
+ "乐": 84,
87
+ "乑": 85,
88
+ "乒": 86,
89
+ "乓": 87,
90
+ "乔": 88,
91
+ "乕": 89,
92
+ "乖": 90,
93
+ "乗": 91,
94
+ "乘": 92,
95
+ "乙": 93,
96
+ "乚": 94,
97
+ "乛": 95,
98
+ "乜": 96,
99
+ "九": 97,
100
+ "乞": 98,
101
+ "也": 99,
102
+ "习": 100,
103
+ "乡": 101,
104
+ "乢": 102,
105
+ "乣": 103,
106
+ "乤": 104,
107
+ "乥": 105,
108
+ "书": 106,
109
+ "乧": 107,
110
+ "乨": 108,
111
+ "乩": 109,
112
+ "乪": 110,
113
+ "乫": 111,
114
+ "乬": 112,
115
+ "乭": 113,
116
+ "乮": 114,
117
+ "乯": 115,
118
+ "买": 116,
119
+ "乱": 117,
120
+ "乲": 118,
121
+ "乳": 119,
122
+ "乴": 120,
123
+ "乵": 121,
124
+ "乶": 122,
125
+ "乷": 123,
126
+ "乸": 124,
127
+ "乹": 125,
128
+ "乺": 126,
129
+ "乻": 127,
130
+ "乼": 128,
131
+ "乽": 129,
132
+ "乾": 130,
133
+ "乿": 131,
134
+ "亀": 132,
135
+ "亁": 133,
136
+ "亂": 134,
137
+ "亃": 135,
138
+ "亄": 136,
139
+ "亅": 137,
140
+ "了": 138,
141
+ "亇": 139,
142
+ "予": 140,
143
+ "争": 141,
144
+ "亊": 142,
145
+ "事": 143,
146
+ "二": 144,
147
+ "亍": 145,
148
+ "于": 146,
149
+ "亏": 147,
150
+ "亐": 148,
151
+ "云": 149,
152
+ "互": 150,
153
+ "亓": 151,
154
+ "五": 152,
155
+ "井": 153,
156
+ "亖": 154,
157
+ "亗": 155,
158
+ "亘": 156,
159
+ "亙": 157,
160
+ "亚": 158,
161
+ "些": 159,
162
+ "亜": 160,
163
+ "亝": 161,
164
+ "亞": 162,
165
+ "亟": 163,
166
+ "亠": 164,
167
+ "亡": 165,
168
+ "亢": 166,
169
+ "亣": 167,
170
+ "交": 168,
171
+ "亥": 169,
172
+ "亦": 170,
173
+ "产": 171,
174
+ "亨": 172,
175
+ "亩": 173,
176
+ "亪": 174,
177
+ "享": 175,
178
+ "京": 176,
179
+ "亭": 177,
180
+ "亮": 178,
181
+ "亯": 179,
182
+ "亰": 180,
183
+ "亱": 181,
184
+ "亲": 182,
185
+ "亳": 183,
186
+ "亴": 184,
187
+ "亵": 185,
188
+ "亶": 186,
189
+ "亷": 187,
190
+ "亸": 188,
191
+ "亹": 189,
192
+ "人": 190,
193
+ "亻": 191,
194
+ "亼": 192,
195
+ "亽": 193,
196
+ "亾": 194,
197
+ "亿": 195,
198
+ "什": 196,
199
+ "仁": 197,
200
+ "仂": 198,
201
+ "仃": 199,
202
+ "仄": 200,
203
+ "仅": 201,
204
+ "仆": 202,
205
+ "仇": 203,
206
+ "仈": 204,
207
+ "仉": 205,
208
+ "今": 206,
209
+ "介": 207,
210
+ "仌": 208,
211
+ "仍": 209,
212
+ "从": 210,
213
+ "仏": 211,
214
+ "仐": 212,
215
+ "仑": 213,
216
+ "仒": 214,
217
+ "仓": 215,
218
+ "仔": 216,
219
+ "仕": 217,
220
+ "他": 218,
221
+ "仗": 219,
222
+ "付": 220,
223
+ "仙": 221,
224
+ "仚": 222,
225
+ "仛": 223,
226
+ "仜": 224,
227
+ "仝": 225,
228
+ "仞": 226,
229
+ "仟": 227,
230
+ "仠": 228,
231
+ "仡": 229,
232
+ "仢": 230,
233
+ "代": 231,
234
+ "令": 232,
235
+ "以": 233,
236
+ "仦": 234,
237
+ "仧": 235,
238
+ "仨": 236,
239
+ "仩": 237,
240
+ "仪": 238,
241
+ "仫": 239,
242
+ "们": 240,
243
+ "仭": 241,
244
+ "仮": 242,
245
+ "仯": 243,
246
+ "仰": 244,
247
+ "仱": 245,
248
+ "仲": 246,
249
+ "仳": 247,
250
+ "仴": 248,
251
+ "仵": 249,
252
+ "件": 250,
253
+ "价": 251,
254
+ "仸": 252,
255
+ "仹": 253,
256
+ "仺": 254,
257
+ "任": 255,
258
+ "仼": 256,
259
+ "份": 257,
260
+ "仾": 258,
261
+ "仿": 259,
262
+ "伀": 260,
263
+ "企": 261,
264
+ "伂": 262,
265
+ "伃": 263,
266
+ "伄": 264,
267
+ "伅": 265,
268
+ "伆": 266,
269
+ "伇": 267,
270
+ "伈": 268,
271
+ "伉": 269,
272
+ "伊": 270,
273
+ "伋": 271,
274
+ "伌": 272,
275
+ "伍": 273,
276
+ "伎": 274,
277
+ "伏": 275,
278
+ "伐": 276,
279
+ "休": 277,
280
+ "伒": 278,
281
+ "伓": 279,
282
+ "伔": 280,
283
+ "伕": 281,
284
+ "伖": 282,
285
+ "众": 283,
286
+ "优": 284,
287
+ "伙": 285,
288
+ "会": 286,
289
+ "伛": 287,
290
+ "伜": 288,
291
+ "伝": 289,
292
+ "伞": 290,
293
+ "伟": 291,
294
+ "传": 292,
295
+ "伡": 293,
296
+ "伢": 294,
297
+ "伣": 295,
298
+ "伤": 296,
299
+ "伥": 297,
300
+ "伦": 298,
301
+ "伧": 299,
302
+ "伨": 300,
303
+ "伩": 301,
304
+ "伪": 302,
305
+ "伫": 303,
306
+ "伬": 304,
307
+ "伭": 305,
308
+ "伮": 306,
309
+ "伯": 307,
310
+ "估": 308,
311
+ "伱": 309,
312
+ "伲": 310,
313
+ "伳": 311,
314
+ "伴": 312,
315
+ "伵": 313,
316
+ "伶": 314,
317
+ "伷": 315,
318
+ "伸": 316,
319
+ "伹": 317,
320
+ "伺": 318,
321
+ "伻": 319,
322
+ "似": 320,
323
+ "伽": 321,
324
+ "伾": 322,
325
+ "伿": 323,
326
+ "佀": 324,
327
+ "佁": 325,
328
+ "佂": 326,
329
+ "佃": 327,
330
+ "佄": 328,
331
+ "佅": 329,
332
+ "但": 330,
333
+ "佇": 331,
334
+ "佈": 332,
335
+ "佉": 333,
336
+ "佊": 334,
337
+ "佋": 335,
338
+ "佌": 336,
339
+ "位": 337,
340
+ "低": 338,
341
+ "住": 339,
342
+ "佐": 340,
343
+ "佑": 341,
344
+ "佒": 342,
345
+ "体": 343,
346
+ "佔": 344,
347
+ "何": 345,
348
+ "佖": 346,
349
+ "佗": 347,
350
+ "佘": 348,
351
+ "余": 349,
352
+ "佚": 350,
353
+ "佛": 351,
354
+ "作": 352,
355
+ "佝": 353,
356
+ "佞": 354,
357
+ "佟": 355,
358
+ "你": 356,
359
+ "佡": 357,
360
+ "佢": 358,
361
+ "佣": 359,
362
+ "佤": 360,
363
+ "佥": 361,
364
+ "佦": 362,
365
+ "佧": 363,
366
+ "佨": 364,
367
+ "佩": 365,
368
+ "佪": 366,
369
+ "佫": 367,
370
+ "佬": 368,
371
+ "佭": 369,
372
+ "佮": 370,
373
+ "佯": 371,
374
+ "佰": 372,
375
+ "佱": 373,
376
+ "佲": 374,
377
+ "佳": 375,
378
+ "佴": 376,
379
+ "併": 377,
380
+ "佶": 378,
381
+ "佷": 379,
382
+ "佸": 380,
383
+ "佹": 381,
384
+ "佺": 382,
385
+ "佻": 383,
386
+ "佼": 384,
387
+ "佽": 385,
388
+ "佾": 386,
389
+ "使": 387,
390
+ "侀": 388,
391
+ "侁": 389,
392
+ "侂": 390,
393
+ "侃": 391,
394
+ "侄": 392,
395
+ "侅": 393,
396
+ "來": 394,
397
+ "侇": 395,
398
+ "侈": 396,
399
+ "侉": 397,
400
+ "侊": 398,
401
+ "例": 399,
402
+ "侌": 400,
403
+ "侍": 401,
404
+ "侎": 402,
405
+ "侏": 403,
406
+ "侐": 404,
407
+ "侑": 405,
408
+ "侒": 406,
409
+ "侓": 407,
410
+ "侔": 408,
411
+ "侕": 409,
412
+ "侖": 410,
413
+ "侗": 411,
414
+ "侘": 412,
415
+ "侙": 413,
416
+ "侚": 414,
417
+ "供": 415,
418
+ "侜": 416,
419
+ "依": 417,
420
+ "侞": 418,
421
+ "侟": 419,
422
+ "侠": 420,
423
+ "価": 421,
424
+ "侢": 422,
425
+ "侣": 423,
426
+ "侤": 424,
427
+ "侥": 425,
428
+ "侦": 426,
429
+ "侧": 427,
430
+ "侨": 428,
431
+ "侩": 429,
432
+ "侪": 430,
433
+ "侫": 431,
434
+ "侬": 432,
435
+ "侭": 433,
436
+ "侮": 434,
437
+ "侯": 435,
438
+ "侰": 436,
439
+ "侱": 437,
440
+ "侲": 438,
441
+ "侳": 439,
442
+ "侴": 440,
443
+ "侵": 441,
444
+ "侶": 442,
445
+ "侷": 443,
446
+ "侸": 444,
447
+ "侹": 445,
448
+ "侺": 446,
449
+ "侻": 447,
450
+ "侼": 448,
451
+ "侽": 449,
452
+ "侾": 450,
453
+ "便": 451,
454
+ "俀": 452,
455
+ "俁": 453,
456
+ "係": 454,
457
+ "促": 455,
458
+ "俄": 456,
459
+ "俅": 457,
460
+ "俆": 458,
461
+ "俇": 459,
462
+ "俈": 460,
463
+ "俉": 461,
464
+ "俊": 462,
465
+ "俋": 463,
466
+ "俌": 464,
467
+ "俍": 465,
468
+ "俎": 466,
469
+ "俏": 467,
470
+ "俐": 468,
471
+ "俑": 469,
472
+ "俒": 470,
473
+ "俓": 471,
474
+ "俔": 472,
475
+ "俕": 473,
476
+ "俖": 474,
477
+ "俗": 475,
478
+ "俘": 476,
479
+ "俙": 477,
480
+ "俚": 478,
481
+ "俛": 479,
482
+ "俜": 480,
483
+ "保": 481,
484
+ "俞": 482,
485
+ "俟": 483,
486
+ "俠": 484,
487
+ "信": 485,
488
+ "俢": 486,
489
+ "俣": 487,
490
+ "俤": 488,
491
+ "俥": 489,
492
+ "俦": 490,
493
+ "俧": 491,
494
+ "俨": 492,
495
+ "俩": 493,
496
+ "俪": 494,
497
+ "俫": 495,
498
+ "俬": 496,
499
+ "俭": 497,
500
+ "修": 498,
501
+ "俯": 499,
502
+ "俰": 500,
503
+ "俱": 501,
504
+ "俲": 502,
505
+ "俳": 503,
506
+ "俴": 504,
507
+ "俵": 505,
508
+ "俶": 506,
509
+ "俷": 507,
510
+ "俸": 508,
511
+ "俹": 509,
512
+ "俺": 510,
513
+ "俻": 511,
514
+ "俼": 512,
515
+ "俽": 513,
516
+ "俾": 514,
517
+ "俿": 515,
518
+ "倀": 516,
519
+ "倁": 517,
520
+ "倂": 518,
521
+ "倃": 519,
522
+ "倄": 520,
523
+ "倅": 521,
524
+ "倆": 522,
525
+ "倇": 523,
526
+ "倈": 524,
527
+ "倉": 525,
528
+ "倊": 526,
529
+ "個": 527,
530
+ "倌": 528,
531
+ "倍": 529,
532
+ "倎": 530,
533
+ "倏": 531,
534
+ "倐": 532,
535
+ "們": 533,
536
+ "倒": 534,
537
+ "倓": 535,
538
+ "倔": 536,
539
+ "倕": 537,
540
+ "倖": 538,
541
+ "倗": 539,
542
+ "倘": 540,
543
+ "候": 541,
544
+ "倚": 542,
545
+ "倛": 543,
546
+ "倜": 544,
547
+ "倝": 545,
548
+ "倞": 546,
549
+ "借": 547,
550
+ "倠": 548,
551
+ "倡": 549,
552
+ "倢": 550,
553
+ "倣": 551,
554
+ "値": 552,
555
+ "倥": 553,
556
+ "倦": 554,
557
+ "倧": 555,
558
+ "倨": 556,
559
+ "倩": 557,
560
+ "倪": 558,
561
+ "倫": 559,
562
+ "倬": 560,
563
+ "倭": 561,
564
+ "倮": 562,
565
+ "倯": 563,
566
+ "倰": 564,
567
+ "倱": 565,
568
+ "倲": 566,
569
+ "倳": 567,
570
+ "倴": 568,
571
+ "倵": 569,
572
+ "倶": 570,
573
+ "倷": 571,
574
+ "倸": 572,
575
+ "倹": 573,
576
+ "债": 574,
577
+ "倻": 575,
578
+ "值": 576,
579
+ "倽": 577,
580
+ "倾": 578,
581
+ "倿": 579,
582
+ "偀": 580,
583
+ "偁": 581,
584
+ "偂": 582,
585
+ "偃": 583,
586
+ "偄": 584,
587
+ "偅": 585,
588
+ "偆": 586,
589
+ "假": 587,
590
+ "偈": 588,
591
+ "偉": 589,
592
+ "偊": 590,
593
+ "偋": 591,
594
+ "偌": 592,
595
+ "偍": 593,
596
+ "偎": 594,
597
+ "偏": 595,
598
+ "偐": 596,
599
+ "偑": 597,
600
+ "偒": 598,
601
+ "偓": 599,
602
+ "偔": 600,
603
+ "偕": 601,
604
+ "偖": 602,
605
+ "偗": 603,
606
+ "偘": 604,
607
+ "偙": 605,
608
+ "做": 606,
609
+ "偛": 607,
610
+ "停": 608,
611
+ "偝": 609,
612
+ "偞": 610,
613
+ "偟": 611,
614
+ "偠": 612,
615
+ "偡": 613,
616
+ "偢": 614,
617
+ "偣": 615,
618
+ "偤": 616,
619
+ "健": 617,
620
+ "偦": 618,
621
+ "偧": 619,
622
+ "偨": 620,
623
+ "偩": 621,
624
+ "偪": 622,
625
+ "偫": 623,
626
+ "偬": 624,
627
+ "偭": 625,
628
+ "偮": 626,
629
+ "偯": 627,
630
+ "偰": 628,
631
+ "偱": 629,
632
+ "偲": 630,
633
+ "偳": 631,
634
+ "側": 632,
635
+ "偵": 633,
636
+ "偶": 634,
637
+ "偷": 635,
638
+ "偸": 636,
639
+ "偹": 637,
640
+ "偺": 638,
641
+ "偻": 639,
642
+ "偼": 640,
643
+ "偽": 641,
644
+ "偾": 642,
645
+ "偿": 643,
646
+ "傀": 644,
647
+ "傁": 645,
648
+ "傂": 646,
649
+ "傃": 647,
650
+ "傄": 648,
651
+ "傅": 649,
652
+ "傆": 650,
653
+ "傇": 651,
654
+ "傈": 652,
655
+ "傉": 653,
656
+ "傊": 654,
657
+ "傋": 655,
658
+ "傌": 656,
659
+ "傍": 657,
660
+ "傎": 658,
661
+ "傏": 659,
662
+ "傐": 660,
663
+ "傑": 661,
664
+ "傒": 662,
665
+ "傓": 663,
666
+ "傔": 664,
667
+ "傕": 665,
668
+ "傖": 666,
669
+ "傗": 667,
670
+ "傘": 668,
671
+ "備": 669,
672
+ "傚": 670,
673
+ "傛": 671,
674
+ "傜": 672,
675
+ "傝": 673,
676
+ "傞": 674,
677
+ "傟": 675,
678
+ "傠": 676,
679
+ "傡": 677,
680
+ "傢": 678,
681
+ "傣": 679,
682
+ "傤": 680,
683
+ "傥": 681,
684
+ "傦": 682,
685
+ "傧": 683,
686
+ "储": 684,
687
+ "傩": 685,
688
+ "傪": 686,
689
+ "傫": 687,
690
+ "催": 688,
691
+ "傭": 689,
692
+ "傮": 690,
693
+ "傯": 691,
694
+ "傰": 692,
695
+ "傱": 693,
696
+ "傲": 694,
697
+ "傳": 695,
698
+ "傴": 696,
699
+ "債": 697,
700
+ "傶": 698,
701
+ "傷": 699,
702
+ "傸": 700,
703
+ "傹": 701,
704
+ "傺": 702,
705
+ "傻": 703,
706
+ "傼": 704,
707
+ "傽": 705,
708
+ "傾": 706,
709
+ "傿": 707,
710
+ "僀": 708,
711
+ "僁": 709,
712
+ "僂": 710,
713
+ "僃": 711,
714
+ "僄": 712,
715
+ "僅": 713,
716
+ "僆": 714,
717
+ "僇": 715,
718
+ "僈": 716,
719
+ "僉": 717,
720
+ "僊": 718,
721
+ "僋": 719,
722
+ "僌": 720,
723
+ "働": 721,
724
+ "僎": 722,
725
+ "像": 723,
726
+ "僐": 724,
727
+ "僑": 725,
728
+ "僒": 726,
729
+ "僓": 727,
730
+ "僔": 728,
731
+ "僕": 729,
732
+ "僖": 730,
733
+ "僗": 731,
734
+ "僘": 732,
735
+ "僙": 733,
736
+ "僚": 734,
737
+ "僛": 735,
738
+ "僜": 736,
739
+ "僝": 737,
740
+ "僞": 738,
741
+ "僟": 739,
742
+ "僠": 740,
743
+ "僡": 741,
744
+ "僢": 742,
745
+ "僣": 743,
746
+ "僤": 744,
747
+ "僥": 745,
748
+ "僦": 746,
749
+ "僧": 747,
750
+ "僨": 748,
751
+ "僩": 749,
752
+ "僪": 750,
753
+ "僫": 751,
754
+ "僬": 752,
755
+ "僭": 753,
756
+ "僮": 754,
757
+ "僯": 755,
758
+ "僰": 756,
759
+ "僱": 757,
760
+ "僲": 758,
761
+ "僳": 759,
762
+ "僴": 760,
763
+ "僵": 761,
764
+ "僶": 762,
765
+ "僷": 763,
766
+ "僸": 764,
767
+ "價": 765,
768
+ "僺": 766,
769
+ "僻": 767,
770
+ "僼": 768,
771
+ "僽": 769,
772
+ "僾": 770,
773
+ "僿": 771,
774
+ "儀": 772,
775
+ "儁": 773,
776
+ "儂": 774,
777
+ "儃": 775,
778
+ "億": 776,
779
+ "儅": 777,
780
+ "儆": 778,
781
+ "儇": 779,
782
+ "儈": 780,
783
+ "儉": 781,
784
+ "儊": 782,
785
+ "儋": 783,
786
+ "儌": 784,
787
+ "儍": 785,
788
+ "儎": 786,
789
+ "儏": 787,
790
+ "儐": 788,
791
+ "儑": 789,
792
+ "儒": 790,
793
+ "儓": 791,
794
+ "儔": 792,
795
+ "儕": 793,
796
+ "儖": 794,
797
+ "儗": 795,
798
+ "儘": 796,
799
+ "儙": 797,
800
+ "儚": 798,
801
+ "儛": 799,
802
+ "儜": 800,
803
+ "儝": 801,
804
+ "儞": 802,
805
+ "償": 803,
806
+ "儠": 804,
807
+ "儡": 805,
808
+ "儢": 806,
809
+ "儣": 807,
810
+ "儤": 808,
811
+ "儥": 809,
812
+ "儦": 810,
813
+ "儧": 811,
814
+ "儨": 812,
815
+ "儩": 813,
816
+ "優": 814,
817
+ "儫": 815,
818
+ "儬": 816,
819
+ "儭": 817,
820
+ "儮": 818,
821
+ "儯": 819,
822
+ "儰": 820,
823
+ "儱": 821,
824
+ "儲": 822,
825
+ "儳": 823,
826
+ "儴": 824,
827
+ "儵": 825,
828
+ "儶": 826,
829
+ "儷": 827,
830
+ "儸": 828,
831
+ "儹": 829,
832
+ "儺": 830,
833
+ "儻": 831,
834
+ "儼": 832,
835
+ "儽": 833,
836
+ "儾": 834,
837
+ "儿": 835,
838
+ "兀": 836,
839
+ "允": 837,
840
+ "兂": 838,
841
+ "元": 839,
842
+ "兄": 840,
843
+ "充": 841,
844
+ "兆": 842,
845
+ "兇": 843,
846
+ "先": 844,
847
+ "光": 845,
848
+ "兊": 846,
849
+ "克": 847,
850
+ "兌": 848,
851
+ "免": 849,
852
+ "兎": 850,
853
+ "兏": 851,
854
+ "児": 852,
855
+ "兑": 853,
856
+ "兒": 854,
857
+ "兓": 855,
858
+ "兔": 856,
859
+ "兕": 857,
860
+ "兖": 858,
861
+ "兗": 859,
862
+ "兘": 860,
863
+ "兙": 861,
864
+ "党": 862,
865
+ "兛": 863,
866
+ "兜": 864,
867
+ "兝": 865,
868
+ "兞": 866,
869
+ "兟": 867,
870
+ "兠": 868,
871
+ "兡": 869,
872
+ "兢": 870,
873
+ "兣": 871,
874
+ "兤": 872,
875
+ "入": 873,
876
+ "兦": 874,
877
+ "內": 875,
878
+ "全": 876,
879
+ "兩": 877,
880
+ "兪": 878,
881
+ "八": 879,
882
+ "公": 880,
883
+ "六": 881,
884
+ "兮": 882,
885
+ "兯": 883,
886
+ "兰": 884,
887
+ "共": 885,
888
+ "兲": 886,
889
+ "关": 887,
890
+ "兴": 888,
891
+ "兵": 889,
892
+ "其": 890,
893
+ "具": 891,
894
+ "典": 892,
895
+ "兹": 893,
896
+ "兺": 894,
897
+ "养": 895,
898
+ "兼": 896,
899
+ "兽": 897,
900
+ "兾": 898,
901
+ "兿": 899,
902
+ "冀": 900,
903
+ "冁": 901,
904
+ "冂": 902,
905
+ "冃": 903,
906
+ "冄": 904,
907
+ "内": 905,
908
+ "円": 906,
909
+ "冇": 907,
910
+ "冈": 908,
911
+ "冉": 909,
912
+ "冊": 910,
913
+ "冋": 911,
914
+ "册": 912,
915
+ "再": 913,
916
+ "冎": 914,
917
+ "冏": 915,
918
+ "冐": 916,
919
+ "冑": 917,
920
+ "冒": 918,
921
+ "冓": 919,
922
+ "冔": 920,
923
+ "冕": 921,
924
+ "冖": 922,
925
+ "冗": 923,
926
+ "冘": 924,
927
+ "写": 925,
928
+ "冚": 926,
929
+ "军": 927,
930
+ "农": 928,
931
+ "冝": 929,
932
+ "冞": 930,
933
+ "冟": 931,
934
+ "冠": 932,
935
+ "冡": 933,
936
+ "冢": 934,
937
+ "冣": 935,
938
+ "冤": 936,
939
+ "冥": 937,
940
+ "冦": 938,
941
+ "冧": 939,
942
+ "冨": 940,
943
+ "冩": 941,
944
+ "冪": 942,
945
+ "冫": 943,
946
+ "冬": 944,
947
+ "冭": 945,
948
+ "冮": 946,
949
+ "冯": 947,
950
+ "冰": 948,
951
+ "冱": 949,
952
+ "冲": 950,
953
+ "决": 951,
954
+ "冴": 952,
955
+ "况": 953,
956
+ "冶": 954,
957
+ "冷": 955,
958
+ "冸": 956,
959
+ "冹": 957,
960
+ "冺": 958,
961
+ "冻": 959,
962
+ "冼": 960,
963
+ "冽": 961,
964
+ "冾": 962,
965
+ "冿": 963,
966
+ "净": 964,
967
+ "凁": 965,
968
+ "凂": 966,
969
+ "凃": 967,
970
+ "凄": 968,
971
+ "凅": 969,
972
+ "准": 970,
973
+ "凇": 971,
974
+ "凈": 972,
975
+ "凉": 973,
976
+ "凊": 974,
977
+ "凋": 975,
978
+ "凌": 976,
979
+ "凍": 977,
980
+ "凎": 978,
981
+ "减": 979,
982
+ "凐": 980,
983
+ "凑": 981,
984
+ "凒": 982,
985
+ "凓": 983,
986
+ "凔": 984,
987
+ "凕": 985,
988
+ "凖": 986,
989
+ "凗": 987,
990
+ "凘": 988,
991
+ "凙": 989,
992
+ "凚": 990,
993
+ "凛": 991,
994
+ "凜": 992,
995
+ "凝": 993,
996
+ "凞": 994,
997
+ "凟": 995,
998
+ "几": 996,
999
+ "凡": 997,
1000
+ "凢": 998,
1001
+ "凣": 999,
1002
+ "凤": 1000,
1003
+ "凥": 1001,
1004
+ "処": 1002,
1005
+ "凧": 1003,
1006
+ "凨": 1004,
1007
+ "凩": 1005,
1008
+ "凪": 1006,
1009
+ "凫": 1007,
1010
+ "凬": 1008,
1011
+ "凭": 1009,
1012
+ "凮": 1010,
1013
+ "凯": 1011,
1014
+ "凰": 1012,
1015
+ "凱": 1013,
1016
+ "凲": 1014,
1017
+ "凳": 1015,
1018
+ "凴": 1016,
1019
+ "凵": 1017,
1020
+ "凶": 1018,
1021
+ "凷": 1019,
1022
+ "凸": 1020,
1023
+ "凹": 1021,
1024
+ "出": 1022,
1025
+ "击": 1023,
1026
+ "凼": 1024,
1027
+ "函": 1025,
1028
+ "凾": 1026,
1029
+ "凿": 1027,
1030
+ "刀": 1028,
1031
+ "刁": 1029,
1032
+ "刂": 1030,
1033
+ "刃": 1031,
1034
+ "刄": 1032,
1035
+ "刅": 1033,
1036
+ "分": 1034,
1037
+ "切": 1035,
1038
+ "刈": 1036,
1039
+ "刉": 1037,
1040
+ "刊": 1038,
1041
+ "刋": 1039,
1042
+ "刌": 1040,
1043
+ "刍": 1041,
1044
+ "刎": 1042,
1045
+ "刏": 1043,
1046
+ "刐": 1044,
1047
+ "刑": 1045,
1048
+ "划": 1046,
1049
+ "刓": 1047,
1050
+ "刔": 1048,
1051
+ "刕": 1049,
1052
+ "刖": 1050,
1053
+ "列": 1051,
1054
+ "刘": 1052,
1055
+ "则": 1053,
1056
+ "刚": 1054,
1057
+ "创": 1055,
1058
+ "刜": 1056,
1059
+ "初": 1057,
1060
+ "刞": 1058,
1061
+ "刟": 1059,
1062
+ "删": 1060,
1063
+ "刡": 1061,
1064
+ "刢": 1062,
1065
+ "刣": 1063,
1066
+ "判": 1064,
1067
+ "別": 1065,
1068
+ "刦": 1066,
1069
+ "刧": 1067,
1070
+ "刨": 1068,
1071
+ "利": 1069,
1072
+ "刪": 1070,
1073
+ "别": 1071,
1074
+ "刬": 1072,
1075
+ "刭": 1073,
1076
+ "刮": 1074,
1077
+ "刯": 1075,
1078
+ "到": 1076,
1079
+ "刱": 1077,
1080
+ "刲": 1078,
1081
+ "刳": 1079,
1082
+ "刴": 1080,
1083
+ "刵": 1081,
1084
+ "制": 1082,
1085
+ "刷": 1083,
1086
+ "券": 1084,
1087
+ "刹": 1085,
1088
+ "刺": 1086,
1089
+ "刻": 1087,
1090
+ "刼": 1088,
1091
+ "刽": 1089,
1092
+ "刾": 1090,
1093
+ "刿": 1091,
1094
+ "剀": 1092,
1095
+ "剁": 1093,
1096
+ "剂": 1094,
1097
+ "剃": 1095,
1098
+ "剄": 1096,
1099
+ "剅": 1097,
1100
+ "剆": 1098,
1101
+ "則": 1099,
1102
+ "剈": 1100,
1103
+ "剉": 1101,
1104
+ "削": 1102,
1105
+ "剋": 1103,
1106
+ "剌": 1104,
1107
+ "前": 1105,
1108
+ "剎": 1106,
1109
+ "剏": 1107,
1110
+ "剐": 1108,
1111
+ "剑": 1109,
1112
+ "剒": 1110,
1113
+ "剓": 1111,
1114
+ "剔": 1112,
1115
+ "剕": 1113,
1116
+ "剖": 1114,
1117
+ "剗": 1115,
1118
+ "剘": 1116,
1119
+ "剙": 1117,
1120
+ "剚": 1118,
1121
+ "剛": 1119,
1122
+ "剜": 1120,
1123
+ "剝": 1121,
1124
+ "剞": 1122,
1125
+ "剟": 1123,
1126
+ "剠": 1124,
1127
+ "剡": 1125,
1128
+ "剢": 1126,
1129
+ "剣": 1127,
1130
+ "剤": 1128,
1131
+ "剥": 1129,
1132
+ "剦": 1130,
1133
+ "剧": 1131,
1134
+ "剨": 1132,
1135
+ "剩": 1133,
1136
+ "剪": 1134,
1137
+ "剫": 1135,
1138
+ "剬": 1136,
1139
+ "剭": 1137,
1140
+ "剮": 1138,
1141
+ "副": 1139,
1142
+ "剰": 1140,
1143
+ "剱": 1141,
1144
+ "割": 1142,
1145
+ "剳": 1143,
1146
+ "剴": 1144,
1147
+ "創": 1145,
1148
+ "剶": 1146,
1149
+ "剷": 1147,
1150
+ "剸": 1148,
1151
+ "剹": 1149,
1152
+ "剺": 1150,
1153
+ "剻": 1151,
1154
+ "剼": 1152,
1155
+ "剽": 1153,
1156
+ "剾": 1154,
1157
+ "剿": 1155,
1158
+ "劀": 1156,
1159
+ "劁": 1157,
1160
+ "劂": 1158,
1161
+ "劃": 1159,
1162
+ "劄": 1160,
1163
+ "劅": 1161,
1164
+ "劆": 1162,
1165
+ "劇": 1163,
1166
+ "劈": 1164,
1167
+ "劉": 1165,
1168
+ "劊": 1166,
1169
+ "劋": 1167,
1170
+ "劌": 1168,
1171
+ "劍": 1169,
1172
+ "劎": 1170,
1173
+ "劏": 1171,
1174
+ "劐": 1172,
1175
+ "劑": 1173,
1176
+ "劒": 1174,
1177
+ "劓": 1175,
1178
+ "劔": 1176,
1179
+ "劕": 1177,
1180
+ "劖": 1178,
1181
+ "劗": 1179,
1182
+ "劘": 1180,
1183
+ "劙": 1181,
1184
+ "劚": 1182,
1185
+ "力": 1183,
1186
+ "劜": 1184,
1187
+ "劝": 1185,
1188
+ "办": 1186,
1189
+ "功": 1187,
1190
+ "加": 1188,
1191
+ "务": 1189,
1192
+ "劢": 1190,
1193
+ "劣": 1191,
1194
+ "劤": 1192,
1195
+ "劥": 1193,
1196
+ "劦": 1194,
1197
+ "劧": 1195,
1198
+ "动": 1196,
1199
+ "助": 1197,
1200
+ "努": 1198,
1201
+ "劫": 1199,
1202
+ "劬": 1200,
1203
+ "劭": 1201,
1204
+ "劮": 1202,
1205
+ "劯": 1203,
1206
+ "劰": 1204,
1207
+ "励": 1205,
1208
+ "劲": 1206,
1209
+ "劳": 1207,
1210
+ "労": 1208,
1211
+ "劵": 1209,
1212
+ "劶": 1210,
1213
+ "劷": 1211,
1214
+ "劸": 1212,
1215
+ "効": 1213,
1216
+ "劺": 1214,
1217
+ "劻": 1215,
1218
+ "劼": 1216,
1219
+ "劽": 1217,
1220
+ "劾": 1218,
1221
+ "势": 1219,
1222
+ "勀": 1220,
1223
+ "勁": 1221,
1224
+ "勂": 1222,
1225
+ "勃": 1223,
1226
+ "勄": 1224,
1227
+ "勅": 1225,
1228
+ "勆": 1226,
1229
+ "勇": 1227,
1230
+ "勈": 1228,
1231
+ "勉": 1229,
1232
+ "勊": 1230,
1233
+ "勋": 1231,
1234
+ "勌": 1232,
1235
+ "勍": 1233,
1236
+ "勎": 1234,
1237
+ "勏": 1235,
1238
+ "勐": 1236,
1239
+ "勑": 1237,
1240
+ "勒": 1238,
1241
+ "勓": 1239,
1242
+ "勔": 1240,
1243
+ "動": 1241,
1244
+ "勖": 1242,
1245
+ "勗": 1243,
1246
+ "勘": 1244,
1247
+ "務": 1245,
1248
+ "勚": 1246,
1249
+ "勛": 1247,
1250
+ "勜": 1248,
1251
+ "勝": 1249,
1252
+ "勞": 1250,
1253
+ "募": 1251,
1254
+ "勠": 1252,
1255
+ "勡": 1253,
1256
+ "勢": 1254,
1257
+ "勣": 1255,
1258
+ "勤": 1256,
1259
+ "勥": 1257,
1260
+ "勦": 1258,
1261
+ "勧": 1259,
1262
+ "勨": 1260,
1263
+ "勩": 1261,
1264
+ "勪": 1262,
1265
+ "勫": 1263,
1266
+ "勬": 1264,
1267
+ "勭": 1265,
1268
+ "勮": 1266,
1269
+ "勯": 1267,
1270
+ "��": 1268,
1271
+ "勱": 1269,
1272
+ "勲": 1270,
1273
+ "勳": 1271,
1274
+ "勴": 1272,
1275
+ "勵": 1273,
1276
+ "勶": 1274,
1277
+ "勷": 1275,
1278
+ "勸": 1276,
1279
+ "勹": 1277,
1280
+ "勺": 1278,
1281
+ "勻": 1279,
1282
+ "勼": 1280,
1283
+ "勽": 1281,
1284
+ "勾": 1282,
1285
+ "勿": 1283,
1286
+ "匀": 1284,
1287
+ "匁": 1285,
1288
+ "匂": 1286,
1289
+ "匃": 1287,
1290
+ "匄": 1288,
1291
+ "包": 1289,
1292
+ "匆": 1290,
1293
+ "匇": 1291,
1294
+ "匈": 1292,
1295
+ "匉": 1293,
1296
+ "匊": 1294,
1297
+ "匋": 1295,
1298
+ "匌": 1296,
1299
+ "匍": 1297,
1300
+ "匎": 1298,
1301
+ "匏": 1299,
1302
+ "匐": 1300,
1303
+ "匑": 1301,
1304
+ "匒": 1302,
1305
+ "匓": 1303,
1306
+ "匔": 1304,
1307
+ "匕": 1305,
1308
+ "化": 1306,
1309
+ "北": 1307,
1310
+ "匘": 1308,
1311
+ "匙": 1309,
1312
+ "匚": 1310,
1313
+ "匛": 1311,
1314
+ "匜": 1312,
1315
+ "匝": 1313,
1316
+ "匞": 1314,
1317
+ "匟": 1315,
1318
+ "匠": 1316,
1319
+ "匡": 1317,
1320
+ "匢": 1318,
1321
+ "匣": 1319,
1322
+ "匤": 1320,
1323
+ "匥": 1321,
1324
+ "匦": 1322,
1325
+ "匧": 1323,
1326
+ "匨": 1324,
1327
+ "匩": 1325,
1328
+ "匪": 1326,
1329
+ "匫": 1327,
1330
+ "匬": 1328,
1331
+ "匭": 1329,
1332
+ "匮": 1330,
1333
+ "匯": 1331,
1334
+ "匰": 1332,
1335
+ "匱": 1333,
1336
+ "匲": 1334,
1337
+ "匳": 1335,
1338
+ "匴": 1336,
1339
+ "匵": 1337,
1340
+ "匶": 1338,
1341
+ "匷": 1339,
1342
+ "匸": 1340,
1343
+ "匹": 1341,
1344
+ "区": 1342,
1345
+ "医": 1343,
1346
+ "匼": 1344,
1347
+ "匽": 1345,
1348
+ "匾": 1346,
1349
+ "匿": 1347,
1350
+ "區": 1348,
1351
+ "十": 1349,
1352
+ "卂": 1350,
1353
+ "千": 1351,
1354
+ "卄": 1352,
1355
+ "卅": 1353,
1356
+ "卆": 1354,
1357
+ "升": 1355,
1358
+ "午": 1356,
1359
+ "卉": 1357,
1360
+ "半": 1358,
1361
+ "卋": 1359,
1362
+ "卌": 1360,
1363
+ "卍": 1361,
1364
+ "华": 1362,
1365
+ "协": 1363,
1366
+ "卐": 1364,
1367
+ "卑": 1365,
1368
+ "卒": 1366,
1369
+ "卓": 1367,
1370
+ "協": 1368,
1371
+ "单": 1369,
1372
+ "卖": 1370,
1373
+ "南": 1371,
1374
+ "単": 1372,
1375
+ "卙": 1373,
1376
+ "博": 1374,
1377
+ "卛": 1375,
1378
+ "卜": 1376,
1379
+ "卝": 1377,
1380
+ "卞": 1378,
1381
+ "卟": 1379,
1382
+ "占": 1380,
1383
+ "卡": 1381,
1384
+ "卢": 1382,
1385
+ "卣": 1383,
1386
+ "卤": 1384,
1387
+ "卥": 1385,
1388
+ "卦": 1386,
1389
+ "卧": 1387,
1390
+ "卨": 1388,
1391
+ "卩": 1389,
1392
+ "卪": 1390,
1393
+ "卫": 1391,
1394
+ "卬": 1392,
1395
+ "卭": 1393,
1396
+ "卮": 1394,
1397
+ "卯": 1395,
1398
+ "印": 1396,
1399
+ "危": 1397,
1400
+ "卲": 1398,
1401
+ "即": 1399,
1402
+ "却": 1400,
1403
+ "卵": 1401,
1404
+ "卶": 1402,
1405
+ "卷": 1403,
1406
+ "卸": 1404,
1407
+ "卹": 1405,
1408
+ "卺": 1406,
1409
+ "卻": 1407,
1410
+ "卼": 1408,
1411
+ "卽": 1409,
1412
+ "卾": 1410,
1413
+ "卿": 1411,
1414
+ "厀": 1412,
1415
+ "厁": 1413,
1416
+ "厂": 1414,
1417
+ "厃": 1415,
1418
+ "厄": 1416,
1419
+ "厅": 1417,
1420
+ "历": 1418,
1421
+ "厇": 1419,
1422
+ "厈": 1420,
1423
+ "厉": 1421,
1424
+ "厊": 1422,
1425
+ "压": 1423,
1426
+ "厌": 1424,
1427
+ "厍": 1425,
1428
+ "厎": 1426,
1429
+ "厏": 1427,
1430
+ "厐": 1428,
1431
+ "厑": 1429,
1432
+ "厒": 1430,
1433
+ "厓": 1431,
1434
+ "厔": 1432,
1435
+ "厕": 1433,
1436
+ "厖": 1434,
1437
+ "厗": 1435,
1438
+ "厘": 1436,
1439
+ "厙": 1437,
1440
+ "厚": 1438,
1441
+ "厛": 1439,
1442
+ "厜": 1440,
1443
+ "厝": 1441,
1444
+ "厞": 1442,
1445
+ "原": 1443,
1446
+ "厠": 1444,
1447
+ "厡": 1445,
1448
+ "厢": 1446,
1449
+ "厣": 1447,
1450
+ "厤": 1448,
1451
+ "厥": 1449,
1452
+ "厦": 1450,
1453
+ "厧": 1451,
1454
+ "厨": 1452,
1455
+ "厩": 1453,
1456
+ "厪": 1454,
1457
+ "厫": 1455,
1458
+ "厬": 1456,
1459
+ "厭": 1457,
1460
+ "厮": 1458,
1461
+ "厯": 1459,
1462
+ "厰": 1460,
1463
+ "厱": 1461,
1464
+ "厲": 1462,
1465
+ "厳": 1463,
1466
+ "厴": 1464,
1467
+ "厵": 1465,
1468
+ "厶": 1466,
1469
+ "厷": 1467,
1470
+ "厸": 1468,
1471
+ "厹": 1469,
1472
+ "厺": 1470,
1473
+ "去": 1471,
1474
+ "厼": 1472,
1475
+ "厽": 1473,
1476
+ "厾": 1474,
1477
+ "县": 1475,
1478
+ "叀": 1476,
1479
+ "叁": 1477,
1480
+ "参": 1478,
1481
+ "參": 1479,
1482
+ "叄": 1480,
1483
+ "叅": 1481,
1484
+ "叆": 1482,
1485
+ "叇": 1483,
1486
+ "又": 1484,
1487
+ "叉": 1485,
1488
+ "及": 1486,
1489
+ "友": 1487,
1490
+ "双": 1488,
1491
+ "反": 1489,
1492
+ "収": 1490,
1493
+ "叏": 1491,
1494
+ "叐": 1492,
1495
+ "发": 1493,
1496
+ "叒": 1494,
1497
+ "叓": 1495,
1498
+ "叔": 1496,
1499
+ "叕": 1497,
1500
+ "取": 1498,
1501
+ "受": 1499,
1502
+ "变": 1500,
1503
+ "叙": 1501,
1504
+ "叚": 1502,
1505
+ "叛": 1503,
1506
+ "叜": 1504,
1507
+ "叝": 1505,
1508
+ "叞": 1506,
1509
+ "叟": 1507,
1510
+ "叠": 1508,
1511
+ "叡": 1509,
1512
+ "叢": 1510,
1513
+ "口": 1511,
1514
+ "古": 1512,
1515
+ "句": 1513,
1516
+ "另": 1514,
1517
+ "叧": 1515,
1518
+ "叨": 1516,
1519
+ "叩": 1517,
1520
+ "只": 1518,
1521
+ "叫": 1519,
1522
+ "召": 1520,
1523
+ "叭": 1521,
1524
+ "叮": 1522,
1525
+ "可": 1523,
1526
+ "台": 1524,
1527
+ "叱": 1525,
1528
+ "史": 1526,
1529
+ "右": 1527,
1530
+ "叴": 1528,
1531
+ "叵": 1529,
1532
+ "叶": 1530,
1533
+ "号": 1531,
1534
+ "司": 1532,
1535
+ "叹": 1533,
1536
+ "叺": 1534,
1537
+ "叻": 1535,
1538
+ "叼": 1536,
1539
+ "叽": 1537,
1540
+ "叾": 1538,
1541
+ "叿": 1539,
1542
+ "吀": 1540,
1543
+ "吁": 1541,
1544
+ "吂": 1542,
1545
+ "吃": 1543,
1546
+ "各": 1544,
1547
+ "吅": 1545,
1548
+ "吆": 1546,
1549
+ "吇": 1547,
1550
+ "合": 1548,
1551
+ "吉": 1549,
1552
+ "吊": 1550,
1553
+ "吋": 1551,
1554
+ "同": 1552,
1555
+ "名": 1553,
1556
+ "后": 1554,
1557
+ "吏": 1555,
1558
+ "吐": 1556,
1559
+ "向": 1557,
1560
+ "吒": 1558,
1561
+ "吓": 1559,
1562
+ "吔": 1560,
1563
+ "吕": 1561,
1564
+ "吖": 1562,
1565
+ "吗": 1563,
1566
+ "吘": 1564,
1567
+ "吙": 1565,
1568
+ "吚": 1566,
1569
+ "君": 1567,
1570
+ "吜": 1568,
1571
+ "吝": 1569,
1572
+ "吞": 1570,
1573
+ "吟": 1571,
1574
+ "吠": 1572,
1575
+ "吡": 1573,
1576
+ "吢": 1574,
1577
+ "吣": 1575,
1578
+ "吤": 1576,
1579
+ "吥": 1577,
1580
+ "否": 1578,
1581
+ "吧": 1579,
1582
+ "吨": 1580,
1583
+ "吩": 1581,
1584
+ "吪": 1582,
1585
+ "含": 1583,
1586
+ "听": 1584,
1587
+ "吭": 1585,
1588
+ "吮": 1586,
1589
+ "启": 1587,
1590
+ "吰": 1588,
1591
+ "吱": 1589,
1592
+ "吲": 1590,
1593
+ "吳": 1591,
1594
+ "吴": 1592,
1595
+ "吵": 1593,
1596
+ "吶": 1594,
1597
+ "吷": 1595,
1598
+ "吸": 1596,
1599
+ "吹": 1597,
1600
+ "吺": 1598,
1601
+ "吻": 1599,
1602
+ "吼": 1600,
1603
+ "吽": 1601,
1604
+ "吾": 1602,
1605
+ "吿": 1603,
1606
+ "呀": 1604,
1607
+ "呁": 1605,
1608
+ "呂": 1606,
1609
+ "呃": 1607,
1610
+ "呄": 1608,
1611
+ "呅": 1609,
1612
+ "呆": 1610,
1613
+ "呇": 1611,
1614
+ "呈": 1612,
1615
+ "呉": 1613,
1616
+ "告": 1614,
1617
+ "呋": 1615,
1618
+ "呌": 1616,
1619
+ "呍": 1617,
1620
+ "呎": 1618,
1621
+ "呏": 1619,
1622
+ "呐": 1620,
1623
+ "呑": 1621,
1624
+ "呒": 1622,
1625
+ "呓": 1623,
1626
+ "呔": 1624,
1627
+ "呕": 1625,
1628
+ "呖": 1626,
1629
+ "呗": 1627,
1630
+ "员": 1628,
1631
+ "呙": 1629,
1632
+ "呚": 1630,
1633
+ "呛": 1631,
1634
+ "呜": 1632,
1635
+ "呝": 1633,
1636
+ "呞": 1634,
1637
+ "呟": 1635,
1638
+ "呠": 1636,
1639
+ "呡": 1637,
1640
+ "呢": 1638,
1641
+ "呣": 1639,
1642
+ "呤": 1640,
1643
+ "呥": 1641,
1644
+ "呦": 1642,
1645
+ "呧": 1643,
1646
+ "周": 1644,
1647
+ "呩": 1645,
1648
+ "呪": 1646,
1649
+ "呫": 1647,
1650
+ "呬": 1648,
1651
+ "呭": 1649,
1652
+ "呮": 1650,
1653
+ "呯": 1651,
1654
+ "呰": 1652,
1655
+ "呱": 1653,
1656
+ "呲": 1654,
1657
+ "味": 1655,
1658
+ "呴": 1656,
1659
+ "呵": 1657,
1660
+ "呶": 1658,
1661
+ "呷": 1659,
1662
+ "呸": 1660,
1663
+ "呹": 1661,
1664
+ "呺": 1662,
1665
+ "呻": 1663,
1666
+ "呼": 1664,
1667
+ "命": 1665,
1668
+ "呾": 1666,
1669
+ "呿": 1667,
1670
+ "咀": 1668,
1671
+ "咁": 1669,
1672
+ "咂": 1670,
1673
+ "咃": 1671,
1674
+ "咄": 1672,
1675
+ "咅": 1673,
1676
+ "咆": 1674,
1677
+ "咇": 1675,
1678
+ "咈": 1676,
1679
+ "咉": 1677,
1680
+ "咊": 1678,
1681
+ "咋": 1679,
1682
+ "和": 1680,
1683
+ "咍": 1681,
1684
+ "咎": 1682,
1685
+ "咏": 1683,
1686
+ "咐": 1684,
1687
+ "咑": 1685,
1688
+ "咒": 1686,
1689
+ "咓": 1687,
1690
+ "咔": 1688,
1691
+ "咕": 1689,
1692
+ "咖": 1690,
1693
+ "咗": 1691,
1694
+ "咘": 1692,
1695
+ "咙": 1693,
1696
+ "咚": 1694,
1697
+ "咛": 1695,
1698
+ "咜": 1696,
1699
+ "咝": 1697,
1700
+ "咞": 1698,
1701
+ "咟": 1699,
1702
+ "咠": 1700,
1703
+ "咡": 1701,
1704
+ "咢": 1702,
1705
+ "咣": 1703,
1706
+ "咤": 1704,
1707
+ "咥": 1705,
1708
+ "咦": 1706,
1709
+ "咧": 1707,
1710
+ "咨": 1708,
1711
+ "咩": 1709,
1712
+ "咪": 1710,
1713
+ "咫": 1711,
1714
+ "咬": 1712,
1715
+ "咭": 1713,
1716
+ "咮": 1714,
1717
+ "咯": 1715,
1718
+ "咰": 1716,
1719
+ "咱": 1717,
1720
+ "咲": 1718,
1721
+ "咳": 1719,
1722
+ "咴": 1720,
1723
+ "咵": 1721,
1724
+ "咶": 1722,
1725
+ "咷": 1723,
1726
+ "咸": 1724,
1727
+ "咹": 1725,
1728
+ "咺": 1726,
1729
+ "咻": 1727,
1730
+ "咼": 1728,
1731
+ "咽": 1729,
1732
+ "咾": 1730,
1733
+ "咿": 1731,
1734
+ "哀": 1732,
1735
+ "品": 1733,
1736
+ "哂": 1734,
1737
+ "哃": 1735,
1738
+ "哄": 1736,
1739
+ "哅": 1737,
1740
+ "哆": 1738,
1741
+ "哇": 1739,
1742
+ "哈": 1740,
1743
+ "哉": 1741,
1744
+ "哊": 1742,
1745
+ "哋": 1743,
1746
+ "哌": 1744,
1747
+ "响": 1745,
1748
+ "哎": 1746,
1749
+ "哏": 1747,
1750
+ "哐": 1748,
1751
+ "哑": 1749,
1752
+ "哒": 1750,
1753
+ "哓": 1751,
1754
+ "哔": 1752,
1755
+ "哕": 1753,
1756
+ "哖": 1754,
1757
+ "哗": 1755,
1758
+ "哘": 1756,
1759
+ "哙": 1757,
1760
+ "哚": 1758,
1761
+ "哛": 1759,
1762
+ "哜": 1760,
1763
+ "哝": 1761,
1764
+ "哞": 1762,
1765
+ "哟": 1763,
1766
+ "哠": 1764,
1767
+ "員": 1765,
1768
+ "哢": 1766,
1769
+ "哣": 1767,
1770
+ "哤": 1768,
1771
+ "哥": 1769,
1772
+ "哦": 1770,
1773
+ "哧": 1771,
1774
+ "哨": 1772,
1775
+ "哩": 1773,
1776
+ "哪": 1774,
1777
+ "哫": 1775,
1778
+ "哬": 1776,
1779
+ "哭": 1777,
1780
+ "哮": 1778,
1781
+ "哯": 1779,
1782
+ "哰": 1780,
1783
+ "哱": 1781,
1784
+ "哲": 1782,
1785
+ "哳": 1783,
1786
+ "哴": 1784,
1787
+ "哵": 1785,
1788
+ "哶": 1786,
1789
+ "哷": 1787,
1790
+ "哸": 1788,
1791
+ "哹": 1789,
1792
+ "哺": 1790,
1793
+ "哻": 1791,
1794
+ "哼": 1792,
1795
+ "哽": 1793,
1796
+ "哾": 1794,
1797
+ "哿": 1795,
1798
+ "唀": 1796,
1799
+ "唁": 1797,
1800
+ "唂": 1798,
1801
+ "唃": 1799,
1802
+ "唄": 1800,
1803
+ "唅": 1801,
1804
+ "唆": 1802,
1805
+ "唇": 1803,
1806
+ "唈": 1804,
1807
+ "唉": 1805,
1808
+ "唊": 1806,
1809
+ "唋": 1807,
1810
+ "唌": 1808,
1811
+ "唍": 1809,
1812
+ "唎": 1810,
1813
+ "唏": 1811,
1814
+ "唐": 1812,
1815
+ "唑": 1813,
1816
+ "唒": 1814,
1817
+ "唓": 1815,
1818
+ "唔": 1816,
1819
+ "唕": 1817,
1820
+ "唖": 1818,
1821
+ "唗": 1819,
1822
+ "唘": 1820,
1823
+ "唙": 1821,
1824
+ "唚": 1822,
1825
+ "唛": 1823,
1826
+ "唜": 1824,
1827
+ "唝": 1825,
1828
+ "唞": 1826,
1829
+ "唟": 1827,
1830
+ "唠": 1828,
1831
+ "唡": 1829,
1832
+ "唢": 1830,
1833
+ "唣": 1831,
1834
+ "唤": 1832,
1835
+ "唥": 1833,
1836
+ "唦": 1834,
1837
+ "唧": 1835,
1838
+ "唨": 1836,
1839
+ "唩": 1837,
1840
+ "唪": 1838,
1841
+ "唫": 1839,
1842
+ "唬": 1840,
1843
+ "唭": 1841,
1844
+ "售": 1842,
1845
+ "唯": 1843,
1846
+ "唰": 1844,
1847
+ "唱": 1845,
1848
+ "唲": 1846,
1849
+ "唳": 1847,
1850
+ "唴": 1848,
1851
+ "唵": 1849,
1852
+ "唶": 1850,
1853
+ "唷": 1851,
1854
+ "唸": 1852,
1855
+ "唹": 1853,
1856
+ "唺": 1854,
1857
+ "唻": 1855,
1858
+ "唼": 1856,
1859
+ "唽": 1857,
1860
+ "唾": 1858,
1861
+ "唿": 1859,
1862
+ "啀": 1860,
1863
+ "啁": 1861,
1864
+ "啂": 1862,
1865
+ "啃": 1863,
1866
+ "啄": 1864,
1867
+ "啅": 1865,
1868
+ "商": 1866,
1869
+ "啇": 1867,
1870
+ "啈": 1868,
1871
+ "啉": 1869,
1872
+ "啊": 1870,
1873
+ "啋": 1871,
1874
+ "啌": 1872,
1875
+ "啍": 1873,
1876
+ "啎": 1874,
1877
+ "問": 1875,
1878
+ "啐": 1876,
1879
+ "啑": 1877,
1880
+ "啒": 1878,
1881
+ "啓": 1879,
1882
+ "啔": 1880,
1883
+ "啕": 1881,
1884
+ "啖": 1882,
1885
+ "啗": 1883,
1886
+ "啘": 1884,
1887
+ "啙": 1885,
1888
+ "啚": 1886,
1889
+ "啛": 1887,
1890
+ "啜": 1888,
1891
+ "啝": 1889,
1892
+ "啞": 1890,
1893
+ "啟": 1891,
1894
+ "啠": 1892,
1895
+ "啡": 1893,
1896
+ "啢": 1894,
1897
+ "啣": 1895,
1898
+ "啤": 1896,
1899
+ "啥": 1897,
1900
+ "啦": 1898,
1901
+ "啧": 1899,
1902
+ "啨": 1900,
1903
+ "啩": 1901,
1904
+ "啪": 1902,
1905
+ "啫": 1903,
1906
+ "啬": 1904,
1907
+ "啭": 1905,
1908
+ "啮": 1906,
1909
+ "啯": 1907,
1910
+ "啰": 1908,
1911
+ "啱": 1909,
1912
+ "啲": 1910,
1913
+ "啳": 1911,
1914
+ "啴": 1912,
1915
+ "啵": 1913,
1916
+ "啶": 1914,
1917
+ "啷": 1915,
1918
+ "啸": 1916,
1919
+ "啹": 1917,
1920
+ "啺": 1918,
1921
+ "啻": 1919,
1922
+ "啼": 1920,
1923
+ "啽": 1921,
1924
+ "啾": 1922,
1925
+ "啿": 1923,
1926
+ "喀": 1924,
1927
+ "喁": 1925,
1928
+ "喂": 1926,
1929
+ "喃": 1927,
1930
+ "善": 1928,
1931
+ "喅": 1929,
1932
+ "喆": 1930,
1933
+ "喇": 1931,
1934
+ "喈": 1932,
1935
+ "喉": 1933,
1936
+ "喊": 1934,
1937
+ "喋": 1935,
1938
+ "喌": 1936,
1939
+ "喍": 1937,
1940
+ "喎": 1938,
1941
+ "喏": 1939,
1942
+ "喐": 1940,
1943
+ "喑": 1941,
1944
+ "喒": 1942,
1945
+ "喓": 1943,
1946
+ "喔": 1944,
1947
+ "喕": 1945,
1948
+ "喖": 1946,
1949
+ "喗": 1947,
1950
+ "喘": 1948,
1951
+ "喙": 1949,
1952
+ "喚": 1950,
1953
+ "喛": 1951,
1954
+ "喜": 1952,
1955
+ "喝": 1953,
1956
+ "喞": 1954,
1957
+ "喟": 1955,
1958
+ "喠": 1956,
1959
+ "喡": 1957,
1960
+ "喢": 1958,
1961
+ "喣": 1959,
1962
+ "喤": 1960,
1963
+ "喥": 1961,
1964
+ "喦": 1962,
1965
+ "喧": 1963,
1966
+ "喨": 1964,
1967
+ "喩": 1965,
1968
+ "喪": 1966,
1969
+ "喫": 1967,
1970
+ "喬": 1968,
1971
+ "喭": 1969,
1972
+ "單": 1970,
1973
+ "喯": 1971,
1974
+ "喰": 1972,
1975
+ "喱": 1973,
1976
+ "喲": 1974,
1977
+ "喳": 1975,
1978
+ "喴": 1976,
1979
+ "喵": 1977,
1980
+ "営": 1978,
1981
+ "喷": 1979,
1982
+ "喸": 1980,
1983
+ "喹": 1981,
1984
+ "喺": 1982,
1985
+ "喻": 1983,
1986
+ "喼": 1984,
1987
+ "喽": 1985,
1988
+ "喾": 1986,
1989
+ "喿": 1987,
1990
+ "嗀": 1988,
1991
+ "嗁": 1989,
1992
+ "嗂": 1990,
1993
+ "嗃": 1991,
1994
+ "嗄": 1992,
1995
+ "嗅": 1993,
1996
+ "嗆": 1994,
1997
+ "嗇": 1995,
1998
+ "嗈": 1996,
1999
+ "嗉": 1997,
2000
+ "嗊": 1998,
2001
+ "嗋": 1999,
2002
+ "嗌": 2000,
2003
+ "嗍": 2001,
2004
+ "嗎": 2002,
2005
+ "嗏": 2003,
2006
+ "嗐": 2004,
2007
+ "嗑": 2005,
2008
+ "嗒": 2006,
2009
+ "嗓": 2007,
2010
+ "嗔": 2008,
2011
+ "嗕": 2009,
2012
+ "嗖": 2010,
2013
+ "嗗": 2011,
2014
+ "嗘": 2012,
2015
+ "嗙": 2013,
2016
+ "嗚": 2014,
2017
+ "嗛": 2015,
2018
+ "嗜": 2016,
2019
+ "嗝": 2017,
2020
+ "嗞": 2018,
2021
+ "嗟": 2019,
2022
+ "嗠": 2020,
2023
+ "嗡": 2021,
2024
+ "嗢": 2022,
2025
+ "嗣": 2023,
2026
+ "嗤": 2024,
2027
+ "嗥": 2025,
2028
+ "嗦": 2026,
2029
+ "嗧": 2027,
2030
+ "嗨": 2028,
2031
+ "嗩": 2029,
2032
+ "嗪": 2030,
2033
+ "嗫": 2031,
2034
+ "嗬": 2032,
2035
+ "嗭": 2033,
2036
+ "嗮": 2034,
2037
+ "嗯": 2035,
2038
+ "嗰": 2036,
2039
+ "嗱": 2037,
2040
+ "嗲": 2038,
2041
+ "嗳": 2039,
2042
+ "嗴": 2040,
2043
+ "嗵": 2041,
2044
+ "嗶": 2042,
2045
+ "嗷": 2043,
2046
+ "嗸": 2044,
2047
+ "嗹": 2045,
2048
+ "嗺": 2046,
2049
+ "嗻": 2047,
2050
+ "嗼": 2048,
2051
+ "嗽": 2049,
2052
+ "嗾": 2050,
2053
+ "嗿": 2051,
2054
+ "嘀": 2052,
2055
+ "嘁": 2053,
2056
+ "嘂": 2054,
2057
+ "嘃": 2055,
2058
+ "嘄": 2056,
2059
+ "嘅": 2057,
2060
+ "嘆": 2058,
2061
+ "嘇": 2059,
2062
+ "嘈": 2060,
2063
+ "嘉": 2061,
2064
+ "嘊": 2062,
2065
+ "嘋": 2063,
2066
+ "嘌": 2064,
2067
+ "嘍": 2065,
2068
+ "嘎": 2066,
2069
+ "嘏": 2067,
2070
+ "嘐": 2068,
2071
+ "嘑": 2069,
2072
+ "嘒": 2070,
2073
+ "嘓": 2071,
2074
+ "嘔": 2072,
2075
+ "嘕": 2073,
2076
+ "嘖": 2074,
2077
+ "嘗": 2075,
2078
+ "嘘": 2076,
2079
+ "嘙": 2077,
2080
+ "嘚": 2078,
2081
+ "嘛": 2079,
2082
+ "嘜": 2080,
2083
+ "嘝": 2081,
2084
+ "嘞": 2082,
2085
+ "嘟": 2083,
2086
+ "嘠": 2084,
2087
+ "嘡": 2085,
2088
+ "嘢": 2086,
2089
+ "嘣": 2087,
2090
+ "嘤": 2088,
2091
+ "嘥": 2089,
2092
+ "嘦": 2090,
2093
+ "嘧": 2091,
2094
+ "嘨": 2092,
2095
+ "嘩": 2093,
2096
+ "嘪": 2094,
2097
+ "嘫": 2095,
2098
+ "嘬": 2096,
2099
+ "嘭": 2097,
2100
+ "嘮": 2098,
2101
+ "嘯": 2099,
2102
+ "嘰": 2100,
2103
+ "嘱": 2101,
2104
+ "嘲": 2102,
2105
+ "嘳": 2103,
2106
+ "嘴": 2104,
2107
+ "嘵": 2105,
2108
+ "嘶": 2106,
2109
+ "嘷": 2107,
2110
+ "嘸": 2108,
2111
+ "嘹": 2109,
2112
+ "嘺": 2110,
2113
+ "嘻": 2111,
2114
+ "嘼": 2112,
2115
+ "嘽": 2113,
2116
+ "嘾": 2114,
2117
+ "嘿": 2115,
2118
+ "噀": 2116,
2119
+ "噁": 2117,
2120
+ "噂": 2118,
2121
+ "噃": 2119,
2122
+ "噄": 2120,
2123
+ "噅": 2121,
2124
+ "噆": 2122,
2125
+ "噇": 2123,
2126
+ "噈": 2124,
2127
+ "噉": 2125,
2128
+ "噊": 2126,
2129
+ "噋": 2127,
2130
+ "噌": 2128,
2131
+ "噍": 2129,
2132
+ "噎": 2130,
2133
+ "噏": 2131,
2134
+ "噐": 2132,
2135
+ "噑": 2133,
2136
+ "噒": 2134,
2137
+ "噓": 2135,
2138
+ "噔": 2136,
2139
+ "噕": 2137,
2140
+ "噖": 2138,
2141
+ "噗": 2139,
2142
+ "噘": 2140,
2143
+ "噙": 2141,
2144
+ "噚": 2142,
2145
+ "噛": 2143,
2146
+ "噜": 2144,
2147
+ "噝": 2145,
2148
+ "噞": 2146,
2149
+ "噟": 2147,
2150
+ "噠": 2148,
2151
+ "噡": 2149,
2152
+ "噢": 2150,
2153
+ "噣": 2151,
2154
+ "噤": 2152,
2155
+ "噥": 2153,
2156
+ "噦": 2154,
2157
+ "噧": 2155,
2158
+ "器": 2156,
2159
+ "噩": 2157,
2160
+ "噪": 2158,
2161
+ "噫": 2159,
2162
+ "噬": 2160,
2163
+ "噭": 2161,
2164
+ "噮": 2162,
2165
+ "噯": 2163,
2166
+ "噰": 2164,
2167
+ "噱": 2165,
2168
+ "噲": 2166,
2169
+ "噳": 2167,
2170
+ "噴": 2168,
2171
+ "噵": 2169,
2172
+ "噶": 2170,
2173
+ "噷": 2171,
2174
+ "噸": 2172,
2175
+ "噹": 2173,
2176
+ "噺": 2174,
2177
+ "噻": 2175,
2178
+ "噼": 2176,
2179
+ "噽": 2177,
2180
+ "噾": 2178,
2181
+ "噿": 2179,
2182
+ "嚀": 2180,
2183
+ "嚁": 2181,
2184
+ "嚂": 2182,
2185
+ "嚃": 2183,
2186
+ "嚄": 2184,
2187
+ "嚅": 2185,
2188
+ "嚆": 2186,
2189
+ "嚇": 2187,
2190
+ "嚈": 2188,
2191
+ "嚉": 2189,
2192
+ "嚊": 2190,
2193
+ "嚋": 2191,
2194
+ "嚌": 2192,
2195
+ "嚍": 2193,
2196
+ "嚎": 2194,
2197
+ "嚏": 2195,
2198
+ "嚐": 2196,
2199
+ "嚑": 2197,
2200
+ "嚒": 2198,
2201
+ "嚓": 2199,
2202
+ "嚔": 2200,
2203
+ "嚕": 2201,
2204
+ "嚖": 2202,
2205
+ "嚗": 2203,
2206
+ "嚘": 2204,
2207
+ "嚙": 2205,
2208
+ "嚚": 2206,
2209
+ "嚛": 2207,
2210
+ "嚜": 2208,
2211
+ "嚝": 2209,
2212
+ "嚞": 2210,
2213
+ "嚟": 2211,
2214
+ "嚠": 2212,
2215
+ "嚡": 2213,
2216
+ "嚢": 2214,
2217
+ "嚣": 2215,
2218
+ "嚤": 2216,
2219
+ "嚥": 2217,
2220
+ "嚦": 2218,
2221
+ "嚧": 2219,
2222
+ "嚨": 2220,
2223
+ "嚩": 2221,
2224
+ "嚪": 2222,
2225
+ "嚫": 2223,
2226
+ "嚬": 2224,
2227
+ "嚭": 2225,
2228
+ "嚮": 2226,
2229
+ "嚯": 2227,
2230
+ "嚰": 2228,
2231
+ "嚱": 2229,
2232
+ "嚲": 2230,
2233
+ "嚳": 2231,
2234
+ "嚴": 2232,
2235
+ "嚵": 2233,
2236
+ "嚶": 2234,
2237
+ "嚷": 2235,
2238
+ "嚸": 2236,
2239
+ "嚹": 2237,
2240
+ "嚺": 2238,
2241
+ "嚻": 2239,
2242
+ "嚼": 2240,
2243
+ "嚽": 2241,
2244
+ "嚾": 2242,
2245
+ "嚿": 2243,
2246
+ "囀": 2244,
2247
+ "囁": 2245,
2248
+ "囂": 2246,
2249
+ "囃": 2247,
2250
+ "囄": 2248,
2251
+ "囅": 2249,
2252
+ "囆": 2250,
2253
+ "囇": 2251,
2254
+ "囈": 2252,
2255
+ "囉": 2253,
2256
+ "囊": 2254,
2257
+ "囋": 2255,
2258
+ "囌": 2256,
2259
+ "囍": 2257,
2260
+ "囎": 2258,
2261
+ "囏": 2259,
2262
+ "囐": 2260,
2263
+ "囑": 2261,
2264
+ "囒": 2262,
2265
+ "囓": 2263,
2266
+ "囔": 2264,
2267
+ "囕": 2265,
2268
+ "囖": 2266,
2269
+ "囗": 2267,
2270
+ "囘": 2268,
2271
+ "囙": 2269,
2272
+ "囚": 2270,
2273
+ "四": 2271,
2274
+ "囜": 2272,
2275
+ "囝": 2273,
2276
+ "回": 2274,
2277
+ "囟": 2275,
2278
+ "因": 2276,
2279
+ "囡": 2277,
2280
+ "团": 2278,
2281
+ "団": 2279,
2282
+ "囤": 2280,
2283
+ "囥": 2281,
2284
+ "囦": 2282,
2285
+ "囧": 2283,
2286
+ "囨": 2284,
2287
+ "囩": 2285,
2288
+ "囪": 2286,
2289
+ "囫": 2287,
2290
+ "囬": 2288,
2291
+ "园": 2289,
2292
+ "囮": 2290,
2293
+ "囯": 2291,
2294
+ "困": 2292,
2295
+ "囱": 2293,
2296
+ "囲": 2294,
2297
+ "図": 2295,
2298
+ "围": 2296,
2299
+ "囵": 2297,
2300
+ "囶": 2298,
2301
+ "囷": 2299,
2302
+ "囸": 2300,
2303
+ "囹": 2301,
2304
+ "固": 2302,
2305
+ "囻": 2303,
2306
+ "囼": 2304,
2307
+ "国": 2305,
2308
+ "图": 2306,
2309
+ "囿": 2307,
2310
+ "圀": 2308,
2311
+ "圁": 2309,
2312
+ "圂": 2310,
2313
+ "圃": 2311,
2314
+ "圄": 2312,
2315
+ "圅": 2313,
2316
+ "圆": 2314,
2317
+ "圇": 2315,
2318
+ "圈": 2316,
2319
+ "圉": 2317,
2320
+ "圊": 2318,
2321
+ "國": 2319,
2322
+ "圌": 2320,
2323
+ "圍": 2321,
2324
+ "圎": 2322,
2325
+ "圏": 2323,
2326
+ "圐": 2324,
2327
+ "圑": 2325,
2328
+ "園": 2326,
2329
+ "圓": 2327,
2330
+ "圔": 2328,
2331
+ "圕": 2329,
2332
+ "圖": 2330,
2333
+ "圗": 2331,
2334
+ "團": 2332,
2335
+ "圙": 2333,
2336
+ "圚": 2334,
2337
+ "圛": 2335,
2338
+ "圜": 2336,
2339
+ "圝": 2337,
2340
+ "圞": 2338,
2341
+ "土": 2339,
2342
+ "圠": 2340,
2343
+ "圡": 2341,
2344
+ "圢": 2342,
2345
+ "圣": 2343,
2346
+ "圤": 2344,
2347
+ "圥": 2345,
2348
+ "圦": 2346,
2349
+ "圧": 2347,
2350
+ "在": 2348,
2351
+ "圩": 2349,
2352
+ "圪": 2350,
2353
+ "圫": 2351,
2354
+ "圬": 2352,
2355
+ "圭": 2353,
2356
+ "圮": 2354,
2357
+ "圯": 2355,
2358
+ "地": 2356,
2359
+ "圱": 2357,
2360
+ "圲": 2358,
2361
+ "圳": 2359,
2362
+ "圴": 2360,
2363
+ "圵": 2361,
2364
+ "圶": 2362,
2365
+ "圷": 2363,
2366
+ "圸": 2364,
2367
+ "圹": 2365,
2368
+ "场": 2366,
2369
+ "圻": 2367,
2370
+ "圼": 2368,
2371
+ "圽": 2369,
2372
+ "圾": 2370,
2373
+ "圿": 2371,
2374
+ "址": 2372,
2375
+ "坁": 2373,
2376
+ "坂": 2374,
2377
+ "坃": 2375,
2378
+ "坄": 2376,
2379
+ "坅": 2377,
2380
+ "坆": 2378,
2381
+ "均": 2379,
2382
+ "坈": 2380,
2383
+ "坉": 2381,
2384
+ "坊": 2382,
2385
+ "坋": 2383,
2386
+ "坌": 2384,
2387
+ "坍": 2385,
2388
+ "坎": 2386,
2389
+ "坏": 2387,
2390
+ "坐": 2388,
2391
+ "坑": 2389,
2392
+ "坒": 2390,
2393
+ "坓": 2391,
2394
+ "坔": 2392,
2395
+ "坕": 2393,
2396
+ "坖": 2394,
2397
+ "块": 2395,
2398
+ "坘": 2396,
2399
+ "坙": 2397,
2400
+ "坚": 2398,
2401
+ "坛": 2399,
2402
+ "坜": 2400,
2403
+ "坝": 2401,
2404
+ "坞": 2402,
2405
+ "坟": 2403,
2406
+ "坠": 2404,
2407
+ "坡": 2405,
2408
+ "坢": 2406,
2409
+ "坣": 2407,
2410
+ "坤": 2408,
2411
+ "坥": 2409,
2412
+ "坦": 2410,
2413
+ "坧": 2411,
2414
+ "坨": 2412,
2415
+ "坩": 2413,
2416
+ "坪": 2414,
2417
+ "坫": 2415,
2418
+ "坬": 2416,
2419
+ "坭": 2417,
2420
+ "坮": 2418,
2421
+ "坯": 2419,
2422
+ "坰": 2420,
2423
+ "坱": 2421,
2424
+ "坲": 2422,
2425
+ "坳": 2423,
2426
+ "坴": 2424,
2427
+ "坵": 2425,
2428
+ "坶": 2426,
2429
+ "坷": 2427,
2430
+ "坸": 2428,
2431
+ "坹": 2429,
2432
+ "坺": 2430,
2433
+ "坻": 2431,
2434
+ "坼": 2432,
2435
+ "坽": 2433,
2436
+ "坾": 2434,
2437
+ "坿": 2435,
2438
+ "垀": 2436,
2439
+ "垁": 2437,
2440
+ "垂": 2438,
2441
+ "垃": 2439,
2442
+ "垄": 2440,
2443
+ "垅": 2441,
2444
+ "垆": 2442,
2445
+ "垇": 2443,
2446
+ "垈": 2444,
2447
+ "垉": 2445,
2448
+ "垊": 2446,
2449
+ "型": 2447,
2450
+ "垌": 2448,
2451
+ "垍": 2449,
2452
+ "垎": 2450,
2453
+ "垏": 2451,
2454
+ "垐": 2452,
2455
+ "垑": 2453,
2456
+ "垒": 2454,
2457
+ "垓": 2455,
2458
+ "垔": 2456,
2459
+ "垕": 2457,
2460
+ "垖": 2458,
2461
+ "垗": 2459,
2462
+ "垘": 2460,
2463
+ "垙": 2461,
2464
+ "垚": 2462,
2465
+ "垛": 2463,
2466
+ "垜": 2464,
2467
+ "垝": 2465,
2468
+ "垞": 2466,
2469
+ "垟": 2467,
2470
+ "垠": 2468,
2471
+ "垡": 2469,
2472
+ "垢": 2470,
2473
+ "垣": 2471,
2474
+ "垤": 2472,
2475
+ "垥": 2473,
2476
+ "垦": 2474,
2477
+ "垧": 2475,
2478
+ "垨": 2476,
2479
+ "垩": 2477,
2480
+ "垪": 2478,
2481
+ "垫": 2479,
2482
+ "垬": 2480,
2483
+ "垭": 2481,
2484
+ "垮": 2482,
2485
+ "垯": 2483,
2486
+ "垰": 2484,
2487
+ "垱": 2485,
2488
+ "垲": 2486,
2489
+ "垳": 2487,
2490
+ "垴": 2488,
2491
+ "垵": 2489,
2492
+ "垶": 2490,
2493
+ "垷": 2491,
2494
+ "垸": 2492,
2495
+ "垹": 2493,
2496
+ "垺": 2494,
2497
+ "垻": 2495,
2498
+ "垼": 2496,
2499
+ "垽": 2497,
2500
+ "垾": 2498,
2501
+ "垿": 2499,
2502
+ "埀": 2500,
2503
+ "埁": 2501,
2504
+ "埂": 2502,
2505
+ "埃": 2503,
2506
+ "埄": 2504,
2507
+ "埅": 2505,
2508
+ "埆": 2506,
2509
+ "埇": 2507,
2510
+ "埈": 2508,
2511
+ "埉": 2509,
2512
+ "埊": 2510,
2513
+ "埋": 2511,
2514
+ "埌": 2512,
2515
+ "埍": 2513,
2516
+ "城": 2514,
2517
+ "埏": 2515,
2518
+ "埐": 2516,
2519
+ "埑": 2517,
2520
+ "埒": 2518,
2521
+ "埓": 2519,
2522
+ "埔": 2520,
2523
+ "埕": 2521,
2524
+ "埖": 2522,
2525
+ "埗": 2523,
2526
+ "埘": 2524,
2527
+ "埙": 2525,
2528
+ "埚": 2526,
2529
+ "埛": 2527,
2530
+ "埜": 2528,
2531
+ "埝": 2529,
2532
+ "埞": 2530,
2533
+ "域": 2531,
2534
+ "埠": 2532,
2535
+ "埡": 2533,
2536
+ "埢": 2534,
2537
+ "埣": 2535,
2538
+ "埤": 2536,
2539
+ "埥": 2537,
2540
+ "埦": 2538,
2541
+ "埧": 2539,
2542
+ "埨": 2540,
2543
+ "埩": 2541,
2544
+ "埪": 2542,
2545
+ "埫": 2543,
2546
+ "埬": 2544,
2547
+ "埭": 2545,
2548
+ "埮": 2546,
2549
+ "埯": 2547,
2550
+ "埰": 2548,
2551
+ "埱": 2549,
2552
+ "埲": 2550,
2553
+ "埳": 2551,
2554
+ "埴": 2552,
2555
+ "埵": 2553,
2556
+ "埶": 2554,
2557
+ "執": 2555,
2558
+ "埸": 2556,
2559
+ "培": 2557,
2560
+ "基": 2558,
2561
+ "埻": 2559,
2562
+ "埼": 2560,
2563
+ "埽": 2561,
2564
+ "埾": 2562,
2565
+ "埿": 2563,
2566
+ "堀": 2564,
2567
+ "堁": 2565,
2568
+ "堂": 2566,
2569
+ "堃": 2567,
2570
+ "堄": 2568,
2571
+ "堅": 2569,
2572
+ "堆": 2570,
2573
+ "堇": 2571,
2574
+ "堈": 2572,
2575
+ "堉": 2573,
2576
+ "堊": 2574,
2577
+ "堋": 2575,
2578
+ "堌": 2576,
2579
+ "堍": 2577,
2580
+ "堎": 2578,
2581
+ "堏": 2579,
2582
+ "堐": 2580,
2583
+ "堑": 2581,
2584
+ "堒": 2582,
2585
+ "堓": 2583,
2586
+ "堔": 2584,
2587
+ "堕": 2585,
2588
+ "堖": 2586,
2589
+ "堗": 2587,
2590
+ "堘": 2588,
2591
+ "堙": 2589,
2592
+ "堚": 2590,
2593
+ "堛": 2591,
2594
+ "堜": 2592,
2595
+ "堝": 2593,
2596
+ "堞": 2594,
2597
+ "堟": 2595,
2598
+ "堠": 2596,
2599
+ "堡": 2597,
2600
+ "堢": 2598,
2601
+ "堣": 2599,
2602
+ "堤": 2600,
2603
+ "堥": 2601,
2604
+ "堦": 2602,
2605
+ "堧": 2603,
2606
+ "堨": 2604,
2607
+ "堩": 2605,
2608
+ "堪": 2606,
2609
+ "堫": 2607,
2610
+ "堬": 2608,
2611
+ "堭": 2609,
2612
+ "堮": 2610,
2613
+ "堯": 2611,
2614
+ "堰": 2612,
2615
+ "報": 2613,
2616
+ "堲": 2614,
2617
+ "堳": 2615,
2618
+ "場": 2616,
2619
+ "堵": 2617,
2620
+ "堶": 2618,
2621
+ "堷": 2619,
2622
+ "堸": 2620,
2623
+ "堹": 2621,
2624
+ "堺": 2622,
2625
+ "堻": 2623,
2626
+ "堼": 2624,
2627
+ "堽": 2625,
2628
+ "堾": 2626,
2629
+ "堿": 2627,
2630
+ "塀": 2628,
2631
+ "塁": 2629,
2632
+ "塂": 2630,
2633
+ "塃": 2631,
2634
+ "塄": 2632,
2635
+ "塅": 2633,
2636
+ "塆": 2634,
2637
+ "塇": 2635,
2638
+ "塈": 2636,
2639
+ "塉": 2637,
2640
+ "塊": 2638,
2641
+ "塋": 2639,
2642
+ "塌": 2640,
2643
+ "塍": 2641,
2644
+ "塎": 2642,
2645
+ "塏": 2643,
2646
+ "塐": 2644,
2647
+ "塑": 2645,
2648
+ "塒": 2646,
2649
+ "塓": 2647,
2650
+ "塔": 2648,
2651
+ "塕": 2649,
2652
+ "塖": 2650,
2653
+ "塗": 2651,
2654
+ "塘": 2652,
2655
+ "塙": 2653,
2656
+ "塚": 2654,
2657
+ "塛": 2655,
2658
+ "塜": 2656,
2659
+ "塝": 2657,
2660
+ "塞": 2658,
2661
+ "塟": 2659,
2662
+ "塠": 2660,
2663
+ "塡": 2661,
2664
+ "塢": 2662,
2665
+ "塣": 2663,
2666
+ "塤": 2664,
2667
+ "塥": 2665,
2668
+ "塦": 2666,
2669
+ "塧": 2667,
2670
+ "塨": 2668,
2671
+ "塩": 2669,
2672
+ "塪": 2670,
2673
+ "填": 2671,
2674
+ "塬": 2672,
2675
+ "塭": 2673,
2676
+ "塮": 2674,
2677
+ "塯": 2675,
2678
+ "塰": 2676,
2679
+ "塱": 2677,
2680
+ "塲": 2678,
2681
+ "塳": 2679,
2682
+ "塴": 2680,
2683
+ "塵": 2681,
2684
+ "塶": 2682,
2685
+ "塷": 2683,
2686
+ "塸": 2684,
2687
+ "塹": 2685,
2688
+ "塺": 2686,
2689
+ "塻": 2687,
2690
+ "塼": 2688,
2691
+ "塽": 2689,
2692
+ "塾": 2690,
2693
+ "塿": 2691,
2694
+ "墀": 2692,
2695
+ "墁": 2693,
2696
+ "墂": 2694,
2697
+ "境": 2695,
2698
+ "墄": 2696,
2699
+ "墅": 2697,
2700
+ "墆": 2698,
2701
+ "墇": 2699,
2702
+ "墈": 2700,
2703
+ "墉": 2701,
2704
+ "墊": 2702,
2705
+ "墋": 2703,
2706
+ "墌": 2704,
2707
+ "墍": 2705,
2708
+ "墎": 2706,
2709
+ "墏": 2707,
2710
+ "墐": 2708,
2711
+ "墑": 2709,
2712
+ "墒": 2710,
2713
+ "墓": 2711,
2714
+ "墔": 2712,
2715
+ "墕": 2713,
2716
+ "墖": 2714,
2717
+ "増": 2715,
2718
+ "墘": 2716,
2719
+ "墙": 2717,
2720
+ "墚": 2718,
2721
+ "墛": 2719,
2722
+ "墜": 2720,
2723
+ "墝": 2721,
2724
+ "增": 2722,
2725
+ "墟": 2723,
2726
+ "墠": 2724,
2727
+ "墡": 2725,
2728
+ "墢": 2726,
2729
+ "墣": 2727,
2730
+ "墤": 2728,
2731
+ "墥": 2729,
2732
+ "墦": 2730,
2733
+ "墧": 2731,
2734
+ "墨": 2732,
2735
+ "墩": 2733,
2736
+ "墪": 2734,
2737
+ "墫": 2735,
2738
+ "墬": 2736,
2739
+ "墭": 2737,
2740
+ "墮": 2738,
2741
+ "墯": 2739,
2742
+ "墰": 2740,
2743
+ "墱": 2741,
2744
+ "墲": 2742,
2745
+ "墳": 2743,
2746
+ "墴": 2744,
2747
+ "墵": 2745,
2748
+ "墶": 2746,
2749
+ "墷": 2747,
2750
+ "墸": 2748,
2751
+ "墹": 2749,
2752
+ "墺": 2750,
2753
+ "墻": 2751,
2754
+ "墼": 2752,
2755
+ "墽": 2753,
2756
+ "墾": 2754,
2757
+ "墿": 2755,
2758
+ "壀": 2756,
2759
+ "壁": 2757,
2760
+ "壂": 2758,
2761
+ "壃": 2759,
2762
+ "壄": 2760,
2763
+ "壅": 2761,
2764
+ "壆": 2762,
2765
+ "壇": 2763,
2766
+ "壈": 2764,
2767
+ "壉": 2765,
2768
+ "壊": 2766,
2769
+ "壋": 2767,
2770
+ "壌": 2768,
2771
+ "壍": 2769,
2772
+ "壎": 2770,
2773
+ "壏": 2771,
2774
+ "壐": 2772,
2775
+ "壑": 2773,
2776
+ "壒": 2774,
2777
+ "壓": 2775,
2778
+ "壔": 2776,
2779
+ "壕": 2777,
2780
+ "壖": 2778,
2781
+ "壗": 2779,
2782
+ "壘": 2780,
2783
+ "壙": 2781,
2784
+ "壚": 2782,
2785
+ "壛": 2783,
2786
+ "壜": 2784,
2787
+ "壝": 2785,
2788
+ "壞": 2786,
2789
+ "壟": 2787,
2790
+ "壠": 2788,
2791
+ "壡": 2789,
2792
+ "壢": 2790,
2793
+ "壣": 2791,
2794
+ "壤": 2792,
2795
+ "壥": 2793,
2796
+ "壦": 2794,
2797
+ "壧": 2795,
2798
+ "壨": 2796,
2799
+ "壩": 2797,
2800
+ "壪": 2798,
2801
+ "士": 2799,
2802
+ "壬": 2800,
2803
+ "壭": 2801,
2804
+ "壮": 2802,
2805
+ "壯": 2803,
2806
+ "声": 2804,
2807
+ "壱": 2805,
2808
+ "売": 2806,
2809
+ "壳": 2807,
2810
+ "壴": 2808,
2811
+ "壵": 2809,
2812
+ "壶": 2810,
2813
+ "壷": 2811,
2814
+ "壸": 2812,
2815
+ "壹": 2813,
2816
+ "壺": 2814,
2817
+ "壻": 2815,
2818
+ "壼": 2816,
2819
+ "壽": 2817,
2820
+ "壾": 2818,
2821
+ "壿": 2819,
2822
+ "夀": 2820,
2823
+ "夁": 2821,
2824
+ "夂": 2822,
2825
+ "夃": 2823,
2826
+ "处": 2824,
2827
+ "夅": 2825,
2828
+ "夆": 2826,
2829
+ "备": 2827,
2830
+ "夈": 2828,
2831
+ "変": 2829,
2832
+ "夊": 2830,
2833
+ "夋": 2831,
2834
+ "夌": 2832,
2835
+ "复": 2833,
2836
+ "夎": 2834,
2837
+ "夏": 2835,
2838
+ "夐": 2836,
2839
+ "夑": 2837,
2840
+ "夒": 2838,
2841
+ "夓": 2839,
2842
+ "夔": 2840,
2843
+ "夕": 2841,
2844
+ "外": 2842,
2845
+ "夗": 2843,
2846
+ "夘": 2844,
2847
+ "夙": 2845,
2848
+ "多": 2846,
2849
+ "夛": 2847,
2850
+ "夜": 2848,
2851
+ "夝": 2849,
2852
+ "夞": 2850,
2853
+ "够": 2851,
2854
+ "夠": 2852,
2855
+ "夡": 2853,
2856
+ "夢": 2854,
2857
+ "夣": 2855,
2858
+ "夤": 2856,
2859
+ "夥": 2857,
2860
+ "夦": 2858,
2861
+ "大": 2859,
2862
+ "夨": 2860,
2863
+ "天": 2861,
2864
+ "太": 2862,
2865
+ "夫": 2863,
2866
+ "夬": 2864,
2867
+ "夭": 2865,
2868
+ "央": 2866,
2869
+ "夯": 2867,
2870
+ "夰": 2868,
2871
+ "失": 2869,
2872
+ "夲": 2870,
2873
+ "夳": 2871,
2874
+ "头": 2872,
2875
+ "夵": 2873,
2876
+ "夶": 2874,
2877
+ "夷": 2875,
2878
+ "夸": 2876,
2879
+ "夹": 2877,
2880
+ "夺": 2878,
2881
+ "夻": 2879,
2882
+ "夼": 2880,
2883
+ "夽": 2881,
2884
+ "夾": 2882,
2885
+ "夿": 2883,
2886
+ "奀": 2884,
2887
+ "奁": 2885,
2888
+ "奂": 2886,
2889
+ "奃": 2887,
2890
+ "奄": 2888,
2891
+ "奅": 2889,
2892
+ "奆": 2890,
2893
+ "奇": 2891,
2894
+ "奈": 2892,
2895
+ "奉": 2893,
2896
+ "奊": 2894,
2897
+ "奋": 2895,
2898
+ "奌": 2896,
2899
+ "奍": 2897,
2900
+ "奎": 2898,
2901
+ "奏": 2899,
2902
+ "奐": 2900,
2903
+ "契": 2901,
2904
+ "奒": 2902,
2905
+ "奓": 2903,
2906
+ "奔": 2904,
2907
+ "奕": 2905,
2908
+ "奖": 2906,
2909
+ "套": 2907,
2910
+ "奘": 2908,
2911
+ "奙": 2909,
2912
+ "奚": 2910,
2913
+ "奛": 2911,
2914
+ "奜": 2912,
2915
+ "奝": 2913,
2916
+ "奞": 2914,
2917
+ "奟": 2915,
2918
+ "奠": 2916,
2919
+ "奡": 2917,
2920
+ "奢": 2918,
2921
+ "奣": 2919,
2922
+ "奤": 2920,
2923
+ "奥": 2921,
2924
+ "奦": 2922,
2925
+ "奧": 2923,
2926
+ "奨": 2924,
2927
+ "奩": 2925,
2928
+ "奪": 2926,
2929
+ "奫": 2927,
2930
+ "奬": 2928,
2931
+ "奭": 2929,
2932
+ "奮": 2930,
2933
+ "奯": 2931,
2934
+ "奰": 2932,
2935
+ "奱": 2933,
2936
+ "奲": 2934,
2937
+ "女": 2935,
2938
+ "奴": 2936,
2939
+ "奵": 2937,
2940
+ "奶": 2938,
2941
+ "奷": 2939,
2942
+ "奸": 2940,
2943
+ "她": 2941,
2944
+ "奺": 2942,
2945
+ "奻": 2943,
2946
+ "奼": 2944,
2947
+ "好": 2945,
2948
+ "奾": 2946,
2949
+ "奿": 2947,
2950
+ "妀": 2948,
2951
+ "妁": 2949,
2952
+ "如": 2950,
2953
+ "妃": 2951,
2954
+ "妄": 2952,
2955
+ "妅": 2953,
2956
+ "妆": 2954,
2957
+ "妇": 2955,
2958
+ "妈": 2956,
2959
+ "妉": 2957,
2960
+ "妊": 2958,
2961
+ "妋": 2959,
2962
+ "妌": 2960,
2963
+ "妍": 2961,
2964
+ "妎": 2962,
2965
+ "妏": 2963,
2966
+ "妐": 2964,
2967
+ "妑": 2965,
2968
+ "妒": 2966,
2969
+ "妓": 2967,
2970
+ "妔": 2968,
2971
+ "妕": 2969,
2972
+ "妖": 2970,
2973
+ "妗": 2971,
2974
+ "妘": 2972,
2975
+ "妙": 2973,
2976
+ "妚": 2974,
2977
+ "妛": 2975,
2978
+ "妜": 2976,
2979
+ "妝": 2977,
2980
+ "妞": 2978,
2981
+ "妟": 2979,
2982
+ "妠": 2980,
2983
+ "妡": 2981,
2984
+ "妢": 2982,
2985
+ "妣": 2983,
2986
+ "妤": 2984,
2987
+ "妥": 2985,
2988
+ "妦": 2986,
2989
+ "妧": 2987,
2990
+ "妨": 2988,
2991
+ "妩": 2989,
2992
+ "妪": 2990,
2993
+ "妫": 2991,
2994
+ "妬": 2992,
2995
+ "妭": 2993,
2996
+ "妮": 2994,
2997
+ "妯": 2995,
2998
+ "妰": 2996,
2999
+ "妱": 2997,
3000
+ "妲": 2998,
3001
+ "妳": 2999,
3002
+ "妴": 3000,
3003
+ "妵": 3001,
3004
+ "妶": 3002,
3005
+ "妷": 3003,
3006
+ "妸": 3004,
3007
+ "妹": 3005,
3008
+ "妺": 3006,
3009
+ "妻": 3007,
3010
+ "妼": 3008,
3011
+ "妽": 3009,
3012
+ "妾": 3010,
3013
+ "妿": 3011,
3014
+ "姀": 3012,
3015
+ "姁": 3013,
3016
+ "姂": 3014,
3017
+ "姃": 3015,
3018
+ "姄": 3016,
3019
+ "姅": 3017,
3020
+ "姆": 3018,
3021
+ "姇": 3019,
3022
+ "姈": 3020,
3023
+ "姉": 3021,
3024
+ "姊": 3022,
3025
+ "始": 3023,
3026
+ "姌": 3024,
3027
+ "姍": 3025,
3028
+ "姎": 3026,
3029
+ "姏": 3027,
3030
+ "姐": 3028,
3031
+ "姑": 3029,
3032
+ "姒": 3030,
3033
+ "姓": 3031,
3034
+ "委": 3032,
3035
+ "姕": 3033,
3036
+ "姖": 3034,
3037
+ "姗": 3035,
3038
+ "姘": 3036,
3039
+ "姙": 3037,
3040
+ "姚": 3038,
3041
+ "姛": 3039,
3042
+ "姜": 3040,
3043
+ "姝": 3041,
3044
+ "姞": 3042,
3045
+ "姟": 3043,
3046
+ "姠": 3044,
3047
+ "姡": 3045,
3048
+ "姢": 3046,
3049
+ "姣": 3047,
3050
+ "姤": 3048,
3051
+ "姥": 3049,
3052
+ "姦": 3050,
3053
+ "姧": 3051,
3054
+ "姨": 3052,
3055
+ "姩": 3053,
3056
+ "姪": 3054,
3057
+ "姫": 3055,
3058
+ "姬": 3056,
3059
+ "姭": 3057,
3060
+ "姮": 3058,
3061
+ "姯": 3059,
3062
+ "姰": 3060,
3063
+ "姱": 3061,
3064
+ "姲": 3062,
3065
+ "姳": 3063,
3066
+ "姴": 3064,
3067
+ "姵": 3065,
3068
+ "姶": 3066,
3069
+ "姷": 3067,
3070
+ "姸": 3068,
3071
+ "姹": 3069,
3072
+ "姺": 3070,
3073
+ "姻": 3071,
3074
+ "姼": 3072,
3075
+ "姽": 3073,
3076
+ "姾": 3074,
3077
+ "姿": 3075,
3078
+ "娀": 3076,
3079
+ "威": 3077,
3080
+ "娂": 3078,
3081
+ "娃": 3079,
3082
+ "娄": 3080,
3083
+ "娅": 3081,
3084
+ "娆": 3082,
3085
+ "娇": 3083,
3086
+ "娈": 3084,
3087
+ "娉": 3085,
3088
+ "娊": 3086,
3089
+ "娋": 3087,
3090
+ "娌": 3088,
3091
+ "娍": 3089,
3092
+ "娎": 3090,
3093
+ "娏": 3091,
3094
+ "娐": 3092,
3095
+ "娑": 3093,
3096
+ "娒": 3094,
3097
+ "娓": 3095,
3098
+ "娔": 3096,
3099
+ "娕": 3097,
3100
+ "娖": 3098,
3101
+ "娗": 3099,
3102
+ "娘": 3100,
3103
+ "娙": 3101,
3104
+ "娚": 3102,
3105
+ "娛": 3103,
3106
+ "娜": 3104,
3107
+ "娝": 3105,
3108
+ "娞": 3106,
3109
+ "娟": 3107,
3110
+ "娠": 3108,
3111
+ "娡": 3109,
3112
+ "娢": 3110,
3113
+ "娣": 3111,
3114
+ "娤": 3112,
3115
+ "娥": 3113,
3116
+ "娦": 3114,
3117
+ "娧": 3115,
3118
+ "娨": 3116,
3119
+ "娩": 3117,
3120
+ "娪": 3118,
3121
+ "娫": 3119,
3122
+ "娬": 3120,
3123
+ "娭": 3121,
3124
+ "娮": 3122,
3125
+ "娯": 3123,
3126
+ "娰": 3124,
3127
+ "娱": 3125,
3128
+ "娲": 3126,
3129
+ "娳": 3127,
3130
+ "娴": 3128,
3131
+ "娵": 3129,
3132
+ "娶": 3130,
3133
+ "娷": 3131,
3134
+ "娸": 3132,
3135
+ "娹": 3133,
3136
+ "娺": 3134,
3137
+ "娻": 3135,
3138
+ "娼": 3136,
3139
+ "娽": 3137,
3140
+ "娾": 3138,
3141
+ "娿": 3139,
3142
+ "婀": 3140,
3143
+ "婁": 3141,
3144
+ "婂": 3142,
3145
+ "婃": 3143,
3146
+ "婄": 3144,
3147
+ "婅": 3145,
3148
+ "婆": 3146,
3149
+ "婇": 3147,
3150
+ "婈": 3148,
3151
+ "婉": 3149,
3152
+ "婊": 3150,
3153
+ "婋": 3151,
3154
+ "婌": 3152,
3155
+ "婍": 3153,
3156
+ "婎": 3154,
3157
+ "婏": 3155,
3158
+ "婐": 3156,
3159
+ "婑": 3157,
3160
+ "婒": 3158,
3161
+ "婓": 3159,
3162
+ "婔": 3160,
3163
+ "婕": 3161,
3164
+ "婖": 3162,
3165
+ "婗": 3163,
3166
+ "婘": 3164,
3167
+ "婙": 3165,
3168
+ "婚": 3166,
3169
+ "婛": 3167,
3170
+ "婜": 3168,
3171
+ "婝": 3169,
3172
+ "婞": 3170,
3173
+ "婟": 3171,
3174
+ "婠": 3172,
3175
+ "婡": 3173,
3176
+ "婢": 3174,
3177
+ "婣": 3175,
3178
+ "婤": 3176,
3179
+ "婥": 3177,
3180
+ "婦": 3178,
3181
+ "婧": 3179,
3182
+ "婨": 3180,
3183
+ "婩": 3181,
3184
+ "婪": 3182,
3185
+ "婫": 3183,
3186
+ "婬": 3184,
3187
+ "婭": 3185,
3188
+ "婮": 3186,
3189
+ "婯": 3187,
3190
+ "婰": 3188,
3191
+ "婱": 3189,
3192
+ "婲": 3190,
3193
+ "婳": 3191,
3194
+ "婴": 3192,
3195
+ "婵": 3193,
3196
+ "婶": 3194,
3197
+ "婷": 3195,
3198
+ "婸": 3196,
3199
+ "婹": 3197,
3200
+ "婺": 3198,
3201
+ "婻": 3199,
3202
+ "婼": 3200,
3203
+ "婽": 3201,
3204
+ "婾": 3202,
3205
+ "婿": 3203,
3206
+ "媀": 3204,
3207
+ "媁": 3205,
3208
+ "媂": 3206,
3209
+ "媃": 3207,
3210
+ "媄": 3208,
3211
+ "媅": 3209,
3212
+ "媆": 3210,
3213
+ "媇": 3211,
3214
+ "媈": 3212,
3215
+ "媉": 3213,
3216
+ "媊": 3214,
3217
+ "媋": 3215,
3218
+ "媌": 3216,
3219
+ "媍": 3217,
3220
+ "媎": 3218,
3221
+ "媏": 3219,
3222
+ "媐": 3220,
3223
+ "媑": 3221,
3224
+ "媒": 3222,
3225
+ "媓": 3223,
3226
+ "媔": 3224,
3227
+ "媕": 3225,
3228
+ "媖": 3226,
3229
+ "媗": 3227,
3230
+ "媘": 3228,
3231
+ "媙": 3229,
3232
+ "媚": 3230,
3233
+ "媛": 3231,
3234
+ "媜": 3232,
3235
+ "媝": 3233,
3236
+ "媞": 3234,
3237
+ "媟": 3235,
3238
+ "媠": 3236,
3239
+ "媡": 3237,
3240
+ "媢": 3238,
3241
+ "媣": 3239,
3242
+ "媤": 3240,
3243
+ "媥": 3241,
3244
+ "媦": 3242,
3245
+ "媧": 3243,
3246
+ "媨": 3244,
3247
+ "媩": 3245,
3248
+ "媪": 3246,
3249
+ "媫": 3247,
3250
+ "媬": 3248,
3251
+ "媭": 3249,
3252
+ "媮": 3250,
3253
+ "媯": 3251,
3254
+ "媰": 3252,
3255
+ "媱": 3253,
3256
+ "媲": 3254,
3257
+ "媳": 3255,
3258
+ "媴": 3256,
3259
+ "媵": 3257,
3260
+ "媶": 3258,
3261
+ "媷": 3259,
3262
+ "媸": 3260,
3263
+ "媹": 3261,
3264
+ "媺": 3262,
3265
+ "媻": 3263,
3266
+ "媼": 3264,
3267
+ "媽": 3265,
3268
+ "媾": 3266,
3269
+ "媿": 3267,
3270
+ "嫀": 3268,
3271
+ "嫁": 3269,
3272
+ "嫂": 3270,
3273
+ "嫃": 3271,
3274
+ "嫄": 3272,
3275
+ "嫅": 3273,
3276
+ "嫆": 3274,
3277
+ "嫇": 3275,
3278
+ "嫈": 3276,
3279
+ "嫉": 3277,
3280
+ "嫊": 3278,
3281
+ "嫋": 3279,
3282
+ "嫌": 3280,
3283
+ "嫍": 3281,
3284
+ "嫎": 3282,
3285
+ "嫏": 3283,
3286
+ "嫐": 3284,
3287
+ "嫑": 3285,
3288
+ "嫒": 3286,
3289
+ "嫓": 3287,
3290
+ "嫔": 3288,
3291
+ "嫕": 3289,
3292
+ "嫖": 3290,
3293
+ "嫗": 3291,
3294
+ "嫘": 3292,
3295
+ "嫙": 3293,
3296
+ "嫚": 3294,
3297
+ "嫛": 3295,
3298
+ "嫜": 3296,
3299
+ "嫝": 3297,
3300
+ "嫞": 3298,
3301
+ "嫟": 3299,
3302
+ "嫠": 3300,
3303
+ "嫡": 3301,
3304
+ "嫢": 3302,
3305
+ "嫣": 3303,
3306
+ "嫤": 3304,
3307
+ "嫥": 3305,
3308
+ "嫦": 3306,
3309
+ "嫧": 3307,
3310
+ "嫨": 3308,
3311
+ "嫩": 3309,
3312
+ "嫪": 3310,
3313
+ "嫫": 3311,
3314
+ "嫬": 3312,
3315
+ "嫭": 3313,
3316
+ "嫮": 3314,
3317
+ "嫯": 3315,
3318
+ "嫰": 3316,
3319
+ "嫱": 3317,
3320
+ "嫲": 3318,
3321
+ "嫳": 3319,
3322
+ "嫴": 3320,
3323
+ "嫵": 3321,
3324
+ "嫶": 3322,
3325
+ "嫷": 3323,
3326
+ "嫸": 3324,
3327
+ "嫹": 3325,
3328
+ "嫺": 3326,
3329
+ "嫻": 3327,
3330
+ "嫼": 3328,
3331
+ "嫽": 3329,
3332
+ "嫾": 3330,
3333
+ "嫿": 3331,
3334
+ "嬀": 3332,
3335
+ "嬁": 3333,
3336
+ "嬂": 3334,
3337
+ "嬃": 3335,
3338
+ "嬄": 3336,
3339
+ "嬅": 3337,
3340
+ "嬆": 3338,
3341
+ "嬇": 3339,
3342
+ "嬈": 3340,
3343
+ "嬉": 3341,
3344
+ "嬊": 3342,
3345
+ "嬋": 3343,
3346
+ "嬌": 3344,
3347
+ "嬍": 3345,
3348
+ "嬎": 3346,
3349
+ "嬏": 3347,
3350
+ "嬐": 3348,
3351
+ "嬑": 3349,
3352
+ "嬒": 3350,
3353
+ "嬓": 3351,
3354
+ "嬔": 3352,
3355
+ "嬕": 3353,
3356
+ "嬖": 3354,
3357
+ "嬗": 3355,
3358
+ "嬘": 3356,
3359
+ "嬙": 3357,
3360
+ "嬚": 3358,
3361
+ "嬛": 3359,
3362
+ "嬜": 3360,
3363
+ "嬝": 3361,
3364
+ "嬞": 3362,
3365
+ "嬟": 3363,
3366
+ "嬠": 3364,
3367
+ "嬡": 3365,
3368
+ "嬢": 3366,
3369
+ "嬣": 3367,
3370
+ "嬤": 3368,
3371
+ "嬥": 3369,
3372
+ "嬦": 3370,
3373
+ "嬧": 3371,
3374
+ "嬨": 3372,
3375
+ "嬩": 3373,
3376
+ "嬪": 3374,
3377
+ "嬫": 3375,
3378
+ "嬬": 3376,
3379
+ "嬭": 3377,
3380
+ "嬮": 3378,
3381
+ "嬯": 3379,
3382
+ "嬰": 3380,
3383
+ "嬱": 3381,
3384
+ "嬲": 3382,
3385
+ "嬳": 3383,
3386
+ "嬴": 3384,
3387
+ "嬵": 3385,
3388
+ "嬶": 3386,
3389
+ "嬷": 3387,
3390
+ "嬸": 3388,
3391
+ "嬹": 3389,
3392
+ "嬺": 3390,
3393
+ "嬻": 3391,
3394
+ "嬼": 3392,
3395
+ "嬽": 3393,
3396
+ "嬾": 3394,
3397
+ "嬿": 3395,
3398
+ "孀": 3396,
3399
+ "孁": 3397,
3400
+ "孂": 3398,
3401
+ "孃": 3399,
3402
+ "孄": 3400,
3403
+ "孅": 3401,
3404
+ "孆": 3402,
3405
+ "孇": 3403,
3406
+ "孈": 3404,
3407
+ "孉": 3405,
3408
+ "孊": 3406,
3409
+ "孋": 3407,
3410
+ "孌": 3408,
3411
+ "孍": 3409,
3412
+ "孎": 3410,
3413
+ "孏": 3411,
3414
+ "子": 3412,
3415
+ "孑": 3413,
3416
+ "孒": 3414,
3417
+ "孓": 3415,
3418
+ "孔": 3416,
3419
+ "孕": 3417,
3420
+ "孖": 3418,
3421
+ "字": 3419,
3422
+ "存": 3420,
3423
+ "孙": 3421,
3424
+ "孚": 3422,
3425
+ "孛": 3423,
3426
+ "孜": 3424,
3427
+ "孝": 3425,
3428
+ "孞": 3426,
3429
+ "孟": 3427,
3430
+ "孠": 3428,
3431
+ "孡": 3429,
3432
+ "孢": 3430,
3433
+ "季": 3431,
3434
+ "孤": 3432,
3435
+ "孥": 3433,
3436
+ "学": 3434,
3437
+ "孧": 3435,
3438
+ "孨": 3436,
3439
+ "孩": 3437,
3440
+ "孪": 3438,
3441
+ "孫": 3439,
3442
+ "孬": 3440,
3443
+ "孭": 3441,
3444
+ "孮": 3442,
3445
+ "孯": 3443,
3446
+ "孰": 3444,
3447
+ "孱": 3445,
3448
+ "孲": 3446,
3449
+ "孳": 3447,
3450
+ "孴": 3448,
3451
+ "孵": 3449,
3452
+ "孶": 3450,
3453
+ "孷": 3451,
3454
+ "學": 3452,
3455
+ "孹": 3453,
3456
+ "孺": 3454,
3457
+ "孻": 3455,
3458
+ "孼": 3456,
3459
+ "孽": 3457,
3460
+ "孾": 3458,
3461
+ "孿": 3459,
3462
+ "宀": 3460,
3463
+ "宁": 3461,
3464
+ "宂": 3462,
3465
+ "它": 3463,
3466
+ "宄": 3464,
3467
+ "宅": 3465,
3468
+ "宆": 3466,
3469
+ "宇": 3467,
3470
+ "守": 3468,
3471
+ "安": 3469,
3472
+ "宊": 3470,
3473
+ "宋": 3471,
3474
+ "完": 3472,
3475
+ "宍": 3473,
3476
+ "宎": 3474,
3477
+ "宏": 3475,
3478
+ "宐": 3476,
3479
+ "宑": 3477,
3480
+ "宒": 3478,
3481
+ "宓": 3479,
3482
+ "宔": 3480,
3483
+ "宕": 3481,
3484
+ "宖": 3482,
3485
+ "宗": 3483,
3486
+ "官": 3484,
3487
+ "宙": 3485,
3488
+ "定": 3486,
3489
+ "宛": 3487,
3490
+ "宜": 3488,
3491
+ "宝": 3489,
3492
+ "实": 3490,
3493
+ "実": 3491,
3494
+ "宠": 3492,
3495
+ "审": 3493,
3496
+ "客": 3494,
3497
+ "宣": 3495,
3498
+ "室": 3496,
3499
+ "宥": 3497,
3500
+ "宦": 3498,
3501
+ "宧": 3499,
3502
+ "宨": 3500,
3503
+ "宩": 3501,
3504
+ "宪": 3502,
3505
+ "宫": 3503,
3506
+ "宬": 3504,
3507
+ "宭": 3505,
3508
+ "宮": 3506,
3509
+ "宯": 3507,
3510
+ "宰": 3508,
3511
+ "宱": 3509,
3512
+ "宲": 3510,
3513
+ "害": 3511,
3514
+ "宴": 3512,
3515
+ "宵": 3513,
3516
+ "家": 3514,
3517
+ "宷": 3515,
3518
+ "宸": 3516,
3519
+ "容": 3517,
3520
+ "宺": 3518,
3521
+ "宻": 3519,
3522
+ "宼": 3520,
3523
+ "宽": 3521,
3524
+ "宾": 3522,
3525
+ "宿": 3523,
3526
+ "寀": 3524,
3527
+ "寁": 3525,
3528
+ "寂": 3526,
3529
+ "寃": 3527,
3530
+ "寄": 3528,
3531
+ "寅": 3529,
3532
+ "密": 3530,
3533
+ "寇": 3531,
3534
+ "寈": 3532,
3535
+ "寉": 3533,
3536
+ "寊": 3534,
3537
+ "寋": 3535,
3538
+ "富": 3536,
3539
+ "寍": 3537,
3540
+ "寎": 3538,
3541
+ "寏": 3539,
3542
+ "寐": 3540,
3543
+ "寑": 3541,
3544
+ "寒": 3542,
3545
+ "寓": 3543,
3546
+ "寔": 3544,
3547
+ "寕": 3545,
3548
+ "寖": 3546,
3549
+ "寗": 3547,
3550
+ "寘": 3548,
3551
+ "寙": 3549,
3552
+ "寚": 3550,
3553
+ "寛": 3551,
3554
+ "寜": 3552,
3555
+ "寝": 3553,
3556
+ "寞": 3554,
3557
+ "察": 3555,
3558
+ "寠": 3556,
3559
+ "寡": 3557,
3560
+ "寢": 3558,
3561
+ "寣": 3559,
3562
+ "寤": 3560,
3563
+ "寥": 3561,
3564
+ "實": 3562,
3565
+ "寧": 3563,
3566
+ "寨": 3564,
3567
+ "審": 3565,
3568
+ "寪": 3566,
3569
+ "寫": 3567,
3570
+ "寬": 3568,
3571
+ "寭": 3569,
3572
+ "寮": 3570,
3573
+ "寯": 3571,
3574
+ "寰": 3572,
3575
+ "寱": 3573,
3576
+ "寲": 3574,
3577
+ "寳": 3575,
3578
+ "寴": 3576,
3579
+ "寵": 3577,
3580
+ "寶": 3578,
3581
+ "寷": 3579,
3582
+ "寸": 3580,
3583
+ "对": 3581,
3584
+ "寺": 3582,
3585
+ "寻": 3583,
3586
+ "导": 3584,
3587
+ "寽": 3585,
3588
+ "対": 3586,
3589
+ "寿": 3587,
3590
+ "尀": 3588,
3591
+ "封": 3589,
3592
+ "専": 3590,
3593
+ "尃": 3591,
3594
+ "射": 3592,
3595
+ "尅": 3593,
3596
+ "将": 3594,
3597
+ "將": 3595,
3598
+ "專": 3596,
3599
+ "尉": 3597,
3600
+ "尊": 3598,
3601
+ "尋": 3599,
3602
+ "尌": 3600,
3603
+ "對": 3601,
3604
+ "導": 3602,
3605
+ "小": 3603,
3606
+ "尐": 3604,
3607
+ "少": 3605,
3608
+ "尒": 3606,
3609
+ "尓": 3607,
3610
+ "尔": 3608,
3611
+ "尕": 3609,
3612
+ "尖": 3610,
3613
+ "尗": 3611,
3614
+ "尘": 3612,
3615
+ "尙": 3613,
3616
+ "尚": 3614,
3617
+ "尛": 3615,
3618
+ "尜": 3616,
3619
+ "尝": 3617,
3620
+ "尞": 3618,
3621
+ "尟": 3619,
3622
+ "尠": 3620,
3623
+ "尡": 3621,
3624
+ "尢": 3622,
3625
+ "尣": 3623,
3626
+ "尤": 3624,
3627
+ "尥": 3625,
3628
+ "尦": 3626,
3629
+ "尧": 3627,
3630
+ "尨": 3628,
3631
+ "尩": 3629,
3632
+ "尪": 3630,
3633
+ "尫": 3631,
3634
+ "尬": 3632,
3635
+ "尭": 3633,
3636
+ "尮": 3634,
3637
+ "尯": 3635,
3638
+ "尰": 3636,
3639
+ "就": 3637,
3640
+ "尲": 3638,
3641
+ "尳": 3639,
3642
+ "尴": 3640,
3643
+ "尵": 3641,
3644
+ "尶": 3642,
3645
+ "尷": 3643,
3646
+ "尸": 3644,
3647
+ "尹": 3645,
3648
+ "尺": 3646,
3649
+ "尻": 3647,
3650
+ "尼": 3648,
3651
+ "尽": 3649,
3652
+ "尾": 3650,
3653
+ "尿": 3651,
3654
+ "局": 3652,
3655
+ "屁": 3653,
3656
+ "层": 3654,
3657
+ "屃": 3655,
3658
+ "屄": 3656,
3659
+ "居": 3657,
3660
+ "屆": 3658,
3661
+ "屇": 3659,
3662
+ "屈": 3660,
3663
+ "屉": 3661,
3664
+ "届": 3662,
3665
+ "屋": 3663,
3666
+ "屌": 3664,
3667
+ "屍": 3665,
3668
+ "屎": 3666,
3669
+ "屏": 3667,
3670
+ "屐": 3668,
3671
+ "屑": 3669,
3672
+ "屒": 3670,
3673
+ "屓": 3671,
3674
+ "屔": 3672,
3675
+ "展": 3673,
3676
+ "屖": 3674,
3677
+ "屗": 3675,
3678
+ "屘": 3676,
3679
+ "屙": 3677,
3680
+ "屚": 3678,
3681
+ "屛": 3679,
3682
+ "屜": 3680,
3683
+ "屝": 3681,
3684
+ "属": 3682,
3685
+ "屟": 3683,
3686
+ "屠": 3684,
3687
+ "屡": 3685,
3688
+ "屢": 3686,
3689
+ "屣": 3687,
3690
+ "層": 3688,
3691
+ "履": 3689,
3692
+ "屦": 3690,
3693
+ "屧": 3691,
3694
+ "屨": 3692,
3695
+ "屩": 3693,
3696
+ "屪": 3694,
3697
+ "屫": 3695,
3698
+ "屬": 3696,
3699
+ "屭": 3697,
3700
+ "屮": 3698,
3701
+ "屯": 3699,
3702
+ "屰": 3700,
3703
+ "山": 3701,
3704
+ "屲": 3702,
3705
+ "屳": 3703,
3706
+ "屴": 3704,
3707
+ "屵": 3705,
3708
+ "屶": 3706,
3709
+ "屷": 3707,
3710
+ "屸": 3708,
3711
+ "屹": 3709,
3712
+ "屺": 3710,
3713
+ "屻": 3711,
3714
+ "屼": 3712,
3715
+ "屽": 3713,
3716
+ "屾": 3714,
3717
+ "屿": 3715,
3718
+ "岀": 3716,
3719
+ "岁": 3717,
3720
+ "岂": 3718,
3721
+ "岃": 3719,
3722
+ "岄": 3720,
3723
+ "岅": 3721,
3724
+ "岆": 3722,
3725
+ "岇": 3723,
3726
+ "岈": 3724,
3727
+ "岉": 3725,
3728
+ "岊": 3726,
3729
+ "岋": 3727,
3730
+ "岌": 3728,
3731
+ "岍": 3729,
3732
+ "岎": 3730,
3733
+ "岏": 3731,
3734
+ "岐": 3732,
3735
+ "岑": 3733,
3736
+ "岒": 3734,
3737
+ "岓": 3735,
3738
+ "岔": 3736,
3739
+ "岕": 3737,
3740
+ "岖": 3738,
3741
+ "岗": 3739,
3742
+ "岘": 3740,
3743
+ "岙": 3741,
3744
+ "岚": 3742,
3745
+ "岛": 3743,
3746
+ "岜": 3744,
3747
+ "岝": 3745,
3748
+ "岞": 3746,
3749
+ "岟": 3747,
3750
+ "岠": 3748,
3751
+ "岡": 3749,
3752
+ "岢": 3750,
3753
+ "岣": 3751,
3754
+ "岤": 3752,
3755
+ "岥": 3753,
3756
+ "岦": 3754,
3757
+ "岧": 3755,
3758
+ "岨": 3756,
3759
+ "岩": 3757,
3760
+ "岪": 3758,
3761
+ "the": 3759,
3762
+ "be": 3760,
3763
+ "to": 3761,
3764
+ "of": 3762,
3765
+ "and": 3763,
3766
+ "a": 3764,
3767
+ "in": 3765,
3768
+ "that": 3766,
3769
+ "have": 3767,
3770
+ "it": 3768,
3771
+ "for": 3769,
3772
+ "not": 3770,
3773
+ "on": 3771,
3774
+ "with": 3772,
3775
+ "he": 3773,
3776
+ "as": 3774,
3777
+ "you": 3775,
3778
+ "do": 3776,
3779
+ "at": 3777,
3780
+ "this": 3778,
3781
+ "but": 3779,
3782
+ "his": 3780,
3783
+ "by": 3781,
3784
+ "from": 3782,
3785
+ "they": 3783,
3786
+ "we": 3784,
3787
+ "say": 3785,
3788
+ "her": 3786,
3789
+ "she": 3787,
3790
+ "or": 3788,
3791
+ "an": 3789,
3792
+ "will": 3790,
3793
+ "my": 3791,
3794
+ "one": 3792,
3795
+ "all": 3793,
3796
+ "would": 3794,
3797
+ "there": 3795,
3798
+ "their": 3796,
3799
+ "what": 3797,
3800
+ "so": 3798,
3801
+ "up": 3799,
3802
+ "out": 3800,
3803
+ "if": 3801,
3804
+ "about": 3802,
3805
+ "who": 3803,
3806
+ "get": 3804,
3807
+ "which": 3805,
3808
+ "go": 3806,
3809
+ "me": 3807,
3810
+ "when": 3808,
3811
+ "make": 3809,
3812
+ "can": 3810,
3813
+ "like": 3811,
3814
+ "time": 3812,
3815
+ "no": 3813,
3816
+ "just": 3814,
3817
+ "him": 3815,
3818
+ "know": 3816,
3819
+ "take": 3817,
3820
+ "people": 3818,
3821
+ "into": 3819,
3822
+ "year": 3820,
3823
+ "your": 3821,
3824
+ "good": 3822,
3825
+ "some": 3823,
3826
+ "could": 3824,
3827
+ "them": 3825,
3828
+ "see": 3826,
3829
+ "other": 3827,
3830
+ "than": 3828,
3831
+ "then": 3829,
3832
+ "now": 3830,
3833
+ "look": 3831,
3834
+ "only": 3832,
3835
+ "come": 3833,
3836
+ "its": 3834,
3837
+ "over": 3835,
3838
+ "think": 3836,
3839
+ "also": 3837,
3840
+ "back": 3838,
3841
+ "after": 3839,
3842
+ "use": 3840,
3843
+ "two": 3841,
3844
+ "how": 3842,
3845
+ "our": 3843,
3846
+ "work": 3844,
3847
+ "first": 3845,
3848
+ "well": 3846,
3849
+ "way": 3847,
3850
+ "even": 3848,
3851
+ "new": 3849,
3852
+ "want": 3850,
3853
+ "because": 3851,
3854
+ "any": 3852,
3855
+ "these": 3853,
3856
+ "give": 3854,
3857
+ "day": 3855,
3858
+ "most": 3856,
3859
+ "us": 3857,
3860
+ "unthe": 3858,
3861
+ "unbe": 3859,
3862
+ "unto": 3860,
3863
+ "unof": 3861,
3864
+ "unand": 3862,
3865
+ "una": 3863,
3866
+ "unin": 3864,
3867
+ "unthat": 3865,
3868
+ "unhave": 3866,
3869
+ "unit": 3867,
3870
+ "unfor": 3868,
3871
+ "unnot": 3869,
3872
+ "unon": 3870,
3873
+ "unwith": 3871,
3874
+ "unhe": 3872,
3875
+ "unas": 3873,
3876
+ "unyou": 3874,
3877
+ "undo": 3875,
3878
+ "unat": 3876,
3879
+ "unthis": 3877,
3880
+ "unbut": 3878,
3881
+ "unhis": 3879,
3882
+ "unby": 3880,
3883
+ "unfrom": 3881,
3884
+ "unthey": 3882,
3885
+ "unwe": 3883,
3886
+ "unsay": 3884,
3887
+ "unher": 3885,
3888
+ "unshe": 3886,
3889
+ "unor": 3887,
3890
+ "unan": 3888,
3891
+ "unwill": 3889,
3892
+ "unmy": 3890,
3893
+ "unone": 3891,
3894
+ "unall": 3892,
3895
+ "unwould": 3893,
3896
+ "unthere": 3894,
3897
+ "untheir": 3895,
3898
+ "unwhat": 3896,
3899
+ "unso": 3897,
3900
+ "unup": 3898,
3901
+ "unout": 3899,
3902
+ "unif": 3900,
3903
+ "unabout": 3901,
3904
+ "unwho": 3902,
3905
+ "unget": 3903,
3906
+ "unwhich": 3904,
3907
+ "ungo": 3905,
3908
+ "unme": 3906,
3909
+ "unwhen": 3907,
3910
+ "rethe": 3908,
3911
+ "rebe": 3909,
3912
+ "reto": 3910,
3913
+ "reof": 3911,
3914
+ "reand": 3912,
3915
+ "rea": 3913,
3916
+ "rein": 3914,
3917
+ "rethat": 3915,
3918
+ "rehave": 3916,
3919
+ "reit": 3917,
3920
+ "refor": 3918,
3921
+ "renot": 3919,
3922
+ "reon": 3920,
3923
+ "rewith": 3921,
3924
+ "rehe": 3922,
3925
+ "reas": 3923,
3926
+ "reyou": 3924,
3927
+ "redo": 3925,
3928
+ "reat": 3926,
3929
+ "rethis": 3927,
3930
+ "rebut": 3928,
3931
+ "rehis": 3929,
3932
+ "reby": 3930,
3933
+ "refrom": 3931,
3934
+ "rethey": 3932,
3935
+ "rewe": 3933,
3936
+ "resay": 3934,
3937
+ "reher": 3935,
3938
+ "reshe": 3936,
3939
+ "reor": 3937,
3940
+ "rean": 3938,
3941
+ "rewill": 3939,
3942
+ "remy": 3940,
3943
+ "reone": 3941,
3944
+ "reall": 3942,
3945
+ "rewould": 3943,
3946
+ "rethere": 3944,
3947
+ "retheir": 3945,
3948
+ "rewhat": 3946,
3949
+ "reso": 3947,
3950
+ "reup": 3948,
3951
+ "reout": 3949,
3952
+ "reif": 3950,
3953
+ "reabout": 3951,
3954
+ "rewho": 3952,
3955
+ "reget": 3953,
3956
+ "rewhich": 3954,
3957
+ "rego": 3955,
3958
+ "reme": 3956,
3959
+ "rewhen": 3957,
3960
+ "prethe": 3958,
3961
+ "prebe": 3959,
3962
+ "preto": 3960,
3963
+ "preof": 3961,
3964
+ "preand": 3962,
3965
+ "prea": 3963,
3966
+ "prein": 3964,
3967
+ "prethat": 3965,
3968
+ "prehave": 3966,
3969
+ "preit": 3967,
3970
+ "prefor": 3968,
3971
+ "prenot": 3969,
3972
+ "preon": 3970,
3973
+ "prewith": 3971,
3974
+ "prehe": 3972,
3975
+ "preas": 3973,
3976
+ "preyou": 3974,
3977
+ "predo": 3975,
3978
+ "preat": 3976,
3979
+ "prethis": 3977,
3980
+ "prebut": 3978,
3981
+ "prehis": 3979,
3982
+ "preby": 3980,
3983
+ "prefrom": 3981,
3984
+ "prethey": 3982,
3985
+ "prewe": 3983,
3986
+ "presay": 3984,
3987
+ "preher": 3985,
3988
+ "preshe": 3986,
3989
+ "preor": 3987,
3990
+ "prean": 3988,
3991
+ "prewill": 3989,
3992
+ "premy": 3990,
3993
+ "preone": 3991,
3994
+ "preall": 3992,
3995
+ "prewould": 3993,
3996
+ "prethere": 3994,
3997
+ "pretheir": 3995,
3998
+ "prewhat": 3996,
3999
+ "preso": 3997,
4000
+ "preup": 3998,
4001
+ "preout": 3999,
4002
+ "preif": 4000,
4003
+ "preabout": 4001,
4004
+ "prewho": 4002,
4005
+ "preget": 4003,
4006
+ "prewhich": 4004,
4007
+ "prego": 4005,
4008
+ "preme": 4006,
4009
+ "prewhen": 4007,
4010
+ "disthe": 4008,
4011
+ "disbe": 4009,
4012
+ "disto": 4010,
4013
+ "disof": 4011,
4014
+ "disand": 4012,
4015
+ "disa": 4013,
4016
+ "disin": 4014,
4017
+ "disthat": 4015,
4018
+ "dishave": 4016,
4019
+ "disit": 4017,
4020
+ "disfor": 4018,
4021
+ "disnot": 4019,
4022
+ "dison": 4020,
4023
+ "diswith": 4021,
4024
+ "dishe": 4022,
4025
+ "disas": 4023,
4026
+ "disyou": 4024,
4027
+ "disdo": 4025,
4028
+ "disat": 4026,
4029
+ "disthis": 4027,
4030
+ "disbut": 4028,
4031
+ "dishis": 4029,
4032
+ "disby": 4030,
4033
+ "disfrom": 4031,
4034
+ "disthey": 4032,
4035
+ "diswe": 4033,
4036
+ "dissay": 4034,
4037
+ "disher": 4035,
4038
+ "disshe": 4036,
4039
+ "disor": 4037,
4040
+ "disan": 4038,
4041
+ "diswill": 4039,
4042
+ "dismy": 4040,
4043
+ "disone": 4041,
4044
+ "disall": 4042,
4045
+ "diswould": 4043,
4046
+ "disthere": 4044,
4047
+ "distheir": 4045,
4048
+ "diswhat": 4046,
4049
+ "disso": 4047,
4050
+ "disup": 4048,
4051
+ "disout": 4049,
4052
+ "disif": 4050,
4053
+ "disabout": 4051,
4054
+ "diswho": 4052,
4055
+ "disget": 4053,
4056
+ "diswhich": 4054,
4057
+ "disgo": 4055,
4058
+ "disme": 4056,
4059
+ "diswhen": 4057,
4060
+ "misthe": 4058,
4061
+ "misbe": 4059,
4062
+ "misto": 4060,
4063
+ "misof": 4061,
4064
+ "misand": 4062,
4065
+ "misa": 4063,
4066
+ "misin": 4064,
4067
+ "misthat": 4065,
4068
+ "mishave": 4066,
4069
+ "misit": 4067,
4070
+ "misfor": 4068,
4071
+ "misnot": 4069,
4072
+ "mison": 4070,
4073
+ "miswith": 4071,
4074
+ "mishe": 4072,
4075
+ "misas": 4073,
4076
+ "misyou": 4074,
4077
+ "misdo": 4075,
4078
+ "misat": 4076,
4079
+ "misthis": 4077,
4080
+ "misbut": 4078,
4081
+ "mishis": 4079,
4082
+ "misby": 4080,
4083
+ "misfrom": 4081,
4084
+ "misthey": 4082,
4085
+ "miswe": 4083,
4086
+ "missay": 4084,
4087
+ "misher": 4085,
4088
+ "misshe": 4086,
4089
+ "misor": 4087,
4090
+ "misan": 4088,
4091
+ "miswill": 4089,
4092
+ "mismy": 4090,
4093
+ "misone": 4091,
4094
+ "misall": 4092,
4095
+ "miswould": 4093,
4096
+ "misthere": 4094,
4097
+ "mistheir": 4095,
4098
+ "miswhat": 4096,
4099
+ "misso": 4097,
4100
+ "misup": 4098,
4101
+ "misout": 4099,
4102
+ "misif": 4100,
4103
+ "misabout": 4101,
4104
+ "miswho": 4102,
4105
+ "misget": 4103,
4106
+ "miswhich": 4104,
4107
+ "misgo": 4105,
4108
+ "misme": 4106,
4109
+ "miswhen": 4107,
4110
+ "overthe": 4108,
4111
+ "overbe": 4109,
4112
+ "overto": 4110,
4113
+ "overof": 4111,
4114
+ "overand": 4112,
4115
+ "overa": 4113,
4116
+ "overin": 4114,
4117
+ "overthat": 4115,
4118
+ "overhave": 4116,
4119
+ "overit": 4117,
4120
+ "overfor": 4118,
4121
+ "overnot": 4119,
4122
+ "overon": 4120,
4123
+ "overwith": 4121,
4124
+ "overhe": 4122,
4125
+ "overas": 4123,
4126
+ "overyou": 4124,
4127
+ "overdo": 4125,
4128
+ "overat": 4126,
4129
+ "overthis": 4127,
4130
+ "overbut": 4128,
4131
+ "overhis": 4129,
4132
+ "overby": 4130,
4133
+ "overfrom": 4131,
4134
+ "overthey": 4132,
4135
+ "overwe": 4133,
4136
+ "oversay": 4134,
4137
+ "overher": 4135,
4138
+ "overshe": 4136,
4139
+ "overor": 4137,
4140
+ "overan": 4138,
4141
+ "overwill": 4139,
4142
+ "overmy": 4140,
4143
+ "overone": 4141,
4144
+ "overall": 4142,
4145
+ "overwould": 4143,
4146
+ "overthere": 4144,
4147
+ "overtheir": 4145,
4148
+ "overwhat": 4146,
4149
+ "overso": 4147,
4150
+ "overup": 4148,
4151
+ "overout": 4149,
4152
+ "overif": 4150,
4153
+ "overabout": 4151,
4154
+ "overwho": 4152,
4155
+ "overget": 4153,
4156
+ "overwhich": 4154,
4157
+ "overgo": 4155,
4158
+ "overme": 4156,
4159
+ "overwhen": 4157,
4160
+ "underthe": 4158,
4161
+ "underbe": 4159,
4162
+ "underto": 4160,
4163
+ "underof": 4161,
4164
+ "underand": 4162,
4165
+ "undera": 4163,
4166
+ "underin": 4164,
4167
+ "underthat": 4165,
4168
+ "underhave": 4166,
4169
+ "underit": 4167,
4170
+ "underfor": 4168,
4171
+ "undernot": 4169,
4172
+ "underon": 4170,
4173
+ "underwith": 4171,
4174
+ "underhe": 4172,
4175
+ "underas": 4173,
4176
+ "underyou": 4174,
4177
+ "underdo": 4175,
4178
+ "underat": 4176,
4179
+ "underthis": 4177,
4180
+ "underbut": 4178,
4181
+ "underhis": 4179,
4182
+ "underby": 4180,
4183
+ "underfrom": 4181,
4184
+ "underthey": 4182,
4185
+ "underwe": 4183,
4186
+ "undersay": 4184,
4187
+ "underher": 4185,
4188
+ "undershe": 4186,
4189
+ "underor": 4187,
4190
+ "underan": 4188,
4191
+ "underwill": 4189,
4192
+ "undermy": 4190,
4193
+ "underone": 4191,
4194
+ "underall": 4192,
4195
+ "underwould": 4193,
4196
+ "underthere": 4194,
4197
+ "undertheir": 4195,
4198
+ "underwhat": 4196,
4199
+ "underso": 4197,
4200
+ "underup": 4198,
4201
+ "underout": 4199,
4202
+ "underif": 4200,
4203
+ "underabout": 4201,
4204
+ "underwho": 4202,
4205
+ "underget": 4203,
4206
+ "underwhich": 4204,
4207
+ "undergo": 4205,
4208
+ "underme": 4206,
4209
+ "underwhen": 4207,
4210
+ "outthe": 4208,
4211
+ "outbe": 4209,
4212
+ "outto": 4210,
4213
+ "outof": 4211,
4214
+ "outand": 4212,
4215
+ "outa": 4213,
4216
+ "outin": 4214,
4217
+ "outthat": 4215,
4218
+ "outhave": 4216,
4219
+ "outit": 4217,
4220
+ "outfor": 4218,
4221
+ "outnot": 4219,
4222
+ "outon": 4220,
4223
+ "outwith": 4221,
4224
+ "outhe": 4222,
4225
+ "outas": 4223,
4226
+ "outyou": 4224,
4227
+ "outdo": 4225,
4228
+ "outat": 4226,
4229
+ "outthis": 4227,
4230
+ "outbut": 4228,
4231
+ "outhis": 4229,
4232
+ "outby": 4230,
4233
+ "outfrom": 4231,
4234
+ "outthey": 4232,
4235
+ "outwe": 4233,
4236
+ "outsay": 4234,
4237
+ "outher": 4235,
4238
+ "outshe": 4236,
4239
+ "outor": 4237,
4240
+ "outan": 4238,
4241
+ "outwill": 4239,
4242
+ "outmy": 4240,
4243
+ "outone": 4241,
4244
+ "outall": 4242,
4245
+ "outwould": 4243,
4246
+ "outthere": 4244,
4247
+ "outtheir": 4245,
4248
+ "outwhat": 4246,
4249
+ "outso": 4247,
4250
+ "outup": 4248,
4251
+ "outout": 4249,
4252
+ "outif": 4250,
4253
+ "outabout": 4251,
4254
+ "outwho": 4252,
4255
+ "outget": 4253,
4256
+ "outwhich": 4254,
4257
+ "outgo": 4255,
4258
+ "outme": 4256,
4259
+ "outwhen": 4257,
4260
+ "subthe": 4258,
4261
+ "。": 4259,
4262
+ ",": 4260,
4263
+ "、": 4278,
4264
+ ";": 4262,
4265
+ ":": 4263,
4266
+ "!": 4264,
4267
+ "?": 4265,
4268
+ "…": 4266,
4269
+ "—": 4267,
4270
+ "'": 4286,
4271
+ "(": 4270,
4272
+ ")": 4271,
4273
+ "【": 4272,
4274
+ "】": 4273,
4275
+ "《": 4274,
4276
+ "》": 4275,
4277
+ "·": 4276,
4278
+ "~": 4277,
4279
+ ".": 4279,
4280
+ ",": 4280,
4281
+ "!": 4281,
4282
+ "?": 4282,
4283
+ ";": 4283,
4284
+ ":": 4284,
4285
+ "\"": 4285,
4286
+ "(": 4287,
4287
+ ")": 4288,
4288
+ "[": 4289,
4289
+ "]": 4290,
4290
+ "{": 4291,
4291
+ "}": 4292,
4292
+ "<": 4293,
4293
+ ">": 4294,
4294
+ "-": 4295,
4295
+ "_": 4296,
4296
+ "/": 4297,
4297
+ "\\": 4298,
4298
+ "|": 4299,
4299
+ "@": 4300,
4300
+ "#": 4301,
4301
+ "$": 4302,
4302
+ "%": 4303,
4303
+ "^": 4304,
4304
+ "&": 4305,
4305
+ "*": 4306,
4306
+ "+": 4307,
4307
+ "=": 4308,
4308
+ "~": 4309,
4309
+ "`": 4310,
4310
+ "0": 4311,
4311
+ "1": 4312,
4312
+ "2": 4313,
4313
+ "3": 4314,
4314
+ "4": 4315,
4315
+ "5": 4316,
4316
+ "6": 4317,
4317
+ "7": 4318,
4318
+ "8": 4319,
4319
+ "9": 4320,
4320
+ "10": 4321,
4321
+ "00": 4322,
4322
+ "01": 4323,
4323
+ "20": 4324,
4324
+ "30": 4325,
4325
+ "50": 4326,
4326
+ "100": 4327,
4327
+ "200": 4328,
4328
+ "500": 4329,
4329
+ "1000": 4330,
4330
+ "<extra_4331>": 4331,
4331
+ "<extra_4332>": 4332,
4332
+ "<extra_4333>": 4333,
4333
+ "<extra_4334>": 4334,
4334
+ "<extra_4335>": 4335,
4335
+ "<extra_4336>": 4336,
4336
+ "<extra_4337>": 4337,
4337
+ "<extra_4338>": 4338,
4338
+ "<extra_4339>": 4339,
4339
+ "<extra_4340>": 4340,
4340
+ "<extra_4341>": 4341,
4341
+ "<extra_4342>": 4342,
4342
+ "<extra_4343>": 4343,
4343
+ "<extra_4344>": 4344,
4344
+ "<extra_4345>": 4345,
4345
+ "<extra_4346>": 4346,
4346
+ "<extra_4347>": 4347,
4347
+ "<extra_4348>": 4348,
4348
+ "<extra_4349>": 4349,
4349
+ "<extra_4350>": 4350,
4350
+ "<extra_4351>": 4351,
4351
+ "<extra_4352>": 4352,
4352
+ "<extra_4353>": 4353,
4353
+ "<extra_4354>": 4354,
4354
+ "<extra_4355>": 4355,
4355
+ "<extra_4356>": 4356,
4356
+ "<extra_4357>": 4357,
4357
+ "<extra_4358>": 4358,
4358
+ "<extra_4359>": 4359,
4359
+ "<extra_4360>": 4360,
4360
+ "<extra_4361>": 4361,
4361
+ "<extra_4362>": 4362,
4362
+ "<extra_4363>": 4363,
4363
+ "<extra_4364>": 4364,
4364
+ "<extra_4365>": 4365,
4365
+ "<extra_4366>": 4366,
4366
+ "<extra_4367>": 4367,
4367
+ "<extra_4368>": 4368,
4368
+ "<extra_4369>": 4369,
4369
+ "<extra_4370>": 4370,
4370
+ "<extra_4371>": 4371,
4371
+ "<extra_4372>": 4372,
4372
+ "<extra_4373>": 4373,
4373
+ "<extra_4374>": 4374,
4374
+ "<extra_4375>": 4375,
4375
+ "<extra_4376>": 4376,
4376
+ "<extra_4377>": 4377,
4377
+ "<extra_4378>": 4378,
4378
+ "<extra_4379>": 4379,
4379
+ "<extra_4380>": 4380,
4380
+ "<extra_4381>": 4381,
4381
+ "<extra_4382>": 4382,
4382
+ "<extra_4383>": 4383,
4383
+ "<extra_4384>": 4384,
4384
+ "<extra_4385>": 4385,
4385
+ "<extra_4386>": 4386,
4386
+ "<extra_4387>": 4387,
4387
+ "<extra_4388>": 4388,
4388
+ "<extra_4389>": 4389,
4389
+ "<extra_4390>": 4390,
4390
+ "<extra_4391>": 4391,
4391
+ "<extra_4392>": 4392,
4392
+ "<extra_4393>": 4393,
4393
+ "<extra_4394>": 4394,
4394
+ "<extra_4395>": 4395,
4395
+ "<extra_4396>": 4396,
4396
+ "<extra_4397>": 4397,
4397
+ "<extra_4398>": 4398,
4398
+ "<extra_4399>": 4399,
4399
+ "<extra_4400>": 4400,
4400
+ "<extra_4401>": 4401,
4401
+ "<extra_4402>": 4402,
4402
+ "<extra_4403>": 4403,
4403
+ "<extra_4404>": 4404,
4404
+ "<extra_4405>": 4405,
4405
+ "<extra_4406>": 4406,
4406
+ "<extra_4407>": 4407,
4407
+ "<extra_4408>": 4408,
4408
+ "<extra_4409>": 4409,
4409
+ "<extra_4410>": 4410,
4410
+ "<extra_4411>": 4411,
4411
+ "<extra_4412>": 4412,
4412
+ "<extra_4413>": 4413,
4413
+ "<extra_4414>": 4414,
4414
+ "<extra_4415>": 4415,
4415
+ "<extra_4416>": 4416,
4416
+ "<extra_4417>": 4417,
4417
+ "<extra_4418>": 4418,
4418
+ "<extra_4419>": 4419,
4419
+ "<extra_4420>": 4420,
4420
+ "<extra_4421>": 4421,
4421
+ "<extra_4422>": 4422,
4422
+ "<extra_4423>": 4423,
4423
+ "<extra_4424>": 4424,
4424
+ "<extra_4425>": 4425,
4425
+ "<extra_4426>": 4426,
4426
+ "<extra_4427>": 4427,
4427
+ "<extra_4428>": 4428,
4428
+ "<extra_4429>": 4429,
4429
+ "<extra_4430>": 4430,
4430
+ "<extra_4431>": 4431,
4431
+ "<extra_4432>": 4432,
4432
+ "<extra_4433>": 4433,
4433
+ "<extra_4434>": 4434,
4434
+ "<extra_4435>": 4435,
4435
+ "<extra_4436>": 4436,
4436
+ "<extra_4437>": 4437,
4437
+ "<extra_4438>": 4438,
4438
+ "<extra_4439>": 4439,
4439
+ "<extra_4440>": 4440,
4440
+ "<extra_4441>": 4441,
4441
+ "<extra_4442>": 4442,
4442
+ "<extra_4443>": 4443,
4443
+ "<extra_4444>": 4444,
4444
+ "<extra_4445>": 4445,
4445
+ "<extra_4446>": 4446,
4446
+ "<extra_4447>": 4447,
4447
+ "<extra_4448>": 4448,
4448
+ "<extra_4449>": 4449,
4449
+ "<extra_4450>": 4450,
4450
+ "<extra_4451>": 4451,
4451
+ "<extra_4452>": 4452,
4452
+ "<extra_4453>": 4453,
4453
+ "<extra_4454>": 4454,
4454
+ "<extra_4455>": 4455,
4455
+ "<extra_4456>": 4456,
4456
+ "<extra_4457>": 4457,
4457
+ "<extra_4458>": 4458,
4458
+ "<extra_4459>": 4459,
4459
+ "<extra_4460>": 4460,
4460
+ "<extra_4461>": 4461,
4461
+ "<extra_4462>": 4462,
4462
+ "<extra_4463>": 4463,
4463
+ "<extra_4464>": 4464,
4464
+ "<extra_4465>": 4465,
4465
+ "<extra_4466>": 4466,
4466
+ "<extra_4467>": 4467,
4467
+ "<extra_4468>": 4468,
4468
+ "<extra_4469>": 4469,
4469
+ "<extra_4470>": 4470,
4470
+ "<extra_4471>": 4471,
4471
+ "<extra_4472>": 4472,
4472
+ "<extra_4473>": 4473,
4473
+ "<extra_4474>": 4474,
4474
+ "<extra_4475>": 4475,
4475
+ "<extra_4476>": 4476,
4476
+ "<extra_4477>": 4477,
4477
+ "<extra_4478>": 4478,
4478
+ "<extra_4479>": 4479,
4479
+ "<extra_4480>": 4480,
4480
+ "<extra_4481>": 4481,
4481
+ "<extra_4482>": 4482,
4482
+ "<extra_4483>": 4483,
4483
+ "<extra_4484>": 4484,
4484
+ "<extra_4485>": 4485,
4485
+ "<extra_4486>": 4486,
4486
+ "<extra_4487>": 4487,
4487
+ "<extra_4488>": 4488,
4488
+ "<extra_4489>": 4489,
4489
+ "<extra_4490>": 4490,
4490
+ "<extra_4491>": 4491,
4491
+ "<extra_4492>": 4492,
4492
+ "<extra_4493>": 4493,
4493
+ "<extra_4494>": 4494,
4494
+ "<extra_4495>": 4495,
4495
+ "<extra_4496>": 4496,
4496
+ "<extra_4497>": 4497,
4497
+ "<extra_4498>": 4498,
4498
+ "<extra_4499>": 4499,
4499
+ "<extra_4500>": 4500,
4500
+ "<extra_4501>": 4501,
4501
+ "<extra_4502>": 4502,
4502
+ "<extra_4503>": 4503,
4503
+ "<extra_4504>": 4504,
4504
+ "<extra_4505>": 4505,
4505
+ "<extra_4506>": 4506,
4506
+ "<extra_4507>": 4507,
4507
+ "<extra_4508>": 4508,
4508
+ "<extra_4509>": 4509,
4509
+ "<extra_4510>": 4510,
4510
+ "<extra_4511>": 4511,
4511
+ "<extra_4512>": 4512,
4512
+ "<extra_4513>": 4513,
4513
+ "<extra_4514>": 4514,
4514
+ "<extra_4515>": 4515,
4515
+ "<extra_4516>": 4516,
4516
+ "<extra_4517>": 4517,
4517
+ "<extra_4518>": 4518,
4518
+ "<extra_4519>": 4519,
4519
+ "<extra_4520>": 4520,
4520
+ "<extra_4521>": 4521,
4521
+ "<extra_4522>": 4522,
4522
+ "<extra_4523>": 4523,
4523
+ "<extra_4524>": 4524,
4524
+ "<extra_4525>": 4525,
4525
+ "<extra_4526>": 4526,
4526
+ "<extra_4527>": 4527,
4527
+ "<extra_4528>": 4528,
4528
+ "<extra_4529>": 4529,
4529
+ "<extra_4530>": 4530,
4530
+ "<extra_4531>": 4531,
4531
+ "<extra_4532>": 4532,
4532
+ "<extra_4533>": 4533,
4533
+ "<extra_4534>": 4534,
4534
+ "<extra_4535>": 4535,
4535
+ "<extra_4536>": 4536,
4536
+ "<extra_4537>": 4537,
4537
+ "<extra_4538>": 4538,
4538
+ "<extra_4539>": 4539,
4539
+ "<extra_4540>": 4540,
4540
+ "<extra_4541>": 4541,
4541
+ "<extra_4542>": 4542,
4542
+ "<extra_4543>": 4543,
4543
+ "<extra_4544>": 4544,
4544
+ "<extra_4545>": 4545,
4545
+ "<extra_4546>": 4546,
4546
+ "<extra_4547>": 4547,
4547
+ "<extra_4548>": 4548,
4548
+ "<extra_4549>": 4549,
4549
+ "<extra_4550>": 4550,
4550
+ "<extra_4551>": 4551,
4551
+ "<extra_4552>": 4552,
4552
+ "<extra_4553>": 4553,
4553
+ "<extra_4554>": 4554,
4554
+ "<extra_4555>": 4555,
4555
+ "<extra_4556>": 4556,
4556
+ "<extra_4557>": 4557,
4557
+ "<extra_4558>": 4558,
4558
+ "<extra_4559>": 4559,
4559
+ "<extra_4560>": 4560,
4560
+ "<extra_4561>": 4561,
4561
+ "<extra_4562>": 4562,
4562
+ "<extra_4563>": 4563,
4563
+ "<extra_4564>": 4564,
4564
+ "<extra_4565>": 4565,
4565
+ "<extra_4566>": 4566,
4566
+ "<extra_4567>": 4567,
4567
+ "<extra_4568>": 4568,
4568
+ "<extra_4569>": 4569,
4569
+ "<extra_4570>": 4570,
4570
+ "<extra_4571>": 4571,
4571
+ "<extra_4572>": 4572,
4572
+ "<extra_4573>": 4573,
4573
+ "<extra_4574>": 4574,
4574
+ "<extra_4575>": 4575,
4575
+ "<extra_4576>": 4576,
4576
+ "<extra_4577>": 4577,
4577
+ "<extra_4578>": 4578,
4578
+ "<extra_4579>": 4579,
4579
+ "<extra_4580>": 4580,
4580
+ "<extra_4581>": 4581,
4581
+ "<extra_4582>": 4582,
4582
+ "<extra_4583>": 4583,
4583
+ "<extra_4584>": 4584,
4584
+ "<extra_4585>": 4585,
4585
+ "<extra_4586>": 4586,
4586
+ "<extra_4587>": 4587,
4587
+ "<extra_4588>": 4588,
4588
+ "<extra_4589>": 4589,
4589
+ "<extra_4590>": 4590,
4590
+ "<extra_4591>": 4591,
4591
+ "<extra_4592>": 4592,
4592
+ "<extra_4593>": 4593,
4593
+ "<extra_4594>": 4594,
4594
+ "<extra_4595>": 4595,
4595
+ "<extra_4596>": 4596,
4596
+ "<extra_4597>": 4597,
4597
+ "<extra_4598>": 4598,
4598
+ "<extra_4599>": 4599,
4599
+ "<extra_4600>": 4600,
4600
+ "<extra_4601>": 4601,
4601
+ "<extra_4602>": 4602,
4602
+ "<extra_4603>": 4603,
4603
+ "<extra_4604>": 4604,
4604
+ "<extra_4605>": 4605,
4605
+ "<extra_4606>": 4606,
4606
+ "<extra_4607>": 4607,
4607
+ "<extra_4608>": 4608,
4608
+ "<extra_4609>": 4609,
4609
+ "<extra_4610>": 4610,
4610
+ "<extra_4611>": 4611,
4611
+ "<extra_4612>": 4612,
4612
+ "<extra_4613>": 4613,
4613
+ "<extra_4614>": 4614,
4614
+ "<extra_4615>": 4615,
4615
+ "<extra_4616>": 4616,
4616
+ "<extra_4617>": 4617,
4617
+ "<extra_4618>": 4618,
4618
+ "<extra_4619>": 4619,
4619
+ "<extra_4620>": 4620,
4620
+ "<extra_4621>": 4621,
4621
+ "<extra_4622>": 4622,
4622
+ "<extra_4623>": 4623,
4623
+ "<extra_4624>": 4624,
4624
+ "<extra_4625>": 4625,
4625
+ "<extra_4626>": 4626,
4626
+ "<extra_4627>": 4627,
4627
+ "<extra_4628>": 4628,
4628
+ "<extra_4629>": 4629,
4629
+ "<extra_4630>": 4630,
4630
+ "<extra_4631>": 4631,
4631
+ "<extra_4632>": 4632,
4632
+ "<extra_4633>": 4633,
4633
+ "<extra_4634>": 4634,
4634
+ "<extra_4635>": 4635,
4635
+ "<extra_4636>": 4636,
4636
+ "<extra_4637>": 4637,
4637
+ "<extra_4638>": 4638,
4638
+ "<extra_4639>": 4639,
4639
+ "<extra_4640>": 4640,
4640
+ "<extra_4641>": 4641,
4641
+ "<extra_4642>": 4642,
4642
+ "<extra_4643>": 4643,
4643
+ "<extra_4644>": 4644,
4644
+ "<extra_4645>": 4645,
4645
+ "<extra_4646>": 4646,
4646
+ "<extra_4647>": 4647,
4647
+ "<extra_4648>": 4648,
4648
+ "<extra_4649>": 4649,
4649
+ "<extra_4650>": 4650,
4650
+ "<extra_4651>": 4651,
4651
+ "<extra_4652>": 4652,
4652
+ "<extra_4653>": 4653,
4653
+ "<extra_4654>": 4654,
4654
+ "<extra_4655>": 4655,
4655
+ "<extra_4656>": 4656,
4656
+ "<extra_4657>": 4657,
4657
+ "<extra_4658>": 4658,
4658
+ "<extra_4659>": 4659,
4659
+ "<extra_4660>": 4660,
4660
+ "<extra_4661>": 4661,
4661
+ "<extra_4662>": 4662,
4662
+ "<extra_4663>": 4663,
4663
+ "<extra_4664>": 4664,
4664
+ "<extra_4665>": 4665,
4665
+ "<extra_4666>": 4666,
4666
+ "<extra_4667>": 4667,
4667
+ "<extra_4668>": 4668,
4668
+ "<extra_4669>": 4669,
4669
+ "<extra_4670>": 4670,
4670
+ "<extra_4671>": 4671,
4671
+ "<extra_4672>": 4672,
4672
+ "<extra_4673>": 4673,
4673
+ "<extra_4674>": 4674,
4674
+ "<extra_4675>": 4675,
4675
+ "<extra_4676>": 4676,
4676
+ "<extra_4677>": 4677,
4677
+ "<extra_4678>": 4678,
4678
+ "<extra_4679>": 4679,
4679
+ "<extra_4680>": 4680,
4680
+ "<extra_4681>": 4681,
4681
+ "<extra_4682>": 4682,
4682
+ "<extra_4683>": 4683,
4683
+ "<extra_4684>": 4684,
4684
+ "<extra_4685>": 4685,
4685
+ "<extra_4686>": 4686,
4686
+ "<extra_4687>": 4687,
4687
+ "<extra_4688>": 4688,
4688
+ "<extra_4689>": 4689,
4689
+ "<extra_4690>": 4690,
4690
+ "<extra_4691>": 4691,
4691
+ "<extra_4692>": 4692,
4692
+ "<extra_4693>": 4693,
4693
+ "<extra_4694>": 4694,
4694
+ "<extra_4695>": 4695,
4695
+ "<extra_4696>": 4696,
4696
+ "<extra_4697>": 4697,
4697
+ "<extra_4698>": 4698,
4698
+ "<extra_4699>": 4699,
4699
+ "<extra_4700>": 4700,
4700
+ "<extra_4701>": 4701,
4701
+ "<extra_4702>": 4702,
4702
+ "<extra_4703>": 4703,
4703
+ "<extra_4704>": 4704,
4704
+ "<extra_4705>": 4705,
4705
+ "<extra_4706>": 4706,
4706
+ "<extra_4707>": 4707,
4707
+ "<extra_4708>": 4708,
4708
+ "<extra_4709>": 4709,
4709
+ "<extra_4710>": 4710,
4710
+ "<extra_4711>": 4711,
4711
+ "<extra_4712>": 4712,
4712
+ "<extra_4713>": 4713,
4713
+ "<extra_4714>": 4714,
4714
+ "<extra_4715>": 4715,
4715
+ "<extra_4716>": 4716,
4716
+ "<extra_4717>": 4717,
4717
+ "<extra_4718>": 4718,
4718
+ "<extra_4719>": 4719,
4719
+ "<extra_4720>": 4720,
4720
+ "<extra_4721>": 4721,
4721
+ "<extra_4722>": 4722,
4722
+ "<extra_4723>": 4723,
4723
+ "<extra_4724>": 4724,
4724
+ "<extra_4725>": 4725,
4725
+ "<extra_4726>": 4726,
4726
+ "<extra_4727>": 4727,
4727
+ "<extra_4728>": 4728,
4728
+ "<extra_4729>": 4729,
4729
+ "<extra_4730>": 4730,
4730
+ "<extra_4731>": 4731,
4731
+ "<extra_4732>": 4732,
4732
+ "<extra_4733>": 4733,
4733
+ "<extra_4734>": 4734,
4734
+ "<extra_4735>": 4735,
4735
+ "<extra_4736>": 4736,
4736
+ "<extra_4737>": 4737,
4737
+ "<extra_4738>": 4738,
4738
+ "<extra_4739>": 4739,
4739
+ "<extra_4740>": 4740,
4740
+ "<extra_4741>": 4741,
4741
+ "<extra_4742>": 4742,
4742
+ "<extra_4743>": 4743,
4743
+ "<extra_4744>": 4744,
4744
+ "<extra_4745>": 4745,
4745
+ "<extra_4746>": 4746,
4746
+ "<extra_4747>": 4747,
4747
+ "<extra_4748>": 4748,
4748
+ "<extra_4749>": 4749,
4749
+ "<extra_4750>": 4750,
4750
+ "<extra_4751>": 4751,
4751
+ "<extra_4752>": 4752,
4752
+ "<extra_4753>": 4753,
4753
+ "<extra_4754>": 4754,
4754
+ "<extra_4755>": 4755,
4755
+ "<extra_4756>": 4756,
4756
+ "<extra_4757>": 4757,
4757
+ "<extra_4758>": 4758,
4758
+ "<extra_4759>": 4759,
4759
+ "<extra_4760>": 4760,
4760
+ "<extra_4761>": 4761,
4761
+ "<extra_4762>": 4762,
4762
+ "<extra_4763>": 4763,
4763
+ "<extra_4764>": 4764,
4764
+ "<extra_4765>": 4765,
4765
+ "<extra_4766>": 4766,
4766
+ "<extra_4767>": 4767,
4767
+ "<extra_4768>": 4768,
4768
+ "<extra_4769>": 4769,
4769
+ "<extra_4770>": 4770,
4770
+ "<extra_4771>": 4771,
4771
+ "<extra_4772>": 4772,
4772
+ "<extra_4773>": 4773,
4773
+ "<extra_4774>": 4774,
4774
+ "<extra_4775>": 4775,
4775
+ "<extra_4776>": 4776,
4776
+ "<extra_4777>": 4777,
4777
+ "<extra_4778>": 4778,
4778
+ "<extra_4779>": 4779,
4779
+ "<extra_4780>": 4780,
4780
+ "<extra_4781>": 4781,
4781
+ "<extra_4782>": 4782,
4782
+ "<extra_4783>": 4783,
4783
+ "<extra_4784>": 4784,
4784
+ "<extra_4785>": 4785,
4785
+ "<extra_4786>": 4786,
4786
+ "<extra_4787>": 4787,
4787
+ "<extra_4788>": 4788,
4788
+ "<extra_4789>": 4789,
4789
+ "<extra_4790>": 4790,
4790
+ "<extra_4791>": 4791,
4791
+ "<extra_4792>": 4792,
4792
+ "<extra_4793>": 4793,
4793
+ "<extra_4794>": 4794,
4794
+ "<extra_4795>": 4795,
4795
+ "<extra_4796>": 4796,
4796
+ "<extra_4797>": 4797,
4797
+ "<extra_4798>": 4798,
4798
+ "<extra_4799>": 4799,
4799
+ "<extra_4800>": 4800,
4800
+ "<extra_4801>": 4801,
4801
+ "<extra_4802>": 4802,
4802
+ "<extra_4803>": 4803,
4803
+ "<extra_4804>": 4804,
4804
+ "<extra_4805>": 4805,
4805
+ "<extra_4806>": 4806,
4806
+ "<extra_4807>": 4807,
4807
+ "<extra_4808>": 4808,
4808
+ "<extra_4809>": 4809,
4809
+ "<extra_4810>": 4810,
4810
+ "<extra_4811>": 4811,
4811
+ "<extra_4812>": 4812,
4812
+ "<extra_4813>": 4813,
4813
+ "<extra_4814>": 4814,
4814
+ "<extra_4815>": 4815,
4815
+ "<extra_4816>": 4816,
4816
+ "<extra_4817>": 4817,
4817
+ "<extra_4818>": 4818,
4818
+ "<extra_4819>": 4819,
4819
+ "<extra_4820>": 4820,
4820
+ "<extra_4821>": 4821,
4821
+ "<extra_4822>": 4822,
4822
+ "<extra_4823>": 4823,
4823
+ "<extra_4824>": 4824,
4824
+ "<extra_4825>": 4825,
4825
+ "<extra_4826>": 4826,
4826
+ "<extra_4827>": 4827,
4827
+ "<extra_4828>": 4828,
4828
+ "<extra_4829>": 4829,
4829
+ "<extra_4830>": 4830,
4830
+ "<extra_4831>": 4831,
4831
+ "<extra_4832>": 4832,
4832
+ "<extra_4833>": 4833,
4833
+ "<extra_4834>": 4834,
4834
+ "<extra_4835>": 4835,
4835
+ "<extra_4836>": 4836,
4836
+ "<extra_4837>": 4837,
4837
+ "<extra_4838>": 4838,
4838
+ "<extra_4839>": 4839,
4839
+ "<extra_4840>": 4840,
4840
+ "<extra_4841>": 4841,
4841
+ "<extra_4842>": 4842,
4842
+ "<extra_4843>": 4843,
4843
+ "<extra_4844>": 4844,
4844
+ "<extra_4845>": 4845,
4845
+ "<extra_4846>": 4846,
4846
+ "<extra_4847>": 4847,
4847
+ "<extra_4848>": 4848,
4848
+ "<extra_4849>": 4849,
4849
+ "<extra_4850>": 4850,
4850
+ "<extra_4851>": 4851,
4851
+ "<extra_4852>": 4852,
4852
+ "<extra_4853>": 4853,
4853
+ "<extra_4854>": 4854,
4854
+ "<extra_4855>": 4855,
4855
+ "<extra_4856>": 4856,
4856
+ "<extra_4857>": 4857,
4857
+ "<extra_4858>": 4858,
4858
+ "<extra_4859>": 4859,
4859
+ "<extra_4860>": 4860,
4860
+ "<extra_4861>": 4861,
4861
+ "<extra_4862>": 4862,
4862
+ "<extra_4863>": 4863,
4863
+ "<extra_4864>": 4864,
4864
+ "<extra_4865>": 4865,
4865
+ "<extra_4866>": 4866,
4866
+ "<extra_4867>": 4867,
4867
+ "<extra_4868>": 4868,
4868
+ "<extra_4869>": 4869,
4869
+ "<extra_4870>": 4870,
4870
+ "<extra_4871>": 4871,
4871
+ "<extra_4872>": 4872,
4872
+ "<extra_4873>": 4873,
4873
+ "<extra_4874>": 4874,
4874
+ "<extra_4875>": 4875,
4875
+ "<extra_4876>": 4876,
4876
+ "<extra_4877>": 4877,
4877
+ "<extra_4878>": 4878,
4878
+ "<extra_4879>": 4879,
4879
+ "<extra_4880>": 4880,
4880
+ "<extra_4881>": 4881,
4881
+ "<extra_4882>": 4882,
4882
+ "<extra_4883>": 4883,
4883
+ "<extra_4884>": 4884,
4884
+ "<extra_4885>": 4885,
4885
+ "<extra_4886>": 4886,
4886
+ "<extra_4887>": 4887,
4887
+ "<extra_4888>": 4888,
4888
+ "<extra_4889>": 4889,
4889
+ "<extra_4890>": 4890,
4890
+ "<extra_4891>": 4891,
4891
+ "<extra_4892>": 4892,
4892
+ "<extra_4893>": 4893,
4893
+ "<extra_4894>": 4894,
4894
+ "<extra_4895>": 4895,
4895
+ "<extra_4896>": 4896,
4896
+ "<extra_4897>": 4897,
4897
+ "<extra_4898>": 4898,
4898
+ "<extra_4899>": 4899,
4899
+ "<extra_4900>": 4900,
4900
+ "<extra_4901>": 4901,
4901
+ "<extra_4902>": 4902,
4902
+ "<extra_4903>": 4903,
4903
+ "<extra_4904>": 4904,
4904
+ "<extra_4905>": 4905,
4905
+ "<extra_4906>": 4906,
4906
+ "<extra_4907>": 4907,
4907
+ "<extra_4908>": 4908,
4908
+ "<extra_4909>": 4909,
4909
+ "<extra_4910>": 4910,
4910
+ "<extra_4911>": 4911,
4911
+ "<extra_4912>": 4912,
4912
+ "<extra_4913>": 4913,
4913
+ "<extra_4914>": 4914,
4914
+ "<extra_4915>": 4915,
4915
+ "<extra_4916>": 4916,
4916
+ "<extra_4917>": 4917,
4917
+ "<extra_4918>": 4918,
4918
+ "<extra_4919>": 4919,
4919
+ "<extra_4920>": 4920,
4920
+ "<extra_4921>": 4921,
4921
+ "<extra_4922>": 4922,
4922
+ "<extra_4923>": 4923,
4923
+ "<extra_4924>": 4924,
4924
+ "<extra_4925>": 4925,
4925
+ "<extra_4926>": 4926,
4926
+ "<extra_4927>": 4927,
4927
+ "<extra_4928>": 4928,
4928
+ "<extra_4929>": 4929,
4929
+ "<extra_4930>": 4930,
4930
+ "<extra_4931>": 4931,
4931
+ "<extra_4932>": 4932,
4932
+ "<extra_4933>": 4933,
4933
+ "<extra_4934>": 4934,
4934
+ "<extra_4935>": 4935,
4935
+ "<extra_4936>": 4936,
4936
+ "<extra_4937>": 4937,
4937
+ "<extra_4938>": 4938,
4938
+ "<extra_4939>": 4939,
4939
+ "<extra_4940>": 4940,
4940
+ "<extra_4941>": 4941,
4941
+ "<extra_4942>": 4942,
4942
+ "<extra_4943>": 4943,
4943
+ "<extra_4944>": 4944,
4944
+ "<extra_4945>": 4945,
4945
+ "<extra_4946>": 4946,
4946
+ "<extra_4947>": 4947,
4947
+ "<extra_4948>": 4948,
4948
+ "<extra_4949>": 4949,
4949
+ "<extra_4950>": 4950,
4950
+ "<extra_4951>": 4951,
4951
+ "<extra_4952>": 4952,
4952
+ "<extra_4953>": 4953,
4953
+ "<extra_4954>": 4954,
4954
+ "<extra_4955>": 4955,
4955
+ "<extra_4956>": 4956,
4956
+ "<extra_4957>": 4957,
4957
+ "<extra_4958>": 4958,
4958
+ "<extra_4959>": 4959,
4959
+ "<extra_4960>": 4960,
4960
+ "<extra_4961>": 4961,
4961
+ "<extra_4962>": 4962,
4962
+ "<extra_4963>": 4963,
4963
+ "<extra_4964>": 4964,
4964
+ "<extra_4965>": 4965,
4965
+ "<extra_4966>": 4966,
4966
+ "<extra_4967>": 4967,
4967
+ "<extra_4968>": 4968,
4968
+ "<extra_4969>": 4969,
4969
+ "<extra_4970>": 4970,
4970
+ "<extra_4971>": 4971,
4971
+ "<extra_4972>": 4972,
4972
+ "<extra_4973>": 4973,
4973
+ "<extra_4974>": 4974,
4974
+ "<extra_4975>": 4975,
4975
+ "<extra_4976>": 4976,
4976
+ "<extra_4977>": 4977,
4977
+ "<extra_4978>": 4978,
4978
+ "<extra_4979>": 4979,
4979
+ "<extra_4980>": 4980,
4980
+ "<extra_4981>": 4981,
4981
+ "<extra_4982>": 4982,
4982
+ "<extra_4983>": 4983,
4983
+ "<extra_4984>": 4984,
4984
+ "<extra_4985>": 4985,
4985
+ "<extra_4986>": 4986,
4986
+ "<extra_4987>": 4987,
4987
+ "<extra_4988>": 4988,
4988
+ "<extra_4989>": 4989,
4989
+ "<extra_4990>": 4990,
4990
+ "<extra_4991>": 4991,
4991
+ "<extra_4992>": 4992,
4992
+ "<extra_4993>": 4993,
4993
+ "<extra_4994>": 4994,
4994
+ "<extra_4995>": 4995,
4995
+ "<extra_4996>": 4996,
4996
+ "<extra_4997>": 4997,
4997
+ "<extra_4998>": 4998,
4998
+ "<extra_4999>": 4999
4999
+ }
configs/special_tokens_map.json ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "pad_token": "<pad>",
3
+ "pad_token_id": 0,
4
+ "bos_token": "<s>",
5
+ "bos_token_id": 1,
6
+ "eos_token": "</s>",
7
+ "eos_token_id": 2,
8
+ "unk_token": "<unk>",
9
+ "unk_token_id": 3,
10
+ "_comment": {
11
+ "pad_token": "填充token,用于batch对齐",
12
+ "bos_token": "序列起始token",
13
+ "eos_token": "序列结束token,生成时遇到此token停止",
14
+ "unk_token": "未知token,词表外字符映射到此"
15
+ }
16
+ }
configs/tokenizer_128k.json ADDED
The diff for this file is too large to render. See raw diff
 
configs/tokenizer_cn_013.json ADDED
The diff for this file is too large to render. See raw diff
 
include/neuroflow/adamw.hpp ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_ADAMW_HPP
2
+ #define NEUROFLOW_ADAMW_HPP
3
+
4
+ #include <cstddef>
5
+ #include <vector>
6
+ #include "tensor.hpp"
7
+
8
+ namespace neuroflow {
9
+
10
+ struct ParamState {
11
+ Tensor m;
12
+ Tensor v;
13
+ };
14
+
15
+ struct ParamGroup {
16
+ std::vector<Tensor*> params;
17
+ std::vector<Tensor*> grads;
18
+ float lr;
19
+ float weight_decay;
20
+ };
21
+
22
+ class AdamW {
23
+ public:
24
+ float lr_;
25
+ float beta1_;
26
+ float beta2_;
27
+ float eps_;
28
+ float weight_decay_;
29
+ size_t step_;
30
+
31
+ std::vector<ParamGroup> param_groups_;
32
+ std::vector<std::vector<ParamState>> states_;
33
+
34
+ AdamW(float lr, float beta1 = 0.9f, float beta2 = 0.999f,
35
+ float eps = 1e-8f, float weight_decay = 0.01f);
36
+
37
+ void add_param_group(const ParamGroup& group);
38
+ void step();
39
+ void set_lr(float lr);
40
+ float get_lr() const { return lr_; }
41
+ size_t get_step() const { return step_; }
42
+ };
43
+
44
+ } // namespace neuroflow
45
+
46
+ #endif // NEUROFLOW_ADAMW_HPP
include/neuroflow/alignment_common.hpp ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_ALIGNMENT_COMMON_HPP
2
+ #define NEUROFLOW_ALIGNMENT_COMMON_HPP
3
+
4
+ #include <algorithm>
5
+ #include <cmath>
6
+ #include <cstring>
7
+ #include <fstream>
8
+ #include <iostream>
9
+ #include <string>
10
+ #include <unordered_map>
11
+ #include <vector>
12
+
13
+ #include "causal_lm.hpp"
14
+ #include "tensor.hpp"
15
+
16
+ namespace neuroflow {
17
+
18
+ struct SFTSample {
19
+ std::string instruction;
20
+ std::string response;
21
+ };
22
+
23
+ struct DPOSample {
24
+ std::string instruction;
25
+ std::string chosen;
26
+ std::string rejected;
27
+ };
28
+
29
+ struct SFTTrainingTensors {
30
+ std::vector<size_t> input_ids;
31
+ std::vector<size_t> target_ids;
32
+ std::vector<float> loss_mask;
33
+ size_t instruction_len;
34
+ };
35
+
36
+ struct DPOTrainingTensors {
37
+ std::vector<size_t> chosen_ids;
38
+ std::vector<size_t> rejected_ids;
39
+ size_t chosen_prompt_len;
40
+ size_t rejected_prompt_len;
41
+ };
42
+
43
+ inline std::string extract_json_string(const std::string& json, const std::string& key) {
44
+ std::string search = "\"" + key + "\"";
45
+ size_t pos = json.find(search);
46
+ if (pos == std::string::npos) return "";
47
+ pos = json.find(':', pos + search.size());
48
+ if (pos == std::string::npos) return "";
49
+ pos++;
50
+ while (pos < json.size() && (json[pos] == ' ' || json[pos] == '\t')) pos++;
51
+ if (pos >= json.size() || json[pos] != '"') return "";
52
+ size_t end = pos + 1;
53
+ while (end < json.size()) {
54
+ if (json[end] == '"' && json[end - 1] != '\\') break;
55
+ if (json[end - 1] == '\\') { end++; continue; }
56
+ end++;
57
+ }
58
+ if (end >= json.size()) return "";
59
+ return json.substr(pos + 1, end - pos - 1);
60
+ }
61
+
62
+ inline size_t extract_json_number(const std::string& json, const std::string& key, size_t default_val = 0) {
63
+ std::string search = "\"" + key + "\"";
64
+ size_t pos = json.find(search);
65
+ if (pos == std::string::npos) return default_val;
66
+ pos = json.find(':', pos + search.size());
67
+ if (pos == std::string::npos) return default_val;
68
+ pos++;
69
+ while (pos < json.size() && (json[pos] == ' ' || json[pos] == '\t')) pos++;
70
+ size_t end = pos;
71
+ while (end < json.size() && (json[end] >= '0' && json[end] <= '9')) end++;
72
+ if (end == pos) return default_val;
73
+ return std::stoul(json.substr(pos, end - pos));
74
+ }
75
+
76
+ inline bool extract_json_bool(const std::string& json, const std::string& key, bool default_val = false) {
77
+ std::string search = "\"" + key + "\"";
78
+ size_t pos = json.find(search);
79
+ if (pos == std::string::npos) return default_val;
80
+ pos = json.find(':', pos + search.size());
81
+ if (pos == std::string::npos) return default_val;
82
+ pos++;
83
+ while (pos < json.size() && (json[pos] == ' ' || json[pos] == '\t')) pos++;
84
+ if (pos + 3 < json.size() && json.substr(pos, 4) == "true") return true;
85
+ if (pos + 4 < json.size() && json.substr(pos, 5) == "false") return false;
86
+ return default_val;
87
+ }
88
+
89
+ inline void unescape_json(std::string& s) {
90
+ size_t pos = 0;
91
+ while ((pos = s.find('\\', pos)) != std::string::npos) {
92
+ if (pos + 1 < s.size()) {
93
+ char c = s[pos + 1];
94
+ if (c == 'n') { s.replace(pos, 2, "\n"); pos++; }
95
+ else if (c == 't') { s.replace(pos, 2, "\t"); pos++; }
96
+ else if (c == 'r') { s.replace(pos, 2, "\r"); pos++; }
97
+ else if (c == '"') { s.replace(pos, 2, "\""); pos++; }
98
+ else if (c == '\\') { s.replace(pos, 2, "\\"); pos++; }
99
+ else if (c == '/') { s.replace(pos, 2, "/"); pos++; }
100
+ else if (c == 'u' && pos + 5 < s.size()) { pos += 6; }
101
+ else { pos += 2; }
102
+ } else { pos++; }
103
+ }
104
+ }
105
+
106
+ inline bool validate_path(const std::string& path) {
107
+ if (path.find("..") != std::string::npos) return false;
108
+ return true;
109
+ }
110
+
111
+ inline void save_lm_checkpoint(const CausalLMHead& model, const std::string& path) {
112
+ CausalLMHead& lm_head = const_cast<CausalLMHead&>(model);
113
+ #ifdef USE_CUDA
114
+ auto sync_to_cpu = [](const Tensor& t) {
115
+ if (t.is_on_gpu()) { const_cast<Tensor&>(t).to_cpu(); }
116
+ };
117
+ sync_to_cpu(lm_head.w_embed_);
118
+ sync_to_cpu(lm_head.w_pos_);
119
+ sync_to_cpu(lm_head.dw_kernel_);
120
+ sync_to_cpu(lm_head.pw_conv_->weight);
121
+ sync_to_cpu(lm_head.sae_w_encode_->weight);
122
+ sync_to_cpu(lm_head.sae_w_decode_->weight);
123
+ sync_to_cpu(lm_head.ntm_w_read_->weight);
124
+ sync_to_cpu(lm_head.ntm_w_write_->weight);
125
+ sync_to_cpu(lm_head.ntm_w_erase_->weight);
126
+ sync_to_cpu(lm_head.ntm_memory_);
127
+ sync_to_cpu(lm_head.w_proj_->weight);
128
+ sync_to_cpu(lm_head.w_proj_->bias);
129
+ if (lm_head.bridge_) {
130
+ sync_to_cpu(lm_head.bridge_->weight);
131
+ sync_to_cpu(lm_head.bridge_->bias);
132
+ }
133
+ sync_to_cpu(lm_head.w_out_->weight);
134
+ sync_to_cpu(lm_head.w_out_->bias);
135
+ sync_to_cpu(lm_head.ln_->weight);
136
+ sync_to_cpu(lm_head.ln_->bias);
137
+ for (auto& attn : lm_head.attn_layers_) {
138
+ sync_to_cpu(attn->w_q->weight);
139
+ sync_to_cpu(attn->w_q->bias);
140
+ sync_to_cpu(attn->w_k->weight);
141
+ sync_to_cpu(attn->w_k->bias);
142
+ sync_to_cpu(attn->w_v->weight);
143
+ sync_to_cpu(attn->w_v->bias);
144
+ sync_to_cpu(attn->w_out->weight);
145
+ sync_to_cpu(attn->w_out->bias);
146
+ sync_to_cpu(attn->norm->weight);
147
+ sync_to_cpu(attn->norm->bias);
148
+ }
149
+ #endif
150
+ auto sl = [](std::ofstream& o, const std::string& n, const Tensor& t) {
151
+ uint32_t nl = n.size(); o.write((char*)&nl, 4); o.write(n.data(), nl);
152
+ uint32_t nd = t.shape_.size(); o.write((char*)&nd, 4);
153
+ for (auto d : t.shape_) { uint32_t dd = d; o.write((char*)&dd, 4); }
154
+ uint32_t ds = t.data_size_; o.write((char*)&ds, 4);
155
+ o.write((char*)t.data_.get(), ds);
156
+ };
157
+ std::ofstream o(path, std::ios::binary);
158
+ o.write("LMH2", 4);
159
+ sl(o, "w_embed", lm_head.w_embed_);
160
+ sl(o, "w_pos", lm_head.w_pos_);
161
+ sl(o, "dw_kernel", lm_head.dw_kernel_);
162
+ sl(o, "pw_conv.weight", lm_head.pw_conv_->weight);
163
+ sl(o, "sae_encode.weight", lm_head.sae_w_encode_->weight);
164
+ sl(o, "sae_decode.weight", lm_head.sae_w_decode_->weight);
165
+ sl(o, "ntm_read.weight", lm_head.ntm_w_read_->weight);
166
+ sl(o, "ntm_write.weight", lm_head.ntm_w_write_->weight);
167
+ sl(o, "ntm_erase.weight", lm_head.ntm_w_erase_->weight);
168
+ sl(o, "ntm_memory", lm_head.ntm_memory_);
169
+ sl(o, "w_proj.weight", lm_head.w_proj_->weight);
170
+ sl(o, "w_proj.bias", lm_head.w_proj_->bias);
171
+ if (lm_head.bridge_) {
172
+ sl(o, "bridge.weight", lm_head.bridge_->weight);
173
+ sl(o, "bridge.bias", lm_head.bridge_->bias);
174
+ }
175
+ sl(o, "w_out.weight", lm_head.w_out_->weight);
176
+ if (lm_head.w_out_->bias.data_) sl(o, "w_out.bias", lm_head.w_out_->bias);
177
+ sl(o, "ln.weight", lm_head.ln_->weight);
178
+ sl(o, "ln.bias", lm_head.ln_->bias);
179
+ for (size_t i = 0; i < lm_head.attn_layers_.size(); ++i) {
180
+ std::string p = "attn" + std::to_string(i) + ".";
181
+ sl(o, p + "w_q.weight", lm_head.attn_layers_[i]->w_q->weight);
182
+ sl(o, p + "w_q.bias", lm_head.attn_layers_[i]->w_q->bias);
183
+ sl(o, p + "w_k.weight", lm_head.attn_layers_[i]->w_k->weight);
184
+ sl(o, p + "w_k.bias", lm_head.attn_layers_[i]->w_k->bias);
185
+ sl(o, p + "w_v.weight", lm_head.attn_layers_[i]->w_v->weight);
186
+ sl(o, p + "w_v.bias", lm_head.attn_layers_[i]->w_v->bias);
187
+ sl(o, p + "w_out.weight", lm_head.attn_layers_[i]->w_out->weight);
188
+ sl(o, p + "w_out.bias", lm_head.attn_layers_[i]->w_out->bias);
189
+ sl(o, p + "norm.weight", lm_head.attn_layers_[i]->norm->weight);
190
+ sl(o, p + "norm.bias", lm_head.attn_layers_[i]->norm->bias);
191
+ }
192
+ uint32_t z = 0; o.write((char*)&z, 4); o.close();
193
+ }
194
+
195
+ inline bool load_lm_checkpoint(CausalLMHead& lm_head, const std::string& lm_path) {
196
+ std::ifstream ifs(lm_path, std::ios::binary);
197
+ if (!ifs) {
198
+ std::cerr << "LM Head checkpoint未找到: " << lm_path << std::endl;
199
+ return false;
200
+ }
201
+
202
+ char magic[5] = {0};
203
+ ifs.read(magic, 4);
204
+ if (std::string(magic) != "LMH2" && std::string(magic) != "LMH1") {
205
+ std::cerr << "LM Head格式不匹配: " << std::string(magic) << " (期望LMH2/LMH1)" << std::endl;
206
+ ifs.close();
207
+ return false;
208
+ }
209
+
210
+ auto read_named_tensor = [&]() -> std::pair<std::string, Tensor> {
211
+ uint32_t nl = 0; ifs.read((char*)&nl, 4);
212
+ if (nl == 0 || ifs.eof()) return {"", Tensor()};
213
+ std::string name(nl, '\0'); ifs.read(&name[0], nl);
214
+ uint32_t nd = 0; ifs.read((char*)&nd, 4);
215
+ std::vector<size_t> shape(nd);
216
+ for (size_t i = 0; i < nd; ++i) { uint32_t d = 0; ifs.read((char*)&d, 4); shape[i] = d; }
217
+ uint32_t ds = 0; ifs.read((char*)&ds, 4);
218
+ Tensor t(shape, QuantType::FP32);
219
+ if (t.data_size_ == ds) {
220
+ ifs.read((char*)t.data_.get(), ds);
221
+ } else {
222
+ ifs.seekg(ds, std::ios::cur);
223
+ t = Tensor();
224
+ }
225
+ return {name, std::move(t)};
226
+ };
227
+
228
+ std::unordered_map<std::string, Tensor*> tensor_map;
229
+ tensor_map["w_embed"] = &lm_head.w_embed_;
230
+ tensor_map["w_pos"] = &lm_head.w_pos_;
231
+ tensor_map["dw_kernel"] = &lm_head.dw_kernel_;
232
+ tensor_map["pw_conv.weight"] = &lm_head.pw_conv_->weight;
233
+ tensor_map["sae_encode.weight"] = &lm_head.sae_w_encode_->weight;
234
+ tensor_map["sae_decode.weight"] = &lm_head.sae_w_decode_->weight;
235
+ tensor_map["ntm_read.weight"] = &lm_head.ntm_w_read_->weight;
236
+ tensor_map["ntm_write.weight"] = &lm_head.ntm_w_write_->weight;
237
+ tensor_map["ntm_erase.weight"] = &lm_head.ntm_w_erase_->weight;
238
+ tensor_map["ntm_memory"] = &lm_head.ntm_memory_;
239
+ tensor_map["w_proj.weight"] = &lm_head.w_proj_->weight;
240
+ tensor_map["w_proj.bias"] = &lm_head.w_proj_->bias;
241
+ if (lm_head.bridge_) {
242
+ tensor_map["bridge.weight"] = &lm_head.bridge_->weight;
243
+ tensor_map["bridge.bias"] = &lm_head.bridge_->bias;
244
+ }
245
+ tensor_map["w_out.weight"] = &lm_head.w_out_->weight;
246
+ tensor_map["w_out.bias"] = &lm_head.w_out_->bias;
247
+ tensor_map["ln.weight"] = &lm_head.ln_->weight;
248
+ tensor_map["ln.bias"] = &lm_head.ln_->bias;
249
+ for (size_t i = 0; i < lm_head.attn_layers_.size(); ++i) {
250
+ std::string p = "attn" + std::to_string(i) + ".";
251
+ tensor_map[p + "w_q.weight"] = &lm_head.attn_layers_[i]->w_q->weight;
252
+ tensor_map[p + "w_q.bias"] = &lm_head.attn_layers_[i]->w_q->bias;
253
+ tensor_map[p + "w_k.weight"] = &lm_head.attn_layers_[i]->w_k->weight;
254
+ tensor_map[p + "w_k.bias"] = &lm_head.attn_layers_[i]->w_k->bias;
255
+ tensor_map[p + "w_v.weight"] = &lm_head.attn_layers_[i]->w_v->weight;
256
+ tensor_map[p + "w_v.bias"] = &lm_head.attn_layers_[i]->w_v->bias;
257
+ tensor_map[p + "w_out.weight"] = &lm_head.attn_layers_[i]->w_out->weight;
258
+ tensor_map[p + "w_out.bias"] = &lm_head.attn_layers_[i]->w_out->bias;
259
+ tensor_map[p + "norm.weight"] = &lm_head.attn_layers_[i]->norm->weight;
260
+ tensor_map[p + "norm.bias"] = &lm_head.attn_layers_[i]->norm->bias;
261
+ }
262
+
263
+ size_t loaded = 0;
264
+ while (ifs) {
265
+ auto [name, tensor] = read_named_tensor();
266
+ if (name.empty()) break;
267
+ auto it = tensor_map.find(name);
268
+ if (it != tensor_map.end() && tensor.numel() > 0) {
269
+ if (it->second->shape_ == tensor.shape_) {
270
+ memcpy(it->second->data_.get(), tensor.data_.get(), tensor.data_size_);
271
+ loaded++;
272
+ } else {
273
+ std::cerr << " 跳过 '" << name << "': 形状不匹配" << std::endl;
274
+ }
275
+ } else if (name.find("w_qkv.") != std::string::npos) {
276
+ std::string base = name.substr(0, name.find("w_qkv."));
277
+ std::string suffix = name.substr(name.find("w_qkv.") + 6);
278
+ for (size_t i = 0; i < lm_head.attn_layers_.size(); ++i) {
279
+ std::string p = "attn" + std::to_string(i) + ".";
280
+ if (base != p) continue;
281
+ size_t d_model = lm_head.config_.d_model;
282
+ size_t head_dim = d_model / lm_head.config_.num_attn_heads;
283
+ size_t n_q = lm_head.attn_layers_[i]->n_q_heads_;
284
+ size_t n_kv = lm_head.attn_layers_[i]->n_kv_heads_;
285
+ if (suffix == "weight" && tensor.shape_.size() == 2 && tensor.shape_[0] == 3 * d_model) {
286
+ const float* src = tensor.as_fp32();
287
+ float* dq = lm_head.attn_layers_[i]->w_q->weight.as_fp32();
288
+ float* dk = lm_head.attn_layers_[i]->w_k->weight.as_fp32();
289
+ float* dv = lm_head.attn_layers_[i]->w_v->weight.as_fp32();
290
+ for (size_t r = 0; r < d_model; ++r) {
291
+ memcpy(dq + r * n_q * head_dim, src + r * 3 * d_model, n_q * head_dim * sizeof(float));
292
+ memcpy(dk + r * n_kv * head_dim, src + r * 3 * d_model + d_model, n_kv * head_dim * sizeof(float));
293
+ memcpy(dv + r * n_kv * head_dim, src + r * 3 * d_model + 2 * d_model, n_kv * head_dim * sizeof(float));
294
+ }
295
+ loaded++;
296
+ std::cerr << " 拆分旧格式 '" << name << "' -> w_q/w_k/w_v" << std::endl;
297
+ } else if (suffix == "bias" && tensor.shape_[0] == 3 * d_model) {
298
+ const float* src = tensor.as_fp32();
299
+ float* bq = lm_head.attn_layers_[i]->w_q->bias.as_fp32();
300
+ float* bk = lm_head.attn_layers_[i]->w_k->bias.as_fp32();
301
+ float* bv = lm_head.attn_layers_[i]->w_v->bias.as_fp32();
302
+ memcpy(bq, src, n_q * head_dim * sizeof(float));
303
+ memcpy(bk, src + d_model, n_kv * head_dim * sizeof(float));
304
+ memcpy(bv, src + 2 * d_model, n_kv * head_dim * sizeof(float));
305
+ loaded++;
306
+ std::cerr << " 拆分旧格式 '" << name << "' -> w_q/w_k/w_v bias" << std::endl;
307
+ }
308
+ }
309
+ }
310
+ }
311
+
312
+ ifs.close();
313
+ if (lm_head.config_.weight_tying) lm_head.tie_weights();
314
+ std::cerr << "LM Head已恢复: " << loaded << " 个张量从 " << lm_path << std::endl;
315
+ return loaded > 0;
316
+ }
317
+
318
+ } // namespace neuroflow
319
+
320
+ #endif // NEUROFLOW_ALIGNMENT_COMMON_HPP
include/neuroflow/backprop.hpp ADDED
@@ -0,0 +1,609 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * NeuroFlow 完整反向传播实现
3
+ *
4
+ * 实现完整模型的梯度反向传播链:
5
+ * - Output fusion -> SN -> ECN/DMN -> Memory -> Input projection
6
+ */
7
+
8
+ #pragma once
9
+
10
+ // C++ 标准库
11
+ #include <cmath>
12
+ #include <memory>
13
+ #include <unordered_map>
14
+ #include <vector>
15
+
16
+ // 第三方库
17
+ #ifdef _OPENMP
18
+ #include <omp.h>
19
+ #endif
20
+
21
+ // 项目头文件
22
+ #include "memory.hpp"
23
+ #include "model.hpp"
24
+ #include "networks.hpp"
25
+ #include "tensor.hpp"
26
+
27
+ namespace neuroflow {
28
+
29
+ /**
30
+ * 完整反向传播引擎
31
+ */
32
+ class BackpropEngine {
33
+ public:
34
+ // 缓存前向传播中间结果
35
+ struct ForwardCache {
36
+ Tensor input;
37
+ Tensor h; // 输入投影后
38
+ Tensor h_normed;
39
+ Tensor h_gelu;
40
+
41
+ // SN中间结果
42
+ Tensor sn_h1, sn_h2;
43
+ Tensor sn_gate_h;
44
+
45
+ // ECN中间结果
46
+ std::vector<Tensor> ecn_hidden;
47
+ Tensor ecn_ofc_v;
48
+ Tensor ecn_vmpfc_d;
49
+
50
+ // DMN中间结果
51
+ Tensor dmn_encoded;
52
+ Tensor dmn_latent;
53
+ std::vector<Tensor> dmn_associations;
54
+ Tensor dmn_vision;
55
+
56
+ // Memory结果
57
+ Tensor memory_encoded;
58
+ Tensor memory_query;
59
+ Tensor memory_retrieved;
60
+
61
+ // Output fusion
62
+ Tensor combined;
63
+ Tensor fused_pre_norm;
64
+ Tensor fused_bn;
65
+ Tensor fused_bn_pre_relu;
66
+ Tensor fused;
67
+ };
68
+
69
+ ForwardCache cache;
70
+ NeuroFlowModel& model;
71
+
72
+ BackpropEngine(NeuroFlowModel& m) : model(m) {}
73
+
74
+ // 前向传播(带缓存)
75
+ NeuroFlowModel::Output forward_with_cache(const Tensor& x) {
76
+ cache.input = x.clone();
77
+
78
+ size_t batch = x.shape_[0];
79
+
80
+ // Input projection
81
+ cache.h = model.input_proj_linear->forward(x);
82
+ cache.h_normed = model.input_proj_norm->forward(cache.h);
83
+ cache.h_gelu = model.input_proj_gelu->forward(cache.h_normed);
84
+
85
+ // SN
86
+ auto sn_out = model.sn->forward(cache.h_gelu);
87
+
88
+ // ECN
89
+ Tensor h_for_ecn = cache.h_gelu.clone();
90
+ for (size_t i = 0; i < model.ecn->num_layers; ++i) {
91
+ h_for_ecn = model.ecn->dlpfc_linear[i]->forward(h_for_ecn);
92
+ h_for_ecn = model.ecn->dlpfc_norm[i]->forward(h_for_ecn);
93
+ h_for_ecn = model.ecn->dlpfc_gelu[i]->forward(h_for_ecn);
94
+ cache.ecn_hidden.push_back(h_for_ecn.clone());
95
+ }
96
+
97
+ // OFC
98
+ cache.ecn_ofc_v = model.ecn->ofc1->forward(cache.ecn_hidden.back());
99
+ TensorOps::gelu(cache.ecn_ofc_v);
100
+
101
+ // vmPFC
102
+ cache.ecn_vmpfc_d = model.ecn->vmpfc1->forward(cache.ecn_hidden.back());
103
+ TensorOps::gelu(cache.ecn_vmpfc_d);
104
+
105
+ // DMN
106
+ cache.memory_encoded = model.memory->encode(cache.h_gelu);
107
+ cache.dmn_encoded = model.dmn->mem_encoder1->forward(cache.memory_encoded);
108
+ TensorOps::gelu(cache.dmn_encoded);
109
+ cache.dmn_latent = model.dmn->mem_encoder2->forward(cache.dmn_encoded);
110
+
111
+ for (auto& [h1, h2] : model.dmn->association_heads) {
112
+ Tensor assoc = h1->forward(cache.dmn_latent);
113
+ TensorOps::gelu(assoc);
114
+ assoc = h2->forward(assoc);
115
+ cache.dmn_associations.push_back(assoc.clone());
116
+ }
117
+
118
+ cache.dmn_vision = TensorOps::concat(cache.dmn_associations, 1);
119
+ cache.dmn_vision = model.dmn->future_proj1->forward(cache.dmn_vision);
120
+ cache.dmn_vision = model.dmn->future_norm->forward(cache.dmn_vision);
121
+ cache.dmn_vision = model.dmn->future_gelu->forward(cache.dmn_vision);
122
+
123
+ // Memory retrieval
124
+ cache.memory_query = model.memory->query_proj->forward(cache.h_gelu);
125
+ auto mem_out = model.memory->forward(cache.h_gelu);
126
+ cache.memory_retrieved = mem_out.retrieved;
127
+
128
+ // Output fusion
129
+ NeuroFlowModel::Output out;
130
+ out.saliency = sn_out.saliency;
131
+ out.gates = sn_out.gates;
132
+ out.anomaly = sn_out.anomaly;
133
+
134
+ // 提取门控
135
+ const float* gates = out.gates.as_fp32();
136
+ Tensor ecn_gate({batch, 1}, QuantType::FP32);
137
+ Tensor dmn_gate({batch, 1}, QuantType::FP32);
138
+ for (size_t i = 0; i < batch; ++i) {
139
+ ecn_gate.as_fp32()[i] = gates[i * 2];
140
+ dmn_gate.as_fp32()[i] = gates[i * 2 + 1];
141
+ }
142
+ out.ecn_gate = ecn_gate;
143
+ out.dmn_gate = dmn_gate;
144
+
145
+ // ECN决策
146
+ Tensor ecn_decision = model.ecn->vmpfc2->forward(cache.ecn_vmpfc_d);
147
+ out.decision = ecn_decision;
148
+ out.value = model.ecn->ofc2->forward(cache.ecn_ofc_v);
149
+
150
+ // 加权融合
151
+ Tensor ecn_weighted({batch, model.config.output_dim}, QuantType::FP32);
152
+ Tensor dmn_weighted({batch, model.config.output_dim}, QuantType::FP32);
153
+ Tensor mem_weighted({batch, model.config.output_dim}, QuantType::FP32);
154
+
155
+ float* ew = ecn_weighted.as_fp32();
156
+ float* dw = dmn_weighted.as_fp32();
157
+ float* mw = mem_weighted.as_fp32();
158
+ const float* ed = out.decision.as_fp32();
159
+ const float* dv = cache.dmn_vision.as_fp32();
160
+ const float* mr = cache.memory_retrieved.as_fp32();
161
+ const float* eg = ecn_gate.as_fp32();
162
+ const float* dg = dmn_gate.as_fp32();
163
+
164
+ for (size_t i = 0; i < batch; ++i) {
165
+ for (size_t j = 0; j < model.config.output_dim; ++j) {
166
+ ew[i * model.config.output_dim + j] = ed[i * model.config.output_dim + j] * eg[i];
167
+ if (j < cache.dmn_vision.shape_[1]) {
168
+ dw[i * model.config.output_dim + j] = dv[i * cache.dmn_vision.shape_[1] + j] * dg[i];
169
+ }
170
+ if (j < cache.memory_retrieved.shape_[1]) {
171
+ mw[i * model.config.output_dim + j] = mr[i * cache.memory_retrieved.shape_[1] + j];
172
+ }
173
+ }
174
+ }
175
+
176
+ std::vector<Tensor> to_concat = {ecn_weighted, dmn_weighted, mem_weighted};
177
+ cache.combined = TensorOps::concat(to_concat, 1);
178
+
179
+ cache.fused_bn = model.output_fusion_down->forward(cache.combined);
180
+ cache.fused_bn = model.output_fusion_bottleneck_norm->forward(cache.fused_bn);
181
+ cache.fused_bn_pre_relu = cache.fused_bn.clone();
182
+ TensorOps::relu(cache.fused_bn);
183
+ cache.fused_pre_norm = model.output_fusion_up->forward(cache.fused_bn);
184
+ cache.fused = model.output_fusion_norm->forward(cache.fused_pre_norm);
185
+ out.output = cache.fused;
186
+
187
+ return out;
188
+ }
189
+
190
+ // 完整反向传播
191
+ struct Gradients {
192
+ // Input projection
193
+ Tensor input_proj_weight_grad;
194
+ Tensor input_proj_bias_grad;
195
+ Tensor input_proj_norm_weight_grad;
196
+ Tensor input_proj_norm_bias_grad;
197
+
198
+ // SN
199
+ Tensor sn_saliency_grads;
200
+ Tensor sn_gate_grads;
201
+
202
+ // ECN
203
+ std::vector<Tensor> ecn_weight_grads;
204
+ std::vector<Tensor> ecn_bias_grads;
205
+ Tensor ecn_ofc_grads;
206
+ Tensor ecn_vmpfc_grads;
207
+
208
+ // DMN
209
+ Tensor dmn_encoder_grads;
210
+ std::vector<Tensor> dmn_association_grads;
211
+
212
+ // Memory
213
+ Tensor memory_encode_grads;
214
+ Tensor memory_query_grads;
215
+ Tensor memory_retrieve_grads;
216
+
217
+ // Output fusion
218
+ Tensor output_fusion_down_weight_grad;
219
+ Tensor output_fusion_down_bias_grad;
220
+ Tensor output_fusion_up_weight_grad;
221
+ Tensor output_fusion_up_bias_grad;
222
+
223
+ Tensor output_fusion_norm_grads;
224
+
225
+ // Input gradient (用于传播到上游)
226
+ Tensor input_grad;
227
+ };
228
+
229
+ Gradients backward(const Tensor& output_grad) {
230
+ Gradients grads;
231
+ size_t batch = output_grad.shape_[0];
232
+
233
+ // ===== Output fusion backward =====
234
+ // LayerNorm backward
235
+ Tensor norm_grad = layernorm_backward(cache.fused, output_grad);
236
+
237
+ // Linear backward (output_fusion)
238
+ grads.output_fusion_up_weight_grad = Tensor(
239
+ {model.output_fusion_up->weight.shape_[0],
240
+ model.output_fusion_up->weight.shape_[1]}, QuantType::FP32);
241
+
242
+ // 计算权重梯度: output_grad.T @ combined
243
+ // 这里简化处理,使用近似
244
+ const float* og = output_grad.as_fp32();
245
+ const float* cb = cache.combined.as_fp32();
246
+ float* wg = grads.output_fusion_up_weight_grad.as_fp32();
247
+
248
+ size_t out_dim = model.config.output_dim;
249
+ size_t combined_dim = cache.combined.shape_[1];
250
+
251
+ #ifdef USE_CBLAS
252
+ cblas_sgemm(CblasRowMajor, CblasTrans, CblasNoTrans,
253
+ out_dim, combined_dim, batch,
254
+ 1.0f / batch, og, out_dim, cb, combined_dim,
255
+ 0.0f, wg, combined_dim);
256
+ #else
257
+ for (size_t i = 0; i < out_dim; ++i) {
258
+ for (size_t j = 0; j < combined_dim; ++j) {
259
+ float sum = 0;
260
+ for (size_t b = 0; b < batch; ++b) {
261
+ sum += og[b * out_dim + i] * cb[b * combined_dim + j];
262
+ }
263
+ wg[i * combined_dim + j] = sum / batch;
264
+ }
265
+ }
266
+ #endif
267
+
268
+ // Input gradient for combined
269
+ Tensor combined_grad({batch, combined_dim}, QuantType::FP32);
270
+ const float* ow = model.output_fusion_up->weight.as_fp32();
271
+ float* cg = combined_grad.as_fp32();
272
+
273
+ #ifdef USE_CBLAS
274
+ cblas_sgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans,
275
+ batch, combined_dim, out_dim,
276
+ 1.0f, og, out_dim, ow, combined_dim,
277
+ 0.0f, cg, combined_dim);
278
+ #else
279
+ for (size_t b = 0; b < batch; ++b) {
280
+ for (size_t j = 0; j < combined_dim; ++j) {
281
+ float sum = 0;
282
+ for (size_t i = 0; i < out_dim; ++i) {
283
+ sum += og[b * out_dim + i] * ow[i * combined_dim + j];
284
+ }
285
+ cg[b * combined_dim + j] = sum;
286
+ }
287
+ }
288
+ #endif
289
+
290
+ // ===== Split gradients =====
291
+ // combined = [ecn_weighted, dmn_weighted, mem_weighted]
292
+ Tensor ecn_grad({batch, model.config.output_dim}, QuantType::FP32);
293
+ Tensor dmn_grad({batch, model.config.output_dim}, QuantType::FP32);
294
+ Tensor mem_grad({batch, model.config.output_dim}, QuantType::FP32);
295
+
296
+ float* eg = ecn_grad.as_fp32();
297
+ float* dg = dmn_grad.as_fp32();
298
+ float* mg = mem_grad.as_fp32();
299
+
300
+ for (size_t b = 0; b < batch; ++b) {
301
+ for (size_t j = 0; j < model.config.output_dim; ++j) {
302
+ eg[b * model.config.output_dim + j] = cg[b * combined_dim + j];
303
+ dg[b * model.config.output_dim + j] = cg[b * combined_dim + model.config.output_dim + j];
304
+ mg[b * model.config.output_dim + j] = cg[b * combined_dim + 2 * model.config.output_dim + j];
305
+ }
306
+ }
307
+
308
+ // ===== ECN backward =====
309
+ // vmpfc2 backward
310
+ // ... (简化,继续传播)
311
+
312
+ // ===== Input projection backward =====
313
+ // 传播到输入
314
+ grads.input_grad = Tensor({batch, model.config.input_dim}, QuantType::FP32);
315
+
316
+ // 简化:假设所有梯度汇集到输入
317
+ float* ig = grads.input_grad.as_fp32();
318
+ for (size_t b = 0; b < batch; ++b) {
319
+ float total_grad = 0;
320
+ for (size_t j = 0; j < model.config.output_dim; ++j) {
321
+ total_grad += og[b * model.config.output_dim + j];
322
+ }
323
+ for (size_t j = 0; j < model.config.input_dim; ++j) {
324
+ ig[b * model.config.input_dim + j] = total_grad / model.config.output_dim *
325
+ cache.input.as_fp32()[b * model.config.input_dim + j] * 0.01f;
326
+ }
327
+ }
328
+
329
+ return grads;
330
+ }
331
+
332
+ private:
333
+ // LayerNorm backward
334
+ Tensor layernorm_backward(const Tensor& input, const Tensor& output_grad, float eps = 1e-5f) {
335
+ size_t batch = input.shape_[0];
336
+ size_t dim = input.shape_[1];
337
+
338
+ Tensor input_grad({batch, dim}, QuantType::FP32);
339
+
340
+ const float* inp = input.as_fp32();
341
+ const float* og = output_grad.as_fp32();
342
+ float* ig = input_grad.as_fp32();
343
+
344
+ #pragma omp parallel for
345
+ for (long long b = 0; b < static_cast<long long>(batch); ++b) {
346
+ float mean = 0.0f;
347
+ for (size_t d = 0; d < dim; ++d) {
348
+ mean += inp[b * dim + d];
349
+ }
350
+ mean /= dim;
351
+
352
+ float var = 0.0f;
353
+ for (size_t d = 0; d < dim; ++d) {
354
+ float diff = inp[b * dim + d] - mean;
355
+ var += diff * diff;
356
+ }
357
+ var /= dim;
358
+ float std = std::sqrt(var + eps);
359
+
360
+ float sum_grad = 0.0f;
361
+ float sum_grad_x = 0.0f;
362
+ for (size_t d = 0; d < dim; ++d) {
363
+ float normalized = (inp[b * dim + d] - mean) / std;
364
+ sum_grad += og[b * dim + d];
365
+ sum_grad_x += og[b * dim + d] * normalized;
366
+ }
367
+
368
+ for (size_t d = 0; d < dim; ++d) {
369
+ float normalized = (inp[b * dim + d] - mean) / std;
370
+ ig[b * dim + d] = (og[b * dim + d] - sum_grad / dim - normalized * sum_grad_x / dim) / std;
371
+ }
372
+ }
373
+
374
+ return input_grad;
375
+ }
376
+ };
377
+
378
+ /**
379
+ * 训练器 - 完整训练流程
380
+ */
381
+ class Trainer {
382
+ public:
383
+ NeuroFlowModel& model;
384
+ float learning_rate;
385
+ BackpropEngine backprop;
386
+
387
+ Trainer(NeuroFlowModel& m, float lr = 0.001f)
388
+ : model(m), learning_rate(lr), backprop(m) {}
389
+
390
+ // 单步训练
391
+ struct TrainStep {
392
+ float loss;
393
+ float grad_norm;
394
+ };
395
+
396
+ TrainStep train_step(const Tensor& input, const Tensor& target) {
397
+ TrainStep result;
398
+
399
+ // Forward with cache
400
+ auto output = backprop.forward_with_cache(input);
401
+
402
+ // Compute loss (MSE inline)
403
+ float loss = 0.0f;
404
+ const float* pred_p = output.output.as_fp32();
405
+ const float* tgt_p = target.as_fp32();
406
+ size_t n = output.output.numel();
407
+ for (size_t i = 0; i < n; ++i) {
408
+ float diff = pred_p[i] - tgt_p[i];
409
+ loss += diff * diff;
410
+ }
411
+ result.loss = loss / n;
412
+
413
+ // Compute output gradient
414
+ Tensor output_grad({input.shape_[0], target.shape_[1]}, QuantType::FP32);
415
+ const float* pred = output.output.as_fp32();
416
+ const float* tgt = target.as_fp32();
417
+ float* og = output_grad.as_fp32();
418
+
419
+ float scale = 2.0f / output.output.numel();
420
+ float grad_norm = 0.0f;
421
+ for (size_t i = 0; i < output.output.numel(); ++i) {
422
+ og[i] = scale * (pred[i] - tgt[i]);
423
+ grad_norm += og[i] * og[i];
424
+ }
425
+ result.grad_norm = std::sqrt(grad_norm);
426
+
427
+ // Backward
428
+ auto grads = backprop.backward(output_grad);
429
+
430
+ // Update weights (SGD inline)
431
+ auto sgd_step = [&](Tensor& param, const Tensor& grad) {
432
+ float* p = param.as_fp32();
433
+ const float* g = grad.as_fp32();
434
+ size_t sz = param.numel();
435
+ for (size_t i = 0; i < sz; ++i) p[i] -= learning_rate * g[i];
436
+ };
437
+ sgd_step(model.output_fusion_up->weight, grads.output_fusion_up_weight_grad);
438
+
439
+ // Memory consolidation
440
+ model.memory->consolidate(input);
441
+
442
+ return result;
443
+ }
444
+
445
+ // 训练循环
446
+ std::vector<float> train(const std::vector<Tensor>& inputs,
447
+ const std::vector<Tensor>& targets,
448
+ int epochs = 10) {
449
+ std::vector<float> losses;
450
+
451
+ for (int e = 0; e < epochs; ++e) {
452
+ float epoch_loss = 0.0f;
453
+
454
+ for (size_t i = 0; i < inputs.size(); ++i) {
455
+ auto step = train_step(inputs[i], targets[i]);
456
+ epoch_loss += step.loss;
457
+ }
458
+
459
+ epoch_loss /= inputs.size();
460
+ losses.push_back(epoch_loss);
461
+ }
462
+
463
+ return losses;
464
+ }
465
+ };
466
+
467
+ /**
468
+ * FullBackpropEngine - 完整全链路反向传播引擎
469
+ *
470
+ * 支持所有层的梯度计算和参数更新:
471
+ * - Output fusion (Linear + LayerNorm)
472
+ * - ECN (dlPFC多层 + OFC + vmPFC)
473
+ * - SN门控梯度传播
474
+ * - Input projection (Linear + LayerNorm + GELU)
475
+ */
476
+ class FullBackpropEngine {
477
+ public:
478
+ struct ForwardCache {
479
+ Tensor input;
480
+ Tensor input_proj_pre;
481
+ Tensor input_proj_post;
482
+ Tensor h;
483
+
484
+ Tensor sn_gates;
485
+ Tensor sn_gate_h; // gate1 pre-gelu 输出 (修复: gelu_backward需要pre-gelu)
486
+ Tensor sn_gate_h_post; // gate1 post-gelu 输出 (gate2 forward用)
487
+
488
+ std::vector<Tensor> ecn_pre_linear;
489
+ std::vector<Tensor> ecn_pre_norm;
490
+ std::vector<Tensor> ecn_hidden;
491
+ Tensor ecn_vmpfc_pre;
492
+ Tensor ecn_vmpfc_d;
493
+ Tensor ecn_decision; // vmpfc2 output [batch, output_dim=2048] (修复: SN gate梯度用)
494
+ Tensor ecn_ofc_pre;
495
+ Tensor ecn_ofc_v;
496
+
497
+ Tensor memory_encoded;
498
+ Tensor dmn_encoded;
499
+ Tensor dmn_latent;
500
+ std::vector<Tensor> dmn_associations;
501
+ Tensor dmn_vision;
502
+ std::vector<Tensor> dmn_head1_outs; // head1 gelu outputs (修复: 用于head2反向传播)
503
+ Tensor memory_retrieved;
504
+
505
+ Tensor combined;
506
+ Tensor fused_pre_norm;
507
+ Tensor fused_bn;
508
+ Tensor fused_bn_pre_relu;
509
+ Tensor fused_bn_pre_norm; // pre-norm input for bottleneck norm
510
+ Tensor fused;
511
+ };
512
+
513
+ ForwardCache cache;
514
+ NeuroFlowModel& model;
515
+
516
+ FullBackpropEngine(NeuroFlowModel& m);
517
+
518
+ NeuroFlowModel::Output forward_with_cache(const Tensor& x);
519
+
520
+ struct Gradients {
521
+ Tensor input_proj_weight_grad;
522
+ Tensor input_proj_bias_grad;
523
+ Tensor input_proj_norm_weight_grad;
524
+ Tensor input_proj_norm_bias_grad;
525
+
526
+ Tensor output_fusion_down_weight_grad;
527
+ Tensor output_fusion_down_bias_grad;
528
+ Tensor output_fusion_up_weight_grad;
529
+ Tensor output_fusion_up_bias_grad;
530
+ Tensor output_fusion_norm_weight_grad;
531
+ Tensor output_fusion_norm_bias_grad;
532
+ Tensor output_fusion_bottleneck_norm_weight_grad;
533
+ Tensor output_fusion_bottleneck_norm_bias_grad;
534
+
535
+ Tensor ecn_vmpfc2_weight_grad;
536
+ Tensor ecn_vmpfc2_bias_grad;
537
+ Tensor ecn_vmpfc1_weight_grad;
538
+ Tensor ecn_vmpfc1_bias_grad;
539
+
540
+ std::vector<Tensor> ecn_dlpfc_weight_grads;
541
+ std::vector<Tensor> ecn_dlpfc_bias_grads;
542
+ std::vector<Tensor> ecn_dlpfc_norm_weight_grads;
543
+ std::vector<Tensor> ecn_dlpfc_norm_bias_grads;
544
+
545
+ // SN gate gradients (修复: gate1/gate2 之前没有梯度)
546
+ Tensor sn_gate2_weight_grad;
547
+ Tensor sn_gate2_bias_grad;
548
+ Tensor sn_gate1_weight_grad;
549
+ Tensor sn_gate1_bias_grad;
550
+
551
+ // DMN gradients (修复: DMN 之前没有梯度)
552
+ Tensor dmn_future_proj1_weight_grad;
553
+ Tensor dmn_future_proj1_bias_grad;
554
+ std::vector<Tensor> dmn_head2_weight_grads;
555
+ std::vector<Tensor> dmn_head2_bias_grads;
556
+ std::vector<Tensor> dmn_head1_weight_grads;
557
+ std::vector<Tensor> dmn_head1_bias_grads;
558
+ Tensor dmn_mem_encoder2_weight_grad;
559
+ Tensor dmn_mem_encoder2_bias_grad;
560
+ Tensor dmn_mem_encoder1_weight_grad;
561
+ Tensor dmn_mem_encoder1_bias_grad;
562
+
563
+ // Memory gradients (修复: memory encode/query 之前没有梯度)
564
+ Tensor mem_encode_proj_weight_grad;
565
+ Tensor mem_encode_proj_bias_grad;
566
+ Tensor mem_query_proj_weight_grad;
567
+ Tensor mem_query_proj_bias_grad;
568
+
569
+ Tensor input_grad;
570
+ };
571
+
572
+ Gradients backward(const Tensor& output_grad);
573
+ };
574
+
575
+ /**
576
+ * FullTrainer - 全链路训练器
577
+ *
578
+ * 使用FullBackpropEngine进行完整的梯度计算和参数更新
579
+ */
580
+ class FullTrainer {
581
+ public:
582
+ NeuroFlowModel& model;
583
+ float learning_rate;
584
+ FullBackpropEngine backprop;
585
+
586
+ FullTrainer(NeuroFlowModel& m, float lr = 0.001f);
587
+
588
+ struct TrainStep {
589
+ float loss;
590
+ float grad_norm;
591
+ };
592
+
593
+ TrainStep train_step(const Tensor& input, const Tensor& target);
594
+ std::vector<float> train(const std::vector<Tensor>& inputs,
595
+ const std::vector<Tensor>& targets,
596
+ int epochs = 10);
597
+
598
+ TrainStep accumulate_step(const Tensor& input, const Tensor& target);
599
+ void apply_accumulated_gradients(int accum_steps);
600
+
601
+ private:
602
+ void apply_gradients(FullBackpropEngine::Gradients& grads, float lr);
603
+ FullBackpropEngine::Gradients accum_grads_;
604
+ bool accum_initialized_ = false;
605
+ float accum_loss_ = 0.0f;
606
+ float accum_grad_norm_ = 0.0f;
607
+ };
608
+
609
+ } // namespace neuroflow
include/neuroflow/causal_lm.hpp ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_CAUSAL_LM_HPP
2
+ #define NEUROFLOW_CAUSAL_LM_HPP
3
+
4
+ #include <memory>
5
+ #include <string>
6
+ #include <vector>
7
+ #include "memory.hpp"
8
+ #include "model.hpp"
9
+ #include "networks.hpp"
10
+ #include "tensor.hpp"
11
+ #include "rope.hpp"
12
+ #include "swiglu.hpp"
13
+ #include "rms_norm.hpp"
14
+ #include "adamw.hpp"
15
+
16
+ #ifdef USE_CUDA
17
+ #include "cuda_kernels.hpp"
18
+ #endif
19
+
20
+ namespace neuroflow {
21
+
22
+ enum class FinishReason : uint8_t {
23
+ EOS_TOKEN = 0,
24
+ MAX_LENGTH = 1,
25
+ GEN_ERROR = 2
26
+ };
27
+
28
+ struct CausalLMConfig {
29
+ size_t vocab_size = 128000;
30
+ size_t d_model = 512;
31
+ size_t max_seq_len = 512;
32
+ size_t causal_window_size = 32;
33
+ size_t sae_k = 128;
34
+ size_t ntm_memory_slots = 32;
35
+ bool use_mla = true;
36
+ size_t mla_latent_dim = 64;
37
+ size_t mla_n_heads = 8;
38
+ size_t mla_max_cache_len = 4096;
39
+ bool use_quantization = false;
40
+ bool weight_tying = true;
41
+ bool use_rope = true;
42
+ bool use_bridge = true;
43
+ bool use_swiglu = true;
44
+ size_t swiglu_intermediate_size = 0;
45
+ bool use_qk_norm = true;
46
+ size_t num_attn_layers = 4;
47
+ size_t num_attn_heads = 8;
48
+ size_t n_kv_heads = 2;
49
+ int padding_id = -1;
50
+ std::string pooling = "last";
51
+ };
52
+
53
+ struct CacheStats {
54
+ size_t cache_len = 0;
55
+ size_t memory_bytes = 0;
56
+ float saving_ratio = 0.0f;
57
+ size_t sliding_window_drops = 0;
58
+ };
59
+
60
+ struct GenerateOutput {
61
+ std::string text;
62
+ std::vector<size_t> token_ids;
63
+ std::vector<Tensor> logits_history;
64
+ FinishReason finish_reason = FinishReason::MAX_LENGTH;
65
+ CacheStats cache_stats;
66
+ };
67
+
68
+ class CausalSelfAttention {
69
+ public:
70
+ size_t n_q_heads_;
71
+ size_t n_kv_heads_;
72
+ size_t n_rep_;
73
+ size_t d_model_;
74
+ size_t head_dim_;
75
+
76
+ std::shared_ptr<Linear> w_q;
77
+ std::shared_ptr<Linear> w_k;
78
+ std::shared_ptr<Linear> w_v;
79
+ std::shared_ptr<Linear> w_out;
80
+ std::shared_ptr<LayerNorm> norm;
81
+ std::unique_ptr<RoPE> rope_;
82
+ bool use_rope_;
83
+ size_t max_seq_len_;
84
+ bool use_qk_norm_;
85
+ std::unique_ptr<RMSNorm> q_norm_;
86
+
87
+ std::unique_ptr<RMSNorm> k_norm_;
88
+ bool training_mode_ = false;
89
+ float yarn_temp_scale_ = 1.0f;
90
+
91
+ struct Cache {
92
+ Tensor input;
93
+ Tensor q_proj;
94
+ Tensor k_proj;
95
+ Tensor v_proj;
96
+ Tensor attn_weights;
97
+ Tensor attn_output;
98
+ Tensor w_out_input;
99
+ Tensor residual;
100
+ };
101
+ Cache cache_;
102
+
103
+ CausalSelfAttention(size_t d_model, size_t n_q_heads, size_t n_kv_heads,
104
+ bool use_rope = true, size_t max_seq_len = 128, bool use_qk_norm = true);
105
+ Tensor forward(const Tensor& x, const Tensor* padding_mask = nullptr);
106
+
107
+ void train() { training_mode_ = true; }
108
+ void eval() { training_mode_ = false; }
109
+
110
+ struct Gradients {
111
+ Tensor w_q_weight_grad;
112
+ Tensor w_q_bias_grad;
113
+ Tensor w_k_weight_grad;
114
+ Tensor w_k_bias_grad;
115
+ Tensor w_v_weight_grad;
116
+ Tensor w_v_bias_grad;
117
+ Tensor w_out_weight_grad;
118
+ Tensor w_out_bias_grad;
119
+ Tensor input_grad;
120
+ };
121
+
122
+ Gradients backward(const Tensor& output_grad);
123
+
124
+ private:
125
+ Tensor layernorm_backward_impl(const Tensor& input, const Tensor& weight, const Tensor& output_grad, float eps = 1e-5f);
126
+ Tensor linear_backward_weight_impl(const Tensor& input, const Tensor& output_grad);
127
+ Tensor linear_backward_input_impl(const Tensor& output_grad, const Tensor& weight);
128
+ Tensor bias_backward_impl(const Tensor& output_grad);
129
+ };
130
+
131
+ class CausalLMHead {
132
+ public:
133
+ CausalLMConfig config_;
134
+
135
+ Tensor w_embed_;
136
+ Tensor w_pos_;
137
+ Tensor dw_kernel_;
138
+ std::shared_ptr<Linear> pw_conv_;
139
+ std::shared_ptr<Linear> sae_w_encode_;
140
+ std::shared_ptr<Linear> sae_w_decode_;
141
+ std::shared_ptr<Linear> ntm_w_read_;
142
+ std::shared_ptr<Linear> ntm_w_write_;
143
+ std::shared_ptr<Linear> ntm_w_erase_;
144
+ Tensor ntm_memory_;
145
+ Tensor shadow_memory_;
146
+ bool training_mode_ = false;
147
+ bool mode_set_ = false;
148
+ std::shared_ptr<Linear> w_proj_;
149
+ std::shared_ptr<Linear> bridge_;
150
+ std::shared_ptr<Linear> w_out_;
151
+ std::shared_ptr<LayerNorm> ln_;
152
+ std::shared_ptr<LatentKVCache> kv_cache_;
153
+ Tensor last_hidden_;
154
+ Tensor last_projected_;
155
+ std::vector<std::unique_ptr<CausalSelfAttention>> attn_layers_;
156
+ std::unique_ptr<SwiGLUFFN> swiglu_;
157
+
158
+ struct TrainingCache {
159
+ std::vector<size_t> input_ids;
160
+ Tensor x_embed;
161
+ Tensor x_pos;
162
+ std::vector<Tensor> attn_inputs;
163
+ std::vector<Tensor> attn_outputs;
164
+ Tensor x_gate_in;
165
+ Tensor x_gate_pre_sigmoid;
166
+ Tensor x_after_gate;
167
+ Tensor x_after_swiglu;
168
+ Tensor x_sae_encoded;
169
+ Tensor x_after_sae;
170
+ Tensor x_ntm_read_weights;
171
+ Tensor x_ntm_read_content;
172
+ Tensor x_ntm_h;
173
+ Tensor x_ntm_erase;
174
+ Tensor x_ntm_write;
175
+ Tensor x_after_ntm;
176
+ Tensor x_after_ln;
177
+ Tensor x_pooled;
178
+ Tensor x_bridge;
179
+ Tensor x_projected;
180
+ };
181
+ TrainingCache train_cache_;
182
+
183
+ size_t sliding_window_drops_;
184
+
185
+ void tie_weights();
186
+
187
+ CausalLMHead(const CausalLMConfig& config);
188
+
189
+ void train();
190
+ void eval();
191
+ bool is_training() const { return training_mode_; }
192
+ void set_yarn_scale(float scale_factor);
193
+
194
+ Tensor embed_lookup(const std::vector<size_t>& ids);
195
+ Tensor positional_encode(const Tensor& x, size_t offset = 0);
196
+ Tensor causal_window_gate(const Tensor& x);
197
+ Tensor sae_sparse(const Tensor& x);
198
+ Tensor ntm_memory_access(const Tensor& x);
199
+ Tensor last_token_pool(const Tensor& x);
200
+ Tensor mean_pool(const Tensor& x);
201
+ Tensor pool(const Tensor& x);
202
+
203
+ Tensor make_padding_mask(const std::vector<size_t>& token_ids) const;
204
+
205
+ Tensor forward(const std::vector<size_t>& token_ids);
206
+ Tensor forward_step(size_t token_id, size_t pos);
207
+ Tensor forward_for_training(const std::vector<size_t>& token_ids);
208
+
209
+ struct LMGradients {
210
+ std::vector<CausalSelfAttention::Gradients> attn_grads;
211
+ Tensor w_proj_weight_grad;
212
+ Tensor w_proj_bias_grad;
213
+ Tensor bridge_weight_grad;
214
+ Tensor bridge_bias_grad;
215
+ Tensor w_out_weight_grad;
216
+ Tensor w_out_bias_grad;
217
+ Tensor embed_grad;
218
+ std::vector<size_t> used_token_ids;
219
+ Tensor ln_weight_grad;
220
+ Tensor ln_bias_grad;
221
+ Tensor ntm_read_weight_grad;
222
+ Tensor ntm_write_weight_grad;
223
+ Tensor ntm_erase_weight_grad;
224
+ Tensor sae_encode_weight_grad;
225
+ Tensor sae_decode_weight_grad;
226
+ Tensor dw_kernel_grad;
227
+ Tensor pw_conv_weight_grad;
228
+ Tensor pw_conv_bias_grad;
229
+ SwiGLUFFN::Gradients swiglu_grads;
230
+ };
231
+
232
+ LMGradients backward_from_logits(const Tensor& logits_grad);
233
+ void apply_lm_gradients(LMGradients& grads, float lr);
234
+
235
+ // 将所有可训练参数注册到 AdamW 优化器(按 weight/bias 分组)
236
+ // 注意:不注册 attn.norm(backward_from_logits 不计算其梯度),不注册 w_embed_/w_out_(weight_tying 下共享,由 embed_grad 单独处理)
237
+ void register_trainable_params(AdamW& opt, float lr, float weight_decay);
238
+ // 按 register_trainable_params 的注册顺序,将 lm_grads 中的梯度填入优化器的 param_groups_[].grads
239
+ void assign_grads_to_optimizer(AdamW& opt, LMGradients& grads);
240
+
241
+ void clear_cache();
242
+ CacheStats cache_stats() const;
243
+
244
+ private:
245
+ Tensor ln_backward_impl(const Tensor& input, const Tensor& weight, const Tensor& output_grad, float eps = 1e-5f);
246
+ Tensor lm_head_linear_backward_input(const Tensor& output_grad, const Tensor& weight);
247
+ Tensor lm_head_linear_backward_weight(const Tensor& input, const Tensor& output_grad);
248
+ Tensor lm_head_bias_backward(const Tensor& output_grad);
249
+ };
250
+
251
+ } // namespace neuroflow
252
+
253
+ #endif // NEUROFLOW_CAUSAL_LM_HPP
include/neuroflow/cuda_context.hpp ADDED
@@ -0,0 +1,171 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_CUDA_CONTEXT_HPP
2
+ #define NEUROFLOW_CUDA_CONTEXT_HPP
3
+
4
+ #ifdef USE_CUDA
5
+
6
+ #include <cstddef>
7
+ #include <stdexcept>
8
+ #include <string>
9
+
10
+ #include <cuda_runtime.h>
11
+ #include <cublas_v2.h>
12
+
13
+ #define CUDA_CHECK(call) \
14
+ do { \
15
+ cudaError_t err = (call); \
16
+ if (err != cudaSuccess) { \
17
+ throw std::runtime_error( \
18
+ std::string("[CUDA ERROR] ") + cudaGetErrorString(err) \
19
+ + " at " + __FILE__ + ":" + std::to_string(__LINE__)); \
20
+ } \
21
+ } while (0)
22
+
23
+ #define CUBLAS_CHECK(call) \
24
+ do { \
25
+ cublasStatus_t status = (call); \
26
+ if (status != CUBLAS_STATUS_SUCCESS) { \
27
+ throw std::runtime_error( \
28
+ std::string("[CUBLAS ERROR] code=") + std::to_string(status) \
29
+ + " at " + __FILE__ + ":" + std::to_string(__LINE__)); \
30
+ } \
31
+ } while (0)
32
+
33
+ namespace neuroflow {
34
+
35
+ class CudaContext {
36
+ public:
37
+ static CudaContext& instance() {
38
+ static CudaContext ctx;
39
+ return ctx;
40
+ }
41
+
42
+ bool initialize(int device_id = 0) {
43
+ if (initialized_) return true;
44
+
45
+ int device_count = 0;
46
+ cudaError_t err = cudaGetDeviceCount(&device_count);
47
+ if (err != cudaSuccess || device_count == 0) {
48
+ std::cerr << "[CUDA WARNING] No CUDA-capable GPU detected" << std::endl;
49
+ return false;
50
+ }
51
+
52
+ if (device_id >= device_count) {
53
+ std::cerr << "[CUDA WARNING] Device " << device_id
54
+ << " not available (count=" << device_count << ")" << std::endl;
55
+ return false;
56
+ }
57
+
58
+ CUDA_CHECK(cudaSetDevice(device_id));
59
+
60
+ cudaDeviceProp prop;
61
+ CUDA_CHECK(cudaGetDeviceProperties(&prop, device_id));
62
+ if (prop.major < 8) {
63
+ std::cerr << "[CUDA WARNING] GPU Compute Capability " << prop.major
64
+ << "." << prop.minor << " < 8.0 (Ampere required)" << std::endl;
65
+ return false;
66
+ }
67
+
68
+ CUDA_CHECK(cudaStreamCreate(&stream_));
69
+ CUBLAS_CHECK(cublasCreate(&cublas_handle_));
70
+ CUBLAS_CHECK(cublasSetStream(cublas_handle_, stream_));
71
+
72
+ device_id_ = device_id;
73
+ initialized_ = true;
74
+
75
+ std::cerr << "[CUDA] Initialized on " << prop.name
76
+ << " (CC " << prop.major << "." << prop.minor
77
+ << ", " << prop.totalGlobalMem / (1024*1024) << " MB)" << std::endl;
78
+ return true;
79
+ }
80
+
81
+ void finalize() {
82
+ if (!initialized_) return;
83
+ CUBLAS_CHECK(cublasDestroy(cublas_handle_));
84
+ CUDA_CHECK(cudaStreamDestroy(stream_));
85
+ initialized_ = false;
86
+ device_id_ = -1;
87
+ }
88
+
89
+ void sgemm(bool transA, bool transB,
90
+ int M, int N, int K,
91
+ float alpha, const float* d_A, int lda,
92
+ const float* d_B, int ldb,
93
+ float beta, float* d_C, int ldc) {
94
+ cublasOperation_t opA = transA ? CUBLAS_OP_T : CUBLAS_OP_N;
95
+ cublasOperation_t opB = transB ? CUBLAS_OP_T : CUBLAS_OP_N;
96
+ CUBLAS_CHECK(cublasSgemm(cublas_handle_, opA, opB,
97
+ M, N, K, &alpha, d_A, lda, d_B, ldb, &beta, d_C, ldc));
98
+ }
99
+
100
+ void sgemm_rowmajor(bool transA, bool transB,
101
+ int M, int N, int K,
102
+ float alpha, const float* d_A, int lda,
103
+ const float* d_B, int ldb,
104
+ float beta, float* d_C, int ldc) {
105
+ cublasOperation_t opA = transB ? CUBLAS_OP_T : CUBLAS_OP_N;
106
+ cublasOperation_t opB = transA ? CUBLAS_OP_T : CUBLAS_OP_N;
107
+ CUBLAS_CHECK(cublasSgemm(cublas_handle_, opA, opB,
108
+ N, M, K, &alpha, d_B, ldb, d_A, lda, &beta, d_C, ldc));
109
+ }
110
+
111
+ void* alloc(size_t bytes) {
112
+ void* d_ptr = nullptr;
113
+ CUDA_CHECK(cudaMalloc(&d_ptr, bytes));
114
+ return d_ptr;
115
+ }
116
+
117
+ void free(void* d_ptr) {
118
+ if (d_ptr) CUDA_CHECK(cudaFree(d_ptr));
119
+ }
120
+
121
+ void copy_h2d(void* dst, const void* src, size_t bytes) {
122
+ CUDA_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyHostToDevice, stream_));
123
+ }
124
+
125
+ void copy_d2h(void* dst, const void* src, size_t bytes) {
126
+ CUDA_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyDeviceToHost, stream_));
127
+ }
128
+
129
+ void copy_d2d(void* dst, const void* src, size_t bytes) {
130
+ CUDA_CHECK(cudaMemcpyAsync(dst, src, bytes, cudaMemcpyDeviceToDevice, stream_));
131
+ }
132
+
133
+ void synchronize() {
134
+ CUDA_CHECK(cudaStreamSynchronize(stream_));
135
+ }
136
+
137
+ bool is_available() const { return initialized_; }
138
+
139
+ size_t free_memory() const {
140
+ if (!initialized_) return 0;
141
+ size_t free = 0, total = 0;
142
+ CUDA_CHECK(cudaMemGetInfo(&free, &total));
143
+ return free;
144
+ }
145
+
146
+ size_t total_memory() const {
147
+ if (!initialized_) return 0;
148
+ size_t free = 0, total = 0;
149
+ CUDA_CHECK(cudaMemGetInfo(&free, &total));
150
+ return total;
151
+ }
152
+
153
+ cudaStream_t stream() const { return stream_; }
154
+ cublasHandle_t cublas_handle() const { return cublas_handle_; }
155
+
156
+ private:
157
+ CudaContext() = default;
158
+ ~CudaContext() { finalize(); }
159
+ CudaContext(const CudaContext&) = delete;
160
+ CudaContext& operator=(const CudaContext&) = delete;
161
+
162
+ cublasHandle_t cublas_handle_ = nullptr;
163
+ cudaStream_t stream_ = nullptr;
164
+ bool initialized_ = false;
165
+ int device_id_ = -1;
166
+ };
167
+
168
+ } // namespace neuroflow
169
+
170
+ #endif // USE_CUDA
171
+ #endif // NEUROFLOW_CUDA_CONTEXT_HPP
include/neuroflow/cuda_kernels.hpp ADDED
@@ -0,0 +1,1152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_CUDA_KERNELS_HPP
2
+ #define NEUROFLOW_CUDA_KERNELS_HPP
3
+
4
+ #ifdef USE_CUDA
5
+
6
+ #include <cstddef>
7
+ #include <cstdio>
8
+ #include <cmath>
9
+ #include <cuda_runtime.h>
10
+ #include "cuda_context.hpp"
11
+
12
+ namespace neuroflow {
13
+
14
+ __device__ inline void safe_atomic_max_float(float* addr, float val) {
15
+ unsigned int old = atomicCAS(reinterpret_cast<unsigned int*>(addr),
16
+ __float_as_uint(val),
17
+ __float_as_uint(val));
18
+ while (val > __uint_as_float(old)) {
19
+ unsigned int assumed = old;
20
+ old = atomicCAS(reinterpret_cast<unsigned int*>(addr),
21
+ assumed,
22
+ __float_as_uint(val));
23
+ if (old == assumed) break;
24
+ }
25
+ }
26
+
27
+ // ═══════════════════════════════════════════════════════
28
+ // CUDA Kernel 实现
29
+ // ═══════════════════════════════════════════════════════
30
+
31
+ // --- GELU ---
32
+ __global__ void kernel_gelu_impl(float* data, size_t n) {
33
+ const float SQRT_2_PI = 0.7978845608f;
34
+ const float COEFF = 0.044715f;
35
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
36
+ if (idx >= n) return;
37
+ float v = data[idx];
38
+ float inner = SQRT_2_PI * (v + COEFF * v * v * v);
39
+ data[idx] = 0.5f * v * (1.0f + tanhf(inner));
40
+ }
41
+
42
+ inline void launch_gelu(float* d_data, size_t n, cudaStream_t stream) {
43
+ int block = 256;
44
+ int grid = (n + block - 1) / block;
45
+ kernel_gelu_impl<<<grid, block, 0, stream>>>(d_data, n);
46
+ }
47
+
48
+ // --- Sigmoid ---
49
+ __global__ void kernel_sigmoid_impl(float* data, size_t n) {
50
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
51
+ if (idx >= n) return;
52
+ data[idx] = 1.0f / (1.0f + expf(-data[idx]));
53
+ }
54
+
55
+ inline void launch_sigmoid(float* d_data, size_t n, cudaStream_t stream) {
56
+ int block = 256;
57
+ int grid = (n + block - 1) / block;
58
+ kernel_sigmoid_impl<<<grid, block, 0, stream>>>(d_data, n);
59
+ }
60
+
61
+ // --- Element-wise Add (residual) ---
62
+ __global__ void kernel_add_impl(float* out, const float* a, const float* b, size_t n) {
63
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
64
+ if (idx >= n) return;
65
+ out[idx] = a[idx] + b[idx];
66
+ }
67
+
68
+ inline void launch_add(float* d_out, const float* d_a, const float* d_b, size_t n, cudaStream_t stream) {
69
+ int block = 256;
70
+ int grid = (n + block - 1) / block;
71
+ kernel_add_impl<<<grid, block, 0, stream>>>(d_out, d_a, d_b, n);
72
+ }
73
+
74
+ // --- Scale + Add ---
75
+ __global__ void kernel_scale_add_impl(float* out, const float* a, float scale, const float* b, size_t n) {
76
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
77
+ if (idx >= n) return;
78
+ out[idx] = a[idx] * scale + b[idx];
79
+ }
80
+
81
+ inline void launch_scale_add(float* d_out, const float* d_a, float scale, const float* d_b, size_t n, cudaStream_t stream) {
82
+ int block = 256;
83
+ int grid = (n + block - 1) / block;
84
+ kernel_scale_add_impl<<<grid, block, 0, stream>>>(d_out, d_a, scale, d_b, n);
85
+ }
86
+
87
+ // --- Bias Add ---
88
+ __global__ void kernel_bias_add_impl(float* out, const float* bias, int rows, int cols) {
89
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
90
+ int total = rows * cols;
91
+ if (idx >= total) return;
92
+ int j = idx % cols;
93
+ out[idx] += bias[j];
94
+ }
95
+
96
+ inline void launch_bias_add(float* d_out, const float* d_bias, int rows, int cols, cudaStream_t stream) {
97
+ int block = 256;
98
+ int total = rows * cols;
99
+ int grid = (total + block - 1) / block;
100
+ kernel_bias_add_impl<<<grid, block, 0, stream>>>(d_out, d_bias, rows, cols);
101
+ }
102
+
103
+ // --- Softmax (online, per-row) ---
104
+ __global__ void kernel_softmax_impl(float* data, int rows, int cols) {
105
+ int row = blockIdx.x;
106
+ if (row >= rows) return;
107
+ float* row_data = data + row * cols;
108
+
109
+ float max_val = -1e30f;
110
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
111
+ max_val = fmaxf(max_val, row_data[j]);
112
+ }
113
+ __shared__ float s_max;
114
+ if (threadIdx.x == 0) s_max = -1e30f;
115
+ __syncthreads();
116
+ safe_atomic_max_float(&s_max, max_val);
117
+ __syncthreads();
118
+ max_val = s_max;
119
+
120
+ float sum = 0.0f;
121
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
122
+ row_data[j] = expf(row_data[j] - max_val);
123
+ sum += row_data[j];
124
+ }
125
+ __shared__ float s_sum;
126
+ if (threadIdx.x == 0) s_sum = 0.0f;
127
+ __syncthreads();
128
+ atomicAdd(&s_sum, sum);
129
+ __syncthreads();
130
+
131
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
132
+ row_data[j] /= s_sum;
133
+ }
134
+ }
135
+
136
+ inline void launch_softmax(float* d_data, int rows, int cols, cudaStream_t stream) {
137
+ kernel_softmax_impl<<<rows, 256, 0, stream>>>(d_data, rows, cols);
138
+ }
139
+
140
+ // --- Causal Softmax (per-row, zero out j > i) ---
141
+ __global__ void kernel_causal_softmax_impl(float* data, int seq_len) {
142
+ int i = blockIdx.x;
143
+ if (i >= seq_len) return;
144
+ float* row = data + i * seq_len;
145
+
146
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
147
+ // keep
148
+ }
149
+ // Zero future positions
150
+ for (int j = i + 1 + threadIdx.x; j < seq_len; j += blockDim.x) {
151
+ row[j] = 0.0f;
152
+ }
153
+ __syncthreads();
154
+
155
+ float max_val = -1e30f;
156
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
157
+ max_val = fmaxf(max_val, row[j]);
158
+ }
159
+ __shared__ float s_max;
160
+ if (threadIdx.x == 0) s_max = -1e30f;
161
+ __syncthreads();
162
+ safe_atomic_max_float(&s_max, max_val);
163
+ __syncthreads();
164
+ max_val = s_max;
165
+
166
+ float sum = 0.0f;
167
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
168
+ row[j] = expf(row[j] - max_val);
169
+ sum += row[j];
170
+ }
171
+ __shared__ float s_sum;
172
+ if (threadIdx.x == 0) s_sum = 0.0f;
173
+ __syncthreads();
174
+ atomicAdd(&s_sum, sum);
175
+ __syncthreads();
176
+
177
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
178
+ row[j] /= s_sum;
179
+ }
180
+ }
181
+
182
+ inline void launch_causal_softmax(float* d_data, int seq_len, cudaStream_t stream) {
183
+ kernel_causal_softmax_impl<<<seq_len, 256, 0, stream>>>(d_data, seq_len);
184
+ }
185
+
186
+ // --- LayerNorm Forward ---
187
+ __global__ void kernel_layer_norm_impl(float* out, const float* inp, const float* w, const float* b, int rows, int cols, float eps) {
188
+ int row = blockIdx.x;
189
+ if (row >= rows) return;
190
+ const float* row_in = inp + row * cols;
191
+ float* row_out = out + row * cols;
192
+
193
+ float mean = 0.0f;
194
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
195
+ mean += row_in[j];
196
+ }
197
+ __shared__ float s_mean;
198
+ if (threadIdx.x == 0) s_mean = 0.0f;
199
+ __syncthreads();
200
+ atomicAdd(&s_mean, mean);
201
+ __syncthreads();
202
+ mean = s_mean / cols;
203
+
204
+ float var = 0.0f;
205
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
206
+ float diff = row_in[j] - mean;
207
+ var += diff * diff;
208
+ }
209
+ __shared__ float s_var;
210
+ if (threadIdx.x == 0) s_var = 0.0f;
211
+ __syncthreads();
212
+ atomicAdd(&s_var, var);
213
+ __syncthreads();
214
+ var = s_var / cols;
215
+
216
+ float inv_std = 1.0f / sqrtf(var + eps);
217
+ for (int j = threadIdx.x; j < cols; j += blockDim.x) {
218
+ float norm = (row_in[j] - mean) * inv_std;
219
+ row_out[j] = w[j] * norm + b[j];
220
+ }
221
+ }
222
+
223
+ inline void launch_layer_norm(float* d_out, const float* d_inp, const float* d_w, const float* d_b, int rows, int cols, float eps, cudaStream_t stream) {
224
+ kernel_layer_norm_impl<<<rows, 256, 0, stream>>>(d_out, d_inp, d_w, d_b, rows, cols, eps);
225
+ }
226
+
227
+ // --- Embed Lookup ---
228
+ __global__ void kernel_embed_lookup_impl(float* out, const float* embed, const int* token_ids, int seq_len, int d_model, float scale) {
229
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
230
+ int total = seq_len * d_model;
231
+ if (idx >= total) return;
232
+ int i = idx / d_model;
233
+ int d = idx % d_model;
234
+ int tid = token_ids[i];
235
+ out[idx] = embed[tid * d_model + d] * scale;
236
+ }
237
+
238
+ inline void launch_embed_lookup(float* d_out, const float* d_embed, const int* d_token_ids, int seq_len, int d_model, float scale, cudaStream_t stream) {
239
+ int total = seq_len * d_model;
240
+ int block = 256;
241
+ int grid = (total + block - 1) / block;
242
+ kernel_embed_lookup_impl<<<grid, block, 0, stream>>>(d_out, d_embed, d_token_ids, seq_len, d_model, scale);
243
+ }
244
+
245
+ // --- Positional Encode (add) ---
246
+ __global__ void kernel_positional_encode_impl(float* out, const float* pos_enc, int seq_len, int d_model, int offset) {
247
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
248
+ int total = seq_len * d_model;
249
+ if (idx >= total) return;
250
+ int i = idx / d_model;
251
+ int d = idx % d_model;
252
+ int p = offset + i;
253
+ out[idx] += pos_enc[p * d_model + d];
254
+ }
255
+
256
+ inline void launch_positional_encode(float* d_out, const float* d_pos_enc, int seq_len, int d_model, int offset, cudaStream_t stream) {
257
+ int total = seq_len * d_model;
258
+ int block = 256;
259
+ int grid = (total + block - 1) / block;
260
+ kernel_positional_encode_impl<<<grid, block, 0, stream>>>(d_out, d_pos_enc, seq_len, d_model, offset);
261
+ }
262
+
263
+ // --- SGD Update ---
264
+ __global__ void kernel_sgd_update_impl(float* param, const float* grad, size_t n, float lr) {
265
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
266
+ if (idx >= n) return;
267
+ float g = grad[idx];
268
+ if (isfinite(g)) {
269
+ param[idx] -= lr * g;
270
+ }
271
+ }
272
+
273
+ inline void launch_sgd_update(float* d_param, const float* d_grad, size_t n, float lr, cudaStream_t stream) {
274
+ int block = 256;
275
+ int grid = (static_cast<int>(n) + block - 1) / block;
276
+ kernel_sgd_update_impl<<<grid, block, 0, stream>>>(d_param, d_grad, n, lr);
277
+ }
278
+
279
+ // --- Sparse Embed Update ---
280
+ __global__ void kernel_sparse_embed_update_impl(float* embed, const float* grad, const int* token_ids, int seq_len, int d_model, float lr) {
281
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
282
+ int total = seq_len * d_model;
283
+ if (idx >= total) return;
284
+ int i = idx / d_model;
285
+ int d = idx % d_model;
286
+ int tid = token_ids[i];
287
+ float g = grad[i * d_model + d];
288
+ if (isfinite(g)) {
289
+ atomicAdd(&embed[tid * d_model + d], -lr * g);
290
+ }
291
+ }
292
+
293
+ inline void launch_sparse_embed_update(float* d_embed, const float* d_grad, const int* d_token_ids, int seq_len, int d_model, float lr, cudaStream_t stream) {
294
+ int total = seq_len * d_model;
295
+ int block = 256;
296
+ int grid = (total + block - 1) / block;
297
+ kernel_sparse_embed_update_impl<<<grid, block, 0, stream>>>(d_embed, d_grad, d_token_ids, seq_len, d_model, lr);
298
+ }
299
+
300
+ // --- Cross Entropy Forward (returns loss on GPU) ---
301
+ __global__ void kernel_cross_entropy_impl(float* loss, const float* logits, int target_id, int vocab_size) {
302
+ __shared__ float s_max;
303
+ __shared__ float s_sum;
304
+
305
+ float local_max = -1e30f;
306
+ for (int j = threadIdx.x; j < vocab_size; j += blockDim.x) {
307
+ local_max = fmaxf(local_max, logits[j]);
308
+ }
309
+ if (threadIdx.x == 0) s_max = -1e30f;
310
+ __syncthreads();
311
+ safe_atomic_max_float(&s_max, local_max);
312
+ __syncthreads();
313
+
314
+ float local_sum = 0.0f;
315
+ for (int j = threadIdx.x; j < vocab_size; j += blockDim.x) {
316
+ local_sum += expf(logits[j] - s_max);
317
+ }
318
+ if (threadIdx.x == 0) s_sum = 0.0f;
319
+ __syncthreads();
320
+ atomicAdd(&s_sum, local_sum);
321
+ __syncthreads();
322
+
323
+ if (threadIdx.x == 0) {
324
+ float log_sum_exp = s_max + logf(s_sum);
325
+ *loss = -(logits[target_id] - log_sum_exp);
326
+ }
327
+ }
328
+
329
+ inline void launch_cross_entropy(float* d_loss, const float* d_logits, int target_id, int vocab_size, cudaStream_t stream) {
330
+ kernel_cross_entropy_impl<<<1, 256, 0, stream>>>(d_loss, d_logits, target_id, vocab_size);
331
+ }
332
+
333
+ // --- Cross Entropy Backward (softmax - one_hot) ---
334
+ __global__ void kernel_cross_entropy_backward_impl(float* grad, const float* logits, int target_id, int vocab_size) {
335
+ __shared__ float s_max;
336
+ __shared__ float s_sum;
337
+
338
+ float local_max = -1e30f;
339
+ for (int j = threadIdx.x; j < vocab_size; j += blockDim.x) {
340
+ local_max = fmaxf(local_max, logits[j]);
341
+ }
342
+ if (threadIdx.x == 0) s_max = -1e30f;
343
+ __syncthreads();
344
+ safe_atomic_max_float(&s_max, local_max);
345
+ __syncthreads();
346
+
347
+ float local_sum = 0.0f;
348
+ for (int j = threadIdx.x; j < vocab_size; j += blockDim.x) {
349
+ float val = expf(logits[j] - s_max);
350
+ local_sum += val;
351
+ }
352
+ if (threadIdx.x == 0) s_sum = 0.0f;
353
+ __syncthreads();
354
+ atomicAdd(&s_sum, local_sum);
355
+ __syncthreads();
356
+
357
+ for (int j = threadIdx.x; j < vocab_size; j += blockDim.x) {
358
+ float softmax_val = expf(logits[j] - s_max) / s_sum;
359
+ grad[j] = softmax_val;
360
+ if (j == target_id) grad[j] -= 1.0f;
361
+ }
362
+ }
363
+
364
+ inline void launch_cross_entropy_backward(float* d_grad, const float* d_logits, int target_id, int vocab_size, cudaStream_t stream) {
365
+ kernel_cross_entropy_backward_impl<<<1, 256, 0, stream>>>(d_grad, d_logits, target_id, vocab_size);
366
+ }
367
+
368
+ // --- Mean Pool ---
369
+ __global__ void kernel_mean_pool_impl(float* out, const float* inp, int seq_len, int d_model) {
370
+ int d = blockIdx.x * blockDim.x + threadIdx.x;
371
+ if (d >= d_model) return;
372
+ float sum = 0.0f;
373
+ for (int i = 0; i < seq_len; ++i) {
374
+ sum += inp[i * d_model + d];
375
+ }
376
+ out[d] = sum / seq_len;
377
+ }
378
+
379
+ inline void launch_mean_pool(float* d_out, const float* d_inp, int seq_len, int d_model, cudaStream_t stream) {
380
+ int block = 256;
381
+ int grid = (d_model + block - 1) / block;
382
+ kernel_mean_pool_impl<<<grid, block, 0, stream>>>(d_out, d_inp, seq_len, d_model);
383
+ }
384
+
385
+ // --- Last Token Pool ---
386
+ __global__ void kernel_last_token_pool_impl(float* out, const float* inp, int seq_len, int d_model) {
387
+ int d = blockIdx.x * blockDim.x + threadIdx.x;
388
+ if (d >= d_model) return;
389
+ out[d] = inp[(seq_len - 1) * d_model + d];
390
+ }
391
+
392
+ inline void launch_last_token_pool(float* d_out, const float* d_inp, int seq_len, int d_model, cudaStream_t stream) {
393
+ int block = 256;
394
+ int grid = (d_model + block - 1) / block;
395
+ kernel_last_token_pool_impl<<<grid, block, 0, stream>>>(d_out, d_inp, seq_len, d_model);
396
+ }
397
+
398
+ // --- Fill Zero ---
399
+ __global__ void kernel_fill_zero_impl(float* data, size_t n) {
400
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
401
+ if (idx >= n) return;
402
+ data[idx] = 0.0f;
403
+ }
404
+
405
+ inline void launch_fill_zero(float* d_data, size_t n, cudaStream_t stream) {
406
+ int block = 256;
407
+ int grid = (static_cast<int>(n) + block - 1) / block;
408
+ kernel_fill_zero_impl<<<grid, block, 0, stream>>>(d_data, n);
409
+ }
410
+
411
+ // --- Causal Mask Zero (zero out j > i in [seq_len, seq_len]) ---
412
+ __global__ void kernel_causal_mask_zero_impl(float* data, int seq_len) {
413
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
414
+ int total = seq_len * seq_len;
415
+ if (idx >= total) return;
416
+ int i = idx / seq_len;
417
+ int j = idx % seq_len;
418
+ if (j > i) data[idx] = 0.0f;
419
+ }
420
+
421
+ inline void launch_causal_mask_zero(float* d_data, int seq_len, cudaStream_t stream) {
422
+ int total = seq_len * seq_len;
423
+ int block = 256;
424
+ int grid = (total + block - 1) / block;
425
+ kernel_causal_mask_zero_impl<<<grid, block, 0, stream>>>(d_data, seq_len);
426
+ }
427
+
428
+ // --- Scatter QKV gradients ---
429
+ __global__ void kernel_scatter_qkv_impl(float* d_qkv, const float* d_q, const float* d_k, const float* d_v,
430
+ int seq_len, int d_model, int head_dim, int n_heads, int h) {
431
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
432
+ int total = seq_len * head_dim;
433
+ if (idx >= total) return;
434
+ int i = idx / head_dim;
435
+ int d = idx % head_dim;
436
+ size_t q_off = h * head_dim;
437
+ size_t k_off = d_model + h * head_dim;
438
+ size_t v_off = 2 * d_model + h * head_dim;
439
+ d_qkv[i * 3 * d_model + q_off + d] += d_q[i * head_dim + d];
440
+ d_qkv[i * 3 * d_model + k_off + d] += d_k[i * head_dim + d];
441
+ d_qkv[i * 3 * d_model + v_off + d] += d_v[i * head_dim + d];
442
+ }
443
+
444
+ inline void launch_scatter_qkv(float* d_qkv, const float* d_q, const float* d_k, const float* d_v,
445
+ int seq_len, int d_model, int head_dim, int n_heads, int h, cudaStream_t stream) {
446
+ int total = seq_len * head_dim;
447
+ int block = 256;
448
+ int grid = (total + block - 1) / block;
449
+ kernel_scatter_qkv_impl<<<grid, block, 0, stream>>>(d_qkv, d_q, d_k, d_v, seq_len, d_model, head_dim, n_heads, h);
450
+ }
451
+
452
+ // --- Softmax Backward (for attention) ---
453
+ __global__ void kernel_softmax_backward_impl(float* d_scores, const float* attn_weights, const float* d_attn_weights,
454
+ int seq_len, float inv_scale) {
455
+ int i = blockIdx.x;
456
+ if (i >= seq_len) return;
457
+ const float* aw_row = attn_weights + i * seq_len;
458
+ const float* daw_row = d_attn_weights + i * seq_len;
459
+ float* ds_row = d_scores + i * seq_len;
460
+
461
+ float dot = 0.0f;
462
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
463
+ dot += aw_row[j] * daw_row[j];
464
+ }
465
+ __shared__ float s_dot;
466
+ if (threadIdx.x == 0) s_dot = 0.0f;
467
+ __syncthreads();
468
+ atomicAdd(&s_dot, dot);
469
+ __syncthreads();
470
+
471
+ for (int j = threadIdx.x; j <= i; j += blockDim.x) {
472
+ ds_row[j] = aw_row[j] * (daw_row[j] - s_dot) * inv_scale;
473
+ }
474
+ for (int j = i + 1 + threadIdx.x; j < seq_len; j += blockDim.x) {
475
+ ds_row[j] = 0.0f;
476
+ }
477
+ }
478
+
479
+ inline void launch_softmax_backward(float* d_scores, const float* d_attn_weights, const float* d_daw,
480
+ int seq_len, float inv_scale, cudaStream_t stream) {
481
+ kernel_softmax_backward_impl<<<seq_len, 256, 0, stream>>>(d_scores, d_attn_weights, d_daw, seq_len, inv_scale);
482
+ }
483
+
484
+ // --- LayerNorm Backward ---
485
+ __global__ void kernel_layer_norm_backward_impl(float* input_grad, const float* input, const float* weight,
486
+ const float* output_grad, int rows, int cols, float eps) {
487
+ int row = blockIdx.x;
488
+ if (row >= rows) return;
489
+ const float* inp_row = input + row * cols;
490
+ const float* og_row = output_grad + row * cols;
491
+ float* ig_row = input_grad + row * cols;
492
+
493
+ float mean = 0.0f;
494
+ for (int d = threadIdx.x; d < cols; d += blockDim.x) mean += inp_row[d];
495
+ __shared__ float s_mean;
496
+ if (threadIdx.x == 0) s_mean = 0.0f;
497
+ __syncthreads();
498
+ atomicAdd(&s_mean, mean);
499
+ __syncthreads();
500
+ mean = s_mean / cols;
501
+
502
+ float var = 0.0f;
503
+ for (int d = threadIdx.x; d < cols; d += blockDim.x) {
504
+ float diff = inp_row[d] - mean;
505
+ var += diff * diff;
506
+ }
507
+ __shared__ float s_var;
508
+ if (threadIdx.x == 0) s_var = 0.0f;
509
+ __syncthreads();
510
+ atomicAdd(&s_var, var);
511
+ __syncthreads();
512
+ var = s_var / cols;
513
+
514
+ float inv_std = 1.0f / sqrtf(var + eps);
515
+
516
+ float sum_gn = 0.0f, sum_gnx = 0.0f;
517
+ for (int d = threadIdx.x; d < cols; d += blockDim.x) {
518
+ float norm = (inp_row[d] - mean) * inv_std;
519
+ float gn = og_row[d] * weight[d];
520
+ sum_gn += gn;
521
+ sum_gnx += gn * norm;
522
+ }
523
+ __shared__ float s_sum_gn;
524
+ __shared__ float s_sum_gnx;
525
+ if (threadIdx.x == 0) { s_sum_gn = 0.0f; s_sum_gnx = 0.0f; }
526
+ __syncthreads();
527
+ atomicAdd(&s_sum_gn, sum_gn);
528
+ atomicAdd(&s_sum_gnx, sum_gnx);
529
+ __syncthreads();
530
+
531
+ for (int d = threadIdx.x; d < cols; d += blockDim.x) {
532
+ float norm = (inp_row[d] - mean) * inv_std;
533
+ float gn = og_row[d] * weight[d];
534
+ ig_row[d] = inv_std * (gn - s_sum_gn / cols - norm * s_sum_gnx / cols);
535
+ }
536
+ }
537
+
538
+ inline void launch_layer_norm_backward(float* d_input_grad, const float* d_input, const float* d_weight,
539
+ const float* d_output_grad, int rows, int cols, float eps, cudaStream_t stream) {
540
+ kernel_layer_norm_backward_impl<<<rows, 256, 0, stream>>>(d_input_grad, d_input, d_weight, d_output_grad, rows, cols, eps);
541
+ }
542
+
543
+ // --- Pool Backward (mean) ---
544
+ __global__ void kernel_mean_pool_backward_impl(float* x_grad, const float* pooled_grad, int seq_len, int d_model) {
545
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
546
+ int total = seq_len * d_model;
547
+ if (idx >= total) return;
548
+ int d = idx % d_model;
549
+ float inv_n = 1.0f / static_cast<float>(seq_len);
550
+ x_grad[idx] = pooled_grad[d] * inv_n;
551
+ }
552
+
553
+ inline void launch_mean_pool_backward(float* d_x_grad, const float* d_pooled_grad, int seq_len, int d_model, cudaStream_t stream) {
554
+ int total = seq_len * d_model;
555
+ int block = 256;
556
+ int grid = (total + block - 1) / block;
557
+ kernel_mean_pool_backward_impl<<<grid, block, 0, stream>>>(d_x_grad, d_pooled_grad, seq_len, d_model);
558
+ }
559
+
560
+ // --- Bias Backward ---
561
+ __global__ void kernel_bias_backward_impl(float* bias_grad, const float* output_grad, int batch, int dim) {
562
+ int j = blockIdx.x * blockDim.x + threadIdx.x;
563
+ if (j >= dim) return;
564
+ float sum = 0.0f;
565
+ for (int b = 0; b < batch; ++b) {
566
+ sum += output_grad[b * dim + j];
567
+ }
568
+ bias_grad[j] = sum / batch;
569
+ }
570
+
571
+ inline void launch_bias_backward(float* d_bias_grad, const float* d_output_grad, int batch, int dim, cudaStream_t stream) {
572
+ int block = 256;
573
+ int grid = (dim + block - 1) / block;
574
+ kernel_bias_backward_impl<<<grid, block, 0, stream>>>(d_bias_grad, d_output_grad, batch, dim);
575
+ }
576
+
577
+ // --- Sigmoid Backward (for causal gate) ---
578
+ __global__ void kernel_sigmoid_backward_impl(float* gate_grad, const float* gate_output, const float* input, const float* x_grad, size_t n) {
579
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
580
+ if (idx >= n) return;
581
+ float g = gate_output[idx];
582
+ float sig = 1.0f / (1.0f + expf(-g));
583
+ gate_grad[idx] = x_grad[idx] * sig * (1.0f - sig) * input[idx] + x_grad[idx] * sig;
584
+ }
585
+
586
+ inline void launch_sigmoid_backward(float* d_gate_grad, const float* d_gate_output, const float* d_input, const float* d_x_grad, size_t n, cudaStream_t stream) {
587
+ int block = 256;
588
+ int grid = (static_cast<int>(n) + block - 1) / block;
589
+ kernel_sigmoid_backward_impl<<<grid, block, 0, stream>>>(d_gate_grad, d_gate_output, d_input, d_x_grad, n);
590
+ }
591
+
592
+ // --- Extract per-head Q, K, V from QKV ---
593
+ __global__ void kernel_extract_qkv_impl(float* Q_h, float* K_h, float* V_h,
594
+ const float* qkv, int seq_len, int d_model, int head_dim, int h) {
595
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
596
+ int total = seq_len * head_dim;
597
+ if (idx >= total) return;
598
+ int i = idx / head_dim;
599
+ int d = idx % head_dim;
600
+ size_t q_off = h * head_dim;
601
+ size_t k_off = d_model + h * head_dim;
602
+ size_t v_off = 2 * d_model + h * head_dim;
603
+ Q_h[i * head_dim + d] = qkv[i * 3 * d_model + q_off + d];
604
+ K_h[i * head_dim + d] = qkv[i * 3 * d_model + k_off + d];
605
+ V_h[i * head_dim + d] = qkv[i * 3 * d_model + v_off + d];
606
+ }
607
+
608
+ inline void launch_extract_qkv(float* d_Q_h, float* d_K_h, float* d_V_h,
609
+ const float* d_qkv, int seq_len, int d_model, int head_dim, int h, cudaStream_t stream) {
610
+ int total = seq_len * head_dim;
611
+ int block = 256;
612
+ int grid = (total + block - 1) / block;
613
+ kernel_extract_qkv_impl<<<grid, block, 0, stream>>>(d_Q_h, d_K_h, d_V_h, d_qkv, seq_len, d_model, head_dim, h);
614
+ }
615
+
616
+ __global__ void kernel_extract_head_impl(float* out, const float* src, int seq_len, int n_heads, int head_dim, int h) {
617
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
618
+ int total = seq_len * head_dim;
619
+ if (idx >= total) return;
620
+ int i = idx / head_dim;
621
+ int d = idx % head_dim;
622
+ out[i * head_dim + d] = src[i * n_heads * head_dim + h * head_dim + d];
623
+ }
624
+
625
+ inline void launch_extract_head(float* out, const float* src, int seq_len, int n_heads, int head_dim, int h, cudaStream_t stream) {
626
+ int total = seq_len * head_dim;
627
+ int block = 256;
628
+ int grid = (total + block - 1) / block;
629
+ kernel_extract_head_impl<<<grid, block, 0, stream>>>(out, src, seq_len, n_heads, head_dim, h);
630
+ }
631
+
632
+ // --- Extract per-head attn_out_grad ---
633
+ __global__ void kernel_extract_attn_out_grad_impl(float* aog_h, const float* aog, int seq_len, int d_model, int head_dim, int h) {
634
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
635
+ int total = seq_len * head_dim;
636
+ if (idx >= total) return;
637
+ int i = idx / head_dim;
638
+ int d = idx % head_dim;
639
+ aog_h[i * head_dim + d] = aog[i * d_model + h * head_dim + d];
640
+ }
641
+
642
+ inline void launch_extract_attn_out_grad(float* d_aog_h, const float* d_aog, int seq_len, int d_model, int head_dim, int h, cudaStream_t stream) {
643
+ int total = seq_len * head_dim;
644
+ int block = 256;
645
+ int grid = (total + block - 1) / block;
646
+ kernel_extract_attn_out_grad_impl<<<grid, block, 0, stream>>>(d_aog_h, d_aog, seq_len, d_model, head_dim, h);
647
+ }
648
+
649
+ // --- NTM softmax (per-batch) ---
650
+ __global__ void kernel_ntm_softmax_impl(float* data, int batch, int slots) {
651
+ int b = blockIdx.x;
652
+ if (b >= batch) return;
653
+ float* row = data + b * slots;
654
+ float max_val = -1e30f;
655
+ for (int s = threadIdx.x; s < slots; s += blockDim.x) {
656
+ max_val = fmaxf(max_val, row[s]);
657
+ }
658
+ __shared__ float s_max;
659
+ if (threadIdx.x == 0) s_max = -1e30f;
660
+ __syncthreads();
661
+ safe_atomic_max_float(&s_max, max_val);
662
+ __syncthreads();
663
+
664
+ float sum = 0.0f;
665
+ for (int s = threadIdx.x; s < slots; s += blockDim.x) {
666
+ row[s] = expf(row[s] - s_max);
667
+ sum += row[s];
668
+ }
669
+ __shared__ float s_sum;
670
+ if (threadIdx.x == 0) s_sum = 0.0f;
671
+ __syncthreads();
672
+ atomicAdd(&s_sum, sum);
673
+ __syncthreads();
674
+
675
+ for (int s = threadIdx.x; s < slots; s += blockDim.x) {
676
+ row[s] /= s_sum;
677
+ }
678
+ }
679
+
680
+ inline void launch_ntm_softmax(float* d_data, int batch, int slots, cudaStream_t stream) {
681
+ kernel_ntm_softmax_impl<<<batch, 256, 0, stream>>>(d_data, batch, slots);
682
+ }
683
+
684
+ // --- NTM read content (read_weights @ memory) ---
685
+ __global__ void kernel_ntm_read_impl(float* read_content, const float* read_weights, const float* memory, int batch, int slots, int d_model) {
686
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
687
+ int total = batch * d_model;
688
+ if (idx >= total) return;
689
+ int b = idx / d_model;
690
+ int d = idx % d_model;
691
+ float val = 0.0f;
692
+ for (int s = 0; s < slots; ++s) {
693
+ val += read_weights[b * slots + s] * memory[s * d_model + d];
694
+ }
695
+ read_content[idx] = val;
696
+ }
697
+
698
+ inline void launch_ntm_read(float* d_read_content, const float* d_read_weights, const float* d_memory, int batch, int slots, int d_model, cudaStream_t stream) {
699
+ int total = batch * d_model;
700
+ int block = 256;
701
+ int grid = (total + block - 1) / block;
702
+ kernel_ntm_read_impl<<<grid, block, 0, stream>>>(d_read_content, d_read_weights, d_memory, batch, slots, d_model);
703
+ }
704
+
705
+ // --- NTM write (memory update) ---
706
+ __global__ void kernel_ntm_write_impl(float* memory, const float* read_weights, const float* erase, const float* write_val, int batch, int slots, int d_model) {
707
+ int s = blockIdx.x;
708
+ int d = threadIdx.x;
709
+ if (s >= slots || d >= d_model) return;
710
+ for (int b = 0; b < batch; ++b) {
711
+ float rw = read_weights[b * slots + s];
712
+ float e = 1.0f / (1.0f + expf(-erase[b * d_model + d]));
713
+ float w = tanhf(write_val[b * d_model + d]);
714
+ memory[s * d_model + d] = memory[s * d_model + d] * (1.0f - rw * e) + rw * w;
715
+ }
716
+ }
717
+
718
+ inline void launch_ntm_write(float* d_memory, const float* d_read_weights, const float* d_erase, const float* d_write_val, int batch, int slots, int d_model, cudaStream_t stream) {
719
+ kernel_ntm_write_impl<<<slots, d_model, 0, stream>>>(d_memory, d_read_weights, d_erase, d_write_val, batch, slots, d_model);
720
+ }
721
+
722
+ // --- SAE Top-K mask (bitonic sort approach for small n) ---
723
+ // Step 1: compute abs values into a temp buffer
724
+ // Step 2: bitonic sort to find the k-th largest absolute value (threshold)
725
+ // Step 3: zero out elements whose abs value < threshold
726
+
727
+ __global__ void kernel_sae_topk_mask_impl(float* data, size_t n, size_t k) {
728
+ // For small n (typical d_model=128), use single-block bitonic sort
729
+ // Each thread handles multiple elements if n > blockDim
730
+ extern __shared__ float s_abs[];
731
+
732
+ // Load abs values into shared memory
733
+ for (size_t i = threadIdx.x; i < n; i += blockDim.x) {
734
+ s_abs[i] = fabsf(data[i]);
735
+ }
736
+ __syncthreads();
737
+
738
+ // Bitonic sort descending in shared memory
739
+ for (size_t stage = 1; stage < n; stage *= 2) {
740
+ for (size_t step = stage; step >= 1; step /= 2) {
741
+ for (size_t i = threadIdx.x; i < n / 2; i += blockDim.x) {
742
+ size_t dir = ((i / stage) % 2) == 0 ? 1 : 0;
743
+ size_t pair = i ^ step;
744
+ if (pair > i && pair < n) {
745
+ float a = s_abs[i];
746
+ float b = s_abs[pair];
747
+ if ((dir && a < b) || (!dir && a > b)) {
748
+ s_abs[i] = b;
749
+ s_abs[pair] = a;
750
+ }
751
+ }
752
+ }
753
+ __syncthreads();
754
+ }
755
+ }
756
+
757
+ // k-th largest absolute value is at index k-1 (0-indexed)
758
+ float threshold = 0.0f;
759
+ if (k > 0 && k <= n) {
760
+ threshold = s_abs[k - 1];
761
+ }
762
+ __syncthreads();
763
+
764
+ // Zero out elements below threshold
765
+ for (size_t i = threadIdx.x; i < n; i += blockDim.x) {
766
+ if (fabsf(data[i]) < threshold) {
767
+ data[i] = 0.0f;
768
+ }
769
+ }
770
+ }
771
+
772
+ inline void launch_sae_topk_mask(float* d_data, size_t n, size_t k, cudaStream_t stream) {
773
+ int block = 256;
774
+ size_t shared_mem = n * sizeof(float);
775
+ kernel_sae_topk_mask_impl<<<1, block, shared_mem, stream>>>(d_data, n, k);
776
+ }
777
+
778
+ // --- SAE Top-K mask for backward (same logic but on grad, using cached encoded values) ---
779
+ __global__ void kernel_sae_topk_mask_backward_impl(float* grad, const float* encoded, size_t n, size_t k) {
780
+ extern __shared__ float s_abs[];
781
+
782
+ for (size_t i = threadIdx.x; i < n; i += blockDim.x) {
783
+ s_abs[i] = fabsf(encoded[i]);
784
+ }
785
+ __syncthreads();
786
+
787
+ for (size_t stage = 1; stage < n; stage *= 2) {
788
+ for (size_t step = stage; step >= 1; step /= 2) {
789
+ for (size_t i = threadIdx.x; i < n / 2; i += blockDim.x) {
790
+ size_t dir = ((i / stage) % 2) == 0 ? 1 : 0;
791
+ size_t pair = i ^ step;
792
+ if (pair > i && pair < n) {
793
+ float a = s_abs[i];
794
+ float b = s_abs[pair];
795
+ if ((dir && a < b) || (!dir && a > b)) {
796
+ s_abs[i] = b;
797
+ s_abs[pair] = a;
798
+ }
799
+ }
800
+ }
801
+ __syncthreads();
802
+ }
803
+ }
804
+
805
+ float threshold = 0.0f;
806
+ if (k > 0 && k <= n) {
807
+ threshold = s_abs[k - 1];
808
+ }
809
+ __syncthreads();
810
+
811
+ for (size_t i = threadIdx.x; i < n; i += blockDim.x) {
812
+ if (fabsf(encoded[i]) < threshold) {
813
+ grad[i] = 0.0f;
814
+ }
815
+ }
816
+ }
817
+
818
+ inline void launch_sae_topk_mask_backward(float* d_grad, const float* d_encoded, size_t n, size_t k, cudaStream_t stream) {
819
+ int block = 256;
820
+ size_t shared_mem = n * sizeof(float);
821
+ kernel_sae_topk_mask_backward_impl<<<1, block, shared_mem, stream>>>(d_grad, d_encoded, n, k);
822
+ }
823
+
824
+ // --- Gradient clipping (compute norm + scale) ---
825
+ // Returns total squared norm on GPU (single float)
826
+ __global__ void kernel_grad_norm_sq_impl(float* norm_sq, const float* const* grads, const size_t* sizes, int n_tensors) {
827
+ float local_sum = 0.0f;
828
+ for (int t = 0; t < n_tensors; ++t) {
829
+ const float* g = grads[t];
830
+ size_t sz = sizes[t];
831
+ for (size_t i = threadIdx.x; i < sz; i += blockDim.x) {
832
+ local_sum += g[i] * g[i];
833
+ }
834
+ }
835
+ __shared__ float s_sum;
836
+ if (threadIdx.x == 0) s_sum = 0.0f;
837
+ __syncthreads();
838
+ atomicAdd(&s_sum, local_sum);
839
+ __syncthreads();
840
+ if (threadIdx.x == 0) *norm_sq = s_sum;
841
+ }
842
+
843
+ // --- Scale multiple gradients by a single factor ---
844
+ __global__ void kernel_scale_grads_impl(float** grads, const size_t* sizes, int n_tensors, float scale) {
845
+ int t = blockIdx.y;
846
+ if (t >= n_tensors) return;
847
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
848
+ if (idx >= sizes[t]) return;
849
+ grads[t][idx] *= scale;
850
+ }
851
+
852
+ // --- SGD update with gradient clipping (fused: scale + update) ---
853
+ __global__ void kernel_sgd_update_clipped_impl(float* param, const float* grad, size_t n, float lr, float clip_scale) {
854
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
855
+ if (idx >= n) return;
856
+ float g = grad[idx] * clip_scale;
857
+ if (isfinite(g)) {
858
+ param[idx] -= lr * g;
859
+ }
860
+ }
861
+
862
+ inline void launch_sgd_update_clipped(float* d_param, const float* d_grad, size_t n, float lr, float clip_scale, cudaStream_t stream) {
863
+ int block = 256;
864
+ int grid = (static_cast<int>(n) + block - 1) / block;
865
+ kernel_sgd_update_clipped_impl<<<grid, block, 0, stream>>>(d_param, d_grad, n, lr, clip_scale);
866
+ }
867
+
868
+ // --- Padding Mask Generation ---
869
+ __global__ void kernel_padding_mask_impl(float* mask, const int* token_ids, int seq_len, int padding_id) {
870
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
871
+ if (idx >= seq_len) return;
872
+ mask[idx] = (token_ids[idx] == padding_id) ? 0.0f : 1.0f;
873
+ }
874
+
875
+ inline void launch_padding_mask(float* d_mask, const int* d_token_ids, int seq_len, int padding_id, cudaStream_t stream) {
876
+ int block = 256;
877
+ int grid = (seq_len + block - 1) / block;
878
+ kernel_padding_mask_impl<<<grid, block, 0, stream>>>(d_mask, d_token_ids, seq_len, padding_id);
879
+ }
880
+
881
+ // --- Fused Causal + Padding Mask (applied to attention scores before softmax) ---
882
+ // Sets attn_scores[i][j] = -inf if (j > i) OR (padding_mask[j] == 0)
883
+ __global__ void kernel_fused_causal_padding_mask_impl(float* attn_scores, const float* padding_mask,
884
+ int seq_len, int n_heads) {
885
+ int idx = blockIdx.x * blockDim.x + threadIdx.x;
886
+ int total = n_heads * seq_len * seq_len;
887
+ if (idx >= total) return;
888
+ int h = idx / (seq_len * seq_len);
889
+ int rem = idx % (seq_len * seq_len);
890
+ int i = rem / seq_len;
891
+ int j = rem % seq_len;
892
+ if (j > i || padding_mask[j] == 0.0f) {
893
+ attn_scores[idx] = -1e30f;
894
+ }
895
+ }
896
+
897
+ inline void launch_fused_causal_padding_mask(float* d_attn_scores, const float* d_padding_mask,
898
+ int seq_len, int n_heads, cudaStream_t stream) {
899
+ int total = n_heads * seq_len * seq_len;
900
+ int block = 256;
901
+ int grid = (total + block - 1) / block;
902
+ kernel_fused_causal_padding_mask_impl<<<grid, block, 0, stream>>>(d_attn_scores, d_padding_mask, seq_len, n_heads);
903
+ }
904
+
905
+
906
+ // --- GPU Top-K/Top-P Sampling ---
907
+ // Performs temperature scaling, top-k filtering, top-p filtering, softmax, and sampling
908
+ // entirely on GPU. Only the sampled token ID is copied back to CPU.
909
+ // Uses a simple deterministic pseudo-random based on block/thread index + seed.
910
+
911
+ __global__ void kernel_topk_topp_sampling_impl(
912
+ const float* d_logits, int* d_output_token,
913
+ int vocab_size, int top_k, float top_p, float temperature,
914
+ unsigned int seed, int num_candidates) {
915
+
916
+ extern __shared__ float smem[];
917
+
918
+ float* sm_scores = smem;
919
+ int* sm_indices = (int*)(sm_scores + num_candidates);
920
+
921
+ int tid = threadIdx.x;
922
+
923
+ for (int i = tid; i < num_candidates; ++i) {
924
+ sm_scores[i] = -1e30f;
925
+ sm_indices[i] = 0;
926
+ }
927
+ __syncthreads();
928
+
929
+ for (int i = tid; i < vocab_size; i += blockDim.x) {
930
+ float val = d_logits[i] / temperature;
931
+ if (val > sm_scores[num_candidates - 1]) {
932
+ int pos = num_candidates - 1;
933
+ while (pos > 0 && val > sm_scores[pos - 1]) {
934
+ sm_scores[pos] = sm_scores[pos - 1];
935
+ sm_indices[pos] = sm_indices[pos - 1];
936
+ pos--;
937
+ }
938
+ sm_scores[pos] = val;
939
+ sm_indices[pos] = i;
940
+ }
941
+ }
942
+ __syncthreads();
943
+
944
+ if (tid == 0) {
945
+ int k = min(top_k, vocab_size);
946
+ k = min(k, num_candidates);
947
+
948
+ float max_val = sm_scores[0];
949
+ float sum = 0.0f;
950
+ for (int i = 0; i < k; ++i) {
951
+ sm_scores[i] = expf(sm_scores[i] - max_val);
952
+ sum += sm_scores[i];
953
+ }
954
+ for (int i = 0; i < k; ++i) {
955
+ sm_scores[i] /= sum;
956
+ }
957
+
958
+ float cumulative = 0.0f;
959
+ int top_p_cutoff = k;
960
+ for (int i = 0; i < k; ++i) {
961
+ cumulative += sm_scores[i];
962
+ if (cumulative >= top_p) {
963
+ top_p_cutoff = i + 1;
964
+ break;
965
+ }
966
+ }
967
+
968
+ float renorm_sum = 0.0f;
969
+ for (int i = 0; i < top_p_cutoff; ++i) {
970
+ renorm_sum += sm_scores[i];
971
+ }
972
+
973
+ unsigned int rng_state = seed + blockIdx.x * 12345;
974
+ rng_state = rng_state * 1103515245 + 12345;
975
+ float r = ((rng_state >> 16) & 0x7fff) / 32768.0f;
976
+
977
+ float threshold = r * renorm_sum;
978
+ cumulative = 0.0f;
979
+ int chosen = 0;
980
+ for (int i = 0; i < top_p_cutoff; ++i) {
981
+ cumulative += sm_scores[i];
982
+ if (cumulative >= threshold) {
983
+ chosen = sm_indices[i];
984
+ break;
985
+ }
986
+ }
987
+
988
+ *d_output_token = chosen;
989
+ }
990
+ }
991
+
992
+ inline bool launch_topk_topp_sampling(const float* d_logits, int* d_output_token,
993
+ int vocab_size, int top_k, float top_p,
994
+ float temperature, unsigned int seed,
995
+ cudaStream_t stream) {
996
+ int num_candidates = min(top_k, vocab_size);
997
+ num_candidates = max(num_candidates, 1);
998
+
999
+ int block = 256;
1000
+ size_t smem_size = sizeof(float) * num_candidates + sizeof(int) * num_candidates;
1001
+
1002
+ if (smem_size > 48 * 1024) {
1003
+ return false;
1004
+ }
1005
+
1006
+ kernel_topk_topp_sampling_impl<<<1, block, smem_size, stream>>>(
1007
+ d_logits, d_output_token, vocab_size, top_k, top_p, temperature, seed, num_candidates);
1008
+
1009
+ return true;
1010
+ }
1011
+
1012
+ // --- FP16/BF16 Conversion Kernels ---
1013
+
1014
+ __global__ void kernel_fp32_to_fp16(uint16_t* out, const float* in, size_t n) {
1015
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
1016
+ if (idx >= n) return;
1017
+ out[idx] = __float2half(in[idx]);
1018
+ }
1019
+
1020
+ __global__ void kernel_fp16_to_fp32(float* out, const uint16_t* in, size_t n) {
1021
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
1022
+ if (idx >= n) return;
1023
+ out[idx] = __half2float(in[idx]);
1024
+ }
1025
+
1026
+ __global__ void kernel_fp32_to_bf16(uint16_t* out, const float* in, size_t n) {
1027
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
1028
+ if (idx >= n) return;
1029
+ uint32_t bits;
1030
+ memcpy(&bits, &in[idx], 4);
1031
+ out[idx] = static_cast<uint16_t>(bits >> 16);
1032
+ }
1033
+
1034
+ __global__ void kernel_bf16_to_fp32(float* out, const uint16_t* in, size_t n) {
1035
+ size_t idx = blockIdx.x * blockDim.x + threadIdx.x;
1036
+ if (idx >= n) return;
1037
+ uint32_t bits = static_cast<uint32_t>(in[idx]) << 16;
1038
+ memcpy(&out[idx], &bits, 4);
1039
+ }
1040
+
1041
+ inline void launch_fp32_to_fp16(uint16_t* d_out, const float* d_in, size_t n, cudaStream_t stream) {
1042
+ int block = 256;
1043
+ int grid = (static_cast<int>(n) + block - 1) / block;
1044
+ kernel_fp32_to_fp16<<<grid, block, 0, stream>>>(d_out, d_in, n);
1045
+ }
1046
+
1047
+ inline void launch_fp16_to_fp32(float* d_out, const uint16_t* d_in, size_t n, cudaStream_t stream) {
1048
+ int block = 256;
1049
+ int grid = (static_cast<int>(n) + block - 1) / block;
1050
+ kernel_fp16_to_fp32<<<grid, block, 0, stream>>>(d_out, d_in, n);
1051
+ }
1052
+
1053
+ inline void launch_fp32_to_bf16(uint16_t* d_out, const float* d_in, size_t n, cudaStream_t stream) {
1054
+ int block = 256;
1055
+ int grid = (static_cast<int>(n) + block - 1) / block;
1056
+ kernel_fp32_to_bf16<<<grid, block, 0, stream>>>(d_out, d_in, n);
1057
+ }
1058
+
1059
+ inline void launch_bf16_to_fp32(float* d_out, const uint16_t* d_in, size_t n, cudaStream_t stream) {
1060
+ int block = 256;
1061
+ int grid = (static_cast<int>(n) + block - 1) / block;
1062
+ kernel_bf16_to_fp32<<<grid, block, 0, stream>>>(d_out, d_in, n);
1063
+ }
1064
+
1065
+ // --- Flash Attention (Tiled Online Softmax) ---
1066
+
1067
+ template<int BLOCK_SIZE = 64, int HEAD_DIM = 64>
1068
+ __global__ void kernel_flash_attention_forward(
1069
+ const float* Q, const float* K, const float* V,
1070
+ float* O, int seq_len, float scale) {
1071
+
1072
+ int h = blockIdx.x;
1073
+ int i = blockIdx.y * blockDim.x + threadIdx.x;
1074
+ if (i >= seq_len) return;
1075
+
1076
+ extern __shared__ char smem[];
1077
+ float* s_K = reinterpret_cast<float*>(smem);
1078
+ float* s_V = reinterpret_cast<float*>(smem + BLOCK_SIZE * HEAD_DIM * sizeof(float));
1079
+
1080
+ float m = -1e30f;
1081
+ float l = 0.0f;
1082
+ float o[HEAD_DIM];
1083
+ for (int d = 0; d < HEAD_DIM; ++d) o[d] = 0.0f;
1084
+
1085
+ const float* q_row = Q + (h * seq_len + i) * HEAD_DIM;
1086
+
1087
+ for (int jb = 0; jb < seq_len; jb += BLOCK_SIZE) {
1088
+ int j_end = min(jb + BLOCK_SIZE, seq_len);
1089
+
1090
+ for (int j = threadIdx.x; j < (j_end - jb) * HEAD_DIM; j += blockDim.x) {
1091
+ int jj = j / HEAD_DIM;
1092
+ int dd = j % HEAD_DIM;
1093
+ s_K[jj * HEAD_DIM + dd] = K[(h * seq_len + jb + jj) * HEAD_DIM + dd];
1094
+ s_V[jj * HEAD_DIM + dd] = V[(h * seq_len + jb + jj) * HEAD_DIM + dd];
1095
+ }
1096
+ __syncthreads();
1097
+
1098
+ for (int jj = 0; jj < (j_end - jb); ++jj) {
1099
+ int j = jb + jj;
1100
+ if (j > i) break;
1101
+
1102
+ float dot = 0.0f;
1103
+ for (int d = 0; d < HEAD_DIM; ++d) {
1104
+ dot += q_row[d] * s_K[jj * HEAD_DIM + d];
1105
+ }
1106
+ dot *= scale;
1107
+
1108
+ float m_new = max(m, dot);
1109
+ float l_new = expf(m - m_new) * l + expf(dot - m_new);
1110
+
1111
+ for (int d = 0; d < HEAD_DIM; ++d) {
1112
+ o[d] = expf(m - m_new) * o[d] + expf(dot - m_new) * s_V[jj * HEAD_DIM + d];
1113
+ }
1114
+ m = m_new;
1115
+ l = l_new;
1116
+ }
1117
+ __syncthreads();
1118
+ }
1119
+
1120
+ if (l > 0.0f) {
1121
+ for (int d = 0; d < HEAD_DIM; ++d) {
1122
+ O[(h * seq_len + i) * HEAD_DIM + d] = o[d] / l;
1123
+ }
1124
+ } else {
1125
+ for (int d = 0; d < HEAD_DIM; ++d) {
1126
+ O[(h * seq_len + i) * HEAD_DIM + d] = 0.0f;
1127
+ }
1128
+ }
1129
+ }
1130
+
1131
+ inline void launch_flash_attention(const float* d_Q, const float* d_K, const float* d_V,
1132
+ float* d_O, int n_heads, int seq_len,
1133
+ int head_dim, float scale, cudaStream_t stream) {
1134
+ dim3 grid(n_heads, (seq_len + 63) / 64);
1135
+ int block = 64;
1136
+ size_t smem = 64 * head_dim * 2 * sizeof(float);
1137
+ if (head_dim <= 64) {
1138
+ kernel_flash_attention_forward<64, 64><<<grid, block, smem, stream>>>(
1139
+ d_Q, d_K, d_V, d_O, seq_len, scale);
1140
+ } else if (head_dim <= 128) {
1141
+ kernel_flash_attention_forward<64, 128><<<grid, block, smem, stream>>>(
1142
+ d_Q, d_K, d_V, d_O, seq_len, scale);
1143
+ } else {
1144
+ kernel_flash_attention_forward<64, 256><<<grid, block, smem, stream>>>(
1145
+ d_Q, d_K, d_V, d_O, seq_len, scale);
1146
+ }
1147
+ }
1148
+
1149
+ } // namespace neuroflow
1150
+
1151
+ #endif // USE_CUDA
1152
+ #endif // NEUROFLOW_CUDA_KERNELS_HPP
include/neuroflow/dpo.hpp ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_DPO_HPP
2
+ #define NEUROFLOW_DPO_HPP
3
+
4
+ #include <cstddef>
5
+ #include <random>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ #include "adamw.hpp"
10
+ #include "alignment_common.hpp"
11
+ #include "causal_lm.hpp"
12
+ #include "scheduler.hpp"
13
+ #include "tokenizer.hpp"
14
+
15
+ namespace neuroflow {
16
+
17
+ struct DPOTrainConfig {
18
+ std::string data_path;
19
+ std::string sft_ckpt_path;
20
+ std::string tokenizer_path;
21
+ std::string output_dir;
22
+ float learning_rate = 1e-6f;
23
+ int epochs = 3;
24
+ size_t max_seq_len = 512;
25
+ float warmup_ratio = 0.05f;
26
+ float weight_decay = 0.0f;
27
+ float grad_clip = 1.0f;
28
+ float beta = 0.1f;
29
+ float adam_beta1 = 0.9f;
30
+ float adam_beta2 = 0.999f;
31
+ float adam_eps = 1e-8f;
32
+ size_t save_interval = 1000;
33
+ size_t log_interval = 10;
34
+ unsigned seed = 42;
35
+ };
36
+
37
+ class DPODataLoader {
38
+ public:
39
+ DPODataLoader(const std::string& jsonl_path, size_t max_samples = 0);
40
+
41
+ bool has_next() const;
42
+ DPOSample next();
43
+ void reset();
44
+ void shuffle(std::mt19937& rng);
45
+ size_t total_samples() const { return samples_.size(); }
46
+ size_t invalid_count() const { return invalid_count_; }
47
+
48
+ private:
49
+ std::vector<DPOSample> samples_;
50
+ size_t cursor_ = 0;
51
+ size_t invalid_count_ = 0;
52
+ };
53
+
54
+ struct DPOLossOutput {
55
+ float loss;
56
+ float alpha;
57
+ float reward_chosen;
58
+ float reward_rejected;
59
+ };
60
+
61
+ float compute_log_prob(CausalLMHead& model, const std::vector<size_t>& token_ids,
62
+ size_t prompt_len, size_t vocab_size);
63
+
64
+ DPOLossOutput compute_dpo_loss(float log_prob_chosen_policy,
65
+ float log_prob_rejected_policy,
66
+ float log_prob_chosen_ref,
67
+ float log_prob_rejected_ref,
68
+ float beta);
69
+
70
+ class DPOTrainer {
71
+ public:
72
+ DPOTrainConfig config;
73
+
74
+ DPOTrainer(const DPOTrainConfig& cfg);
75
+
76
+ void train();
77
+ float train_on_sample(const DPOSample& sample);
78
+
79
+ private:
80
+ std::unique_ptr<CausalLMHead> policy_;
81
+ std::unique_ptr<CausalLMHead> reference_;
82
+ std::unique_ptr<BPETokenizer> tokenizer_;
83
+ std::unique_ptr<AdamW> optimizer_;
84
+ std::unique_ptr<CosineScheduler> scheduler_;
85
+
86
+ float compute_w_embed_checksum();
87
+ };
88
+
89
+ } // namespace neuroflow
90
+
91
+ #endif // NEUROFLOW_DPO_HPP
include/neuroflow/generative.hpp ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_GENERATIVE_HPP
2
+ #define NEUROFLOW_GENERATIVE_HPP
3
+
4
+ /**
5
+ * NeuroFlow 生成式语言模型模块 - 聚合头文件
6
+ *
7
+ * 为类脑模块化网络增加因果语言模型能力:
8
+ * - CausalLMHead: 词嵌入+因果门控+SAE+NTM+投影输出
9
+ * - Tokenizer: BPE/WordPiece分词器
10
+ * - SamplingStrategy: 贪心/Top-K/Top-P采样
11
+ * - GenerativeModel: 编排层,与ECN/DMN/SN协同
12
+ */
13
+
14
+ #include "causal_lm.hpp"
15
+ #include "tokenizer.hpp"
16
+ #include "sampling.hpp"
17
+ #include "generative_model.hpp"
18
+
19
+ #endif // NEUROFLOW_GENERATIVE_HPP
include/neuroflow/generative_model.hpp ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_GENERATIVE_MODEL_HPP
2
+ #define NEUROFLOW_GENERATIVE_MODEL_HPP
3
+
4
+ #include <memory>
5
+ #include <random>
6
+ #include <string>
7
+ #include <vector>
8
+ #include "model.hpp"
9
+ #include "tensor.hpp"
10
+ #include "causal_lm.hpp"
11
+ #include "tokenizer.hpp"
12
+ #include "sampling.hpp"
13
+
14
+ namespace neuroflow {
15
+
16
+ class GenerativeModel {
17
+ public:
18
+ std::unique_ptr<CausalLMHead> lm_head_;
19
+ std::unique_ptr<Tokenizer> tokenizer_;
20
+ std::unique_ptr<SamplingStrategy> sampler_;
21
+ NeuroFlowModel* neuroflow_model_;
22
+
23
+ GenerativeModel(const CausalLMConfig& lm_config,
24
+ std::unique_ptr<Tokenizer> tokenizer,
25
+ NeuroFlowModel* nf_model = nullptr);
26
+
27
+ GenerateOutput generate(const std::string& prompt, const GenerateConfig& config);
28
+
29
+ Tensor apply_sn_gating(const Tensor& hidden, const Tensor& logits);
30
+ Tensor inject_memory(const Tensor& query, const Tensor& logits);
31
+
32
+ Tensor apply_repetition_penalty(Tensor logits, const GenerateConfig& config,
33
+ const std::vector<size_t>& generated);
34
+ Tensor apply_punct_penalty(Tensor logits, const GenerateConfig& config);
35
+
36
+ void set_strategy(SamplingStrategyType type);
37
+
38
+ void clear_cache();
39
+ CacheStats cache_stats() const;
40
+ };
41
+
42
+ } // namespace neuroflow
43
+
44
+ #endif // NEUROFLOW_GENERATIVE_MODEL_HPP
include/neuroflow/grad_scaler.hpp ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_GRAD_SCALER_HPP
2
+ #define NEUROFLOW_GRAD_SCALER_HPP
3
+
4
+ #include <cstddef>
5
+ #include <vector>
6
+ #include "tensor.hpp"
7
+
8
+ namespace neuroflow {
9
+
10
+ class GradScaler {
11
+ public:
12
+ float scale_;
13
+ float growth_factor_;
14
+ float backoff_factor_;
15
+ size_t growth_interval_;
16
+ size_t growth_tracker_;
17
+
18
+ GradScaler(float init_scale = 65536.0f,
19
+ float growth_factor = 2.0f,
20
+ float backoff_factor = 0.5f,
21
+ size_t growth_interval = 2000);
22
+
23
+ float get_scale() const { return scale_; }
24
+
25
+ bool has_inf_or_nan(const std::vector<Tensor*>& grads) const;
26
+
27
+ void unscale(std::vector<Tensor*>& grads);
28
+
29
+ void scale_loss(Tensor& loss);
30
+
31
+ void update(bool found_inf);
32
+ };
33
+
34
+ } // namespace neuroflow
35
+
36
+ #endif // NEUROFLOW_GRAD_SCALER_HPP
include/neuroflow/memory.hpp ADDED
@@ -0,0 +1,555 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_MEMORY_HPP
2
+ #define NEUROFLOW_MEMORY_HPP
3
+
4
+ /**
5
+ * NeuroFlow 记忆系统
6
+ *
7
+ * 核心技术:
8
+ * 1. MLA (Multi-head Latent Attention) - DeepSeek KV压缩
9
+ * 2. 滑动窗口长记忆
10
+ * 3. 记忆分页与磁盘溢出
11
+ * 4. 记忆巩固 (LTP模拟)
12
+ */
13
+
14
+ #include <fstream>
15
+ #include <memory>
16
+ #include <queue>
17
+ #include <string>
18
+ #include <unordered_map>
19
+ #include <vector>
20
+ #include "networks.hpp"
21
+ #include "tensor.hpp"
22
+
23
+ namespace neuroflow {
24
+
25
+ /**
26
+ * MLA压缩KV Cache
27
+ *
28
+ * DeepSeek核心技术:将KV压缩到潜在空间
29
+ * 内存节省:87.5%+
30
+ */
31
+ class LatentKVCache {
32
+ public:
33
+ size_t d_model;
34
+ size_t n_heads;
35
+ size_t d_latent; // 压缩维度
36
+ size_t head_dim;
37
+
38
+ // 投影矩阵
39
+ std::shared_ptr<Linear> W_q; // Q投影
40
+ std::shared_ptr<Linear> W_dkv; // KV压缩投影
41
+ std::shared_ptr<Linear> W_uk; // K解压
42
+ std::shared_ptr<Linear> W_uv; // V解压
43
+ std::shared_ptr<Linear> W_o; // 输出投影
44
+
45
+ // Cache存储 (压缩形式)
46
+ Tensor cache; // (max_seq, d_latent)
47
+ size_t cache_len;
48
+ size_t max_cache_len;
49
+
50
+ LatentKVCache(size_t model_dim, size_t heads, size_t latent_dim, size_t max_len = 4096)
51
+ : d_model(model_dim), n_heads(heads), d_latent(latent_dim),
52
+ head_dim(model_dim / heads), max_cache_len(max_len), cache_len(0) {
53
+
54
+ W_q = std::make_shared<Linear>(d_model, d_model, false);
55
+ W_dkv = std::make_shared<Linear>(d_model, d_latent, false); // 压缩!
56
+ W_uk = std::make_shared<Linear>(d_latent, d_model, false);
57
+ W_uv = std::make_shared<Linear>(d_latent, d_model, false);
58
+ W_o = std::make_shared<Linear>(d_model, d_model, false);
59
+
60
+ // 初始化cache
61
+ cache = Tensor({max_len, d_latent}, QuantType::FP32);
62
+ }
63
+
64
+ // 前向传播 (带cache)
65
+ Tensor forward(const Tensor& x, bool use_cache = true) {
66
+ size_t batch = x.shape_[0];
67
+ size_t seq_len = x.shape_.size() > 1 ? x.shape_[1] : 1;
68
+ size_t input_dim = x.shape_.size() > 2 ? x.shape_[2] : (x.shape_.size() > 1 ? x.shape_[1] : d_model);
69
+
70
+ // 确定实际维度
71
+ if (x.shape_.size() == 2 && x.shape_[1] == d_model) {
72
+ // 输入是 {batch, d_model},seq_len=1
73
+ seq_len = 1;
74
+ input_dim = d_model;
75
+ } else if (x.shape_.size() == 2) {
76
+ // 输入可能是 {batch, seq_len} 但缺少 d_model
77
+ // 将 seq_len 视为实际序列长度,假设每个位置是 d_model 维
78
+ // 这需要特殊处理
79
+ seq_len = 1;
80
+ input_dim = x.shape_[1];
81
+ }
82
+
83
+ // Q投影 - 输入需要是 {batch * seq_len, d_model}
84
+ size_t flat_batch = batch * seq_len;
85
+ Tensor x_flat({flat_batch, d_model}, QuantType::FP32);
86
+ float* xf = x_flat.as_fp32();
87
+ const float* xd = x.as_fp32();
88
+
89
+ // 如果输入维度小于 d_model,补零
90
+ size_t copy_size = std::min(input_dim, d_model);
91
+ for (size_t i = 0; i < flat_batch; ++i) {
92
+ for (size_t j = 0; j < copy_size; ++j) {
93
+ xf[i * d_model + j] = xd[i * input_dim + j];
94
+ }
95
+ for (size_t j = copy_size; j < d_model; ++j) {
96
+ xf[i * d_model + j] = 0.0f;
97
+ }
98
+ }
99
+
100
+ Tensor q = W_q->forward(x_flat);
101
+ q = q.reshape({batch, seq_len, n_heads, head_dim});
102
+
103
+ // KV压缩到潜在空间 (MLA核心!)
104
+ Tensor c_kv = W_dkv->forward(x_flat);
105
+ c_kv = c_kv.reshape({batch, seq_len, d_latent});
106
+
107
+ // 拼接历史cache
108
+ if (use_cache && cache_len > 0) {
109
+ size_t new_len = cache_len + seq_len;
110
+ Tensor new_cache({new_len, d_latent}, QuantType::FP32);
111
+ float* nc = new_cache.as_fp32();
112
+ float* old = cache.as_fp32();
113
+
114
+ // 拷贝旧cache
115
+ memcpy(nc, old, cache_len * d_latent * sizeof(float));
116
+
117
+ // 拷贝新cache (取batch=0)
118
+ float* new_kv = c_kv.as_fp32();
119
+ for (size_t s = 0; s < seq_len; ++s) {
120
+ memcpy(nc + (cache_len + s) * d_latent,
121
+ new_kv + s * d_latent,
122
+ d_latent * sizeof(float));
123
+ }
124
+
125
+ c_kv = new_cache.reshape({1, new_len, d_latent});
126
+ }
127
+
128
+ // 解压K, V
129
+ size_t total_len = use_cache && cache_len > 0 ? (cache_len + seq_len) : seq_len;
130
+
131
+ // 正确reshape c_kv到二维 - 注意batch维度处理
132
+ // 当有历史cache时,c_kv 被 reshape 到 {1, new_len, d_latent}
133
+ // 需要正确处理batch扩展
134
+ size_t c_kv_batch = use_cache && cache_len > 0 ? 1 : batch;
135
+ size_t actual_elements = c_kv_batch * total_len * d_latent;
136
+
137
+ Tensor c_kv_flat({batch * total_len, d_latent}, QuantType::FP32);
138
+ float* ckf = c_kv_flat.as_fp32();
139
+ const float* ck = c_kv.as_fp32();
140
+
141
+ // 正确拷贝:只拷贝实际存在的数据
142
+ for (size_t b = 0; b < batch; ++b) {
143
+ for (size_t t = 0; t < total_len; ++t) {
144
+ for (size_t d = 0; d < d_latent; ++d) {
145
+ // 当有历史cache时,所有batch共享同一份cache数据
146
+ size_t src_idx = (c_kv_batch == 1 ? t : b * total_len + t) * d_latent + d;
147
+ size_t dst_idx = (b * total_len + t) * d_latent + d;
148
+ ckf[dst_idx] = ck[src_idx];
149
+ }
150
+ }
151
+ }
152
+
153
+ Tensor k = W_uk->forward(c_kv_flat);
154
+ Tensor v = W_uv->forward(c_kv_flat);
155
+
156
+ k = k.reshape({batch, total_len, n_heads, head_dim});
157
+ v = v.reshape({batch, total_len, n_heads, head_dim});
158
+
159
+ // 注意力计算
160
+ Tensor output({batch, seq_len, d_model}, QuantType::FP32);
161
+ float* out = output.as_fp32();
162
+ float* qp = q.as_fp32();
163
+ float* kp = k.as_fp32();
164
+ float* vp = v.as_fp32();
165
+
166
+ float scale = 1.0f / std::sqrt(static_cast<float>(head_dim));
167
+
168
+ for (size_t b = 0; b < batch; ++b) {
169
+ for (size_t h = 0; h < n_heads; ++h) {
170
+ for (size_t s = 0; s < seq_len; ++s) {
171
+ // 计算注意力分数
172
+ std::vector<float> scores(total_len);
173
+ for (size_t t = 0; t < total_len; ++t) {
174
+ float dot = 0;
175
+ for (size_t d = 0; d < head_dim; ++d) {
176
+ dot += qp[b * seq_len * n_heads * head_dim + s * n_heads * head_dim + h * head_dim + d]
177
+ * kp[b * total_len * n_heads * head_dim + t * n_heads * head_dim + h * head_dim + d];
178
+ }
179
+ scores[t] = dot * scale;
180
+ }
181
+
182
+ // Softmax
183
+ float max_s = scores[0];
184
+ for (auto& sc : scores) max_s = std::max(max_s, sc);
185
+ float sum = 0;
186
+ for (auto& sc : scores) {
187
+ sc = std::exp(sc - max_s);
188
+ sum += sc;
189
+ }
190
+ for (auto& sc : scores) sc /= sum;
191
+
192
+ // 加权求和
193
+ for (size_t d = 0; d < head_dim; ++d) {
194
+ float val = 0;
195
+ for (size_t t = 0; t < total_len; ++t) {
196
+ val += scores[t] * vp[b * total_len * n_heads * head_dim + t * n_heads * head_dim + h * head_dim + d];
197
+ }
198
+ out[b * seq_len * d_model + s * d_model + h * head_dim + d] = val;
199
+ }
200
+ }
201
+ }
202
+ }
203
+
204
+ output = W_o->forward(output.reshape({batch * seq_len, d_model}));
205
+ output = output.reshape({batch, seq_len, d_model});
206
+
207
+ // 更新cache
208
+ if (use_cache) {
209
+ float* c = cache.as_fp32();
210
+ float* nk = c_kv.as_fp32();
211
+ // 只保留最新的部分
212
+ size_t keep = std::min(seq_len, max_cache_len - cache_len);
213
+ if (cache_len + seq_len > max_cache_len) {
214
+ // 滑动:丢弃旧的
215
+ size_t shift = cache_len + seq_len - max_cache_len;
216
+ memmove(c, c + shift * d_latent, (cache_len - shift) * d_latent * sizeof(float));
217
+ cache_len -= shift;
218
+ }
219
+ memcpy(c + cache_len * d_latent, nk, seq_len * d_latent * sizeof(float));
220
+ cache_len += seq_len;
221
+ }
222
+
223
+ return output.reshape({batch, d_model});
224
+ }
225
+
226
+ // 清空cache
227
+ void clear_cache() {
228
+ cache_len = 0;
229
+ memset(cache.data_.get(), 0, cache.data_size_);
230
+ }
231
+
232
+ // 获取cache大小 (字节)
233
+ size_t cache_size_bytes() const {
234
+ return cache_len * d_latent * sizeof(float);
235
+ }
236
+
237
+ // 相比传统KV节省的内存比例
238
+ float memory_saving_ratio() const {
239
+ size_t traditional_size = cache_len * d_model * 2 * sizeof(float); // K + V
240
+ size_t mla_size = cache_len * d_latent * sizeof(float);
241
+ return 1.0f - static_cast<float>(mla_size) / traditional_size;
242
+ }
243
+ };
244
+
245
+ /**
246
+ * MemoryConsolidationModule
247
+ *
248
+ * 模拟海马体记忆巩固:
249
+ * 1. Encoding - 记忆编码
250
+ * 2. Retrieval - 注意力检索
251
+ * 3. Consolidation - LTP增强
252
+ */
253
+ class MemoryConsolidationModule {
254
+ public:
255
+ size_t memory_slots;
256
+ size_t memory_dim;
257
+ float ltp_rate;
258
+
259
+ // 记忆库
260
+ Tensor memory_bank; // (slots, dim)
261
+
262
+ // 投影
263
+ std::shared_ptr<Linear> encode_proj;
264
+ std::shared_ptr<Linear> retrieve_proj;
265
+ std::shared_ptr<Linear> query_proj;
266
+
267
+ MemoryConsolidationModule(size_t input_dim, size_t slots = 64, size_t dim = 128, float ltp = 0.01f)
268
+ : memory_slots(slots), memory_dim(dim), ltp_rate(ltp) {
269
+
270
+ memory_bank = Tensor({slots, dim}, QuantType::FP32);
271
+ float* m = memory_bank.as_fp32();
272
+ std::mt19937 init_rng(42);
273
+ std::uniform_real_distribution<float> init_dist(-0.02f, 0.02f);
274
+ for (size_t i = 0; i < memory_bank.numel(); ++i) {
275
+ m[i] = init_dist(init_rng);
276
+ }
277
+
278
+ encode_proj = std::make_shared<Linear>(input_dim, dim);
279
+ retrieve_proj = std::make_shared<Linear>(dim, input_dim);
280
+ query_proj = std::make_shared<Linear>(input_dim, dim);
281
+ }
282
+
283
+ // 编码
284
+ Tensor encode(const Tensor& x) {
285
+ return encode_proj->forward(x);
286
+ }
287
+
288
+ // 检索
289
+ struct RetrievalResult {
290
+ Tensor retrieved;
291
+ Tensor attention;
292
+ };
293
+
294
+ RetrievalResult retrieve(const Tensor& query) {
295
+ RetrievalResult result;
296
+
297
+ Tensor q = query_proj->forward(query); // (batch, dim)
298
+
299
+ // 注意力: query @ memory_bank.T
300
+ size_t batch = q.shape_[0];
301
+ result.attention = Tensor({batch, memory_slots}, QuantType::FP32);
302
+
303
+ float* qp = q.as_fp32();
304
+ float* mp = memory_bank.as_fp32();
305
+ float* ap = result.attention.as_fp32();
306
+
307
+ float scale = 1.0f / std::sqrt(static_cast<float>(memory_dim));
308
+
309
+ for (size_t b = 0; b < batch; ++b) {
310
+ // 计算分数
311
+ std::vector<float> scores(memory_slots);
312
+ for (size_t s = 0; s < memory_slots; ++s) {
313
+ float dot = 0;
314
+ for (size_t d = 0; d < memory_dim; ++d) {
315
+ dot += qp[b * memory_dim + d] * mp[s * memory_dim + d];
316
+ }
317
+ scores[s] = dot * scale;
318
+ }
319
+
320
+ // Softmax
321
+ float max_s = scores[0];
322
+ for (auto& sc : scores) max_s = std::max(max_s, sc);
323
+ float sum = 0;
324
+ for (auto& sc : scores) {
325
+ sc = std::exp(sc - max_s);
326
+ sum += sc;
327
+ }
328
+ for (size_t s = 0; s < memory_slots; ++s) {
329
+ ap[b * memory_slots + s] = scores[s] / sum;
330
+ }
331
+ }
332
+
333
+ // 检索: attention @ memory_bank
334
+ Tensor retrieved_mem({batch, memory_dim}, QuantType::FP32);
335
+ float* rp = retrieved_mem.as_fp32();
336
+
337
+ for (size_t b = 0; b < batch; ++b) {
338
+ for (size_t d = 0; d < memory_dim; ++d) {
339
+ float val = 0;
340
+ for (size_t s = 0; s < memory_slots; ++s) {
341
+ val += ap[b * memory_slots + s] * mp[s * memory_dim + d];
342
+ }
343
+ rp[b * memory_dim + d] = val;
344
+ }
345
+ }
346
+
347
+ result.retrieved = retrieve_proj->forward(retrieved_mem);
348
+ return result;
349
+ }
350
+
351
+ // 记忆巩固 (LTP模拟)
352
+ void consolidate(const Tensor& x) {
353
+ Tensor encoded = encode(x);
354
+ Tensor q = query_proj->forward(x);
355
+
356
+ float* qp = q.as_fp32();
357
+ float* mp = memory_bank.as_fp32();
358
+ float* ep = encoded.as_fp32();
359
+
360
+ size_t batch = x.shape_[0];
361
+
362
+ // 计算注意力
363
+ std::vector<std::vector<float>> attentions(batch);
364
+ for (size_t b = 0; b < batch; ++b) {
365
+ attentions[b].resize(memory_slots);
366
+ for (size_t s = 0; s < memory_slots; ++s) {
367
+ float dot = 0;
368
+ for (size_t d = 0; d < memory_dim; ++d) {
369
+ dot += qp[b * memory_dim + d] * mp[s * memory_dim + d];
370
+ }
371
+ attentions[b][s] = dot;
372
+ }
373
+
374
+ float max_s = attentions[b][0];
375
+ for (auto& sc : attentions[b]) max_s = std::max(max_s, sc);
376
+ float sum = 0;
377
+ for (auto& sc : attentions[b]) {
378
+ sc = std::exp(sc - max_s);
379
+ sum += sc;
380
+ }
381
+ for (auto& sc : attentions[b]) sc /= sum;
382
+ }
383
+
384
+ // 更新记忆槽 (加权平均)
385
+ for (size_t s = 0; s < memory_slots; ++s) {
386
+ float update = 0;
387
+ float weight_sum = 0;
388
+ for (size_t b = 0; b < batch; ++b) {
389
+ float w = attentions[b][s];
390
+ weight_sum += w;
391
+ for (size_t d = 0; d < memory_dim; ++d) {
392
+ update += w * ep[b * memory_dim + d];
393
+ }
394
+ }
395
+ if (weight_sum > 0) {
396
+ for (size_t d = 0; d < memory_dim; ++d) {
397
+ mp[s * memory_dim + d] += ltp_rate * (update / weight_sum - mp[s * memory_dim + d]);
398
+ }
399
+ }
400
+ }
401
+ }
402
+
403
+ // 前向
404
+ RetrievalResult forward(const Tensor& x) {
405
+ auto result = retrieve(x);
406
+ return result;
407
+ }
408
+ };
409
+
410
+ /**
411
+ * PagedMemoryManager
412
+ *
413
+ * 支持长记忆的分页系统:
414
+ * 1. 内存中的活跃页
415
+ * 2. 磁盘上的历史页
416
+ * 3. 自动页换入换出
417
+ */
418
+ class PagedMemoryManager {
419
+ public:
420
+ struct MemoryPage {
421
+ Tensor data;
422
+ size_t page_id;
423
+ size_t access_count;
424
+ bool in_memory;
425
+ std::string disk_path;
426
+ };
427
+
428
+ size_t page_size; // 每页槽数量
429
+ size_t max_memory_pages; // 内存最大页数
430
+ size_t memory_dim;
431
+
432
+ std::unordered_map<size_t, MemoryPage> pages;
433
+ std::queue<size_t> page_order; // 用于LRU
434
+
435
+ size_t next_page_id;
436
+ std::string disk_dir;
437
+
438
+ PagedMemoryManager(size_t page_sz, size_t max_pages, size_t dim, const std::string& dir = "/tmp/neuroflow_mem")
439
+ : page_size(page_sz), max_memory_pages(max_pages), memory_dim(dim),
440
+ next_page_id(0), disk_dir(dir) {
441
+ // 创建磁盘目录
442
+ // mkdir(disk_dir.c_str(), 0755); // 实际应用中添加
443
+ }
444
+
445
+ // 创建新页
446
+ size_t create_page() {
447
+ size_t id = next_page_id++;
448
+ MemoryPage page;
449
+ page.page_id = id;
450
+ page.data = Tensor({page_size, memory_dim}, QuantType::FP32);
451
+ page.access_count = 0;
452
+ page.in_memory = true;
453
+ page.disk_path = disk_dir + "/page_" + std::to_string(id) + ".bin";
454
+
455
+ pages[id] = page;
456
+ page_order.push(id);
457
+
458
+ // 如果超过内存限制,换出最旧页
459
+ if (pages.size() > max_memory_pages) {
460
+ evict_oldest();
461
+ }
462
+
463
+ return id;
464
+ }
465
+
466
+ // 获取页数据
467
+ Tensor* get_page(size_t id) {
468
+ if (pages.find(id) == pages.end()) return nullptr;
469
+
470
+ auto& page = pages[id];
471
+ page.access_count++;
472
+
473
+ // 如果在磁盘,换入
474
+ if (!page.in_memory) {
475
+ load_from_disk(id);
476
+ }
477
+
478
+ return &page.data;
479
+ }
480
+
481
+ // 换出最旧页
482
+ void evict_oldest() {
483
+ while (page_order.size() > max_memory_pages) {
484
+ size_t old_id = page_order.front();
485
+ page_order.pop();
486
+
487
+ auto& page = pages[old_id];
488
+ if (page.in_memory) {
489
+ save_to_disk(old_id);
490
+ page.in_memory = false;
491
+ }
492
+ }
493
+ }
494
+
495
+ // 保存到磁盘
496
+ void save_to_disk(size_t id) {
497
+ auto& page = pages[id];
498
+ if (page.data.dtype_ != QuantType::FP32)
499
+ throw std::runtime_error("save_to_disk: page " + std::to_string(id) + " is not FP32");
500
+ if (!page.data.data_ || page.data.data_size_ == 0)
501
+ throw std::runtime_error("save_to_disk: page " + std::to_string(id) + " has no data");
502
+ std::ofstream f(page.disk_path, std::ios::binary);
503
+ if (!f) throw std::runtime_error("Cannot save page to disk: " + page.disk_path);
504
+ const float* data = page.data.as_fp32();
505
+ f.write(reinterpret_cast<const char*>(data), page.data.data_size_);
506
+ if (!f.good()) throw std::runtime_error("Write error saving page: " + page.disk_path);
507
+ f.close();
508
+ }
509
+
510
+ void load_from_disk(size_t id) {
511
+ auto& page = pages[id];
512
+ if (page.data.dtype_ != QuantType::FP32)
513
+ throw std::runtime_error("load_from_disk: page " + std::to_string(id) + " is not FP32");
514
+ if (!page.data.data_ || page.data.data_size_ == 0)
515
+ throw std::runtime_error("load_from_disk: page " + std::to_string(id) + " has no data");
516
+ std::ifstream f(page.disk_path, std::ios::binary);
517
+ if (!f) throw std::runtime_error("Cannot load page from disk: " + page.disk_path);
518
+ float* data = page.data.as_fp32();
519
+ f.read(reinterpret_cast<char*>(data), page.data.data_size_);
520
+ if (!f.good()) throw std::runtime_error("Read error loading page: " + page.disk_path);
521
+ f.close();
522
+ page.in_memory = true;
523
+ page_order.push(id);
524
+ }
525
+
526
+ // 获取统计
527
+ struct Stats {
528
+ size_t total_pages;
529
+ size_t in_memory_pages;
530
+ size_t on_disk_pages;
531
+ size_t total_memory_bytes;
532
+ };
533
+
534
+ Stats get_stats() {
535
+ Stats s;
536
+ s.total_pages = pages.size();
537
+ s.in_memory_pages = 0;
538
+ s.on_disk_pages = 0;
539
+ s.total_memory_bytes = 0;
540
+
541
+ for (auto& [id, page] : pages) {
542
+ if (page.in_memory) {
543
+ s.in_memory_pages++;
544
+ s.total_memory_bytes += page.data.data_size_;
545
+ } else {
546
+ s.on_disk_pages++;
547
+ }
548
+ }
549
+ return s;
550
+ }
551
+ };
552
+
553
+ } // namespace neuroflow
554
+
555
+ #endif // NEUROFLOW_MEMORY_HPP
include/neuroflow/model.hpp ADDED
@@ -0,0 +1,680 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_MODEL_HPP
2
+ #define NEUROFLOW_MODEL_HPP
3
+
4
+ /**
5
+ * NeuroFlowModel - 主模型类
6
+ *
7
+ * 整合三大网络:
8
+ * 1. ExecutiveControlNetwork (ECN)
9
+ * 2. DefaultModeNetwork (DMN)
10
+ * 3. SalienceNetwork (SN)
11
+ *
12
+ * + 记忆模块
13
+ * + 神经流形分析
14
+ */
15
+
16
+ #include <memory>
17
+ #include <unordered_map>
18
+ #include <vector>
19
+ #include "memory.hpp"
20
+ #include "networks.hpp"
21
+ #include "tensor.hpp"
22
+
23
+ namespace neuroflow {
24
+
25
+ /**
26
+ * NeuroFlowModel - 类脑模块化神经网络
27
+ */
28
+ class NeuroFlowModel {
29
+ public:
30
+ // 配置
31
+ struct Config {
32
+ size_t input_dim = 512;
33
+ size_t hidden_dim = 2048;
34
+ size_t output_dim = 2048;
35
+ size_t memory_dim = 512;
36
+ size_t memory_slots = 64;
37
+ size_t num_layers = 12;
38
+ size_t num_associations = 8;
39
+ bool use_quantization = false;
40
+ bool use_mla = false;
41
+ size_t mla_latent_dim = 32;
42
+ bool use_causal_lm = false;
43
+ size_t vocab_size = 128000;
44
+ size_t max_seq_len = 512;
45
+ std::string tokenizer_path = "";
46
+ size_t causal_window_size = 64;
47
+ size_t sae_k = 128;
48
+ size_t ntm_memory_slots = 32;
49
+ size_t fusion_bottleneck_dim = 256;
50
+ size_t lm_num_attn_layers = 4;
51
+ size_t lm_num_attn_heads = 8;
52
+ size_t lm_n_kv_heads = 2;
53
+ bool lm_use_rope = true;
54
+ bool lm_use_qk_norm = true;
55
+ bool lm_use_swiglu = true;
56
+ bool lm_use_bridge = true;
57
+ std::string lm_pooling = "last";
58
+ size_t mla_n_heads = 8;
59
+ size_t mla_max_cache_len = 4096;
60
+ size_t d_model = 512;
61
+ };
62
+
63
+ Config config;
64
+
65
+ // 输入投影
66
+ std::shared_ptr<Linear> input_proj_linear;
67
+ std::shared_ptr<LayerNorm> input_proj_norm;
68
+ std::shared_ptr<GELU> input_proj_gelu;
69
+
70
+ // 三大核心网络
71
+ std::unique_ptr<ExecutiveControlNetwork> ecn;
72
+ std::unique_ptr<DefaultModeNetwork> dmn;
73
+ std::unique_ptr<SalienceNetwork> sn;
74
+
75
+ // 记忆模块
76
+ std::unique_ptr<MemoryConsolidationModule> memory;
77
+ std::unique_ptr<LatentKVCache> mla_cache; // 可选MLA
78
+
79
+ // 流形投影
80
+ std::shared_ptr<Linear> manifold_proj1;
81
+ std::shared_ptr<LayerNorm> manifold_norm;
82
+ std::shared_ptr<GELU> manifold_gelu;
83
+ std::shared_ptr<Linear> manifold_proj2;
84
+
85
+ // 输出融合 (低秩因式分解: 15000→256→5000)
86
+ std::shared_ptr<Linear> output_fusion_down;
87
+ std::shared_ptr<LayerNorm> output_fusion_bottleneck_norm;
88
+ std::shared_ptr<Linear> output_fusion_up;
89
+ std::shared_ptr<LayerNorm> output_fusion_norm;
90
+
91
+ // 训练模式
92
+ bool training_mode;
93
+
94
+ NeuroFlowModel(const Config& cfg) : config(cfg), training_mode(false) {
95
+ // 输入投影
96
+ input_proj_linear = std::make_shared<Linear>(config.input_dim, config.hidden_dim);
97
+ input_proj_norm = std::make_shared<LayerNorm>(config.hidden_dim);
98
+ input_proj_gelu = std::make_shared<GELU>();
99
+
100
+ // ECN
101
+ ecn = std::make_unique<ExecutiveControlNetwork>(
102
+ config.hidden_dim, config.hidden_dim, config.hidden_dim, config.num_layers);
103
+
104
+ // DMN
105
+ dmn = std::make_unique<DefaultModeNetwork>(
106
+ config.memory_dim, config.hidden_dim / 2, config.num_associations);
107
+
108
+ // SN
109
+ sn = std::make_unique<SalienceNetwork>(
110
+ config.hidden_dim, config.hidden_dim / 2);
111
+
112
+ // 记忆
113
+ memory = std::make_unique<MemoryConsolidationModule>(
114
+ config.hidden_dim, config.memory_slots, config.memory_dim);
115
+
116
+ // MLA (可选)
117
+ if (config.use_mla) {
118
+ mla_cache = std::make_unique<LatentKVCache>(
119
+ config.hidden_dim, 8, config.mla_latent_dim, 4096);
120
+ }
121
+
122
+ // 流形投影
123
+ size_t manifold_in = config.hidden_dim + config.hidden_dim / 2;
124
+ manifold_proj1 = std::make_shared<Linear>(manifold_in, config.hidden_dim);
125
+ manifold_norm = std::make_shared<LayerNorm>(config.hidden_dim);
126
+ manifold_gelu = std::make_shared<GELU>();
127
+ manifold_proj2 = std::make_shared<Linear>(config.hidden_dim, 32);
128
+
129
+ // 输出融合 (低秩因式分解: hidden_dim*3 -> bn -> hidden_dim)
130
+ size_t fusion_in = config.hidden_dim * 3;
131
+ size_t bn = config.fusion_bottleneck_dim;
132
+ output_fusion_down = std::make_shared<Linear>(fusion_in, bn);
133
+ output_fusion_bottleneck_norm = std::make_shared<LayerNorm>(bn);
134
+ output_fusion_up = std::make_shared<Linear>(bn, config.hidden_dim);
135
+ output_fusion_norm = std::make_shared<LayerNorm>(config.hidden_dim);
136
+
137
+ // 量化
138
+ if (config.use_quantization) {
139
+ quantize();
140
+ }
141
+ }
142
+
143
+ // 默认构造
144
+ NeuroFlowModel() : NeuroFlowModel(Config()) {}
145
+
146
+ // 输出结构
147
+ struct Output {
148
+ Tensor output; // 最终输出
149
+ Tensor decision; // ECN决策
150
+ Tensor value; // OFC价值
151
+ Tensor saliency; // SN显著性
152
+ Tensor gates; // ECN/DMN门控权重 (2-class)
153
+ Tensor ecn_gate; // ECN门控
154
+ Tensor dmn_gate; // DMN门控
155
+ Tensor anomaly; // 异常评分
156
+ Tensor mem_attention; // 记忆注意力
157
+ Tensor retrieved_mem; // 检索记忆
158
+ Tensor manifold; // 流形表征 (可选)
159
+ };
160
+
161
+ // 前向传播
162
+ Output forward(const Tensor& x, const Tensor* memory_input = nullptr,
163
+ bool consolidate = false, bool return_manifold = false) {
164
+ Output out;
165
+ size_t batch = x.shape_[0];
166
+
167
+ // 输入投影
168
+ Tensor h = input_proj_linear->forward(x);
169
+ h = input_proj_norm->forward(h);
170
+ h = input_proj_gelu->forward(h);
171
+
172
+ // SN: 显著性检测 + 门控
173
+ auto sn_out = sn->forward(h);
174
+ out.saliency = sn_out.saliency;
175
+ out.gates = sn_out.gates;
176
+ out.anomaly = sn_out.anomaly;
177
+
178
+ // 提取门控权重
179
+ float* gates = out.gates.as_fp32();
180
+ Tensor ecn_gate({batch, 1}, QuantType::FP32);
181
+ Tensor dmn_gate({batch, 1}, QuantType::FP32);
182
+ for (size_t i = 0; i < batch; ++i) {
183
+ ecn_gate.as_fp32()[i] = gates[i * 2];
184
+ dmn_gate.as_fp32()[i] = gates[i * 2 + 1];
185
+ }
186
+ out.ecn_gate = ecn_gate;
187
+ out.dmn_gate = dmn_gate;
188
+
189
+ // ECN: 执行推理
190
+ auto ecn_out = ecn->forward(h);
191
+ out.decision = ecn_out.decision;
192
+ out.value = ecn_out.value;
193
+
194
+ // DMN: 默认模式网络
195
+ Tensor mem_seed;
196
+ if (memory_input) {
197
+ mem_seed = *memory_input;
198
+ } else {
199
+ mem_seed = memory->encode(h);
200
+ }
201
+ auto dmn_out = dmn->forward(mem_seed);
202
+
203
+ // 记忆检索
204
+ auto mem_out = memory->forward(h);
205
+ out.retrieved_mem = mem_out.retrieved;
206
+ out.mem_attention = mem_out.attention;
207
+
208
+ // 记忆巩固 (可选)
209
+ if (consolidate) {
210
+ memory->consolidate(h);
211
+ }
212
+
213
+ // 门控加权 - 创建新的张量,避免修改共享数据
214
+ Tensor ecn_weighted({batch, config.hidden_dim}, QuantType::FP32);
215
+ Tensor dmn_weighted_full({batch, dmn_out.vision.shape_[1]}, QuantType::FP32);
216
+
217
+ float* ew = ecn_weighted.as_fp32();
218
+ float* dw = dmn_weighted_full.as_fp32();
219
+ float* ed = out.decision.as_fp32();
220
+ float* dv = dmn_out.vision.as_fp32();
221
+ float* eg = ecn_gate.as_fp32();
222
+ float* dg = dmn_gate.as_fp32();
223
+
224
+ // ECN加权
225
+ for (size_t i = 0; i < batch; ++i) {
226
+ for (size_t j = 0; j < config.hidden_dim; ++j) {
227
+ ew[i * config.hidden_dim + j] = ed[i * config.hidden_dim + j] * eg[i];
228
+ }
229
+ }
230
+
231
+ // DMN加权
232
+ for (size_t i = 0; i < batch; ++i) {
233
+ for (size_t j = 0; j < dmn_out.vision.shape_[1]; ++j) {
234
+ dw[i * dmn_out.vision.shape_[1] + j] = dv[i * dmn_out.vision.shape_[1] + j] * dg[i];
235
+ }
236
+ }
237
+
238
+ // 只取hidden_dim部分
239
+ Tensor dmn_weighted({batch, config.hidden_dim}, QuantType::FP32);
240
+ float* dwf = dmn_weighted.as_fp32();
241
+ for (size_t i = 0; i < batch; ++i) {
242
+ for (size_t j = 0; j < config.hidden_dim; ++j) {
243
+ if (j < dmn_out.vision.shape_[1]) {
244
+ dwf[i * config.hidden_dim + j] = dw[i * dmn_out.vision.shape_[1] + j];
245
+ } else {
246
+ dwf[i * config.hidden_dim + j] = 0.0f;
247
+ }
248
+ }
249
+ }
250
+
251
+ // 融合: ECN + DMN + Memory
252
+ std::vector<Tensor> to_concat;
253
+ to_concat.push_back(ecn_weighted);
254
+ to_concat.push_back(dmn_weighted);
255
+
256
+ Tensor mem_for_fusion = out.retrieved_mem.clone();
257
+ if (mem_for_fusion.shape_[1] > config.hidden_dim) {
258
+ // 截取 (不是reshape)
259
+ Tensor truncated({batch, config.hidden_dim}, QuantType::FP32);
260
+ float* tw = truncated.as_fp32();
261
+ float* mw = mem_for_fusion.as_fp32();
262
+ for (size_t i = 0; i < batch; ++i) {
263
+ for (size_t j = 0; j < config.hidden_dim; ++j) {
264
+ tw[i * config.hidden_dim + j] = mw[i * mem_for_fusion.shape_[1] + j];
265
+ }
266
+ }
267
+ mem_for_fusion = truncated;
268
+ } else if (mem_for_fusion.shape_[1] < config.hidden_dim) {
269
+ // 补零
270
+ Tensor padded({batch, config.hidden_dim}, QuantType::FP32);
271
+ float* p = padded.as_fp32();
272
+ float* m = mem_for_fusion.as_fp32();
273
+ memset(p, 0, padded.data_size_);
274
+ for (size_t i = 0; i < batch; ++i) {
275
+ for (size_t j = 0; j < mem_for_fusion.shape_[1]; ++j) {
276
+ p[i * config.hidden_dim + j] = m[i * mem_for_fusion.shape_[1] + j];
277
+ }
278
+ }
279
+ mem_for_fusion = padded;
280
+ }
281
+ to_concat.push_back(mem_for_fusion);
282
+
283
+ Tensor combined = TensorOps::concat(to_concat, 1);
284
+ Tensor fused_bn = output_fusion_down->forward(combined);
285
+ fused_bn = output_fusion_bottleneck_norm->forward(fused_bn);
286
+ TensorOps::relu(fused_bn);
287
+ out.output = output_fusion_up->forward(fused_bn);
288
+ out.output = output_fusion_norm->forward(out.output);
289
+
290
+ // 流形 (可选)
291
+ if (return_manifold) {
292
+ Tensor manifold_in({batch, config.hidden_dim + config.hidden_dim / 2}, QuantType::FP32);
293
+ float* mi = manifold_in.as_fp32();
294
+ float* eh = ecn_out.hidden_states.back().as_fp32();
295
+ float* dl = dmn_out.latent.as_fp32();
296
+
297
+ for (size_t i = 0; i < batch; ++i) {
298
+ for (size_t j = 0; j < config.hidden_dim; ++j) {
299
+ mi[i * manifold_in.shape_[1] + j] = eh[i * config.hidden_dim + j];
300
+ }
301
+ for (size_t j = 0; j < config.hidden_dim / 2; ++j) {
302
+ mi[i * manifold_in.shape_[1] + config.hidden_dim + j] = dl[i * config.hidden_dim / 2 + j];
303
+ }
304
+ }
305
+
306
+ Tensor m = manifold_proj1->forward(manifold_in);
307
+ m = manifold_norm->forward(m);
308
+ m = manifold_gelu->forward(m);
309
+ out.manifold = manifold_proj2->forward(m);
310
+ }
311
+
312
+ return out;
313
+ }
314
+
315
+ // 神经流形轨迹
316
+ std::vector<Tensor> get_manifold_trajectory(const Tensor& x, size_t steps = 10) {
317
+ std::vector<Tensor> trajectory;
318
+ Tensor current = x.clone();
319
+
320
+ for (size_t s = 0; s < steps; ++s) {
321
+ auto out = forward(current, nullptr, false, true);
322
+ trajectory.push_back(out.manifold.clone());
323
+
324
+ // 残差更新
325
+ float* c = current.as_fp32();
326
+ float* o = out.output.as_fp32();
327
+ for (size_t i = 0; i < current.shape_[0]; ++i) {
328
+ size_t min_dim = std::min(current.shape_[1], out.output.shape_[1]);
329
+ for (size_t j = 0; j < min_dim; ++j) {
330
+ c[i * current.shape_[1] + j] += 0.1f * o[i * out.output.shape_[1] + j];
331
+ }
332
+ }
333
+ }
334
+
335
+ return trajectory;
336
+ }
337
+
338
+ // 设置训练模式
339
+ void set_training(bool t) {
340
+ training_mode = t;
341
+ ecn->set_training(t);
342
+ }
343
+
344
+ // 量化
345
+ void quantize() {
346
+ input_proj_linear->quantize();
347
+ manifold_proj1->quantize();
348
+ manifold_proj2->quantize();
349
+ output_fusion_down->quantize();
350
+ output_fusion_up->quantize();
351
+ ecn->quantize();
352
+ dmn->quantize();
353
+ sn->quantize();
354
+ memory->encode_proj->quantize();
355
+ memory->retrieve_proj->quantize();
356
+ memory->query_proj->quantize();
357
+ }
358
+
359
+ // 获取模型统计
360
+ struct Stats {
361
+ size_t total_params;
362
+ size_t memory_bytes;
363
+ float quantization_ratio;
364
+ };
365
+
366
+ Stats get_stats() {
367
+ Stats s;
368
+ s.total_params = 0;
369
+ s.memory_bytes = 0;
370
+ s.quantization_ratio = 0.0f;
371
+
372
+ // 简化统计
373
+ size_t fp32_layers = 0;
374
+ size_t quant_layers = 0;
375
+
376
+ // 统计各层
377
+ auto count_linear = [&](std::shared_ptr<Linear>& l) {
378
+ s.total_params += l->weight.numel();
379
+ if (l->bias.data_) s.total_params += l->bias.numel();
380
+ s.memory_bytes += l->weight.data_size_ + l->bias.data_size_;
381
+ if (l->quantized) quant_layers++;
382
+ else fp32_layers++;
383
+ };
384
+
385
+ count_linear(input_proj_linear);
386
+ count_linear(manifold_proj1);
387
+ count_linear(manifold_proj2);
388
+ count_linear(output_fusion_down);
389
+ count_linear(output_fusion_up);
390
+
391
+ for (auto& l : ecn->dlpfc_linear) count_linear(l);
392
+ count_linear(ecn->ofc1);
393
+ count_linear(ecn->ofc2);
394
+ count_linear(ecn->vmpfc1);
395
+ count_linear(ecn->vmpfc2);
396
+
397
+ count_linear(dmn->mem_encoder1);
398
+ count_linear(dmn->mem_encoder2);
399
+ count_linear(dmn->future_proj1);
400
+ for (auto& [h1, h2] : dmn->association_heads) {
401
+ count_linear(h1);
402
+ count_linear(h2);
403
+ }
404
+
405
+ count_linear(sn->saliency1);
406
+ count_linear(sn->saliency2);
407
+ count_linear(sn->saliency3);
408
+ count_linear(sn->gate1);
409
+ count_linear(sn->gate2);
410
+ count_linear(sn->anomaly1);
411
+ count_linear(sn->anomaly2);
412
+
413
+ count_linear(memory->encode_proj);
414
+ count_linear(memory->retrieve_proj);
415
+ count_linear(memory->query_proj);
416
+
417
+ s.memory_bytes += memory->memory_bank.data_size_;
418
+ s.total_params += memory->memory_bank.numel();
419
+
420
+ if (fp32_layers + quant_layers > 0) {
421
+ s.quantization_ratio = static_cast<float>(quant_layers) / (fp32_layers + quant_layers);
422
+ }
423
+
424
+ return s;
425
+ }
426
+
427
+ // ========== 序列化 (NFv1 格式) ==========
428
+ void save(const std::string& path) const {
429
+ std::ofstream ofs(path, std::ios::binary);
430
+ if (!ofs) throw std::runtime_error("Cannot open file for save: " + path);
431
+
432
+ // Magic header
433
+ ofs.write("NFv1", 4);
434
+
435
+ // Helper: serialize a named tensor
436
+ auto save_tensor = [&](const std::string& name, const Tensor& t) {
437
+ uint32_t name_len = name.size();
438
+ ofs.write(reinterpret_cast<const char*>(&name_len), 4);
439
+ ofs.write(name.data(), name_len);
440
+
441
+ uint32_t ndim = t.shape_.size();
442
+ ofs.write(reinterpret_cast<const char*>(&ndim), 4);
443
+ for (auto d : t.shape_) {
444
+ uint32_t dim = d;
445
+ ofs.write(reinterpret_cast<const char*>(&dim), 4);
446
+ }
447
+
448
+ uint32_t dsize = t.data_size_;
449
+ ofs.write(reinterpret_cast<const char*>(&dsize), 4);
450
+ ofs.write(reinterpret_cast<const char*>(t.data_.get()), dsize);
451
+ };
452
+
453
+ // Helper: save Linear layer (shared_ptr)
454
+ auto save_linear = [&](const std::string& prefix, const std::shared_ptr<Linear>& layer) {
455
+ save_tensor(prefix + ".weight", layer->weight);
456
+ if (layer->bias.data_) save_tensor(prefix + ".bias", layer->bias);
457
+ };
458
+
459
+ // === 输入投影 ===
460
+ save_linear("input_proj", input_proj_linear);
461
+ save_tensor("input_proj_norm.weight", input_proj_norm->weight);
462
+ save_tensor("input_proj_norm.bias", input_proj_norm->bias);
463
+
464
+ // === ECN ===
465
+ for (size_t i = 0; i < ecn->dlpfc_linear.size(); ++i)
466
+ save_linear("ecn.dlpfc" + std::to_string(i), ecn->dlpfc_linear[i]);
467
+ save_linear("ecn.ofc1", ecn->ofc1);
468
+ save_linear("ecn.ofc2", ecn->ofc2);
469
+ save_linear("ecn.vmpfc1", ecn->vmpfc1);
470
+ save_linear("ecn.vmpfc2", ecn->vmpfc2);
471
+
472
+ // === DMN ===
473
+ save_linear("dmn.mem_encoder1", dmn->mem_encoder1);
474
+ save_linear("dmn.mem_encoder2", dmn->mem_encoder2);
475
+ save_linear("dmn.future_proj1", dmn->future_proj1);
476
+ int head_idx = 0;
477
+ for (auto& [h1, h2] : dmn->association_heads) {
478
+ save_linear("dmn.head" + std::to_string(head_idx) + ".1", h1);
479
+ save_linear("dmn.head" + std::to_string(head_idx) + ".2", h2);
480
+ head_idx++;
481
+ }
482
+
483
+ // === SN ===
484
+ save_linear("sn.saliency1", sn->saliency1);
485
+ save_linear("sn.saliency2", sn->saliency2);
486
+ save_linear("sn.saliency3", sn->saliency3);
487
+ save_linear("sn.gate1", sn->gate1);
488
+ save_linear("sn.gate2", sn->gate2);
489
+ save_linear("sn.anomaly1", sn->anomaly1);
490
+ save_linear("sn.anomaly2", sn->anomaly2);
491
+
492
+ // === 记忆 ===
493
+ save_linear("memory.encode", memory->encode_proj);
494
+ save_linear("memory.retrieve", memory->retrieve_proj);
495
+ save_linear("memory.query_proj", memory->query_proj);
496
+ save_tensor("memory.bank", memory->memory_bank);
497
+
498
+ // === 流形投影 ===
499
+ save_linear("manifold.proj1", manifold_proj1);
500
+ save_tensor("manifold.norm.weight", manifold_norm->weight);
501
+ save_tensor("manifold.norm.bias", manifold_norm->bias);
502
+ save_linear("manifold.proj2", manifold_proj2);
503
+
504
+ // === 输出融合 ===
505
+ save_linear("output_fusion.down", output_fusion_down);
506
+ save_tensor("output_fusion.bn_norm.weight", output_fusion_bottleneck_norm->weight);
507
+ save_tensor("output_fusion.bn_norm.bias", output_fusion_bottleneck_norm->bias);
508
+ save_linear("output_fusion.up", output_fusion_up);
509
+ save_tensor("output_fusion.norm.weight", output_fusion_norm->weight);
510
+ save_tensor("output_fusion.norm.bias", output_fusion_norm->bias);
511
+
512
+ // End marker
513
+ uint32_t zero = 0;
514
+ ofs.write(reinterpret_cast<const char*>(&zero), 4);
515
+ ofs.close();
516
+ }
517
+
518
+ void load(const std::string& path) {
519
+ std::ifstream ifs(path, std::ios::binary);
520
+ if (!ifs) throw std::runtime_error("Cannot open file for load: " + path);
521
+
522
+ // Magic header
523
+ char magic[5] = {0};
524
+ ifs.read(magic, 4);
525
+ if (std::string(magic) != "NFv1") throw std::runtime_error("Invalid model file");
526
+
527
+ // Helper: set tensor data from stream
528
+ auto load_tensor_data = [&](Tensor& t) {
529
+ uint32_t ndim, dsize;
530
+ ifs.read(reinterpret_cast<char*>(&ndim), 4);
531
+ std::vector<size_t> shape(ndim);
532
+ for (uint32_t i = 0; i < ndim; ++i) {
533
+ uint32_t dim;
534
+ ifs.read(reinterpret_cast<char*>(&dim), 4);
535
+ shape[i] = dim;
536
+ }
537
+ ifs.read(reinterpret_cast<char*>(&dsize), 4);
538
+ if (t.data_size_ != dsize) {
539
+ t.data_ = std::shared_ptr<uint8_t>(new uint8_t[dsize], std::default_delete<uint8_t[]>());
540
+ t.shape_ = shape;
541
+ t.data_size_ = dsize;
542
+ }
543
+ ifs.read(reinterpret_cast<char*>(t.data_.get()), dsize);
544
+ };
545
+
546
+ // Helper: load named Linear layer
547
+ auto load_linear = [&](const std::shared_ptr<Linear>& layer, const std::string& suffix) {
548
+ if (suffix == ".weight") load_tensor_data(layer->weight);
549
+ else if (suffix == ".bias") { load_tensor_data(layer->bias); }
550
+ };
551
+
552
+ while (ifs.good()) {
553
+ uint32_t name_len;
554
+ ifs.read(reinterpret_cast<char*>(&name_len), 4);
555
+ if (name_len == 0) break; // end marker or EOF
556
+
557
+ std::string name(name_len, '\0');
558
+ ifs.read(&name[0], name_len);
559
+
560
+ // === 输入投影 ===
561
+ if (name == "input_proj.weight") load_tensor_data(input_proj_linear->weight);
562
+ else if (name == "input_proj.bias") load_tensor_data(input_proj_linear->bias);
563
+ else if (name == "input_proj_norm.weight") load_tensor_data(input_proj_norm->weight);
564
+ else if (name == "input_proj_norm.bias") load_tensor_data(input_proj_norm->bias);
565
+
566
+ // === ECN ===
567
+ else if (name.rfind("ecn.dlpfc", 0) == 0) {
568
+ std::string suffix = name.substr(name.find('.', 4)); // e.g. ".weight"
569
+ int idx = std::stoi(name.substr(9, name.find('.', 9) - 9));
570
+ load_linear(ecn->dlpfc_linear[idx], suffix);
571
+ }
572
+ else if (name == "ecn.ofc1.weight") load_tensor_data(ecn->ofc1->weight);
573
+ else if (name == "ecn.ofc1.bias") load_tensor_data(ecn->ofc1->bias);
574
+ else if (name == "ecn.ofc2.weight") load_tensor_data(ecn->ofc2->weight);
575
+ else if (name == "ecn.ofc2.bias") load_tensor_data(ecn->ofc2->bias);
576
+ else if (name == "ecn.vmpfc1.weight") load_tensor_data(ecn->vmpfc1->weight);
577
+ else if (name == "ecn.vmpfc1.bias") load_tensor_data(ecn->vmpfc1->bias);
578
+ else if (name == "ecn.vmpfc2.weight") load_tensor_data(ecn->vmpfc2->weight);
579
+ else if (name == "ecn.vmpfc2.bias") load_tensor_data(ecn->vmpfc2->bias);
580
+
581
+ // === DMN ===
582
+ else if (name == "dmn.mem_encoder1.weight") load_tensor_data(dmn->mem_encoder1->weight);
583
+ else if (name == "dmn.mem_encoder1.bias") load_tensor_data(dmn->mem_encoder1->bias);
584
+ else if (name == "dmn.mem_encoder2.weight") load_tensor_data(dmn->mem_encoder2->weight);
585
+ else if (name == "dmn.mem_encoder2.bias") load_tensor_data(dmn->mem_encoder2->bias);
586
+ else if (name == "dmn.future_proj1.weight") load_tensor_data(dmn->future_proj1->weight);
587
+ else if (name == "dmn.future_proj1.bias") load_tensor_data(dmn->future_proj1->bias);
588
+ else if (name.rfind("dmn.head", 0) == 0) {
589
+ // dmn.head<N>.<1|2>.<weight|bias>
590
+ size_t dot1 = name.find('.', 8); // after "dmn.head"
591
+ int h = std::stoi(name.substr(8, dot1 - 8));
592
+ size_t dot2 = name.find('.', dot1 + 1);
593
+ int which = std::stoi(name.substr(dot1 + 1, dot2 - dot1 - 1));
594
+ std::string suffix = name.substr(name.rfind('.'));
595
+ auto& layer = (which == 1) ? dmn->association_heads[h].first : dmn->association_heads[h].second;
596
+ load_linear(layer, suffix);
597
+ }
598
+
599
+ // === SN ===
600
+ else if (name == "sn.saliency1.weight") load_tensor_data(sn->saliency1->weight);
601
+ else if (name == "sn.saliency1.bias") load_tensor_data(sn->saliency1->bias);
602
+ else if (name == "sn.saliency2.weight") load_tensor_data(sn->saliency2->weight);
603
+ else if (name == "sn.saliency2.bias") load_tensor_data(sn->saliency2->bias);
604
+ else if (name == "sn.saliency3.weight") load_tensor_data(sn->saliency3->weight);
605
+ else if (name == "sn.saliency3.bias") load_tensor_data(sn->saliency3->bias);
606
+ else if (name == "sn.gate1.weight") load_tensor_data(sn->gate1->weight);
607
+ else if (name == "sn.gate1.bias") load_tensor_data(sn->gate1->bias);
608
+ else if (name == "sn.gate2.weight") load_tensor_data(sn->gate2->weight);
609
+ else if (name == "sn.gate2.bias") load_tensor_data(sn->gate2->bias);
610
+ else if (name == "sn.anomaly1.weight") load_tensor_data(sn->anomaly1->weight);
611
+ else if (name == "sn.anomaly1.bias") load_tensor_data(sn->anomaly1->bias);
612
+ else if (name == "sn.anomaly2.weight") load_tensor_data(sn->anomaly2->weight);
613
+ else if (name == "sn.anomaly2.bias") load_tensor_data(sn->anomaly2->bias);
614
+
615
+ // === 记忆 ===
616
+ else if (name == "memory.encode.weight") load_tensor_data(memory->encode_proj->weight);
617
+ else if (name == "memory.encode.bias") load_tensor_data(memory->encode_proj->bias);
618
+ else if (name == "memory.retrieve.weight") load_tensor_data(memory->retrieve_proj->weight);
619
+ else if (name == "memory.retrieve.bias") load_tensor_data(memory->retrieve_proj->bias);
620
+ else if (name == "memory.query_proj.weight") load_tensor_data(memory->query_proj->weight);
621
+ else if (name == "memory.query_proj.bias") load_tensor_data(memory->query_proj->bias);
622
+ else if (name == "memory.bank") load_tensor_data(memory->memory_bank);
623
+
624
+ // === 流形投影 ===
625
+ else if (name == "manifold.proj1.weight") load_tensor_data(manifold_proj1->weight);
626
+ else if (name == "manifold.proj1.bias") load_tensor_data(manifold_proj1->bias);
627
+ else if (name == "manifold.norm.weight") load_tensor_data(manifold_norm->weight);
628
+ else if (name == "manifold.norm.bias") load_tensor_data(manifold_norm->bias);
629
+ else if (name == "manifold.proj2.weight") load_tensor_data(manifold_proj2->weight);
630
+ else if (name == "manifold.proj2.bias") load_tensor_data(manifold_proj2->bias);
631
+
632
+ // === 输出融合 ===
633
+ else if (name == "output_fusion.down.weight") load_tensor_data(output_fusion_down->weight);
634
+ else if (name == "output_fusion.down.bias") load_tensor_data(output_fusion_down->bias);
635
+ else if (name == "output_fusion.bn_norm.weight") load_tensor_data(output_fusion_bottleneck_norm->weight);
636
+ else if (name == "output_fusion.bn_norm.bias") load_tensor_data(output_fusion_bottleneck_norm->bias);
637
+ else if (name == "output_fusion.up.weight") load_tensor_data(output_fusion_up->weight);
638
+ else if (name == "output_fusion.up.bias") load_tensor_data(output_fusion_up->bias);
639
+ else if (name == "output_fusion.norm.weight") load_tensor_data(output_fusion_norm->weight);
640
+ else if (name == "output_fusion.norm.bias") load_tensor_data(output_fusion_norm->bias);
641
+
642
+ // Unknown layer — skip
643
+ else {
644
+ uint32_t ndim, dsize;
645
+ ifs.read(reinterpret_cast<char*>(&ndim), 4);
646
+ ifs.seekg(ndim * 4, std::ios::cur);
647
+ ifs.read(reinterpret_cast<char*>(&dsize), 4);
648
+ ifs.seekg(dsize, std::ios::cur);
649
+ }
650
+ }
651
+ ifs.close();
652
+ }
653
+ };
654
+
655
+ /**
656
+ * NeuroFlowLite - 超轻量版
657
+ * 适合边缘设备部署
658
+ */
659
+ class NeuroFlowLite : public NeuroFlowModel {
660
+ public:
661
+ NeuroFlowLite(size_t input_dim = 512) : NeuroFlowModel() {
662
+ Config cfg;
663
+ cfg.input_dim = input_dim;
664
+ cfg.hidden_dim = 128;
665
+ cfg.output_dim = 10;
666
+ cfg.memory_dim = 64;
667
+ cfg.memory_slots = 32;
668
+ cfg.num_layers = 1;
669
+ cfg.num_associations = 4;
670
+ cfg.use_quantization = true;
671
+ cfg.use_mla = true;
672
+ cfg.mla_latent_dim = 32;
673
+
674
+ // 需要重新初始化...
675
+ }
676
+ };
677
+
678
+ } // namespace neuroflow
679
+
680
+ #endif // NEUROFLOW_MODEL_HPP
include/neuroflow/multimodal.hpp ADDED
@@ -0,0 +1,441 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_MULTIMODAL_HPP
2
+ #define NEUROFLOW_MULTIMODAL_HPP
3
+
4
+ /**
5
+ * NeuroFlow 多模态模块
6
+ *
7
+ * Vision-Language能力:
8
+ * 1. VisionEncoder - 轻量ViT风格图像编码
9
+ * 2. CrossModalFusion - 文本-图像对齐融合
10
+ * 3. MultiModalAttention - 跨模态注意力
11
+ *
12
+ * 与类脑模块整合:
13
+ * - ECN处理多模态推理决策
14
+ * - DMN处理跨模态联想记忆
15
+ * - SN处理多模态显著性分配
16
+ */
17
+
18
+ #include <cmath>
19
+ #include <memory>
20
+ #include <vector>
21
+ #include "networks.hpp"
22
+ #include "tensor.hpp"
23
+
24
+ namespace neuroflow {
25
+
26
+ /**
27
+ * PatchEmbedding - 图像Patch嵌入
28
+ *
29
+ * 将图像分割成patch并嵌入到向量空间
30
+ * ViT风格,但轻量化实现
31
+ */
32
+ class PatchEmbedding {
33
+ public:
34
+ size_t patch_size; // patch大小 (如16x16)
35
+ size_t image_size; // 图像大小 (如224x224)
36
+ size_t in_channels; // 输入通道 (如3 for RGB)
37
+ size_t embed_dim; // 嵌入维度
38
+ size_t num_patches; // patch数量
39
+
40
+ std::shared_ptr<Linear> proj; // 投影层
41
+ Tensor pos_embedding; // 位置编码
42
+
43
+ PatchEmbedding(size_t img_size = 224, size_t patch = 16,
44
+ size_t channels = 3, size_t embed = 256)
45
+ : image_size(img_size), patch_size(patch),
46
+ in_channels(channels), embed_dim(embed) {
47
+
48
+ // 边界检查:确保 image_size >= patch 且能整除
49
+ if (img_size < patch || img_size % patch != 0) {
50
+ throw std::invalid_argument("image_size must be >= patch_size and divisible by patch_size");
51
+ }
52
+ num_patches = (img_size / patch) * (img_size / patch);
53
+
54
+ // 投影: patch_size*patch_size*channels -> embed_dim
55
+ size_t patch_dim = patch * patch * channels;
56
+ proj = std::make_shared<Linear>(patch_dim, embed_dim);
57
+
58
+ // 位置编码 (可学习)
59
+ pos_embedding = Tensor({num_patches, embed_dim}, QuantType::FP32);
60
+ float* pe = pos_embedding.as_fp32();
61
+ // 使用正弦位置编码初始化
62
+ for (size_t i = 0; i < num_patches; ++i) {
63
+ for (size_t j = 0; j < embed_dim; ++j) {
64
+ if (j % 2 == 0) {
65
+ pe[i * embed_dim + j] = std::sin(i / std::pow(10000, j / static_cast<float>(embed_dim)));
66
+ } else {
67
+ pe[i * embed_dim + j] = std::cos(i / std::pow(10000, (j-1) / static_cast<float>(embed_dim)));
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ // 从图像数据提取patch并嵌入
74
+ Tensor forward(const Tensor& image) {
75
+ // image: {batch, channels, height, width} 或 {batch, height, width, channels}
76
+ size_t batch = image.shape_[0];
77
+
78
+ // 假设输入是 {batch, channels, height, width}
79
+ // 简化处理:将每个patch展平后投影
80
+
81
+ Tensor embedded({batch * num_patches, embed_dim}, QuantType::FP32);
82
+ float* emb = embedded.as_fp32();
83
+ const float* img = image.as_fp32();
84
+ float* pe = pos_embedding.as_fp32();
85
+
86
+ size_t patch_pixels = patch_size * patch_size * in_channels;
87
+ size_t patches_per_row = image_size / patch_size;
88
+
89
+ // 逐patch提取并投影
90
+ for (size_t b = 0; b < batch; ++b) {
91
+ for (size_t pi = 0; pi < patches_per_row; ++pi) {
92
+ for (size_t pj = 0; pj < patches_per_row; ++pj) {
93
+ size_t patch_idx = pi * patches_per_row + pj;
94
+
95
+ // 提取patch数据 (简化版)
96
+ // 实际应该从image中提取对应区域的像素
97
+ // 这里简化为直接使用随机值模拟
98
+
99
+ // 添加位置编码
100
+ for (size_t d = 0; d < embed_dim; ++d) {
101
+ emb[(b * num_patches + patch_idx) * embed_dim + d] =
102
+ pe[patch_idx * embed_dim + d]; // 初始化为位置编码
103
+ }
104
+ }
105
+ }
106
+ }
107
+
108
+ // 投影 (简化:直接使用嵌入)
109
+ // 实际应该调用 proj->forward(patch_flat)
110
+
111
+ return embedded.reshape({batch, num_patches, embed_dim});
112
+ }
113
+ };
114
+
115
+ /**
116
+ * VisionEncoder - 轻量ViT风格图像编码器
117
+ *
118
+ * 特点:
119
+ * - Patch embedding
120
+ * - 简化Transformer层
121
+ * - 输出图像特征向量
122
+ */
123
+ class VisionEncoder {
124
+ public:
125
+ size_t embed_dim;
126
+ size_t num_heads;
127
+ size_t num_layers;
128
+ size_t image_size;
129
+ size_t patch_size;
130
+
131
+ std::shared_ptr<PatchEmbedding> patch_embed;
132
+
133
+ // 简化Transformer层
134
+ std::vector<std::shared_ptr<Linear>> self_attn_qkv;
135
+ std::vector<std::shared_ptr<Linear>> self_attn_proj;
136
+ std::vector<std::shared_ptr<LayerNorm>> attn_norm;
137
+ std::vector<std::shared_ptr<Linear>> mlp_fc1;
138
+ std::vector<std::shared_ptr<Linear>> mlp_fc2;
139
+ std::vector<std::shared_ptr<LayerNorm>> mlp_norm;
140
+
141
+ // 输出投影
142
+ std::shared_ptr<Linear> output_proj;
143
+
144
+ VisionEncoder(size_t img_size = 224, size_t patch = 16,
145
+ size_t embed = 256, size_t heads = 8, size_t layers = 4)
146
+ : image_size(img_size), patch_size(patch),
147
+ embed_dim(embed), num_heads(heads), num_layers(layers) {
148
+
149
+ // Patch embedding
150
+ patch_embed = std::make_shared<PatchEmbedding>(img_size, patch, 3, embed);
151
+
152
+ // 边界检查:确保 embed >= heads
153
+ if (embed < heads || embed % heads != 0) {
154
+ throw std::invalid_argument("embed_dim must be >= num_heads and divisible by num_heads");
155
+ }
156
+ // Transformer层 (简化版)
157
+ size_t head_dim = embed / heads;
158
+
159
+ for (size_t i = 0; i < layers; ++i) {
160
+ // Self-attention Q, K, V
161
+ self_attn_qkv.push_back(std::make_shared<Linear>(embed, embed * 3, false));
162
+ self_attn_proj.push_back(std::make_shared<Linear>(embed, embed));
163
+ attn_norm.push_back(std::make_shared<LayerNorm>(embed));
164
+
165
+ // MLP
166
+ mlp_fc1.push_back(std::make_shared<Linear>(embed, embed * 4));
167
+ mlp_fc2.push_back(std::make_shared<Linear>(embed * 4, embed));
168
+ mlp_norm.push_back(std::make_shared<LayerNorm>(embed));
169
+ }
170
+
171
+ // 输出投影 (将patch序列压缩为单一特征向量)
172
+ output_proj = std::make_shared<Linear>(embed, embed);
173
+ }
174
+
175
+ // 前向传播
176
+ Tensor forward(const Tensor& image) {
177
+ // Patch embedding
178
+ Tensor x = patch_embed->forward(image);
179
+ size_t batch = x.shape_[0];
180
+ size_t num_patches = x.shape_[1];
181
+
182
+ // Transformer层处理
183
+ for (size_t i = 0; i < num_layers; ++i) {
184
+ // Self-attention (简化实现)
185
+ Tensor normed = attn_norm[i]->forward(x.reshape({batch * num_patches, embed_dim}));
186
+ normed = normed.reshape({batch, num_patches, embed_dim});
187
+
188
+ // QKV projection
189
+ Tensor qkv = self_attn_qkv[i]->forward(normed.reshape({batch * num_patches, embed_dim}));
190
+ // 简化:直接使用normed作为attention输出
191
+
192
+ Tensor attn_out({batch * num_patches, embed_dim}, QuantType::FP32);
193
+ float* ao = attn_out.as_fp32();
194
+ float* n = normed.as_fp32();
195
+ for (size_t j = 0; j < batch * num_patches * embed_dim; ++j) {
196
+ ao[j] = n[j]; // 简化:identity
197
+ }
198
+
199
+ attn_out = self_attn_proj[i]->forward(attn_out);
200
+
201
+ // 残差
202
+ float* x_data = x.as_fp32();
203
+ for (size_t j = 0; j < x.numel(); ++j) {
204
+ x_data[j] += ao[j];
205
+ }
206
+
207
+ // MLP
208
+ Tensor mlp_in = mlp_norm[i]->forward(x.reshape({batch * num_patches, embed_dim}));
209
+ Tensor mlp_hidden = mlp_fc1[i]->forward(mlp_in);
210
+ TensorOps::gelu(mlp_hidden);
211
+ Tensor mlp_out = mlp_fc2[i]->forward(mlp_hidden);
212
+
213
+ // 残差
214
+ for (size_t j = 0; j < x.numel(); ++j) {
215
+ x_data[j] += mlp_out.as_fp32()[j];
216
+ }
217
+ }
218
+
219
+ // 全局平均池化 + 输出投影
220
+ Tensor global_feat({batch, embed_dim}, QuantType::FP32);
221
+ float* gf = global_feat.as_fp32();
222
+ float* x_data = x.as_fp32();
223
+
224
+ for (size_t b = 0; b < batch; ++b) {
225
+ for (size_t d = 0; d < embed_dim; ++d) {
226
+ float sum = 0;
227
+ for (size_t p = 0; p < num_patches; ++p) {
228
+ sum += x_data[(b * num_patches + p) * embed_dim + d];
229
+ }
230
+ gf[b * embed_dim + d] = sum / num_patches;
231
+ }
232
+ }
233
+
234
+ return output_proj->forward(global_feat);
235
+ }
236
+
237
+ void quantize() {
238
+ patch_embed->proj->quantize();
239
+ for (auto& l : self_attn_qkv) l->quantize();
240
+ for (auto& l : self_attn_proj) l->quantize();
241
+ for (auto& l : mlp_fc1) l->quantize();
242
+ for (auto& l : mlp_fc2) l->quantize();
243
+ output_proj->quantize();
244
+ }
245
+ };
246
+
247
+ /**
248
+ * CrossModalFusion - 跨模态融合层
249
+ *
250
+ * 将文本特征和图像特征对齐融合
251
+ * 类似CLIP的对比学习风格
252
+ */
253
+ class CrossModalFusion {
254
+ public:
255
+ size_t text_dim;
256
+ size_t image_dim;
257
+ size_t fusion_dim;
258
+
259
+ // 文本投影到公共空间
260
+ std::shared_ptr<Linear> text_proj;
261
+
262
+ // 图像投影到公共空间
263
+ std::shared_ptr<Linear> image_proj;
264
+
265
+ // 融合层
266
+ std::shared_ptr<Linear> fusion_layer;
267
+ std::shared_ptr<LayerNorm> fusion_norm;
268
+
269
+ CrossModalFusion(size_t text_d, size_t image_d, size_t fusion_d)
270
+ : text_dim(text_d), image_dim(image_d), fusion_dim(fusion_d) {
271
+
272
+ text_proj = std::make_shared<Linear>(text_d, fusion_d);
273
+ image_proj = std::make_shared<Linear>(image_d, fusion_d);
274
+ fusion_layer = std::make_shared<Linear>(fusion_d * 2, fusion_d);
275
+ fusion_norm = std::make_shared<LayerNorm>(fusion_d);
276
+ }
277
+
278
+ struct Output {
279
+ Tensor fused; // 融合特征
280
+ Tensor text_feat; // 文本特征 (对齐后)
281
+ Tensor image_feat; // 图像特征 (对齐后)
282
+ Tensor similarity; // 文本-图像相似度分数
283
+ };
284
+
285
+ // 前向传播
286
+ Output forward(const Tensor& text_features, const Tensor& image_features) {
287
+ Output out;
288
+ size_t batch = text_features.shape_[0];
289
+
290
+ // 投影到公共空间
291
+ out.text_feat = text_proj->forward(text_features);
292
+ out.image_feat = image_proj->forward(image_features);
293
+
294
+ // L2归一化 (用于相似度计算)
295
+ float* tf = out.text_feat.as_fp32();
296
+ float* if_ = out.image_feat.as_fp32();
297
+
298
+ for (size_t b = 0; b < batch; ++b) {
299
+ // 文本归一化
300
+ float t_norm = 0;
301
+ for (size_t d = 0; d < fusion_dim; ++d) {
302
+ t_norm += tf[b * fusion_dim + d] * tf[b * fusion_dim + d];
303
+ }
304
+ t_norm = std::sqrt(t_norm) + 1e-8f;
305
+ for (size_t d = 0; d < fusion_dim; ++d) {
306
+ tf[b * fusion_dim + d] /= t_norm;
307
+ }
308
+
309
+ // 图像归一化
310
+ float i_norm = 0;
311
+ for (size_t d = 0; d < fusion_dim; ++d) {
312
+ i_norm += if_[b * fusion_dim + d] * if_[b * fusion_dim + d];
313
+ }
314
+ i_norm = std::sqrt(i_norm) + 1e-8f;
315
+ for (size_t d = 0; d < fusion_dim; ++d) {
316
+ if_[b * fusion_dim + d] /= i_norm;
317
+ }
318
+ }
319
+
320
+ // 计算相似度 (余弦相似度)
321
+ out.similarity = Tensor({batch, 1}, QuantType::FP32);
322
+ float* sim = out.similarity.as_fp32();
323
+
324
+ for (size_t b = 0; b < batch; ++b) {
325
+ float dot = 0;
326
+ for (size_t d = 0; d < fusion_dim; ++d) {
327
+ dot += tf[b * fusion_dim + d] * if_[b * fusion_dim + d];
328
+ }
329
+ sim[b] = dot; // 归一化后的余弦相似度
330
+ }
331
+
332
+ // 融合特征: concat(text_feat, image_feat) -> fusion
333
+ Tensor concat_feat({batch, fusion_dim * 2}, QuantType::FP32);
334
+ float* cf = concat_feat.as_fp32();
335
+
336
+ for (size_t b = 0; b < batch; ++b) {
337
+ for (size_t d = 0; d < fusion_dim; ++d) {
338
+ cf[b * fusion_dim * 2 + d] = tf[b * fusion_dim + d];
339
+ cf[b * fusion_dim * 2 + fusion_dim + d] = if_[b * fusion_dim + d];
340
+ }
341
+ }
342
+
343
+ out.fused = fusion_layer->forward(concat_feat);
344
+ out.fused = fusion_norm->forward(out.fused);
345
+
346
+ return out;
347
+ }
348
+
349
+ void quantize() {
350
+ text_proj->quantize();
351
+ image_proj->quantize();
352
+ fusion_layer->quantize();
353
+ }
354
+ };
355
+
356
+ /**
357
+ * MultiModalAttention - 跨模态注意力
358
+ *
359
+ * 让文本关注图像区域,图像关注文本token
360
+ * 类似LLaVA的cross-attention机制
361
+ */
362
+ class MultiModalAttention {
363
+ public:
364
+ size_t text_dim;
365
+ size_t image_dim;
366
+ size_t num_heads;
367
+ size_t head_dim;
368
+
369
+ // Text -> Image cross-attention
370
+ std::shared_ptr<Linear> text_query;
371
+ std::shared_ptr<Linear> image_key;
372
+ std::shared_ptr<Linear> image_value;
373
+ std::shared_ptr<Linear> text_output;
374
+
375
+ // Image -> Text cross-attention
376
+ std::shared_ptr<Linear> image_query;
377
+ std::shared_ptr<Linear> text_key;
378
+ std::shared_ptr<Linear> text_value;
379
+ std::shared_ptr<Linear> image_output;
380
+
381
+ MultiModalAttention(size_t text_d, size_t image_d, size_t heads = 8)
382
+ : text_dim(text_d), image_dim(image_d), num_heads(heads),
383
+ head_dim(std::min(text_d, image_d) / heads) {
384
+
385
+ // Text -> Image
386
+ text_query = std::make_shared<Linear>(text_d, num_heads * head_dim, false);
387
+ image_key = std::make_shared<Linear>(image_d, num_heads * head_dim, false);
388
+ image_value = std::make_shared<Linear>(image_d, num_heads * head_dim, false);
389
+ text_output = std::make_shared<Linear>(num_heads * head_dim, text_d);
390
+
391
+ // Image -> Text
392
+ image_query = std::make_shared<Linear>(image_d, num_heads * head_dim, false);
393
+ text_key = std::make_shared<Linear>(text_d, num_heads * head_dim, false);
394
+ text_value = std::make_shared<Linear>(text_d, num_heads * head_dim, false);
395
+ image_output = std::make_shared<Linear>(num_heads * head_dim, image_d);
396
+ }
397
+
398
+ // Text attends to Image
399
+ Tensor text_attend_image(const Tensor& text, const Tensor& image) {
400
+ size_t batch = text.shape_[0];
401
+
402
+ // 简化实现:直接处理二维特征
403
+ // 不尝试 reshape 到三维
404
+
405
+ Tensor query = text_query->forward(text);
406
+ Tensor value = image_value->forward(image);
407
+
408
+ size_t out_dim = num_heads * head_dim;
409
+
410
+ // 简化的attention输出
411
+ Tensor output({batch, out_dim}, QuantType::FP32);
412
+ float* q = query.as_fp32();
413
+ float* v = value.as_fp32();
414
+ float* o = output.as_fp32();
415
+
416
+ // 简化:加权平均
417
+ for (size_t b = 0; b < batch; ++b) {
418
+ for (size_t d = 0; d < out_dim; ++d) {
419
+ o[b * out_dim + d] = q[b * out_dim + d] * 0.5f
420
+ + v[b * out_dim + d] * 0.5f;
421
+ }
422
+ }
423
+
424
+ return text_output->forward(output);
425
+ }
426
+
427
+ void quantize() {
428
+ text_query->quantize();
429
+ image_key->quantize();
430
+ image_value->quantize();
431
+ text_output->quantize();
432
+ image_query->quantize();
433
+ text_key->quantize();
434
+ text_value->quantize();
435
+ image_output->quantize();
436
+ }
437
+ };
438
+
439
+ } // namespace neuroflow
440
+
441
+ #endif // NEUROFLOW_MULTIMODAL_HPP
include/neuroflow/multimodal_model.hpp ADDED
@@ -0,0 +1,702 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_MULTIMODAL_MODEL_HPP
2
+ #define NEUROFLOW_MULTIMODAL_MODEL_HPP
3
+
4
+ #include <fstream>
5
+ #include <string>
6
+
7
+ /**
8
+ * NeuroFlowMultiModal - 多模态类脑模块化神经网络
9
+ *
10
+ * 整合:
11
+ * 1. Vision Encoder (图像编码)
12
+ * 2. Cross-Modal Fusion (文本-图像融合)
13
+ * 3. ExecutiveControlNetwork (ECN) - 多模态推理决策
14
+ * 4. DefaultModeNetwork (DMN) - 跨模态联想记忆
15
+ * 5. SalienceNetwork (SN) - 多模态显著性分配
16
+ * 6. Memory Module - 长记忆存储
17
+ */
18
+
19
+ #include "tensor.hpp"
20
+ #include "networks.hpp"
21
+ #include "memory.hpp"
22
+ #include "multimodal.hpp"
23
+ #include <vector>
24
+ #include <memory>
25
+ #include <unordered_map>
26
+
27
+ namespace neuroflow {
28
+
29
+ /**
30
+ * NeuroFlowMultiModal - 多模态类脑神经网络
31
+ */
32
+ class NeuroFlowMultiModal {
33
+ public:
34
+ // 配置
35
+ struct Config {
36
+ size_t text_dim = 512; // 文本特征维度
37
+ size_t image_size = 224; // 图像大小
38
+ size_t patch_size = 16; // ViT patch大小
39
+ size_t vision_dim = 256; // 视觉编码维度
40
+ size_t fusion_dim = 256; // 融合维度
41
+ size_t hidden_dim = 256; // 隐藏维度
42
+ size_t output_dim = 10; // 输出维度
43
+ size_t memory_dim = 128; // 记忆维度
44
+ size_t memory_slots = 64; // 记忆槽数量
45
+ size_t num_layers = 2; // ECN层数
46
+ size_t num_associations = 8; // DMN联想头数量
47
+ size_t vision_layers = 4; // Vision Encoder层数
48
+ size_t vision_heads = 8; // Vision注意力头数
49
+ bool use_quantization = false;
50
+ bool use_mla = false;
51
+ size_t mla_latent_dim = 32;
52
+ };
53
+
54
+ Config config;
55
+
56
+ // ========== 多模态组件 ==========
57
+ std::unique_ptr<VisionEncoder> vision_encoder;
58
+ std::unique_ptr<CrossModalFusion> cross_modal_fusion;
59
+ std::unique_ptr<MultiModalAttention> multimodal_attention;
60
+
61
+ // ========== 类脑模块 ==========
62
+ std::unique_ptr<ExecutiveControlNetwork> ecn;
63
+ std::unique_ptr<DefaultModeNetwork> dmn;
64
+ std::unique_ptr<SalienceNetwork> sn;
65
+ std::unique_ptr<MemoryConsolidationModule> memory;
66
+ std::unique_ptr<LatentKVCache> mla_cache;
67
+
68
+ // ========== 输入投影 ==========
69
+ std::shared_ptr<Linear> text_proj;
70
+ std::shared_ptr<LayerNorm> text_norm;
71
+
72
+ // ========== 融合后处理 ==========
73
+ std::shared_ptr<Linear> multimodal_proj;
74
+ std::shared_ptr<LayerNorm> multimodal_norm;
75
+
76
+ // ========== 输出层 ==========
77
+ std::shared_ptr<Linear> output_layer;
78
+ std::shared_ptr<LayerNorm> output_norm;
79
+
80
+ // ========== 流形投影 ==========
81
+ std::shared_ptr<Linear> manifold_proj1;
82
+ std::shared_ptr<LayerNorm> manifold_norm;
83
+ std::shared_ptr<Linear> manifold_proj2;
84
+
85
+ bool training_mode;
86
+
87
+ NeuroFlowMultiModal(const Config& cfg) : config(cfg), training_mode(false) {
88
+
89
+ // 多模态组件
90
+ vision_encoder = std::make_unique<VisionEncoder>(
91
+ config.image_size, config.patch_size,
92
+ config.vision_dim, config.vision_heads, config.vision_layers);
93
+
94
+ cross_modal_fusion = std::make_unique<CrossModalFusion>(
95
+ config.text_dim, config.vision_dim, config.fusion_dim);
96
+
97
+ multimodal_attention = std::make_unique<MultiModalAttention>(
98
+ config.fusion_dim, config.fusion_dim, 8);
99
+
100
+ // 文本投影
101
+ text_proj = std::make_shared<Linear>(config.text_dim, config.hidden_dim);
102
+ text_norm = std::make_shared<LayerNorm>(config.hidden_dim);
103
+
104
+ // 多模态融合投影
105
+ multimodal_proj = std::make_shared<Linear>(config.fusion_dim, config.hidden_dim);
106
+ multimodal_norm = std::make_shared<LayerNorm>(config.hidden_dim);
107
+
108
+ // 类脑模块 (基于融合后的特征)
109
+ ecn = std::make_unique<ExecutiveControlNetwork>(
110
+ config.hidden_dim, config.hidden_dim, config.output_dim, config.num_layers);
111
+
112
+ dmn = std::make_unique<DefaultModeNetwork>(
113
+ config.memory_dim, config.hidden_dim / 2, config.num_associations);
114
+
115
+ sn = std::make_unique<SalienceNetwork>(
116
+ config.hidden_dim, config.hidden_dim / 2);
117
+
118
+ memory = std::make_unique<MemoryConsolidationModule>(
119
+ config.hidden_dim, config.memory_slots, config.memory_dim);
120
+
121
+ if (config.use_mla) {
122
+ mla_cache = std::make_unique<LatentKVCache>(
123
+ config.hidden_dim, 8, config.mla_latent_dim, 4096);
124
+ }
125
+
126
+ // 输出层
127
+ output_layer = std::make_shared<Linear>(config.hidden_dim, config.output_dim);
128
+ output_norm = std::make_shared<LayerNorm>(config.output_dim);
129
+
130
+ // 流形投影
131
+ manifold_proj1 = std::make_shared<Linear>(config.hidden_dim, config.hidden_dim);
132
+ manifold_norm = std::make_shared<LayerNorm>(config.hidden_dim);
133
+ manifold_proj2 = std::make_shared<Linear>(config.hidden_dim, 32);
134
+
135
+ if (config.use_quantization) {
136
+ quantize();
137
+ }
138
+ }
139
+
140
+ NeuroFlowMultiModal() : NeuroFlowMultiModal(Config()) {}
141
+
142
+ // ========== 输出结构 ==========
143
+ struct Output {
144
+ Tensor output; // 最终输出
145
+ Tensor decision; // ECN决策
146
+ Tensor value; // OFC价值
147
+ Tensor saliency; // SN显著性
148
+ Tensor text_image_sim; // 文本-图像相似度
149
+ Tensor gates; // ECN/DMN门控
150
+ Tensor anomaly; // 异常评分
151
+ Tensor retrieved_mem; // 检索记忆
152
+ Tensor manifold; // 流形表征
153
+ Tensor vision_feat; // 视觉特征
154
+ Tensor text_feat; // 文本特征 (对齐后)
155
+ Tensor fused_feat; // 融合特征
156
+ };
157
+
158
+ // ========== 纯文本模式 ==========
159
+ Output forward_text(const Tensor& text_input) {
160
+ Output out;
161
+ size_t batch = text_input.shape_[0];
162
+
163
+ // 文本投影
164
+ Tensor h = text_proj->forward(text_input);
165
+ h = text_norm->forward(h);
166
+
167
+ // 类脑处理 (纯文本模式)
168
+ auto sn_out = sn->forward(h);
169
+ auto ecn_out = ecn->forward(h);
170
+
171
+ out.saliency = sn_out.saliency;
172
+ out.gates = sn_out.gates;
173
+ out.decision = ecn_out.decision;
174
+ out.value = ecn_out.value;
175
+
176
+ // 记忆
177
+ auto mem_out = memory->forward(h);
178
+ out.retrieved_mem = mem_out.retrieved;
179
+
180
+ // 输出
181
+ out.output = output_layer->forward(h);
182
+ out.output = output_norm->forward(out.output);
183
+
184
+ return out;
185
+ }
186
+
187
+ // ========== 多模态模式 (文本+图像) ==========
188
+ Output forward_multimodal(const Tensor& text_input, const Tensor& image_input,
189
+ bool consolidate = false, bool return_manifold = false) {
190
+ Output out;
191
+ size_t batch = text_input.shape_[0];
192
+
193
+ // 1. Vision Encoder: 图像编码
194
+ Tensor vision_feat = vision_encoder->forward(image_input);
195
+ out.vision_feat = vision_feat.clone();
196
+
197
+ // 2. Cross-Modal Fusion: 文本-图像对齐融合
198
+ auto fusion_out = cross_modal_fusion->forward(text_input, vision_feat);
199
+ out.text_feat = fusion_out.text_feat.clone();
200
+ out.text_image_sim = fusion_out.similarity.clone();
201
+ out.fused_feat = fusion_out.fused.clone();
202
+
203
+ // 3. 多模态融合投影
204
+ Tensor multimodal_h = multimodal_proj->forward(fusion_out.fused);
205
+ multimodal_h = multimodal_norm->forward(multimodal_h);
206
+
207
+ // 4. Cross-Modal Attention (可选增强)
208
+ Tensor text_enhanced = multimodal_attention->text_attend_image(
209
+ text_proj->forward(text_input), vision_feat);
210
+
211
+ // 残差融合
212
+ float* mh = multimodal_h.as_fp32();
213
+ float* te = text_enhanced.as_fp32();
214
+ size_t min_dim = std::min(multimodal_h.shape_[1], text_enhanced.shape_[1]);
215
+ for (size_t b = 0; b < batch; ++b) {
216
+ for (size_t d = 0; d < min_dim; ++d) {
217
+ mh[b * multimodal_h.shape_[1] + d] += 0.3f * te[b * text_enhanced.shape_[1] + d];
218
+ }
219
+ }
220
+
221
+ // 5. Salience Network: 多模态显著性检测
222
+ auto sn_out = sn->forward(multimodal_h);
223
+ out.saliency = sn_out.saliency;
224
+ out.gates = sn_out.gates;
225
+ out.anomaly = sn_out.anomaly;
226
+
227
+ // 提取门控
228
+ float* gates = out.gates.as_fp32();
229
+ Tensor ecn_gate({batch, 1}, QuantType::FP32);
230
+ Tensor dmn_gate({batch, 1}, QuantType::FP32);
231
+ for (size_t i = 0; i < batch; ++i) {
232
+ ecn_gate.as_fp32()[i] = gates[i * 2];
233
+ dmn_gate.as_fp32()[i] = gates[i * 2 + 1];
234
+ }
235
+
236
+ // 6. ECN: 多模态推理决策 (模拟前额叶整合视觉信息做决策)
237
+ auto ecn_out = ecn->forward(multimodal_h);
238
+ out.decision = ecn_out.decision;
239
+ out.value = ecn_out.value;
240
+
241
+ // 7. DMN: 跨模态联想记忆 (模拟后扣带回将视觉与记忆关联)
242
+ Tensor mem_seed = memory->encode(multimodal_h);
243
+ auto dmn_out = dmn->forward(mem_seed);
244
+
245
+ // 8. Memory Retrieval
246
+ auto mem_out = memory->forward(multimodal_h);
247
+ out.retrieved_mem = mem_out.retrieved;
248
+
249
+ if (consolidate) {
250
+ memory->consolidate(multimodal_h);
251
+ }
252
+
253
+ // 9. 门控加权融合
254
+ Tensor ecn_weighted = out.decision.clone();
255
+ Tensor dmn_weighted = dmn_out.vision.reshape({batch, dmn_out.vision.shape_[1]});
256
+
257
+ float* eg = ecn_gate.as_fp32();
258
+ float* dg = dmn_gate.as_fp32();
259
+ float* ew = ecn_weighted.as_fp32();
260
+ float* dw = dmn_weighted.as_fp32();
261
+
262
+ for (size_t i = 0; i < batch; ++i) {
263
+ for (size_t j = 0; j < config.output_dim && j < ecn_weighted.shape_[1]; ++j) {
264
+ ew[i * ecn_weighted.shape_[1] + j] *= eg[i];
265
+ }
266
+ for (size_t j = 0; j < dmn_weighted.shape_[1]; ++j) {
267
+ dw[i * dmn_weighted.shape_[1] + j] *= dg[i];
268
+ }
269
+ }
270
+
271
+ // 10. 最终融合输出
272
+ // 综合ECN决策 + DMN联想 + Memory + 融合特征
273
+ Tensor combined({batch, config.hidden_dim}, QuantType::FP32);
274
+ float* c = combined.as_fp32();
275
+
276
+ // 加权组合
277
+ for (size_t b = 0; b < batch; ++b) {
278
+ for (size_t d = 0; d < config.hidden_dim; ++d) {
279
+ float val = 0;
280
+ if (d < out.decision.shape_[1]) {
281
+ val += 0.3f * ew[b * out.decision.shape_[1] + d];
282
+ }
283
+ if (d < dmn_weighted.shape_[1]) {
284
+ val += 0.2f * dw[b * dmn_weighted.shape_[1] + d];
285
+ }
286
+ if (d < out.retrieved_mem.shape_[1]) {
287
+ val += 0.2f * out.retrieved_mem.as_fp32()[b * out.retrieved_mem.shape_[1] + d];
288
+ }
289
+ if (d < multimodal_h.shape_[1]) {
290
+ val += 0.3f * mh[b * multimodal_h.shape_[1] + d];
291
+ }
292
+ c[b * config.hidden_dim + d] = val;
293
+ }
294
+ }
295
+
296
+ out.output = output_layer->forward(combined);
297
+ out.output = output_norm->forward(out.output);
298
+
299
+ // 11. 流形 (可选)
300
+ if (return_manifold) {
301
+ Tensor manifold_in({batch, config.hidden_dim}, QuantType::FP32);
302
+ float* mi = manifold_in.as_fp32();
303
+ float* eh = ecn_out.hidden_states.back().as_fp32();
304
+
305
+ for (size_t i = 0; i < batch; ++i) {
306
+ for (size_t j = 0; j < config.hidden_dim && j < ecn_out.hidden_states.back().shape_[1]; ++j) {
307
+ mi[i * config.hidden_dim + j] = eh[i * ecn_out.hidden_states.back().shape_[1] + j];
308
+ }
309
+ for (size_t j = ecn_out.hidden_states.back().shape_[1]; j < config.hidden_dim; ++j) {
310
+ mi[i * config.hidden_dim + j] = 0;
311
+ }
312
+ }
313
+
314
+ Tensor m = manifold_proj1->forward(manifold_in);
315
+ m = manifold_norm->forward(m);
316
+ TensorOps::gelu(m);
317
+ out.manifold = manifold_proj2->forward(m);
318
+ }
319
+
320
+ return out;
321
+ }
322
+
323
+ // ========== 通用forward接口 ==========
324
+ Output forward(const Tensor& text_input, const Tensor* image_input = nullptr,
325
+ bool consolidate = false, bool return_manifold = false) {
326
+ if (image_input) {
327
+ return forward_multimodal(text_input, *image_input, consolidate, return_manifold);
328
+ } else {
329
+ return forward_text(text_input);
330
+ }
331
+ }
332
+
333
+ // ========== 图像理解模式 (无文本,纯视觉推理) ==========
334
+ Output forward_image_only(const Tensor& image_input) {
335
+ Output out;
336
+ size_t batch = image_input.shape_[0];
337
+
338
+ // Vision Encoder
339
+ Tensor vision_feat = vision_encoder->forward(image_input);
340
+ out.vision_feat = vision_feat.clone();
341
+
342
+ // 直接投影到隐藏层
343
+ Tensor h = multimodal_proj->forward(vision_feat);
344
+ h = multimodal_norm->forward(h);
345
+
346
+ // 类脑处理 (纯视觉决策)
347
+ auto sn_out = sn->forward(h);
348
+ auto ecn_out = ecn->forward(h);
349
+
350
+ out.saliency = sn_out.saliency;
351
+ out.gates = sn_out.gates;
352
+ out.decision = ecn_out.decision;
353
+ out.value = ecn_out.value;
354
+
355
+ // 记忆
356
+ auto mem_out = memory->forward(h);
357
+ out.retrieved_mem = mem_out.retrieved;
358
+
359
+ // 输出
360
+ out.output = output_layer->forward(h);
361
+ out.output = output_norm->forward(out.output);
362
+
363
+ return out;
364
+ }
365
+
366
+ // ========== 设置训练模式 ==========
367
+ void set_training(bool t) {
368
+ training_mode = t;
369
+ ecn->set_training(t);
370
+ }
371
+
372
+ // ========== 量化 ==========
373
+ void quantize() {
374
+ vision_encoder->quantize();
375
+ cross_modal_fusion->quantize();
376
+ multimodal_attention->quantize();
377
+ text_proj->quantize();
378
+ multimodal_proj->quantize();
379
+ output_layer->quantize();
380
+ manifold_proj1->quantize();
381
+ manifold_proj2->quantize();
382
+ ecn->quantize();
383
+ dmn->quantize();
384
+ sn->quantize();
385
+ memory->encode_proj->quantize();
386
+ memory->retrieve_proj->quantize();
387
+ memory->query_proj->quantize();
388
+ }
389
+
390
+ // ========== 获取模型统计 ==========
391
+ struct Stats {
392
+ size_t total_params;
393
+ size_t vision_params;
394
+ size_t fusion_params;
395
+ size_t brain_params;
396
+ size_t memory_bytes;
397
+ float quantization_ratio;
398
+ };
399
+
400
+ Stats get_stats() {
401
+ Stats s;
402
+ s.total_params = 0;
403
+ s.vision_params = 0;
404
+ s.fusion_params = 0;
405
+ s.brain_params = 0;
406
+ s.memory_bytes = 0;
407
+ s.quantization_ratio = 0.0f;
408
+
409
+ auto count_linear = [&](std::shared_ptr<Linear>& l, size_t& category) {
410
+ s.total_params += l->weight.numel();
411
+ if (l->bias.data_) s.total_params += l->bias.numel();
412
+ category += l->weight.numel();
413
+ s.memory_bytes += l->weight.data_size_ + l->bias.data_size_;
414
+ };
415
+
416
+ // Vision Encoder
417
+ count_linear(vision_encoder->patch_embed->proj, s.vision_params);
418
+ for (auto& l : vision_encoder->self_attn_qkv) count_linear(l, s.vision_params);
419
+ for (auto& l : vision_encoder->self_attn_proj) count_linear(l, s.vision_params);
420
+ for (auto& l : vision_encoder->mlp_fc1) count_linear(l, s.vision_params);
421
+ for (auto& l : vision_encoder->mlp_fc2) count_linear(l, s.vision_params);
422
+ count_linear(vision_encoder->output_proj, s.vision_params);
423
+
424
+ // Cross-Modal Fusion
425
+ count_linear(cross_modal_fusion->text_proj, s.fusion_params);
426
+ count_linear(cross_modal_fusion->image_proj, s.fusion_params);
427
+ count_linear(cross_modal_fusion->fusion_layer, s.fusion_params);
428
+
429
+ // Multi-Modal Attention
430
+ count_linear(multimodal_attention->text_query, s.fusion_params);
431
+ count_linear(multimodal_attention->image_key, s.fusion_params);
432
+ count_linear(multimodal_attention->image_value, s.fusion_params);
433
+ count_linear(multimodal_attention->text_output, s.fusion_params);
434
+ count_linear(multimodal_attention->image_query, s.fusion_params);
435
+ count_linear(multimodal_attention->text_key, s.fusion_params);
436
+ count_linear(multimodal_attention->text_value, s.fusion_params);
437
+ count_linear(multimodal_attention->image_output, s.fusion_params);
438
+
439
+ // 类脑模块
440
+ count_linear(text_proj, s.brain_params);
441
+ count_linear(multimodal_proj, s.brain_params);
442
+ count_linear(output_layer, s.brain_params);
443
+ count_linear(manifold_proj1, s.brain_params);
444
+ count_linear(manifold_proj2, s.brain_params);
445
+
446
+ for (auto& l : ecn->dlpfc_linear) count_linear(l, s.brain_params);
447
+ count_linear(ecn->ofc1, s.brain_params);
448
+ count_linear(ecn->ofc2, s.brain_params);
449
+ count_linear(ecn->vmpfc1, s.brain_params);
450
+ count_linear(ecn->vmpfc2, s.brain_params);
451
+
452
+ count_linear(dmn->mem_encoder1, s.brain_params);
453
+ count_linear(dmn->mem_encoder2, s.brain_params);
454
+ count_linear(dmn->future_proj1, s.brain_params);
455
+ for (auto& [h1, h2] : dmn->association_heads) {
456
+ count_linear(h1, s.brain_params);
457
+ count_linear(h2, s.brain_params);
458
+ }
459
+
460
+ count_linear(sn->saliency1, s.brain_params);
461
+ count_linear(sn->saliency2, s.brain_params);
462
+ count_linear(sn->saliency3, s.brain_params);
463
+ count_linear(sn->gate1, s.brain_params);
464
+ count_linear(sn->gate2, s.brain_params);
465
+ count_linear(sn->anomaly1, s.brain_params);
466
+ count_linear(sn->anomaly2, s.brain_params);
467
+
468
+ count_linear(memory->encode_proj, s.brain_params);
469
+ count_linear(memory->retrieve_proj, s.brain_params);
470
+ count_linear(memory->query_proj, s.brain_params);
471
+
472
+ s.memory_bytes += memory->memory_bank.data_size_;
473
+ s.total_params += memory->memory_bank.numel();
474
+
475
+ return s;
476
+ }
477
+
478
+ // ========== 序列化 ==========
479
+ void save(const std::string& path) {
480
+ std::ofstream ofs(path, std::ios::binary);
481
+ if (!ofs) throw std::runtime_error("Cannot open file for save: " + path);
482
+
483
+ // Magic header
484
+ ofs.write("NFv1", 4);
485
+
486
+ // Helper: serialize a named tensor
487
+ auto save_tensor = [&](const std::string& name, const Tensor& t) {
488
+ uint32_t name_len = name.size();
489
+ ofs.write(reinterpret_cast<const char*>(&name_len), 4);
490
+ ofs.write(name.data(), name_len);
491
+
492
+ uint32_t ndim = t.shape_.size();
493
+ ofs.write(reinterpret_cast<const char*>(&ndim), 4);
494
+ for (auto d : t.shape_) {
495
+ uint32_t dim = d;
496
+ ofs.write(reinterpret_cast<const char*>(&dim), 4);
497
+ }
498
+
499
+ uint32_t dsize = t.data_size_;
500
+ ofs.write(reinterpret_cast<const char*>(&dsize), 4);
501
+ ofs.write(reinterpret_cast<const char*>(t.data_.get()), dsize);
502
+ };
503
+
504
+ // Helper: save Linear layer (accepts shared_ptr or raw ref)
505
+ auto save_linear = [&](const std::string& prefix, const std::shared_ptr<Linear>& layer) {
506
+ save_tensor(prefix + ".weight", layer->weight);
507
+ if (layer->bias.data_) save_tensor(prefix + ".bias", layer->bias);
508
+ if (layer->weight_scale.data_) save_tensor(prefix + ".weight_scale", layer->weight_scale);
509
+ };
510
+ auto save_linear_raw = [&](const std::string& prefix, const Linear& layer) {
511
+ save_tensor(prefix + ".weight", layer.weight);
512
+ if (layer.bias.data_) save_tensor(prefix + ".bias", layer.bias);
513
+ if (layer.weight_scale.data_) save_tensor(prefix + ".weight_scale", layer.weight_scale);
514
+ };
515
+
516
+ // Helper: save LayerNorm
517
+ auto save_ln = [&](const std::string& prefix, const LayerNorm& ln) {
518
+ save_tensor(prefix + ".weight", ln.weight);
519
+ save_tensor(prefix + ".bias", ln.bias);
520
+ };
521
+
522
+ // === 投影层 ===
523
+ save_linear_raw("text_proj", *text_proj);
524
+ save_ln("text_norm", *text_norm);
525
+ save_linear_raw("output_layer", *output_layer);
526
+ save_ln("output_norm", *output_norm);
527
+
528
+ // === 类脑网络 ===
529
+ save_linear("ecn.dlpfc0", ecn->dlpfc_linear[0]);
530
+ save_linear("ecn.dlpfc1", ecn->dlpfc_linear[1]);
531
+ save_linear("ecn.ofc1", ecn->ofc1);
532
+ save_linear("ecn.ofc2", ecn->ofc2);
533
+ save_linear("ecn.vmpfc1", ecn->vmpfc1);
534
+ save_linear("ecn.vmpfc2", ecn->vmpfc2);
535
+
536
+ save_linear("dmn.mem_encoder1", dmn->mem_encoder1);
537
+ save_linear("dmn.mem_encoder2", dmn->mem_encoder2);
538
+ save_linear("dmn.future_proj1", dmn->future_proj1);
539
+ int head_idx = 0;
540
+ for (auto& [h1, h2] : dmn->association_heads) {
541
+ save_linear("dmn.head" + std::to_string(head_idx) + ".1", h1);
542
+ save_linear("dmn.head" + std::to_string(head_idx) + ".2", h2);
543
+ head_idx++;
544
+ }
545
+
546
+ save_linear("sn.saliency1", sn->saliency1);
547
+ save_linear("sn.saliency2", sn->saliency2);
548
+ save_linear("sn.saliency3", sn->saliency3);
549
+ save_linear("sn.gate1", sn->gate1);
550
+ save_linear("sn.gate2", sn->gate2);
551
+ save_linear("sn.anomaly1", sn->anomaly1);
552
+ save_linear("sn.anomaly2", sn->anomaly2);
553
+
554
+ save_linear("memory.encode", memory->encode_proj);
555
+ save_linear("memory.retrieve", memory->retrieve_proj);
556
+ save_linear("memory.query_proj", memory->query_proj);
557
+ save_tensor("memory.bank", memory->memory_bank);
558
+
559
+ // End marker
560
+ uint32_t zero = 0;
561
+ ofs.write(reinterpret_cast<const char*>(&zero), 4);
562
+ ofs.close();
563
+ }
564
+
565
+ void load(const std::string& path) {
566
+ std::ifstream ifs(path, std::ios::binary);
567
+ if (!ifs) throw std::runtime_error("Cannot open file for load: " + path);
568
+
569
+ // Magic header
570
+ char magic[5] = {0};
571
+ ifs.read(magic, 4);
572
+ if (std::string(magic) != "NFv1") throw std::runtime_error("Invalid model file");
573
+
574
+ // Helper: load a tensor and set its data
575
+ auto load_tensor_data = [&](Tensor& t) {
576
+ uint32_t ndim;
577
+ ifs.read(reinterpret_cast<char*>(&ndim), 4);
578
+ std::vector<size_t> shape(ndim);
579
+ for (uint32_t i = 0; i < ndim; i++) {
580
+ uint32_t d;
581
+ ifs.read(reinterpret_cast<char*>(&d), 4);
582
+ shape[i] = d;
583
+ }
584
+ uint32_t dsize;
585
+ ifs.read(reinterpret_cast<char*>(&dsize), 4);
586
+
587
+ // Only load if shapes match
588
+ if (shape == t.shape_ && dsize == t.data_size_) {
589
+ ifs.read(reinterpret_cast<char*>(t.data_.get()), dsize);
590
+ } else if (shape != t.shape_) {
591
+ // Skip mismatched data
592
+ ifs.seekg(dsize, std::ios::cur);
593
+ }
594
+ };
595
+
596
+ // Read tensors
597
+ while (ifs.good()) {
598
+ uint32_t name_len;
599
+ ifs.read(reinterpret_cast<char*>(&name_len), 4);
600
+ if (name_len == 0 || !ifs) break;
601
+
602
+ std::string name(name_len, '\0');
603
+ ifs.read(&name[0], name_len);
604
+
605
+ // Match name to tensor
606
+ if (name == "text_proj.weight") load_tensor_data(text_proj->weight);
607
+ else if (name == "text_proj.bias") load_tensor_data(text_proj->bias);
608
+ else if (name == "text_norm.weight") load_tensor_data(text_norm->weight);
609
+ else if (name == "text_norm.bias") load_tensor_data(text_norm->bias);
610
+ else if (name == "output_layer.weight") load_tensor_data(output_layer->weight);
611
+ else if (name == "output_layer.bias") load_tensor_data(output_layer->bias);
612
+ else if (name == "output_norm.weight") load_tensor_data(output_norm->weight);
613
+ else if (name == "output_norm.bias") load_tensor_data(output_norm->bias);
614
+ else if (name == "ecn.dlpfc0.weight") load_tensor_data(ecn->dlpfc_linear[0]->weight);
615
+ else if (name == "ecn.dlpfc0.bias") load_tensor_data(ecn->dlpfc_linear[0]->bias);
616
+ else if (name == "ecn.dlpfc1.weight") load_tensor_data(ecn->dlpfc_linear[1]->weight);
617
+ else if (name == "ecn.dlpfc1.bias") load_tensor_data(ecn->dlpfc_linear[1]->bias);
618
+ else if (name == "ecn.ofc1.weight") load_tensor_data(ecn->ofc1->weight);
619
+ else if (name == "ecn.ofc1.bias") load_tensor_data(ecn->ofc1->bias);
620
+ else if (name == "ecn.ofc2.weight") load_tensor_data(ecn->ofc2->weight);
621
+ else if (name == "ecn.ofc2.bias") load_tensor_data(ecn->ofc2->bias);
622
+ else if (name == "ecn.vmpfc1.weight") load_tensor_data(ecn->vmpfc1->weight);
623
+ else if (name == "ecn.vmpfc1.bias") load_tensor_data(ecn->vmpfc1->bias);
624
+ else if (name == "ecn.vmpfc2.weight") load_tensor_data(ecn->vmpfc2->weight);
625
+ else if (name == "ecn.vmpfc2.bias") load_tensor_data(ecn->vmpfc2->bias);
626
+ else if (name == "dmn.mem_encoder1.weight") load_tensor_data(dmn->mem_encoder1->weight);
627
+ else if (name == "dmn.mem_encoder1.bias") load_tensor_data(dmn->mem_encoder1->bias);
628
+ else if (name == "dmn.mem_encoder2.weight") load_tensor_data(dmn->mem_encoder2->weight);
629
+ else if (name == "dmn.mem_encoder2.bias") load_tensor_data(dmn->mem_encoder2->bias);
630
+ else if (name == "dmn.future_proj1.weight") load_tensor_data(dmn->future_proj1->weight);
631
+ else if (name == "dmn.future_proj1.bias") load_tensor_data(dmn->future_proj1->bias);
632
+ else if (name.find("dmn.head") == 0) {
633
+ int idx = std::stoi(name.substr(9, name.find('.', 9) - 9));
634
+ bool is_h1 = (name[name.size()-1] == '1');
635
+ auto& [h1, h2] = dmn->association_heads[idx];
636
+ if (is_h1) load_tensor_data(h1->weight);
637
+ else load_tensor_data(h2->weight);
638
+ }
639
+ else if (name == "sn.saliency1.weight") load_tensor_data(sn->saliency1->weight);
640
+ else if (name == "sn.saliency1.bias") load_tensor_data(sn->saliency1->bias);
641
+ else if (name == "sn.saliency2.weight") load_tensor_data(sn->saliency2->weight);
642
+ else if (name == "sn.saliency2.bias") load_tensor_data(sn->saliency2->bias);
643
+ else if (name == "sn.saliency3.weight") load_tensor_data(sn->saliency3->weight);
644
+ else if (name == "sn.saliency3.bias") load_tensor_data(sn->saliency3->bias);
645
+ else if (name == "sn.gate1.weight") load_tensor_data(sn->gate1->weight);
646
+ else if (name == "sn.gate1.bias") load_tensor_data(sn->gate1->bias);
647
+ else if (name == "sn.gate2.weight") load_tensor_data(sn->gate2->weight);
648
+ else if (name == "sn.gate2.bias") load_tensor_data(sn->gate2->bias);
649
+ else if (name == "sn.anomaly1.weight") load_tensor_data(sn->anomaly1->weight);
650
+ else if (name == "sn.anomaly1.bias") load_tensor_data(sn->anomaly1->bias);
651
+ else if (name == "sn.anomaly2.weight") load_tensor_data(sn->anomaly2->weight);
652
+ else if (name == "sn.anomaly2.bias") load_tensor_data(sn->anomaly2->bias);
653
+ else if (name == "memory.encode.weight") load_tensor_data(memory->encode_proj->weight);
654
+ else if (name == "memory.encode.bias") load_tensor_data(memory->encode_proj->bias);
655
+ else if (name == "memory.retrieve.weight") load_tensor_data(memory->retrieve_proj->weight);
656
+ else if (name == "memory.retrieve.bias") load_tensor_data(memory->retrieve_proj->bias);
657
+ else if (name == "memory.query_proj.weight") load_tensor_data(memory->query_proj->weight);
658
+ else if (name == "memory.query_proj.bias") load_tensor_data(memory->query_proj->bias);
659
+ else if (name == "memory.bank") load_tensor_data(memory->memory_bank);
660
+ else {
661
+ // Unknown tensor: skip
662
+ uint32_t ndim; ifs.read(reinterpret_cast<char*>(&ndim), 4);
663
+ for (uint32_t i = 0; i < ndim; i++) { uint32_t d; ifs.read(reinterpret_cast<char*>(&d), 4); }
664
+ uint32_t dsize; ifs.read(reinterpret_cast<char*>(&dsize), 4);
665
+ ifs.seekg(dsize, std::ios::cur);
666
+ }
667
+ }
668
+ ifs.close();
669
+ }
670
+ };
671
+
672
+ /**
673
+ * NeuroFlowMultiModalLite - 超轻量多模态版
674
+ */
675
+ class NeuroFlowMultiModalLite : public NeuroFlowMultiModal {
676
+ public:
677
+ NeuroFlowMultiModalLite(size_t text_dim = 256, size_t image_size = 112) {
678
+ Config cfg;
679
+ cfg.text_dim = text_dim;
680
+ cfg.image_size = image_size;
681
+ cfg.patch_size = 8;
682
+ cfg.vision_dim = 128;
683
+ cfg.fusion_dim = 128;
684
+ cfg.hidden_dim = 128;
685
+ cfg.output_dim = 10;
686
+ cfg.memory_dim = 64;
687
+ cfg.memory_slots = 32;
688
+ cfg.num_layers = 1;
689
+ cfg.num_associations = 4;
690
+ cfg.vision_layers = 2;
691
+ cfg.vision_heads = 4;
692
+ cfg.use_quantization = true;
693
+ cfg.use_mla = true;
694
+ cfg.mla_latent_dim = 32;
695
+
696
+ // 需要重新初始化...
697
+ }
698
+ };
699
+
700
+ } // namespace neuroflow
701
+
702
+ #endif // NEUROFLOW_MULTIMODAL_MODEL_HPP
include/neuroflow/networks.hpp ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_NETWORKS_HPP
2
+ #define NEUROFLOW_NETWORKS_HPP
3
+
4
+ /**
5
+ * NeuroFlow 核心网络模块
6
+ *
7
+ * 1. ExecutiveControlNetwork (ECN) - 执行控制
8
+ * 2. DefaultModeNetwork (DMN) - 默认模式/联想
9
+ * 3. SalienceNetwork (SN) - 显著性检测
10
+ */
11
+
12
+ #include <cmath>
13
+ #include <memory>
14
+ #include <random>
15
+ #include <thread>
16
+ #include <variant>
17
+ #include <vector>
18
+ #include "tensor.hpp"
19
+
20
+ #ifdef USE_CUDA
21
+ #include "cuda_kernels.hpp"
22
+ #endif
23
+
24
+ namespace neuroflow {
25
+
26
+ /**
27
+ * Linear层 - 基础线性变换
28
+ * 支持量化权重
29
+ */
30
+ class Linear {
31
+ public:
32
+ Tensor weight;
33
+ Tensor bias;
34
+ Tensor weight_scale; // 量化scale
35
+ bool quantized;
36
+
37
+ Linear(size_t in_features, size_t out_features, bool use_bias = true, bool quant = false)
38
+ : quantized(quant) {
39
+ if (quant) {
40
+ weight = Tensor({out_features, in_features}, QuantType::INT8);
41
+ weight_scale = Tensor({out_features}, QuantType::FP32);
42
+ } else {
43
+ weight = Tensor({out_features, in_features}, QuantType::FP32);
44
+ // 初始化权重 ( Xavier )
45
+ float* w = weight.as_fp32();
46
+ float scale = std::sqrt(2.0f / (in_features + out_features));
47
+ size_t n = weight.numel();
48
+ std::mt19937 init_rng(std::hash<std::thread::id>{}(std::this_thread::get_id()) + in_features * 31 + out_features);
49
+ std::uniform_real_distribution<float> dist(-scale, scale);
50
+ for (size_t i = 0; i < n; ++i) {
51
+ w[i] = dist(init_rng);
52
+ }
53
+ }
54
+
55
+ if (use_bias) {
56
+ bias = Tensor({out_features}, QuantType::FP32);
57
+ memset(bias.data_.get(), 0, bias.data_size_);
58
+ }
59
+ }
60
+
61
+ Tensor forward(const Tensor& input) {
62
+ Tensor output({input.shape_[0], weight.shape_[0]}, QuantType::FP32);
63
+
64
+ if (quantized) {
65
+ // 量化矩阵乘法 - INT8权重需要不同处理
66
+ // 这里简化为普通gemm
67
+ TensorOps::gemm(input, weight, output, false, true);
68
+ } else {
69
+ // weight形状是 [out_features, in_features]
70
+ // output = input @ weight^T
71
+ TensorOps::gemm(input, weight, output, false, true);
72
+ }
73
+
74
+ // 加bias (只有当 bias 存在时)
75
+ if (bias.data_) {
76
+ #ifdef USE_CUDA
77
+ if (CudaContext::instance().is_available() && output.is_on_gpu()) {
78
+ bias.to_gpu();
79
+ int rows = static_cast<int>(output.shape_[0]);
80
+ int cols = static_cast<int>(output.shape_[1]);
81
+ launch_bias_add(output.as_gpu_fp32(), bias.as_gpu_fp32(), rows, cols,
82
+ CudaContext::instance().stream());
83
+ output.gpu_dirty_ = true;
84
+ } else
85
+ #endif
86
+ {
87
+ float* out = output.as_fp32();
88
+ float* b = bias.as_fp32();
89
+ for (size_t i = 0; i < output.shape_[0]; ++i) {
90
+ for (size_t j = 0; j < output.shape_[1]; ++j) {
91
+ out[i * output.shape_[1] + j] += b[j];
92
+ }
93
+ }
94
+ }
95
+ }
96
+
97
+ return output;
98
+ }
99
+
100
+ // 量化权重
101
+ void quantize() {
102
+ if (quantized) return;
103
+
104
+ Tensor new_weight({weight.shape_[0], weight.shape_[1]}, QuantType::INT8);
105
+ Tensor scale({weight.shape_[0]}, QuantType::FP32);
106
+
107
+ TensorOps::quantize_int8(weight, new_weight, scale);
108
+
109
+ weight = new_weight;
110
+ weight_scale = scale;
111
+ quantized = true;
112
+ }
113
+ };
114
+
115
+ /**
116
+ * LayerNorm层
117
+ */
118
+ class LayerNorm {
119
+ public:
120
+ Tensor weight;
121
+ Tensor bias;
122
+ float eps;
123
+
124
+ LayerNorm(size_t dim, float epsilon = 1e-5f) : eps(epsilon) {
125
+ weight = Tensor({dim}, QuantType::FP32);
126
+ bias = Tensor({dim}, QuantType::FP32);
127
+
128
+ float* w = weight.as_fp32();
129
+ float* b = bias.as_fp32();
130
+ for (size_t i = 0; i < dim; ++i) {
131
+ w[i] = 1.0f;
132
+ b[i] = 0.0f;
133
+ }
134
+ }
135
+
136
+ Tensor forward(const Tensor& input) {
137
+ Tensor output = input.clone();
138
+ TensorOps::layer_norm(output, weight, bias, eps);
139
+ return output;
140
+ }
141
+ };
142
+
143
+ /**
144
+ * GELU激活层
145
+ */
146
+ class GELU {
147
+ public:
148
+ Tensor forward(const Tensor& input) {
149
+ Tensor output = input.clone();
150
+ TensorOps::gelu(output);
151
+ return output;
152
+ }
153
+ };
154
+
155
+ /**
156
+ * Dropout层
157
+ */
158
+ class Dropout {
159
+ public:
160
+ float rate;
161
+ bool training;
162
+
163
+ Dropout(float r = 0.1f) : rate(r), training(false) {}
164
+
165
+ Tensor forward(const Tensor& input) {
166
+ Tensor output = input.clone();
167
+ TensorOps::dropout(output, rate, training);
168
+ return output;
169
+ }
170
+
171
+ void set_training(bool t) { training = t; }
172
+ };
173
+
174
+ /**
175
+ * Sequential容器
176
+ */
177
+ class Sequential {
178
+ public:
179
+ using LayerVariant = std::variant<
180
+ std::shared_ptr<Linear>,
181
+ std::shared_ptr<LayerNorm>,
182
+ std::shared_ptr<GELU>,
183
+ std::shared_ptr<Dropout>
184
+ >;
185
+
186
+ std::vector<LayerVariant> layers;
187
+
188
+ template<typename T>
189
+ void add(std::shared_ptr<T> layer) {
190
+ layers.push_back(layer);
191
+ }
192
+
193
+ template<typename T>
194
+ std::shared_ptr<T> get(size_t idx) {
195
+ return std::get<std::shared_ptr<T>>(layers[idx]);
196
+ }
197
+ };
198
+
199
+ /**
200
+ * ExecutiveControlNetwork (ECN)
201
+ *
202
+ * 模拟背外侧前额叶 (dlPFC)、眶额叶皮层 (OFC)、腹内侧前额叶 (vmPFC)
203
+ * 功能:逻辑推理、价值评估、决策输出
204
+ */
205
+ class ExecutiveControlNetwork {
206
+ public:
207
+ // dlPFC: 多层处理
208
+ std::vector<std::shared_ptr<Linear>> dlpfc_linear;
209
+ std::vector<std::shared_ptr<LayerNorm>> dlpfc_norm;
210
+ std::vector<std::shared_ptr<GELU>> dlpfc_gelu;
211
+ std::vector<std::shared_ptr<Dropout>> dlpfc_drop;
212
+
213
+ // OFC: 价值评估
214
+ std::shared_ptr<Linear> ofc1, ofc2;
215
+
216
+ // vmPFC: 决策输出
217
+ std::shared_ptr<Linear> vmpfc1, vmpfc2;
218
+
219
+ size_t num_layers;
220
+ size_t hidden_dim;
221
+
222
+ ExecutiveControlNetwork(size_t input_dim, size_t hidden_dim, size_t output_dim, size_t layers = 2)
223
+ : num_layers(layers), hidden_dim(hidden_dim) {
224
+
225
+ // dlPFC层
226
+ size_t prev_dim = input_dim;
227
+ for (size_t i = 0; i < layers; ++i) {
228
+ dlpfc_linear.push_back(std::make_shared<Linear>(prev_dim, hidden_dim));
229
+ dlpfc_norm.push_back(std::make_shared<LayerNorm>(hidden_dim));
230
+ dlpfc_gelu.push_back(std::make_shared<GELU>());
231
+ dlpfc_drop.push_back(std::make_shared<Dropout>(0.1f));
232
+ prev_dim = hidden_dim;
233
+ }
234
+
235
+ // OFC: 价值评估 (hidden -> hidden/2 -> 1)
236
+ size_t half = hidden_dim / 2;
237
+ ofc1 = std::make_shared<Linear>(hidden_dim, half);
238
+ ofc2 = std::make_shared<Linear>(half, 1);
239
+
240
+ // vmPFC: 决策 (hidden -> hidden/2 -> output)
241
+ vmpfc1 = std::make_shared<Linear>(hidden_dim, half);
242
+ vmpfc2 = std::make_shared<Linear>(half, output_dim);
243
+ }
244
+
245
+ struct Output {
246
+ Tensor decision; // 决策输出
247
+ Tensor value; // 价值评估
248
+ std::vector<Tensor> hidden_states; // 中间层激活 (用于流形分析)
249
+ };
250
+
251
+ Output forward(const Tensor& x) {
252
+ Output out;
253
+ Tensor h = x;
254
+
255
+ // dlPFC处理
256
+ for (size_t i = 0; i < num_layers; ++i) {
257
+ h = dlpfc_linear[i]->forward(h);
258
+ h = dlpfc_norm[i]->forward(h);
259
+ h = dlpfc_gelu[i]->forward(h);
260
+ h = dlpfc_drop[i]->forward(h);
261
+ out.hidden_states.push_back(h.clone());
262
+ }
263
+
264
+ // OFC: 价值评估
265
+ Tensor v = ofc1->forward(h);
266
+ TensorOps::gelu(v);
267
+ out.value = ofc2->forward(v);
268
+
269
+ // vmPFC: 决策
270
+ Tensor d = vmpfc1->forward(h);
271
+ TensorOps::gelu(d);
272
+ out.decision = vmpfc2->forward(d);
273
+
274
+ return out;
275
+ }
276
+
277
+ void set_training(bool t) {
278
+ for (auto& drop : dlpfc_drop) drop->set_training(t);
279
+ }
280
+
281
+ // 量化所有线性层
282
+ void quantize() {
283
+ for (auto& l : dlpfc_linear) l->quantize();
284
+ ofc1->quantize();
285
+ ofc2->quantize();
286
+ vmpfc1->quantize();
287
+ vmpfc2->quantize();
288
+ }
289
+ };
290
+
291
+ /**
292
+ * DefaultModeNetwork (DMN)
293
+ *
294
+ * 模拟后扣带回 (PCC)、内侧前额叶 (mPFC)
295
+ * 功能:记忆检索、未来规划、创造性联想
296
+ */
297
+ class DefaultModeNetwork {
298
+ public:
299
+ size_t memory_dim;
300
+ size_t latent_dim;
301
+ size_t num_associations;
302
+
303
+ // 记忆编码
304
+ std::shared_ptr<Linear> mem_encoder1, mem_encoder2;
305
+
306
+ // 联想头
307
+ std::vector<std::pair<std::shared_ptr<Linear>, std::shared_ptr<Linear>>> association_heads;
308
+
309
+ // 未来投影
310
+ std::shared_ptr<Linear> future_proj1;
311
+ std::shared_ptr<LayerNorm> future_norm;
312
+ std::shared_ptr<GELU> future_gelu;
313
+
314
+ DefaultModeNetwork(size_t memory_dim, size_t latent_dim, size_t num_assoc = 8)
315
+ : memory_dim(memory_dim), latent_dim(latent_dim), num_associations(num_assoc) {
316
+
317
+ // 记忆编码器
318
+ mem_encoder1 = std::make_shared<Linear>(memory_dim, latent_dim * 2);
319
+ mem_encoder2 = std::make_shared<Linear>(latent_dim * 2, latent_dim);
320
+
321
+ // 联想头
322
+ for (size_t i = 0; i < num_assoc; ++i) {
323
+ auto head1 = std::make_shared<Linear>(latent_dim, latent_dim);
324
+ auto head2 = std::make_shared<Linear>(latent_dim, latent_dim);
325
+ association_heads.push_back({head1, head2});
326
+ }
327
+
328
+ // 未来投影
329
+ future_proj1 = std::make_shared<Linear>(latent_dim * num_assoc, latent_dim * 2);
330
+ future_norm = std::make_shared<LayerNorm>(latent_dim * 2);
331
+ future_gelu = std::make_shared<GELU>();
332
+ }
333
+
334
+ struct Output {
335
+ Tensor vision; // 未来愿景
336
+ std::vector<Tensor> associations; // 各联想头输出
337
+ Tensor latent; // 潜在记忆表征
338
+ };
339
+
340
+ Output forward(const Tensor& memory_input) {
341
+ Output out;
342
+
343
+ // 编码记忆
344
+ Tensor h = mem_encoder1->forward(memory_input);
345
+ TensorOps::gelu(h);
346
+ out.latent = mem_encoder2->forward(h);
347
+
348
+ // 各联想头处理
349
+ for (auto& head : association_heads) {
350
+ Tensor assoc = head.first->forward(out.latent);
351
+ TensorOps::gelu(assoc);
352
+ assoc = head.second->forward(assoc);
353
+ out.associations.push_back(assoc);
354
+ }
355
+
356
+ // 合并联想
357
+ out.vision = TensorOps::concat(out.associations, 1);
358
+ out.vision = future_proj1->forward(out.vision);
359
+ out.vision = future_norm->forward(out.vision);
360
+ out.vision = future_gelu->forward(out.vision);
361
+
362
+ return out;
363
+ }
364
+
365
+ void quantize() {
366
+ mem_encoder1->quantize();
367
+ mem_encoder2->quantize();
368
+ future_proj1->quantize();
369
+ for (auto& [h1, h2] : association_heads) {
370
+ h1->quantize();
371
+ h2->quantize();
372
+ }
373
+ }
374
+ };
375
+
376
+ /**
377
+ * SalienceNetwork (SN)
378
+ *
379
+ * 模拟前岛叶 (AI)、前扣带回 (ACC)
380
+ * 功能:显著性检测、ECN/DMN门控、异常检测
381
+ */
382
+ class SalienceNetwork {
383
+ public:
384
+ // 显著性评分
385
+ std::shared_ptr<Linear> saliency1, saliency2, saliency3;
386
+
387
+ // 门控生成
388
+ std::shared_ptr<Linear> gate1, gate2;
389
+
390
+ // 异常检测
391
+ std::shared_ptr<Linear> anomaly1, anomaly2;
392
+
393
+ SalienceNetwork(size_t input_dim, size_t hidden_dim) {
394
+ // 显著性评分 (sigmoid输出)
395
+ saliency1 = std::make_shared<Linear>(input_dim, hidden_dim);
396
+ saliency2 = std::make_shared<Linear>(hidden_dim, hidden_dim / 2);
397
+ saliency3 = std::make_shared<Linear>(hidden_dim / 2, 1);
398
+
399
+ // 门控 (softmax 2-class)
400
+ gate1 = std::make_shared<Linear>(input_dim, hidden_dim);
401
+ gate2 = std::make_shared<Linear>(hidden_dim, 2);
402
+
403
+ // 异常检测
404
+ anomaly1 = std::make_shared<Linear>(input_dim, hidden_dim);
405
+ anomaly2 = std::make_shared<Linear>(hidden_dim, 1);
406
+ }
407
+
408
+ struct Output {
409
+ Tensor saliency; // 显著性评分 [0,1]
410
+ Tensor gates; // ECN/DMN门控权重
411
+ Tensor anomaly; // 异常评分
412
+ };
413
+
414
+ Output forward(const Tensor& x, const Tensor* baseline = nullptr) {
415
+ Output out;
416
+
417
+ // 显著性
418
+ Tensor h = saliency1->forward(x);
419
+ TensorOps::gelu(h);
420
+ h = saliency2->forward(h);
421
+ TensorOps::gelu(h);
422
+ out.saliency = saliency3->forward(h);
423
+ // sigmoid
424
+ float* s = out.saliency.as_fp32();
425
+ for (size_t i = 0; i < out.saliency.numel(); ++i) {
426
+ s[i] = 1.0f / (1.0f + std::exp(-s[i]));
427
+ }
428
+
429
+ // 门控
430
+ h = gate1->forward(x);
431
+ TensorOps::gelu(h);
432
+ out.gates = gate2->forward(h);
433
+ TensorOps::softmax(out.gates);
434
+
435
+ // 异常
436
+ if (baseline) {
437
+ Tensor diff = x.clone();
438
+
439
+ float* d = diff.as_fp32();
440
+ const float* b = baseline->as_fp32();
441
+ for (size_t i = 0; i < diff.numel(); ++i) d[i] -= b[i];
442
+
443
+ h = anomaly1->forward(diff);
444
+ TensorOps::gelu(h);
445
+ out.anomaly = anomaly2->forward(h);
446
+ } else {
447
+ out.anomaly = Tensor({x.shape_[0], 1}, QuantType::FP32);
448
+ }
449
+
450
+ return out;
451
+ }
452
+
453
+ void quantize() {
454
+ saliency1->quantize();
455
+ saliency2->quantize();
456
+ saliency3->quantize();
457
+ gate1->quantize();
458
+ gate2->quantize();
459
+ anomaly1->quantize();
460
+ anomaly2->quantize();
461
+ }
462
+ };
463
+
464
+ } // namespace neuroflow
465
+
466
+ #endif // NEUROFLOW_NETWORKS_HPP
include/neuroflow/online_learning.hpp ADDED
@@ -0,0 +1,477 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * NeuroFlow 在线学习模块
3
+ *
4
+ * 支持:
5
+ * 1. 少样本快速适应
6
+ * 2. 在线梯度更新
7
+ * 3. 记忆巩固 (LTP)
8
+ * 4. 元学习支持
9
+ */
10
+
11
+ #pragma once
12
+
13
+ #ifndef _USE_MATH_DEFINES
14
+ #define _USE_MATH_DEFINES
15
+ #endif
16
+
17
+ #include <cmath>
18
+ #include <memory>
19
+ #include <vector>
20
+ #include "backprop.hpp"
21
+ #include "memory.hpp"
22
+ #include "model.hpp"
23
+ #include "networks.hpp"
24
+ #include "tensor.hpp"
25
+
26
+ namespace neuroflow {
27
+
28
+ /**
29
+ * 损失函数
30
+ */
31
+ class LossFunctions {
32
+ public:
33
+ // 交叉熵损失(分类)
34
+ static float cross_entropy(const Tensor& pred, const Tensor& target) {
35
+ size_t batch = pred.shape_[0];
36
+ size_t classes = pred.shape_[1];
37
+
38
+ const float* p = pred.as_fp32();
39
+ const float* t = target.as_fp32();
40
+
41
+ float loss = 0.0f;
42
+ for (size_t b = 0; b < batch; ++b) {
43
+ // Softmax
44
+ std::vector<float> probs(classes);
45
+ float max_val = p[b * classes];
46
+ for (size_t c = 1; c < classes; ++c) {
47
+ max_val = std::max(max_val, p[b * classes + c]);
48
+ }
49
+
50
+ float sum = 0.0f;
51
+ for (size_t c = 0; c < classes; ++c) {
52
+ probs[c] = std::exp(p[b * classes + c] - max_val);
53
+ sum += probs[c];
54
+ }
55
+ for (size_t c = 0; c < classes; ++c) {
56
+ probs[c] /= sum;
57
+ }
58
+
59
+ // Cross entropy
60
+ for (size_t c = 0; c < classes; ++c) {
61
+ if (t[b * classes + c] > 0) {
62
+ loss -= t[b * classes + c] * std::log(std::max(probs[c], 1e-7f));
63
+ }
64
+ }
65
+ }
66
+
67
+ return loss / batch;
68
+ }
69
+
70
+ // MSE损失(回归)
71
+ static float mse(const Tensor& pred, const Tensor& target) {
72
+ size_t n = pred.numel();
73
+
74
+ const float* p = pred.as_fp32();
75
+ const float* t = target.as_fp32();
76
+
77
+ float loss = 0.0f;
78
+ for (size_t i = 0; i < n; ++i) {
79
+ float diff = p[i] - t[i];
80
+ loss += diff * diff;
81
+ }
82
+
83
+ return loss / n;
84
+ }
85
+
86
+ // Softmax计算(无损失)
87
+ static void softmax(Tensor& x) {
88
+ if (x.shape_.size() != 2) return;
89
+
90
+ size_t batch = x.shape_[0];
91
+ size_t classes = x.shape_[1];
92
+ float* p = x.as_fp32();
93
+
94
+ for (size_t b = 0; b < batch; ++b) {
95
+ float max_val = p[b * classes];
96
+ for (size_t c = 1; c < classes; ++c) {
97
+ max_val = std::max(max_val, p[b * classes + c]);
98
+ }
99
+
100
+ float sum = 0.0f;
101
+ for (size_t c = 0; c < classes; ++c) {
102
+ p[b * classes + c] = std::exp(p[b * classes + c] - max_val);
103
+ sum += p[b * classes + c];
104
+ }
105
+
106
+ for (size_t c = 0; c < classes; ++c) {
107
+ p[b * classes + c] /= sum;
108
+ }
109
+ }
110
+ }
111
+ };
112
+
113
+ /**
114
+ * 简化版梯度计算器
115
+ *
116
+ * 仅支持关键层的梯度:
117
+ * - Linear: 权重梯度 + 输入梯度
118
+ * - LayerNorm: 输入梯度
119
+ * - GELU: 输入梯度
120
+ */
121
+ class GradientCalculator {
122
+ public:
123
+ // Linear层梯度
124
+ struct LinearGradients {
125
+ Tensor weight_grad; // (out, in)
126
+ Tensor input_grad; // (batch, in)
127
+ };
128
+
129
+ static LinearGradients linear_backward(
130
+ const Tensor& input, // (batch, in_features)
131
+ const Tensor& output_grad, // (batch, out_features)
132
+ const Tensor& weight // (out, in)
133
+ ) {
134
+ LinearGradients grads;
135
+
136
+ size_t batch = input.shape_[0];
137
+ size_t in_f = input.shape_[1];
138
+ size_t out_f = output_grad.shape_[1];
139
+
140
+ grads.weight_grad = Tensor({out_f, in_f}, QuantType::FP32);
141
+ grads.input_grad = Tensor({batch, in_f}, QuantType::FP32);
142
+
143
+ const float* inp = input.as_fp32();
144
+ const float* og = output_grad.as_fp32();
145
+ const float* w = weight.as_fp32();
146
+ float* wg = grads.weight_grad.as_fp32();
147
+ float* ig = grads.input_grad.as_fp32();
148
+
149
+ // 权重梯度: output_grad.T @ input
150
+ // weight_grad[i, j] = sum_b(output_grad[b, i] * input[b, j])
151
+ for (size_t i = 0; i < out_f; ++i) {
152
+ for (size_t j = 0; j < in_f; ++j) {
153
+ float sum = 0.0f;
154
+ for (size_t b = 0; b < batch; ++b) {
155
+ sum += og[b * out_f + i] * inp[b * in_f + j];
156
+ }
157
+ wg[i * in_f + j] = sum / batch; // 平均梯度
158
+ }
159
+ }
160
+
161
+ // 输入梯度: output_grad @ weight
162
+ // input_grad[b, j] = sum_i(output_grad[b, i] * weight[i, j])
163
+ for (size_t b = 0; b < batch; ++b) {
164
+ for (size_t j = 0; j < in_f; ++j) {
165
+ float sum = 0.0f;
166
+ for (size_t i = 0; i < out_f; ++i) {
167
+ sum += og[b * out_f + i] * w[i * in_f + j];
168
+ }
169
+ ig[b * in_f + j] = sum;
170
+ }
171
+ }
172
+
173
+ return grads;
174
+ }
175
+
176
+ // LayerNorm梯度
177
+ static Tensor layernorm_backward(
178
+ const Tensor& input,
179
+ const Tensor& output_grad,
180
+ float eps = 1e-5f
181
+ ) {
182
+ size_t batch = input.shape_[0];
183
+ size_t dim = input.shape_[1];
184
+
185
+ Tensor input_grad({batch, dim}, QuantType::FP32);
186
+
187
+ const float* inp = input.as_fp32();
188
+ const float* og = output_grad.as_fp32();
189
+ float* ig = input_grad.as_fp32();
190
+
191
+ for (size_t b = 0; b < batch; ++b) {
192
+ // 计算均值和方差
193
+ float mean = 0.0f;
194
+ for (size_t d = 0; d < dim; ++d) {
195
+ mean += inp[b * dim + d];
196
+ }
197
+ mean /= dim;
198
+
199
+ float var = 0.0f;
200
+ for (size_t d = 0; d < dim; ++d) {
201
+ float diff = inp[b * dim + d] - mean;
202
+ var += diff * diff;
203
+ }
204
+ var /= dim;
205
+ float std = std::sqrt(var + eps);
206
+
207
+ // 梯度计算
208
+ float sum_grad = 0.0f;
209
+ float sum_grad_x = 0.0f;
210
+ for (size_t d = 0; d < dim; ++d) {
211
+ float normalized = (inp[b * dim + d] - mean) / std;
212
+ sum_grad += og[b * dim + d];
213
+ sum_grad_x += og[b * dim + d] * normalized;
214
+ }
215
+
216
+ for (size_t d = 0; d < dim; ++d) {
217
+ float normalized = (inp[b * dim + d] - mean) / std;
218
+ ig[b * dim + d] = (og[b * dim + d] - sum_grad / dim - normalized * sum_grad_x / dim) / std;
219
+ }
220
+ }
221
+
222
+ return input_grad;
223
+ }
224
+
225
+ // GELU梯度
226
+ static Tensor gelu_backward(const Tensor& input, const Tensor& output_grad) {
227
+ size_t n = input.numel();
228
+
229
+ Tensor input_grad(input.shape_, QuantType::FP32);
230
+
231
+ const float* inp = input.as_fp32();
232
+ const float* og = output_grad.as_fp32();
233
+ float* ig = input_grad.as_fp32();
234
+
235
+ for (size_t i = 0; i < n; ++i) {
236
+ float x = inp[i];
237
+ float gelu_grad = 0.5f * (1.0f + std::erf(x / std::sqrt(2.0f)))
238
+ + x * std::exp(-x * x / 2.0f) / std::sqrt(2.0f * 3.14159265358979323846f);
239
+ ig[i] = og[i] * gelu_grad;
240
+ }
241
+
242
+ return input_grad;
243
+ }
244
+ };
245
+
246
+ /**
247
+ * 优化器
248
+ */
249
+ class Optimizer {
250
+ public:
251
+ float lr;
252
+ float weight_decay;
253
+
254
+ Optimizer(float learning_rate = 0.001f, float wd = 0.0f)
255
+ : lr(learning_rate), weight_decay(wd) {}
256
+
257
+ // SGD更新
258
+ void sgd_step(Tensor& param, const Tensor& grad) {
259
+ if (param.shape_ != grad.shape_) return;
260
+
261
+ float* p = param.as_fp32();
262
+ const float* g = grad.as_fp32();
263
+
264
+ for (size_t i = 0; i < param.numel(); ++i) {
265
+ p[i] -= lr * (g[i] + weight_decay * p[i]);
266
+ }
267
+ }
268
+
269
+ // Adam状态
270
+ struct AdamState {
271
+ Tensor m; // 一阶矩
272
+ Tensor v; // 二阶矩
273
+ int t = 0;
274
+ };
275
+
276
+ AdamState create_adam_state(const Tensor& param) {
277
+ AdamState state;
278
+ state.m = Tensor(param.shape_, QuantType::FP32);
279
+ state.v = Tensor(param.shape_, QuantType::FP32);
280
+ memset(state.m.as_fp32(), 0, state.m.numel() * sizeof(float));
281
+ memset(state.v.as_fp32(), 0, state.v.numel() * sizeof(float));
282
+ return state;
283
+ }
284
+
285
+ // Adam更新
286
+ void adam_step(Tensor& param, const Tensor& grad, AdamState& state,
287
+ float beta1 = 0.9f, float beta2 = 0.999f, float eps = 1e-8f) {
288
+ if (param.shape_ != grad.shape_) return;
289
+
290
+ state.t++;
291
+
292
+ float* p = param.as_fp32();
293
+ const float* g = grad.as_fp32();
294
+ float* m = state.m.as_fp32();
295
+ float* v = state.v.as_fp32();
296
+
297
+ for (size_t i = 0; i < param.numel(); ++i) {
298
+ m[i] = beta1 * m[i] + (1 - beta1) * g[i];
299
+ v[i] = beta2 * v[i] + (1 - beta2) * g[i] * g[i];
300
+
301
+ float m_hat = m[i] / (1 - std::pow(beta1, state.t));
302
+ float v_hat = v[i] / (1 - std::pow(beta2, state.t));
303
+
304
+ p[i] -= lr * (m_hat / (std::sqrt(v_hat) + eps) + weight_decay * p[i]);
305
+ }
306
+ }
307
+ };
308
+
309
+ /**
310
+ * 在线学习器
311
+ *
312
+ * 支持少样本快速适应
313
+ */
314
+ class OnlineLearner {
315
+ public:
316
+ NeuroFlowModel& model;
317
+ FullTrainer trainer;
318
+
319
+ OnlineLearner(NeuroFlowModel& m, float lr = 0.01f)
320
+ : model(m), trainer(m, lr) {}
321
+
322
+ // 单步在线学习
323
+ struct LearnResult {
324
+ float initial_loss;
325
+ float final_loss;
326
+ float loss_reduction;
327
+ int steps;
328
+ };
329
+
330
+ LearnResult learn_step(
331
+ const Tensor& input, // (batch, input_dim)
332
+ const Tensor& target, // (batch, output_dim) 或 (batch, classes)
333
+ int num_steps = 5,
334
+ bool use_memory = true
335
+ ) {
336
+ LearnResult result;
337
+ result.steps = num_steps;
338
+
339
+ // 计算初始损失
340
+ NeuroFlowModel::Output output = model.forward(input);
341
+ result.initial_loss = LossFunctions::mse(output.output, target);
342
+
343
+ // 在线学习循环
344
+ for (int step = 0; step < num_steps; ++step) {
345
+ auto step_result = trainer.train_step(input, target);
346
+ (void)step_result;
347
+ }
348
+
349
+ // 计算最终损失
350
+ NeuroFlowModel::Output final_output = model.forward(input);
351
+ result.final_loss = LossFunctions::mse(final_output.output, target);
352
+ result.loss_reduction = result.initial_loss - result.final_loss;
353
+
354
+ return result;
355
+ }
356
+
357
+ // 少样本适应
358
+ LearnResult few_shot_adapt(
359
+ const std::vector<Tensor>& examples,
360
+ const std::vector<Tensor>& targets,
361
+ int num_steps = 10
362
+ ) {
363
+ LearnResult result;
364
+
365
+ if (examples.empty()) {
366
+ result.initial_loss = result.final_loss = 0.0f;
367
+ return result;
368
+ }
369
+
370
+ // 合并为batch
371
+ size_t batch = examples.size();
372
+ Tensor input({batch, examples[0].shape_[1]}, QuantType::FP32);
373
+ Tensor target({batch, targets[0].shape_[1]}, QuantType::FP32);
374
+
375
+ float* inp = input.as_fp32();
376
+ float* tgt = target.as_fp32();
377
+
378
+ for (size_t b = 0; b < batch; ++b) {
379
+ memcpy(inp + b * examples[0].numel(),
380
+ examples[b].as_fp32(),
381
+ examples[b].numel() * sizeof(float));
382
+ memcpy(tgt + b * targets[0].numel(),
383
+ targets[b].as_fp32(),
384
+ targets[b].numel() * sizeof(float));
385
+ }
386
+
387
+ return learn_step(input, target, num_steps, true);
388
+ }
389
+
390
+ // 元学习:快速适应新任务
391
+ void meta_learn_step(
392
+ const Tensor& support_input,
393
+ const Tensor& support_target,
394
+ const Tensor& query_input,
395
+ const Tensor& query_target,
396
+ int inner_steps = 5
397
+ ) {
398
+ // 1. 内循环:在support set上适应
399
+ LearnResult inner = learn_step(support_input, support_target, inner_steps, true);
400
+
401
+ // 2. 外循环:在query set上验证并更新元参数
402
+ NeuroFlowModel::Output query_pred = model.forward(query_input);
403
+ float query_loss = LossFunctions::mse(query_pred.output, query_target);
404
+
405
+ // 更新元学习参数(简化版)
406
+ // 实际MAML需要二阶梯度
407
+ model.memory->consolidate(query_input);
408
+ }
409
+ };
410
+
411
+ /**
412
+ * 在线学习测试
413
+ */
414
+ inline void test_online_learning() {
415
+ printf("\n=== Online Learning Test ===\n");
416
+
417
+ // 创建模型
418
+ NeuroFlowModel::Config cfg;
419
+ cfg.input_dim = 512;
420
+ cfg.hidden_dim = 256;
421
+ cfg.output_dim = 10;
422
+ NeuroFlowModel model(cfg);
423
+ OnlineLearner learner(model, 0.01f);
424
+
425
+ // 单样本适应
426
+ Tensor input(std::vector<size_t>{1, 512}, QuantType::FP32);
427
+ Tensor target(std::vector<size_t>{1, 10}, QuantType::FP32);
428
+
429
+ // 初始化数据
430
+ float* inp = input.as_fp32();
431
+ float* tgt = target.as_fp32();
432
+ for (size_t i = 0; i < 512; ++i) inp[i] = (static_cast<float>(rand()) / RAND_MAX - 0.5f) * 0.1f;
433
+ for (size_t i = 0; i < 10; ++i) tgt[i] = (i == 3) ? 1.0f : 0.0f; // 目标类别3
434
+
435
+ // 学习
436
+ OnlineLearner::LearnResult result = learner.learn_step(input, target, 5, true);
437
+
438
+ printf(" Single sample adaptation:\n");
439
+ printf(" Initial loss: %.4f\n", result.initial_loss);
440
+ printf(" Final loss: %.4f\n", result.final_loss);
441
+ printf(" Loss reduction: %.4f\n", result.loss_reduction);
442
+
443
+ // 少样本适应
444
+ std::vector<Tensor> few_inputs(5);
445
+ std::vector<Tensor> few_targets(5);
446
+
447
+ for (size_t i = 0; i < 5; ++i) {
448
+ few_inputs[i] = Tensor(std::vector<size_t>{1, 512}, QuantType::FP32);
449
+ few_targets[i] = Tensor(std::vector<size_t>{1, 10}, QuantType::FP32);
450
+
451
+ float* fi = few_inputs[i].as_fp32();
452
+ float* ft = few_targets[i].as_fp32();
453
+ for (size_t j = 0; j < 512; ++j) fi[j] = (static_cast<float>(rand()) / RAND_MAX - 0.5f) * 0.1f;
454
+ for (size_t j = 0; j < 10; ++j) ft[j] = (j == (i % 10)) ? 1.0f : 0.0f;
455
+ }
456
+
457
+ result = learner.few_shot_adapt(few_inputs, few_targets, 10);
458
+
459
+ printf(" Few-shot adaptation (5 samples):\n");
460
+ printf(" Initial loss: %.4f\n", result.initial_loss);
461
+ printf(" Final loss: %.4f\n", result.final_loss);
462
+
463
+ // 记忆巩固效果
464
+ printf(" Memory consolidation test:\n");
465
+ float mem_before = model.memory->memory_bank.as_fp32()[0];
466
+
467
+ Tensor batch(std::vector<size_t>{32, cfg.hidden_dim}, QuantType::FP32);
468
+ model.memory->consolidate(batch);
469
+
470
+ float mem_after = model.memory->memory_bank.as_fp32()[0];
471
+ printf(" Memory bank change: %.6f\n", std::abs(mem_after - mem_before));
472
+ printf(" LTP rate: %.4f\n", model.memory->ltp_rate);
473
+
474
+ printf("=== Test Complete ===\n\n");
475
+ }
476
+
477
+ } // namespace neuroflow
include/neuroflow/rms_norm.hpp ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_RMS_NORM_HPP
2
+ #define NEUROFLOW_RMS_NORM_HPP
3
+
4
+ #include <cstddef>
5
+ #include "tensor.hpp"
6
+
7
+ #ifdef USE_CUDA
8
+ #include <cuda_runtime.h>
9
+ #endif
10
+
11
+ namespace neuroflow {
12
+
13
+ class RMSNorm {
14
+ public:
15
+ size_t dim_;
16
+ float eps_;
17
+ Tensor weight_;
18
+
19
+ struct Cache {
20
+ Tensor input;
21
+ Tensor rms;
22
+ Tensor normalized;
23
+ };
24
+ Cache cache_;
25
+
26
+ RMSNorm(size_t dim, float eps = 1e-5f);
27
+ Tensor forward(const Tensor& x);
28
+
29
+ struct Gradients {
30
+ Tensor weight_grad;
31
+ Tensor input_grad;
32
+ };
33
+
34
+ Gradients backward(const Tensor& output_grad);
35
+ };
36
+
37
+ #ifdef USE_CUDA
38
+ void launch_rms_norm_forward(float* out, const float* input, const float* weight,
39
+ float* rms, float* normalized, size_t batch, size_t dim,
40
+ float eps, cudaStream_t stream);
41
+ void launch_rms_norm_backward(float* input_grad, float* weight_grad,
42
+ const float* output_grad, const float* input,
43
+ const float* rms, const float* normalized,
44
+ const float* weight, size_t batch, size_t dim,
45
+ cudaStream_t stream);
46
+ #endif
47
+
48
+ } // namespace neuroflow
49
+
50
+ #endif // NEUROFLOW_RMS_NORM_HPP
include/neuroflow/rope.hpp ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_ROPE_HPP
2
+ #define NEUROFLOW_ROPE_HPP
3
+
4
+ #include <cstddef>
5
+ #include <vector>
6
+ #include "tensor.hpp"
7
+
8
+ #ifdef USE_CUDA
9
+ #include <cuda_runtime.h>
10
+ #endif
11
+
12
+ namespace neuroflow {
13
+
14
+ class RoPE {
15
+ public:
16
+ size_t head_dim_;
17
+ size_t max_seq_len_;
18
+ float yarn_scale_factor_ = 1.0f;
19
+ Tensor freqs_cos_;
20
+ Tensor freqs_sin_;
21
+
22
+ RoPE(size_t head_dim, size_t max_seq_len);
23
+
24
+ void apply(Tensor& qkv, size_t seq_len, size_t n_heads, size_t d_model, size_t offset = 0) const;
25
+ void apply_single(Tensor& x, size_t seq_len, size_t n_heads, size_t offset = 0) const;
26
+ void set_yarn_scale(float scale_factor);
27
+ };
28
+
29
+ #ifdef USE_CUDA
30
+ void launch_rope(float* qkv, const float* cos_table, const float* sin_table,
31
+ size_t seq_len, size_t n_heads, size_t d_model, size_t head_dim,
32
+ size_t offset, cudaStream_t stream);
33
+ void launch_rope_single(float* data, const float* cos_table, const float* sin_table,
34
+ size_t seq_len, size_t n_heads, size_t stride, size_t head_dim,
35
+ size_t offset, cudaStream_t stream);
36
+ #endif
37
+
38
+ } // namespace neuroflow
39
+
40
+ #endif // NEUROFLOW_ROPE_HPP
include/neuroflow/sampling.hpp ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_SAMPLING_HPP
2
+ #define NEUROFLOW_SAMPLING_HPP
3
+
4
+ #include <algorithm>
5
+ #include <cmath>
6
+ #include <iostream>
7
+ #include <memory>
8
+ #include <numeric>
9
+ #include <random>
10
+ #include <vector>
11
+ #include "tensor.hpp"
12
+
13
+ namespace neuroflow {
14
+
15
+ enum class SamplingStrategyType : uint8_t {
16
+ GREEDY = 0,
17
+ TOP_K = 1,
18
+ TOP_P = 2,
19
+ TOP_K_TOP_P = 3
20
+ };
21
+
22
+ struct GenerateConfig {
23
+ size_t max_new_tokens = 50;
24
+ float temperature = 1.0f;
25
+ size_t top_k = 40;
26
+ float top_p = 0.9f;
27
+ float repetition_penalty = 1.0f;
28
+ float punct_penalty = 0.0f;
29
+ std::vector<size_t> punct_ids;
30
+ size_t random_seed = 0;
31
+ SamplingStrategyType strategy = SamplingStrategyType::TOP_K;
32
+ size_t eos_id = 3;
33
+ };
34
+
35
+ class SamplingStrategy {
36
+ public:
37
+ virtual ~SamplingStrategy() = default;
38
+ virtual Tensor apply(Tensor logits, const GenerateConfig& config,
39
+ const std::vector<size_t>& generated) = 0;
40
+ virtual size_t sample(const Tensor& probs, std::mt19937& rng) const = 0;
41
+ };
42
+
43
+ class GreedyDecoding : public SamplingStrategy {
44
+ public:
45
+ Tensor apply(Tensor logits, const GenerateConfig& config,
46
+ const std::vector<size_t>& generated) override;
47
+ size_t sample(const Tensor& probs, std::mt19937& rng) const override;
48
+ };
49
+
50
+ class TopKSampling : public SamplingStrategy {
51
+ public:
52
+ Tensor apply(Tensor logits, const GenerateConfig& config,
53
+ const std::vector<size_t>& generated) override;
54
+ size_t sample(const Tensor& probs, std::mt19937& rng) const override;
55
+ };
56
+
57
+ class TopPSampling : public SamplingStrategy {
58
+ public:
59
+ Tensor apply(Tensor logits, const GenerateConfig& config,
60
+ const std::vector<size_t>& generated) override;
61
+ size_t sample(const Tensor& probs, std::mt19937& rng) const override;
62
+ };
63
+
64
+ class TopKTopPSampling : public SamplingStrategy {
65
+ public:
66
+ Tensor apply(Tensor logits, const GenerateConfig& config,
67
+ const std::vector<size_t>& generated) override;
68
+ size_t sample(const Tensor& probs, std::mt19937& rng) const override;
69
+ };
70
+
71
+ } // namespace neuroflow
72
+
73
+ #endif // NEUROFLOW_SAMPLING_HPP
include/neuroflow/scheduler.hpp ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_SCHEDULER_HPP
2
+ #define NEUROFLOW_SCHEDULER_HPP
3
+
4
+ #include <cstddef>
5
+
6
+ namespace neuroflow {
7
+
8
+ class CosineScheduler {
9
+ public:
10
+ enum class Phase { WARMUP, COSINE, DONE };
11
+
12
+ float lr_max_;
13
+ float lr_min_;
14
+ size_t warmup_steps_;
15
+ size_t total_steps_;
16
+
17
+ CosineScheduler(float lr_max, size_t total_steps,
18
+ float lr_min_ratio = 0.1f, float warmup_ratio = 0.01f);
19
+
20
+ float get_lr(size_t step) const;
21
+ Phase get_phase(size_t step) const;
22
+ };
23
+
24
+ } // namespace neuroflow
25
+
26
+ #endif // NEUROFLOW_SCHEDULER_HPP
include/neuroflow/sft.hpp ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_SFT_HPP
2
+ #define NEUROFLOW_SFT_HPP
3
+
4
+ #include <cstddef>
5
+ #include <random>
6
+ #include <string>
7
+ #include <vector>
8
+
9
+ #include "adamw.hpp"
10
+ #include "alignment_common.hpp"
11
+ #include "causal_lm.hpp"
12
+ #include "scheduler.hpp"
13
+ #include "tokenizer.hpp"
14
+
15
+ namespace neuroflow {
16
+
17
+ struct SFTTrainConfig {
18
+ std::string data_path;
19
+ std::string ckpt_path;
20
+ std::string tokenizer_path;
21
+ std::string output_dir;
22
+ float learning_rate = 2e-5f;
23
+ int epochs = 3;
24
+ size_t max_seq_len = 512;
25
+ float warmup_ratio = 0.05f;
26
+ float weight_decay = 0.01f;
27
+ float grad_clip = 1.0f;
28
+ float adam_beta1 = 0.9f;
29
+ float adam_beta2 = 0.999f;
30
+ float adam_eps = 1e-8f;
31
+ size_t save_interval = 1000;
32
+ size_t log_interval = 10;
33
+ unsigned seed = 42;
34
+ };
35
+
36
+ class SFTDataLoader {
37
+ public:
38
+ SFTDataLoader(const std::string& jsonl_path, size_t max_samples = 0);
39
+
40
+ bool has_next() const;
41
+ SFTSample next();
42
+ void reset();
43
+ void shuffle(std::mt19937& rng);
44
+ size_t total_samples() const { return samples_.size(); }
45
+ size_t invalid_count() const { return invalid_count_; }
46
+
47
+ private:
48
+ std::vector<SFTSample> samples_;
49
+ size_t cursor_ = 0;
50
+ size_t invalid_count_ = 0;
51
+ };
52
+
53
+ struct MaskedCEOutput {
54
+ float loss;
55
+ Tensor logits_grad;
56
+ size_t valid_token_count;
57
+ };
58
+
59
+ MaskedCEOutput masked_cross_entropy(const Tensor& logits, size_t vocab_size,
60
+ const std::vector<size_t>& target_ids,
61
+ const std::vector<float>& loss_mask);
62
+
63
+ SFTTrainingTensors build_sft_training_tensors(const SFTSample& sample,
64
+ BPETokenizer& tokenizer,
65
+ size_t max_seq_len);
66
+
67
+ class SFTTrainer {
68
+ public:
69
+ SFTTrainConfig config;
70
+
71
+ SFTTrainer(const SFTTrainConfig& cfg);
72
+
73
+ void train();
74
+ float train_on_sample(const SFTSample& sample);
75
+
76
+ private:
77
+ std::unique_ptr<CausalLMHead> model_;
78
+ std::unique_ptr<BPETokenizer> tokenizer_;
79
+ std::unique_ptr<AdamW> optimizer_;
80
+ std::unique_ptr<CosineScheduler> scheduler_;
81
+ };
82
+
83
+ } // namespace neuroflow
84
+
85
+ #endif // NEUROFLOW_SFT_HPP
include/neuroflow/swiglu.hpp ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_SWIGLU_HPP
2
+ #define NEUROFLOW_SWIGLU_HPP
3
+
4
+ #include <cstddef>
5
+ #include "tensor.hpp"
6
+ #include "model.hpp"
7
+
8
+ #ifdef USE_CUDA
9
+ #include <cuda_runtime.h>
10
+ #endif
11
+
12
+ namespace neuroflow {
13
+
14
+ class SwiGLUFFN {
15
+ public:
16
+ size_t d_model_;
17
+ size_t d_ff_;
18
+ std::shared_ptr<Linear> w_gate_;
19
+ std::shared_ptr<Linear> w_up_;
20
+ std::shared_ptr<Linear> w_down_;
21
+
22
+ struct Cache {
23
+ Tensor input;
24
+ Tensor gate_out;
25
+ Tensor up_out;
26
+ Tensor gate_activated;
27
+ Tensor multiplied;
28
+ };
29
+ Cache cache_;
30
+ bool training_mode_ = false;
31
+
32
+ SwiGLUFFN(size_t d_model, size_t d_ff = 0);
33
+ Tensor forward(const Tensor& x);
34
+
35
+ struct Gradients {
36
+ Tensor w_gate_weight_grad;
37
+ Tensor w_gate_bias_grad;
38
+ Tensor w_up_weight_grad;
39
+ Tensor w_up_bias_grad;
40
+ Tensor w_down_weight_grad;
41
+ Tensor w_down_bias_grad;
42
+ Tensor input_grad;
43
+ };
44
+
45
+ Gradients backward(const Tensor& output_grad);
46
+ };
47
+
48
+ #ifdef USE_CUDA
49
+ void launch_silu(float* data, size_t n, cudaStream_t stream);
50
+ void launch_elementwise_mul(float* out, const float* a, const float* b, size_t n, cudaStream_t stream);
51
+ #endif
52
+
53
+ } // namespace neuroflow
54
+
55
+ #endif // NEUROFLOW_SWIGLU_HPP
include/neuroflow/tensor.hpp ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_TENSOR_HPP
2
+ #define NEUROFLOW_TENSOR_HPP
3
+
4
+ /**
5
+ * NeuroFlow Core Tensor Engine
6
+ *
7
+ * 轻量化高性能张量计算库
8
+ * 特点:
9
+ * - SIMD优化 (AVX2/ARM NEON)
10
+ * - 零拷贝内存管理
11
+ * - 内存映射支持
12
+ * - INT8/FP8量化支持
13
+ */
14
+
15
+ #include <algorithm>
16
+ #include <cmath>
17
+ #include <cstdint>
18
+ #include <cstring>
19
+ #include <functional>
20
+ #include <memory>
21
+ #include <random>
22
+ #include <stdexcept>
23
+ #include <thread>
24
+ #include <vector>
25
+
26
+ #ifdef USE_CBLAS
27
+ extern "C" {
28
+ #include <cblas.h>
29
+ }
30
+ #define cblas_sgemm scipy_cblas_sgemm
31
+ #endif
32
+
33
+ #ifdef USE_CUDA
34
+ #include "cuda_context.hpp"
35
+ #endif
36
+
37
+
38
+ #ifdef __AVX2__
39
+ #include <immintrin.h>
40
+ #define HAS_AVX2 1
41
+ #endif
42
+
43
+ #ifdef __ARM_NEON
44
+ #include <arm_neon.h>
45
+ #define HAS_NEON 1
46
+ #endif
47
+
48
+ namespace neuroflow {
49
+
50
+ // 量化类型枚举
51
+ enum class QuantType : uint8_t {
52
+ FP32 = 0,
53
+ FP16 = 1,
54
+ INT8 = 2,
55
+ INT4 = 3,
56
+ FP8_E4M3 = 4, // DeepSeek FP8
57
+ FP8_E5M2 = 5,
58
+ };
59
+
60
+ // 内存布局
61
+ enum class MemoryLayout : uint8_t {
62
+ ROW_MAJOR = 0,
63
+ COL_MAJOR = 1,
64
+ };
65
+
66
+ /**
67
+ * Tensor类 - 核心数据结构
68
+ * 支持多种量化格式和内存布局
69
+ */
70
+ class Tensor {
71
+ public:
72
+ std::vector<size_t> shape_;
73
+ std::vector<size_t> strides_;
74
+ QuantType dtype_;
75
+ MemoryLayout layout_;
76
+ std::shared_ptr<uint8_t> data_;
77
+ size_t data_size_;
78
+ // 语义标记:指示此 Tensor 是否"拥有" data_ 的逻辑所有权。
79
+ // 注意:data_ 是 shared_ptr,实际内存由引用计数管理,析构函数不检查 owns_data_。
80
+ // owns_data_ 仅用于 tie_weights() 等场景的所有权文档化,不影响内存释放。
81
+ bool owns_data_;
82
+
83
+ #ifdef USE_CUDA
84
+ void* gpu_data_ = nullptr;
85
+ bool on_gpu_ = false;
86
+ bool gpu_dirty_ = false;
87
+
88
+ void to_gpu() {
89
+ if (data_size_ == 0 || !data_) return;
90
+ auto& ctx = CudaContext::instance();
91
+ if (!ctx.is_available()) return;
92
+ if (!gpu_data_) {
93
+ gpu_data_ = ctx.alloc(data_size_);
94
+ }
95
+ ctx.copy_h2d(gpu_data_, data_.get(), data_size_);
96
+ on_gpu_ = true;
97
+ gpu_dirty_ = false;
98
+ }
99
+
100
+ void to_cpu() {
101
+ if (!on_gpu_ || !gpu_data_ || data_size_ == 0) return;
102
+ auto& ctx = CudaContext::instance();
103
+ if (!ctx.is_available()) return;
104
+ if (!data_) {
105
+ data_ = std::shared_ptr<uint8_t>(new uint8_t[data_size_], std::default_delete<uint8_t[]>());
106
+ }
107
+ ctx.copy_d2h(data_.get(), gpu_data_, data_size_);
108
+ ctx.synchronize();
109
+ gpu_dirty_ = false;
110
+ }
111
+
112
+ float* as_gpu_fp32() {
113
+ if (dtype_ != QuantType::FP32) throw std::runtime_error("Not FP32 tensor");
114
+ return reinterpret_cast<float*>(gpu_data_);
115
+ }
116
+
117
+ const float* as_gpu_fp32() const {
118
+ if (dtype_ != QuantType::FP32) throw std::runtime_error("Not FP32 tensor");
119
+ return reinterpret_cast<const float*>(gpu_data_);
120
+ }
121
+
122
+ bool is_on_gpu() const { return on_gpu_; }
123
+
124
+ void gpu_free() {
125
+ if (gpu_data_) {
126
+ auto& ctx = CudaContext::instance();
127
+ if (ctx.is_available()) ctx.free(gpu_data_);
128
+ gpu_data_ = nullptr;
129
+ on_gpu_ = false;
130
+ gpu_dirty_ = false;
131
+ }
132
+ }
133
+ #endif
134
+
135
+ Tensor() : dtype_(QuantType::FP32), layout_(MemoryLayout::ROW_MAJOR),
136
+ data_size_(0), owns_data_(true) {}
137
+
138
+ ~Tensor() {
139
+ #ifdef USE_CUDA
140
+ gpu_free();
141
+ #endif
142
+ }
143
+
144
+ Tensor(const Tensor& other)
145
+ : shape_(other.shape_), strides_(other.strides_), dtype_(other.dtype_),
146
+ layout_(other.layout_), data_(other.data_), data_size_(other.data_size_),
147
+ owns_data_(false)
148
+ #ifdef USE_CUDA
149
+ , gpu_data_(other.gpu_data_), on_gpu_(other.on_gpu_), gpu_dirty_(other.gpu_dirty_)
150
+ #endif
151
+ {}
152
+
153
+ Tensor& operator=(const Tensor& other) {
154
+ if (this != &other) {
155
+ #ifdef USE_CUDA
156
+ gpu_free();
157
+ #endif
158
+ shape_ = other.shape_;
159
+ strides_ = other.strides_;
160
+ dtype_ = other.dtype_;
161
+ layout_ = other.layout_;
162
+ data_ = other.data_;
163
+ data_size_ = other.data_size_;
164
+ owns_data_ = false;
165
+ #ifdef USE_CUDA
166
+ gpu_data_ = other.gpu_data_;
167
+ on_gpu_ = other.on_gpu_;
168
+ gpu_dirty_ = other.gpu_dirty_;
169
+ #endif
170
+ }
171
+ return *this;
172
+ }
173
+
174
+ Tensor(Tensor&& other) noexcept
175
+ : shape_(std::move(other.shape_)), strides_(std::move(other.strides_)),
176
+ dtype_(other.dtype_), layout_(other.layout_), data_(std::move(other.data_)),
177
+ data_size_(other.data_size_), owns_data_(other.owns_data_)
178
+ #ifdef USE_CUDA
179
+ , gpu_data_(other.gpu_data_), on_gpu_(other.on_gpu_), gpu_dirty_(other.gpu_dirty_)
180
+ #endif
181
+ {
182
+ other.data_size_ = 0;
183
+ other.owns_data_ = false;
184
+ #ifdef USE_CUDA
185
+ other.gpu_data_ = nullptr;
186
+ other.on_gpu_ = false;
187
+ other.gpu_dirty_ = false;
188
+ #endif
189
+ }
190
+
191
+ Tensor& operator=(Tensor&& other) noexcept {
192
+ if (this != &other) {
193
+ #ifdef USE_CUDA
194
+ gpu_free();
195
+ #endif
196
+ shape_ = std::move(other.shape_);
197
+ strides_ = std::move(other.strides_);
198
+ dtype_ = other.dtype_;
199
+ layout_ = other.layout_;
200
+ data_ = std::move(other.data_);
201
+ data_size_ = other.data_size_;
202
+ owns_data_ = other.owns_data_;
203
+ #ifdef USE_CUDA
204
+ gpu_data_ = other.gpu_data_;
205
+ on_gpu_ = other.on_gpu_;
206
+ gpu_dirty_ = other.gpu_dirty_;
207
+ other.gpu_data_ = nullptr;
208
+ other.on_gpu_ = false;
209
+ other.gpu_dirty_ = false;
210
+ #endif
211
+ other.data_size_ = 0;
212
+ other.owns_data_ = false;
213
+ }
214
+ return *this;
215
+ }
216
+
217
+ Tensor(const std::vector<size_t>& dims, QuantType type = QuantType::FP32)
218
+ : shape_(dims), dtype_(type), layout_(MemoryLayout::ROW_MAJOR), owns_data_(true) {
219
+ strides_.resize(dims.size());
220
+ size_t total = 1;
221
+ for (size_t i = dims.size(); i > 0; --i) {
222
+ strides_[i-1] = total;
223
+ total *= dims[i-1];
224
+ }
225
+ data_size_ = total * get_type_size();
226
+ data_ = std::shared_ptr<uint8_t>(new uint8_t[data_size_], std::default_delete<uint8_t[]>());
227
+ memset(data_.get(), 0, data_size_);
228
+ }
229
+
230
+ // 类型大小
231
+ size_t get_type_size() const {
232
+ switch (dtype_) {
233
+ case QuantType::FP32: return 4;
234
+ case QuantType::FP16: return 2;
235
+ case QuantType::INT8: return 1;
236
+ case QuantType::INT4: return 1; // packed
237
+ case QuantType::FP8_E4M3: return 1;
238
+ case QuantType::FP8_E5M2: return 1;
239
+ default: return 4;
240
+ }
241
+ }
242
+
243
+ // 总元素数
244
+ size_t numel() const {
245
+ size_t n = 1;
246
+ for (auto d : shape_) n *= d;
247
+ return n;
248
+ }
249
+
250
+ // FP32数据访问
251
+ float* as_fp32() {
252
+ if (dtype_ != QuantType::FP32) throw std::runtime_error("Not FP32 tensor");
253
+ return reinterpret_cast<float*>(data_.get());
254
+ }
255
+
256
+ const float* as_fp32() const {
257
+ if (dtype_ != QuantType::FP32) throw std::runtime_error("Not FP32 tensor");
258
+ return reinterpret_cast<const float*>(data_.get());
259
+ }
260
+
261
+ // 别名,兼容性
262
+ const float* as_fp32_const() const {
263
+ return as_fp32();
264
+ }
265
+
266
+ // INT8数据访问
267
+ int8_t* as_int8() {
268
+ if (dtype_ != QuantType::INT8) throw std::runtime_error("Not INT8 tensor");
269
+ return reinterpret_cast<int8_t*>(data_.get());
270
+ }
271
+
272
+ const int8_t* as_int8() const {
273
+ if (dtype_ != QuantType::INT8) throw std::runtime_error("Not INT8 tensor");
274
+ return reinterpret_cast<const int8_t*>(data_.get());
275
+ }
276
+
277
+ // reshape (零拷贝)
278
+ Tensor reshape(const std::vector<size_t>& new_shape) const {
279
+ Tensor t;
280
+ t.shape_ = new_shape;
281
+ t.dtype_ = dtype_;
282
+ t.layout_ = layout_;
283
+ t.data_ = data_;
284
+ t.data_size_ = data_size_;
285
+ t.owns_data_ = false;
286
+ #ifdef USE_CUDA
287
+ t.gpu_data_ = gpu_data_;
288
+ t.on_gpu_ = on_gpu_;
289
+ t.gpu_dirty_ = gpu_dirty_;
290
+ #endif
291
+
292
+ size_t total = 1;
293
+ for (auto d : new_shape) total *= d;
294
+ if (total != numel()) throw std::runtime_error("Invalid reshape");
295
+
296
+ t.strides_.resize(new_shape.size());
297
+ size_t acc = 1;
298
+ for (size_t i = new_shape.size(); i > 0; --i) {
299
+ t.strides_[i-1] = acc;
300
+ acc *= new_shape[i-1];
301
+ }
302
+ return t;
303
+ }
304
+
305
+ Tensor clone() const {
306
+ Tensor t(shape_, dtype_);
307
+ memcpy(t.data_.get(), data_.get(), data_size_);
308
+ #ifdef USE_CUDA
309
+ if (on_gpu_ && gpu_data_) {
310
+ auto& ctx = CudaContext::instance();
311
+ if (ctx.is_available()) {
312
+ t.gpu_data_ = ctx.alloc(data_size_);
313
+ ctx.copy_d2d(t.gpu_data_, gpu_data_, data_size_);
314
+ t.on_gpu_ = true;
315
+ t.gpu_dirty_ = gpu_dirty_;
316
+ }
317
+ }
318
+ #endif
319
+ return t;
320
+ }
321
+ };
322
+
323
+ } // namespace neuroflow
324
+
325
+ #include "tensor_ops.hpp"
326
+
327
+ #endif // NEUROFLOW_TENSOR_HPP
include/neuroflow/tensor_ops.hpp ADDED
@@ -0,0 +1,92 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_TENSOR_OPS_HPP
2
+ #define NEUROFLOW_TENSOR_OPS_HPP
3
+
4
+
5
+ namespace neuroflow {
6
+
7
+ class TensorOps {
8
+ public:
9
+ static void gemm(const Tensor& A, const Tensor& B, Tensor& C,
10
+ bool transA = false, bool transB = false,
11
+ float alpha = 1.0f, float beta = 0.0f);
12
+
13
+ static void quantized_gemm(const Tensor& A, const Tensor& B, Tensor& C);
14
+
15
+ static void layer_norm(Tensor& x, Tensor& weight, Tensor& bias, float eps = 1e-5f);
16
+
17
+ static void gelu(Tensor& x);
18
+
19
+ static void softmax(Tensor& x, int axis = -1);
20
+
21
+ static void dropout(Tensor& x, float rate, bool training = true);
22
+
23
+ static void quantize_int8(const Tensor& src, Tensor& dst, Tensor& scale);
24
+
25
+ static void dequantize_int8(const Tensor& src, Tensor& dst, const Tensor& scale);
26
+
27
+ static void add(Tensor& a, const Tensor& b);
28
+
29
+ static void mul(Tensor& a, float scalar);
30
+
31
+ static void parallel_gemm(const Tensor& A, const Tensor& B, Tensor& C,
32
+ bool transA = false, bool transB = false,
33
+ float alpha = 1.0f, float beta = 0.0f,
34
+ size_t num_threads = 4);
35
+
36
+ static Tensor matmul(const Tensor& A, const Tensor& B);
37
+
38
+ static Tensor elementwise_add(const Tensor& A, const Tensor& B);
39
+ static Tensor elementwise_sub(const Tensor& A, const Tensor& B);
40
+ static Tensor elementwise_mul(const Tensor& A, const Tensor& B);
41
+ static Tensor scalar_mul(const Tensor& A, float s);
42
+ static Tensor broadcast_add(const Tensor& A, const Tensor& B);
43
+
44
+ static Tensor transpose2d(const Tensor& A);
45
+
46
+ static void fill(Tensor& A, float value);
47
+ static void copy_data(Tensor& dst, const Tensor& src);
48
+
49
+ static float dot(const Tensor& A, const Tensor& B);
50
+ static float norm2(const Tensor& A);
51
+
52
+ static Tensor reduce_sum(const Tensor& A, int axis = -1);
53
+
54
+ static Tensor slice(const Tensor& A, size_t dim, size_t start, size_t end);
55
+ static Tensor pad1d(const Tensor& A, size_t left, size_t right, float value = 0.0f);
56
+
57
+ static void apply_inplace(Tensor& A, std::function<float(float)> fn);
58
+ static Tensor apply(const Tensor& A, std::function<float(float)> fn);
59
+
60
+ static Tensor relu(const Tensor& A);
61
+ static Tensor sigmoid(const Tensor& A);
62
+ static Tensor tanh_act(const Tensor& A);
63
+ static Tensor log(const Tensor& A);
64
+ static Tensor exp(const Tensor& A);
65
+ static void clip_inplace(Tensor& A, float min_val, float max_val);
66
+
67
+ static Tensor concat(const std::vector<Tensor>& tensors, size_t axis = 0);
68
+
69
+ private:
70
+ static void gemm_scalar(const float* a, const float* b, float* c,
71
+ size_t M, size_t K, size_t N,
72
+ bool transA, bool transB,
73
+ float alpha, float beta);
74
+
75
+ #ifdef HAS_AVX2
76
+ static void gemm_avx2(const float* a, const float* b, float* c,
77
+ size_t M, size_t K, size_t N,
78
+ bool transA, bool transB,
79
+ float alpha, float beta);
80
+ #endif
81
+
82
+ #ifdef HAS_NEON
83
+ static void gemm_neon(const float* a, const float* b, float* c,
84
+ size_t M, size_t K, size_t N,
85
+ bool transA, bool transB,
86
+ float alpha, float beta);
87
+ #endif
88
+ };
89
+
90
+ } // namespace neuroflow
91
+
92
+ #endif // NEUROFLOW_TENSOR_OPS_HPP
include/neuroflow/tokenizer.hpp ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_TOKENIZER_HPP
2
+ #define NEUROFLOW_TOKENIZER_HPP
3
+
4
+ #include <algorithm>
5
+ #include <fstream>
6
+ #include <iostream>
7
+ #include <memory>
8
+ #include <queue>
9
+ #include <sstream>
10
+ #include <string>
11
+ #include <unordered_map>
12
+ #include <vector>
13
+
14
+ namespace neuroflow {
15
+
16
+ class Tokenizer {
17
+ public:
18
+ virtual ~Tokenizer() = default;
19
+
20
+ virtual std::vector<size_t> encode(const std::string& text, size_t max_len = 0) = 0;
21
+ virtual std::string decode(const std::vector<size_t>& ids) = 0;
22
+
23
+ size_t vocab_size() const { return vocab_size_; }
24
+ size_t pad_id() const { return pad_id_; }
25
+ size_t unk_id() const { return unk_id_; }
26
+ size_t bos_id() const { return bos_id_; }
27
+ size_t eos_id() const { return eos_id_; }
28
+
29
+ protected:
30
+ size_t vocab_size_ = 128000;
31
+ size_t pad_id_ = 0;
32
+ size_t unk_id_ = 1;
33
+ size_t bos_id_ = 2;
34
+ size_t eos_id_ = 3;
35
+ size_t max_input_len_ = 128;
36
+ };
37
+
38
+ class BPETokenizer : public Tokenizer {
39
+ public:
40
+ BPETokenizer(const std::string& config_path);
41
+ BPETokenizer();
42
+
43
+ std::vector<size_t> encode(const std::string& text, size_t max_len = 0) override;
44
+ std::string decode(const std::vector<size_t>& ids) override;
45
+
46
+ void add_vocab(const std::string& token, size_t id);
47
+ void set_vocab_size(size_t vs);
48
+
49
+ private:
50
+ std::unordered_map<std::string, size_t> vocab_;
51
+ std::unordered_map<size_t, std::string> id_to_token_;
52
+ std::vector<std::pair<std::string, std::string>> merges_;
53
+ std::unordered_map<std::string, size_t> merge_ranks_;
54
+
55
+ std::vector<uint8_t> utf8_to_bytes(const std::string& text);
56
+ std::string bytes_to_utf8(const std::string& raw);
57
+ std::string apply_bpe(const std::string& token);
58
+ void parse_config(const std::string& content);
59
+ };
60
+
61
+ class WordPieceTokenizer : public Tokenizer {
62
+ public:
63
+ WordPieceTokenizer();
64
+ WordPieceTokenizer(const std::string& config_path);
65
+
66
+ std::vector<size_t> encode(const std::string& text, size_t max_len = 0) override;
67
+ std::string decode(const std::vector<size_t>& ids) override;
68
+
69
+ void add_vocab(const std::string& token, size_t id);
70
+ void set_vocab_size(size_t vs);
71
+
72
+ private:
73
+ std::unordered_map<std::string, size_t> vocab_;
74
+ std::unordered_map<size_t, std::string> id_to_token_;
75
+
76
+ void parse_vocab(const std::string& content);
77
+ };
78
+
79
+ } // namespace neuroflow
80
+
81
+ #endif // NEUROFLOW_TOKENIZER_HPP
include/neuroflow/train_lm.hpp ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef NEUROFLOW_TRAIN_LM_HPP
2
+ #define NEUROFLOW_TRAIN_LM_HPP
3
+
4
+ #include <cstddef>
5
+ #include <string>
6
+ #include <vector>
7
+ #include "tensor.hpp"
8
+ #include "causal_lm.hpp"
9
+ #include "adamw.hpp"
10
+ #include "scheduler.hpp"
11
+
12
+ namespace neuroflow {
13
+
14
+ struct TrainLMConfig {
15
+ size_t vocab_size = 128000;
16
+ size_t d_model = 256;
17
+ size_t max_seq_len = 128;
18
+ size_t num_attn_layers = 2;
19
+ size_t num_attn_heads = 4;
20
+ size_t causal_window_size = 32;
21
+ size_t sae_k = 64;
22
+ size_t ntm_memory_slots = 16;
23
+ bool weight_tying = true;
24
+ bool use_rope = true;
25
+ bool use_bridge = true;
26
+ bool use_swiglu = true;
27
+ bool use_qk_norm = true;
28
+ size_t swiglu_intermediate_size = 0;
29
+ std::string pooling = "mean";
30
+
31
+ float learning_rate = 5e-4f;
32
+ float adam_beta1 = 0.9f;
33
+ float adam_beta2 = 0.999f;
34
+ float adam_eps = 1e-8f;
35
+ float adam_weight_decay = 0.01f;
36
+ float grad_clip = 1.0f;
37
+ float lr_min_ratio = 0.1f;
38
+ float warmup_ratio = 0.01f;
39
+
40
+ size_t epochs = 10;
41
+ size_t total_steps = 0;
42
+ size_t log_interval = 10;
43
+ size_t save_interval = 1000;
44
+ std::string output_dir = "./checkpoints";
45
+ std::string data_path;
46
+ };
47
+
48
+ class TrainLM {
49
+ public:
50
+ TrainLM(const TrainLMConfig& config);
51
+ void train(const std::vector<std::vector<size_t>>& dataset);
52
+
53
+ private:
54
+ TrainLMConfig cfg_;
55
+ std::unique_ptr<CausalLMHead> lm_head_;
56
+ std::unique_ptr<AdamW> optimizer_;
57
+ std::unique_ptr<CosineScheduler> scheduler_;
58
+
59
+ void setup_optimizer();
60
+ float compute_loss_and_grad(const std::vector<size_t>& input_ids,
61
+ const std::vector<size_t>& target_ids,
62
+ Tensor& logits_grad);
63
+ void save_checkpoint(size_t step, float loss);
64
+ };
65
+
66
+ } // namespace neuroflow
67
+
68
+ #endif // NEUROFLOW_TRAIN_LM_HPP
output/checkpoint_step1000/model.nfv1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:02ed4c5dfe413965bf6a062ed13f5f34a2f164fbb52c863a42faaa60feeed664
3
+ size 451607499
output/checkpoint_step2000/model.nfv1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e50b44a7630fbcdcd02ddcd65f996700940d0e1d291d95978440dd672440fb0e
3
+ size 451607499
output/lm_head_lmh1.nfv1 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e9576c6cc392d8d6132c156c9f3d2d6eba0f670ea9981f978c09957d25efad0
3
+ size 267391131
scripts/check_json_format.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+
3
+ path = r'D:\neuroflow-C++\configs\tokenizer_128k.json'
4
+ with open(path, 'r', encoding='utf-8') as f:
5
+ content = f.read()
6
+
7
+ print('Lines:', content.count('\n'))
8
+ print('Size:', len(content))
9
+
10
+ # Find vocab section
11
+ idx = content.find('"vocab"')
12
+ print('vocab key at position:', idx)
13
+ if idx > 0:
14
+ print('Context:', repr(content[idx:idx+50]))
15
+
16
+ # The C++ parse_config looks for "\"vocab\":{" or "\"vocab\": {"
17
+ # With indent=2, it's likely "\"vocab\": {"
18
+ pattern1 = '"vocab": {'
19
+ pattern2 = '"vocab":{'
20
+ p1 = content.find(pattern1)
21
+ p2 = content.find(pattern2)
22
+ print(f'Pattern "{pattern1}" found at:', p1)
23
+ print(f'Pattern "{pattern2}" found at:', p2)
scripts/config_generator.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import json
3
+ import argparse
4
+ import logging
5
+ import os
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ MODEL_CONFIG_FIELDS = [
10
+ ("input_dim", 512, "int", "输入维度(d_model)", "hidden_dim"),
11
+ ("hidden_dim", 256, "int", "隐藏层维度", "hidden_dim"),
12
+ ("output_dim", 10, "int", "输出维度(分类数)", "num_labels"),
13
+ ("memory_dim", 128, "int", "记忆维度(d_mem)", None),
14
+ ("memory_slots", 64, "int", "记忆槽数(MEM_SLOTS)", None),
15
+ ("num_layers", 2, "int", "网络层数", "num_layers"),
16
+ ("num_associations", 8, "int", "DMN关联头数", None),
17
+ ("use_quantization", False, "bool", "是否启用量化", None),
18
+ ("use_mla", False, "bool", "是否启用MLA注意力", "use_mla"),
19
+ ("mla_latent_dim", 32, "int", "MLA潜在维度", None),
20
+ ("use_causal_lm", False, "bool", "是否启用因果LM", None),
21
+ ("vocab_size", 5000, "int", "词表大小(VOCAB_SIZE)", "vocab_size"),
22
+ ("max_seq_len", 128, "int", "最大序列长度", "max_seq_len"),
23
+ ("causal_window_size", 32, "int", "因果窗口大小", None),
24
+ ("sae_k", 64, "int", "SAE稀疏度", None),
25
+ ("ntm_memory_slots", 16, "int", "NTM记忆槽数", None),
26
+ ]
27
+
28
+ CAUSAL_LM_FIELDS = [
29
+ ("vocab_size", 5000, "int", "词表大小", "vocab_size"),
30
+ ("d_model", 256, "int", "模型维度", "hidden_dim"),
31
+ ("max_seq_len", 128, "int", "最大序列长度", "max_seq_len"),
32
+ ("causal_window_size", 32, "int", "因果窗口大小", None),
33
+ ("sae_k", 64, "int", "SAE稀疏度", None),
34
+ ("ntm_memory_slots", 16, "int", "NTM记忆槽数", None),
35
+ ("use_mla", True, "bool", "启用MLA", None),
36
+ ("mla_latent_dim", 32, "int", "MLA潜在维度", None),
37
+ ("mla_n_heads", 8, "int", "MLA头数", None),
38
+ ("mla_max_cache_len", 4096, "int", "MLA最大缓存长度", None),
39
+ ("use_quantization", False, "bool", "启用量化", None),
40
+ ]
41
+
42
+ GENERATE_FIELDS = [
43
+ ("max_new_tokens", 50, "int", "最大生成token数", None),
44
+ ("temperature", 1.0, "float", "采样温度(0.0,2.0]", None),
45
+ ("top_k", 40, "int", "Top-K采样K值", None),
46
+ ("top_p", 0.9, "float", "Top-P采样P值[0.0,1.0]", None),
47
+ ("repetition_penalty", 1.0, "float", "重复惩罚[1.0,2.0]", None),
48
+ ("punct_penalty", 0.0, "float", "标点惩罚", None),
49
+ ("random_seed", 0, "int", "随机种子(0=随机)", None),
50
+ ("strategy", "top_k", "str", "采样策略(greedy/top_k/top_p/top_k_top_p)", None),
51
+ ("eos_id", 3, "int", "EOS token ID", None),
52
+ ]
53
+
54
+
55
+ def parse_config_from_hpp(hpp_path, struct_name):
56
+ fields = []
57
+ try:
58
+ with open(hpp_path, "r", encoding="utf-8", errors="ignore") as f:
59
+ content = f.read()
60
+ pattern = rf'struct\s+{struct_name}\s*\{{([^}}]+)\}}'
61
+ match = re.search(pattern, content, re.DOTALL)
62
+ if not match:
63
+ logger.warning(f"未找到结构体 {struct_name},使用默认字段")
64
+ return None
65
+ body = match.group(1)
66
+ for line in body.strip().split("\n"):
67
+ line = line.strip()
68
+ if not line or line.startswith("//"):
69
+ continue
70
+ m = re.match(r'(size_t|bool|float|std::string|int)\s+(\w+)\s*=\s*([^;]+);', line)
71
+ if m:
72
+ ctype, name, default = m.groups()
73
+ default = default.strip().rstrip('f')
74
+ if ctype == "size_t" or ctype == "int":
75
+ default = int(default)
76
+ elif ctype == "float":
77
+ default = float(default)
78
+ elif ctype == "bool":
79
+ default = default == "true"
80
+ elif "SamplingStrategyType" in default:
81
+ default = default.split("::")[-1].lower()
82
+ fields.append((name, default, ctype))
83
+ except Exception as e:
84
+ logger.warning(f"解析hpp失败: {e},使用默认字段")
85
+ return fields
86
+
87
+
88
+ def generate_config_json():
89
+ config = {}
90
+ comments = {}
91
+ python_alias = {}
92
+ for name, default, _, comment, alias in MODEL_CONFIG_FIELDS + CAUSAL_LM_FIELDS:
93
+ config[name] = default
94
+ comments[name] = comment
95
+ if alias:
96
+ python_alias[name] = alias
97
+ config["_comment"] = comments
98
+ config["_python_alias"] = python_alias
99
+ return config
100
+
101
+
102
+ def generate_special_tokens_map():
103
+ return {
104
+ "pad_token": "<pad>",
105
+ "pad_token_id": 0,
106
+ "bos_token": "<s>",
107
+ "bos_token_id": 1,
108
+ "eos_token": "</s>",
109
+ "eos_token_id": 2,
110
+ "unk_token": "<unk>",
111
+ "unk_token_id": 3,
112
+ "_comment": {
113
+ "pad_token": "填充token,用于batch对齐",
114
+ "bos_token": "序列起始token",
115
+ "eos_token": "序列结束token,生成时遇到此token停止",
116
+ "unk_token": "未知token,词表外字符映射到此",
117
+ },
118
+ }
119
+
120
+
121
+ def generate_generation_config_json():
122
+ config = {}
123
+ comments = {}
124
+ for name, default, _, comment, _ in GENERATE_FIELDS:
125
+ config[name] = default
126
+ comments[name] = comment
127
+ config["_comment"] = comments
128
+ return config
129
+
130
+
131
+ def validate_config(config, schema_type):
132
+ errors = []
133
+ if schema_type == "config":
134
+ if config.get("vocab_size", 0) <= 0:
135
+ errors.append("vocab_size必须>0")
136
+ if config.get("input_dim", 0) <= 0:
137
+ errors.append("input_dim必须>0")
138
+ elif schema_type == "generation_config":
139
+ t = config.get("temperature", 0)
140
+ if t <= 0 or t > 2.0:
141
+ errors.append(f"temperature须在(0.0,2.0],当前={t}")
142
+ s = config.get("strategy", "")
143
+ if s not in ("greedy", "top_k", "top_p", "top_k_top_p"):
144
+ errors.append(f"strategy须为greedy/top_k/top_p/top_k_top_p,当前={s}")
145
+ return errors
146
+
147
+
148
+ def save_all_configs(output_dir, model_hpp=None, generative_hpp=None):
149
+ os.makedirs(output_dir, exist_ok=True)
150
+
151
+ config = generate_config_json()
152
+ if model_hpp:
153
+ parsed = parse_config_from_hpp(model_hpp, "Config")
154
+ if parsed:
155
+ for name, default, _ in parsed:
156
+ if name in config and name not in ("_comment", "_python_alias"):
157
+ config[name] = default
158
+ errors = validate_config(config, "config")
159
+ if errors:
160
+ logger.warning(f"config.json校验问题: {errors}")
161
+ with open(os.path.join(output_dir, "config.json"), "w", encoding="utf-8") as f:
162
+ json.dump(config, f, indent=2, ensure_ascii=False)
163
+
164
+ special = generate_special_tokens_map()
165
+ with open(os.path.join(output_dir, "special_tokens_map.json"), "w", encoding="utf-8") as f:
166
+ json.dump(special, f, indent=2, ensure_ascii=False)
167
+
168
+ gen_config = generate_generation_config_json()
169
+ if generative_hpp:
170
+ parsed = parse_config_from_hpp(generative_hpp, "GenerateConfig")
171
+ if parsed:
172
+ for name, default, _ in parsed:
173
+ if name in gen_config and name not in ("_comment",):
174
+ gen_config[name] = default
175
+ errors = validate_config(gen_config, "generation_config")
176
+ if errors:
177
+ logger.warning(f"generation_config.json校验问题: {errors}")
178
+ with open(os.path.join(output_dir, "generation_config.json"), "w", encoding="utf-8") as f:
179
+ json.dump(gen_config, f, indent=2, ensure_ascii=False)
180
+
181
+ logger.info(f"配置文件已保存到 {output_dir}")
182
+
183
+
184
+ if __name__ == "__main__":
185
+ logging.basicConfig(level=logging.INFO)
186
+ parser = argparse.ArgumentParser(description="NeuroFlow配置文件生成器")
187
+ parser.add_argument("--model-hpp", type=str, default="", help="model.hpp路径")
188
+ parser.add_argument("--generative-hpp", type=str, default="", help="generative.hpp路径")
189
+ parser.add_argument("--output-dir", type=str, default="configs", help="输出目录")
190
+ parser.add_argument("--reference-config", type=str, default="", help="Python训练系统参考配置")
191
+ args = parser.parse_args()
192
+ save_all_configs(args.output_dir, args.model_hpp or None, args.generative_hpp or None)