| |
|
|
| #pragma once |
|
|
| #include <array> |
| #include <atomic> |
| #include <cstdint> |
| #include <functional> |
| #include <memory> |
| #include <ostream> |
|
|
| #include "src/turbomind/core/core.h" |
| #include "src/turbomind/core/interval.h" |
| #include "src/turbomind/utils/metrics.h" |
|
|
| namespace xgrammar { |
| class GrammarMatcher; |
| class CompiledGrammar; |
| } |
|
|
| namespace turbomind { |
|
|
| struct GenerationConfig { |
| int max_new_tokens = 0; |
| int min_new_tokens = 0; |
|
|
| std::vector<int> eos_ids; |
|
|
| std::array<std::vector<int>, 2> stop_ids; |
| std::array<std::vector<int>, 2> bad_ids; |
|
|
| int top_k = 1; |
| float top_p = 0.f; |
| float min_p = 0.f; |
| float temperature = 1.f; |
|
|
| float repetition_penalty = 1.f; |
|
|
| uint64_t random_seed = 0; |
|
|
| int output_logprobs = 0; |
|
|
| enum OutType |
| { |
| kNone = 0, |
| kAll = 1, |
| kGeneration = 2 |
| }; |
| int output_last_hidden_state = 0; |
| int output_logits = 0; |
| }; |
|
|
| std::ostream& operator<<(std::ostream& os, const GenerationConfig& c); |
|
|
| struct SessionParam { |
| uint64_t id; |
|
|
| int step; |
|
|
| bool start_flag; |
| bool end_flag; |
| bool kill_flag; |
| }; |
|
|
| struct RequestState { |
| int status; |
| int seq_len; |
| }; |
|
|
| struct AtomicRequestState { |
|
|
| std::atomic<RequestState*> data_; |
|
|
| static_assert(std::atomic<RequestState*>::is_always_lock_free); |
|
|
| ~AtomicRequestState() |
| { |
| auto data = exchange(nullptr); |
| } |
|
|
| std::unique_ptr<RequestState> exchange(RequestState* data) |
| { |
| return std::unique_ptr<RequestState>{data_.exchange(data, std::memory_order_acq_rel)}; |
| } |
| }; |
|
|
| struct Request { |
| uint64_t id; |
| uint64_t unique_id; |
|
|
| SessionParam session; |
| GenerationConfig gen_cfg; |
|
|
| bool stream_output; |
|
|
| |
| TensorMap inputs; |
| TensorMap outputs; |
| |
| Tensor_<int> output_ids; |
| Tensor_<int> sequence_length; |
|
|
| std::function<void(int)> end_cb; |
|
|
| std::atomic<int> cancel_flag; |
|
|
| std::function<void()> forward_cb; |
|
|
| std::shared_ptr<AtomicRequestState> state; |
|
|
| std::shared_ptr<RequestMetrics> metrics; |
|
|
| int ec = 0; |
|
|
| enum |
| { |
| kOk = 0, |
| kInvalid = 1, |
| kConflict = 2, |
| kBusy = 3, |
| kInactive = 4, |
| kFail = 5, |
| kTooLong = 6, |
| kFinish = 7, |
| kCancel = 8, |
| kInconsistency = 9, |
| kNoQueue = 10, |
| }; |
|
|
| std::shared_ptr<xgrammar::CompiledGrammar> grammar; |
| std::shared_ptr<xgrammar::GrammarMatcher> matcher; |
| }; |
|
|
| void UpdateState(Request& r, int status, int seq_len); |
|
|
| class Sequence; |
|
|
| |
| struct RequestCache { |
| std::shared_ptr<Request> req; |
| const Sequence* seq; |
| const GenerationConfig& gen_cfg; |
|
|
| RequestCache(std::shared_ptr<Request> r, const Sequence& s): req{std::move(r)}, seq{&s}, gen_cfg{req->gen_cfg} {} |
|
|
| int status = Request::kOk; |
|
|
| |
| |
|
|
| int* token_ids = nullptr; |
| uint8_t* random_state = nullptr; |
|
|
| int step0 = 0; |
| int prompt_len = 0; |
| int max_seq_len = 0; |
|
|
| int hidden_states_offset = 0; |
| int logits_offset = 0; |
|
|
| int seq_len = 0; |
|
|
| int input_len = 0; |
| int history_len = 0; |
|
|
| bool autoregres = false; |
| bool generating = false; |
|
|
| bool done = false; |
|
|
| int alpha = 0; |
| int beta = 0; |
|
|
| float rope_base = 0.f; |
|
|
| Interval output_hidden_states; |
| Interval output_logits; |
| }; |
|
|
| template<class Archive> |
| void serdes(Archive& ar, GenerationConfig& g) |
| { |
| |
| ar & g.max_new_tokens; |
| ar & g.min_new_tokens; |
| ar & g.eos_ids; |
| ar & g.stop_ids[0]; |
| ar & g.stop_ids[1]; |
| ar & g.bad_ids[0]; |
| ar & g.bad_ids[1]; |
| ar & g.top_k; |
| ar & g.top_p; |
| ar & g.min_p; |
| ar & g.temperature; |
| ar & g.repetition_penalty; |
| ar & g.random_seed; |
| ar & g.output_logprobs; |
| ar & g.output_last_hidden_state; |
| ar & g.output_logits; |
| |
| } |
|
|
| template<class Archive> |
| void save_req_output(Archive& ar, const TensorMap& map) |
| { |
| |
| ar & map.size(); |
| for (const auto& [k, t] : map) { |
| TM_CHECK(t.device().type == kCPU); |
| ar & k; |
| ar & t.layout(); |
| ar & t.dtype(); |
| } |
| |
| } |
|
|
| template<class Archive> |
| void load_req_output(Archive& ar, TensorMap& map) |
| { |
| |
| decltype(map.size()) size; |
| ar & size; |
| for (int i = 0; i < size; ++i) { |
| std::string k; |
| Layout layout; |
| DataType dtype; |
| ar & k; |
| ar & layout; |
| ar & dtype; |
| map.emplace(std::move(k), Tensor{layout, dtype, kCPU}); |
| } |
| |
| } |
|
|
| template<class Archive> |
| void serdes(Archive& ar, Request& r) |
| { |
| |
| ar & r.id; |
| ar & r.unique_id; |
| ar & r.session; |
| ar & r.gen_cfg; |
| ar & r.stream_output; |
| ar & r.inputs; |
| if constexpr(Archive::is_loading) { |
| load_req_output(ar, r.outputs); |
| r.output_ids = r.outputs.at("output_ids"); |
| r.sequence_length = r.outputs.at("sequence_length"); |
| } else { |
| save_req_output(ar, r.outputs); |
| } |
| ar & r.ec; |
| |
| } |
|
|
| } |
|
|