Skip to content

Commit 170f01d

Browse files
committed
[UPDATE] Update
[ghstack-poisoned]
1 parent 0756e5b commit 170f01d

10 files changed

Lines changed: 270 additions & 104 deletions

extension/llm/runner/llm_runner_helper.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -325,7 +325,12 @@ static std::unique_ptr<TextLLMRunner> assemble_text_llm_runner(
325325
temperature);
326326
}
327327

328-
std::unique_ptr<TextLLMRunner> create_text_llm_runner_from_program(
328+
// Builds a TextLLMRunner over an already-loaded Program: the runner's Module
329+
// reuses `program` while owning its own method state and KV cache. File-local —
330+
// the per-session construction path for TextLLMEngine (which keeps the backing
331+
// DataLoader alive for the runners' lifetime). External callers go through
332+
// LLMEngine -> LLMSession, not a raw shared-Program runner.
333+
static std::unique_ptr<TextLLMRunner> create_text_llm_runner_from_program(
329334
std::shared_ptr<Program> program,
330335
std::unique_ptr<::tokenizers::Tokenizer> tokenizer,
331336
float temperature,
@@ -413,6 +418,11 @@ Error TextLLMSession::reset() {
413418
void TextLLMSession::stop() {
414419
runner_->stop();
415420
}
421+
422+
std::unique_ptr<LLMSession> make_text_llm_session(
423+
std::unique_ptr<TextLLMRunner> runner) {
424+
return std::make_unique<TextLLMSession>(std::move(runner));
425+
}
416426
} // namespace detail
417427

418428
TextLLMEngine::TextLLMEngine(
@@ -504,8 +514,7 @@ TextLLMEngine::create_session() {
504514
ET_LOG(Error, "TextLLMEngine: failed to build session runner");
505515
return Error::InvalidState;
506516
}
507-
return std::unique_ptr<LLMSession>(
508-
std::make_unique<detail::TextLLMSession>(std::move(runner)));
517+
return detail::make_text_llm_session(std::move(runner));
509518
}
510519

511520
std::unique_ptr<MultimodalRunner> create_multimodal_runner(

extension/llm/runner/llm_runner_helper.h

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -142,33 +142,6 @@ ET_EXPERIMENTAL std::unique_ptr<TextLLMRunner> create_text_llm_runner(
142142
const std::string& method_name = "forward",
143143
Module::LoadMode load_mode = Module::LoadMode::MmapUseMlockIgnoreErrors);
144144

145-
/**
146-
* @brief Creates a TextLLMRunner over an already-loaded Program.
147-
*
148-
* Unlike create_text_llm_runner(model_path, ...), this does not load the model
149-
* file again: the resulting runner's Module reuses `program` while owning its
150-
* own method state and KV cache. This is the per-session construction path for
151-
* TextLLMEngine — N sessions reuse one loaded Program but isolate their mutable
152-
* KV state. Whether they also avoid re-materializing packed weights per session
153-
* is backend-dependent (serving_capacity() is authoritative).
154-
*
155-
* The caller must keep the DataLoader backing `program` alive for the lifetime
156-
* of every runner created from it (TextLLMEngine holds the loader Module).
157-
*
158-
* @param program Shared, already-loaded program.
159-
* @param tokenizer Initialized tokenizer instance (owned by the new runner).
160-
* @param temperature Optional temperature (deprecated; prefer
161-
* GenerationConfig).
162-
* @param method_name Name of the method to execute in the model.
163-
* @return std::unique_ptr<TextLLMRunner> on success, or nullptr on failure.
164-
*/
165-
ET_EXPERIMENTAL std::unique_ptr<TextLLMRunner>
166-
create_text_llm_runner_from_program(
167-
std::shared_ptr<Program> program,
168-
std::unique_ptr<::tokenizers::Tokenizer> tokenizer,
169-
float temperature = -1.0f,
170-
const std::string& method_name = "forward");
171-
172145
/**
173146
* @brief Engine for multi-session text generation over one loaded Program.
174147
*
@@ -225,6 +198,20 @@ class ET_EXPERIMENTAL TextLLMEngine : public LLMEngine {
225198
std::unordered_map<std::string, int64_t> metadata_;
226199
};
227200

201+
namespace detail {
202+
// Implementation detail (not a public API): wraps a TextLLMRunner in an
203+
// LLMSession (the runner -> session seam). The supported entry point is
204+
// LLMEngine::create_session(); this exists only so TextLLMEngine can build its
205+
// sessions and so unit tests can drive the runner's token-step primitives
206+
// through the public LLMSession surface (the concrete adapter type is private).
207+
// Do not depend on wrapping arbitrary runners.
208+
//
209+
// @param runner A loaded TextLLMRunner; ownership transfers to the session.
210+
// @return std::unique_ptr<LLMSession> wrapping `runner`.
211+
std::unique_ptr<LLMSession> make_text_llm_session(
212+
std::unique_ptr<TextLLMRunner> runner);
213+
} // namespace detail
214+
228215
/**
229216
* @brief Creates a MultimodalRunner instance with dependency injection
230217
*

extension/llm/runner/llm_session.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ struct SamplingConfig {
3636
};
3737

3838
/// One decoded step: the exact sampled token id (for prefix-cache id tracking
39-
/// and batching), its decoded text piece (raw bytes; may be a partial UTF-8
40-
/// sequence the caller assembles), and whether it is an EOS token.
39+
/// and batching) and its decoded text piece (raw bytes; may be a partial UTF-8
40+
/// sequence the caller assembles).
41+
///
42+
/// `is_eos` is literal: the sampled token is an end-of-sequence token (use it
43+
/// for the "stop" finish reason, metrics, cache/accounting). `is_terminal` is
44+
/// the loop signal: generation ended at this step — either EOS or a cooperative
45+
/// stop() took effect. A decode loop should end when is_terminal is set; every
46+
/// EOS step is also terminal, but a stop step is terminal without being EOS.
4147
struct DecodeResult {
4248
uint64_t token_id;
4349
std::string text_piece;
4450
bool is_eos;
51+
bool is_terminal;
4552
};
4653

4754
/// How many physical sessions an engine can host, so the server admits logical
@@ -96,8 +103,10 @@ class ET_EXPERIMENTAL LLMSession {
96103

97104
/// Request that a decode_one() loop stop. This is a TOKEN-BOUNDARY,
98105
/// cooperative stop: it is safe to call from another thread, but it does not
99-
/// abort a decode_one() that is already running — it takes effect before the
100-
/// next decode_one() (the loop driver checks between tokens).
106+
/// abort a decode_one() that is already running. It takes effect at the next
107+
/// decode_one(), which then returns a terminal step (is_terminal set, is_eos
108+
/// false) without forwarding a new token. The stop is cleared by the next
109+
/// prefill_tokens() or reset().
101110
virtual void stop() = 0;
102111
};
103112

extension/llm/runner/targets.bzl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,16 @@ def define_common_targets():
113113
name = "runner_lib" + aten_suffix,
114114
exported_headers = [
115115
"text_llm_runner.h",
116-
"text_llm_session.h",
117116
"llm_runner_helper.h",
118117
"llm_session.h",
119118
"constants.h",
120119
],
120+
# Internal: the detail::TextLLMSession adapter (sole friended caller
121+
# of TextLLMRunner's token-step hooks). Private so dependents reach
122+
# it only through LLMEngine/LLMSession + make_text_llm_session().
123+
headers = [
124+
"text_llm_session.h",
125+
],
121126
srcs = [
122127
"text_llm_runner.cpp",
123128
"llm_runner_helper.cpp",

0 commit comments

Comments
 (0)