Buckets:
| namespace neuroflow { | |
| GenerativeModel::GenerativeModel(const CausalLMConfig& lm_config, | |
| std::unique_ptr<Tokenizer> tokenizer, | |
| NeuroFlowModel* nf_model) | |
| : tokenizer_(std::move(tokenizer)), neuroflow_model_(nf_model) { | |
| lm_head_ = std::make_unique<CausalLMHead>(lm_config); | |
| sampler_ = std::make_unique<TopKSampling>(); | |
| } | |
| GenerateOutput GenerativeModel::generate(const std::string& prompt, const GenerateConfig& config) { | |
| GenerateOutput output; | |
| std::vector<size_t> input_ids = tokenizer_->encode(prompt); | |
| std::vector<size_t> generated_ids; | |
| size_t seed = config.random_seed; | |
| if (seed == 0) { | |
| std::random_device rd; | |
| seed = rd(); | |
| } | |
| std::mt19937 rng(seed); | |
| lm_head_->clear_cache(); | |
| if (input_ids.empty()) { | |
| output.finish_reason = FinishReason::GEN_ERROR; | |
| return output; | |
| } | |
| Tensor logits; | |
| if (input_ids.size() > 1) { | |
| std::vector<size_t> prefix(input_ids.begin(), input_ids.end() - 1); | |
| logits = lm_head_->forward(prefix); | |
| } | |
| size_t last_id = input_ids.back(); | |
| for (size_t step = 0; step < config.max_new_tokens; ++step) { | |
| size_t pos = input_ids.size() - 1 + step; | |
| logits = lm_head_->forward_step(last_id, pos); | |
| logits = apply_sn_gating(lm_head_->last_hidden_, logits); | |
| logits = inject_memory(lm_head_->last_hidden_, logits); | |
| logits = apply_repetition_penalty(logits, config, generated_ids); | |
| logits = apply_punct_penalty(logits, config); | |
| Tensor probs = sampler_->apply(logits, config, generated_ids); | |
| size_t next_id = sampler_->sample(probs, rng); | |
| generated_ids.push_back(next_id); | |
| if (next_id == config.eos_id) { | |
| output.finish_reason = FinishReason::EOS_TOKEN; | |
| break; | |
| } | |
| last_id = next_id; | |
| } | |
| if (output.finish_reason != FinishReason::EOS_TOKEN) { | |
| output.finish_reason = FinishReason::MAX_LENGTH; | |
| } | |
| output.token_ids = generated_ids; | |
| output.text = tokenizer_->decode(generated_ids); | |
| output.cache_stats = lm_head_->cache_stats(); | |
| return output; | |
| } | |
| Tensor GenerativeModel::apply_sn_gating(const Tensor& hidden, const Tensor& logits) { | |
| if (!neuroflow_model_) return logits; | |
| try { | |
| auto sn_out = neuroflow_model_->sn->forward(hidden); | |
| float ecn_gate = sn_out.gates.as_fp32()[0]; | |
| float dmn_gate = sn_out.gates.as_fp32()[1]; | |
| if (std::isnan(ecn_gate) || std::isnan(dmn_gate) || | |
| (ecn_gate == 0.0f && dmn_gate == 0.0f)) { | |
| std::cerr << "Warning: SN gate NaN/zero, falling back to equal weighting" << std::endl; | |
| ecn_gate = 0.5f; | |
| dmn_gate = 0.5f; | |
| } | |
| return logits; | |
| } catch (...) { | |
| return logits; | |
| } | |
| } | |
| Tensor GenerativeModel::inject_memory(const Tensor& query, const Tensor& logits) { | |
| if (!neuroflow_model_) return logits; | |
| try { | |
| auto mem_out = neuroflow_model_->memory->retrieve(query); | |
| const float* mp = mem_out.retrieved.as_fp32(); | |
| bool all_zero = true; | |
| for (size_t i = 0; i < mem_out.retrieved.numel(); ++i) { | |
| if (std::abs(mp[i]) > 1e-8f) { all_zero = false; break; } | |
| } | |
| if (all_zero) return logits; | |
| return logits; | |
| } catch (...) { | |
| return logits; | |
| } | |
| } | |
| Tensor GenerativeModel::apply_repetition_penalty(Tensor logits, const GenerateConfig& config, | |
| const std::vector<size_t>& generated) { | |
| if (config.repetition_penalty <= 1.0f || generated.empty()) return logits; | |
| float* data = logits.as_fp32(); | |
| size_t n = logits.numel(); | |
| size_t window = std::min(generated.size(), static_cast<size_t>(20)); | |
| for (size_t i = generated.size() - window; i < generated.size(); ++i) { | |
| size_t tid = generated[i]; | |
| if (tid < n) { | |
| if (data[tid] > 0) { | |
| data[tid] /= config.repetition_penalty; | |
| } else { | |
| data[tid] *= config.repetition_penalty; | |
| } | |
| } | |
| } | |
| return logits; | |
| } | |
| Tensor GenerativeModel::apply_punct_penalty(Tensor logits, const GenerateConfig& config) { | |
| if (config.punct_penalty <= 0.0f || config.punct_ids.empty()) return logits; | |
| float* data = logits.as_fp32(); | |
| size_t n = logits.numel(); | |
| for (size_t pid : config.punct_ids) { | |
| if (pid < n) { | |
| data[pid] -= config.punct_penalty; | |
| } | |
| } | |
| return logits; | |
| } | |
| void GenerativeModel::set_strategy(SamplingStrategyType type) { | |
| switch (type) { | |
| case SamplingStrategyType::GREEDY: | |
| sampler_ = std::make_unique<GreedyDecoding>(); | |
| break; | |
| case SamplingStrategyType::TOP_K: | |
| sampler_ = std::make_unique<TopKSampling>(); | |
| break; | |
| case SamplingStrategyType::TOP_P: | |
| sampler_ = std::make_unique<TopPSampling>(); | |
| break; | |
| case SamplingStrategyType::TOP_K_TOP_P: | |
| sampler_ = std::make_unique<TopKTopPSampling>(); | |
| break; | |
| } | |
| } | |
| void GenerativeModel::clear_cache() { lm_head_->clear_cache(); } | |
| CacheStats GenerativeModel::cache_stats() const { return lm_head_->cache_stats(); } | |
| } // namespace neuroflow |
Xet Storage Details
- Size:
- 5.57 kB
- Xet hash:
- 3fdb01b1488e753a4e99e782cd954e6140a74febf1b7e5a051f96da98a514250
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.