<turbo-stream action="append" target="posts_list"><template>    <div class="postbit" id="292813" data-post-id="292813">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jonatanklosko" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jonatanklosko/120/37940_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jonatanklosko
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Livebook</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<blockquote>
<p>This leads me to believe that even though I had multiple servings the embedding creation is still sequential.</p>
</blockquote>
<p>Only one computation can be running at a time on the given device, so spawning multiple servings is not going to help (unless you have a cluster of multiple nodes, each with its own serving).</p>
<p>Just to be sure, you are using <code>Nx.Serving.batched_run/2</code> and not <code>Nx.Serving.run/2</code> right?</p>
<blockquote>
<p>This is slower, it takes 76 seconds.</p>
</blockquote>
<p>Just the computation or everything including application boot? Note that with <code>compiler: EXLA</code> the serving is going to compile everything into an efficient computation, which may take a bit, but then the computations themselves are faster.</p>
<blockquote>
<p>How do I determine the batch size and the sequence_length?</p>
</blockquote>
<p><code>sequence_length</code> is used to pad/trim the input, usually you want to set it to the longest sequence the model supports, unless you know your inputs are always short and it can be reduced. <code>batch_size</code> depends on several factors, when running on a CPU increasing the <code>batch_size</code> at some point makes the computation take linearly as long since there is no more room for for parallelisation, when running on a GPU it depends on how much computation you can fit into the GPU memory; and in both cases depends on the expected number of requests (if it’s small then it doesn’t make sense to use large batch_size).</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292813" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/22">Post #21</a>
	                </div>
	            </div>
              <div id="likers-container-292813" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292813"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #21"></div>
  </section>
</div>
    <div class="postbit" id="292821" data-post-id="292821">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="benonymus" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benonymus/120/31839_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  benonymus
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hey,</p>
<p>Thanks for the reply!</p>
<p>I am using <code>Nx.Serving.run/2</code> now. I will try out <code>Nx.Serving.batched_run/2</code>.<br>
These are the docs: <a href="https://hexdocs.pm/nx/Nx.Serving.html#module-stateful-process-workflow" class="inline-onebox" rel="noopener nofollow ugc">Nx.Serving — Nx v0.12.1</a><br>
I imagine I can just use <code>Bumblebee.Text.TextEmbedding.text_embedding/3</code> in the place of <code>Nx.Serving.new(Nx.Defn.jit(&amp;print_and_multiply/1))</code>?</p>
<p>So <code>sequence_length</code> is the length of my entry? What is the default?<br>
What is the upside of having a high batch_size on a CPU? What range would you recommend trying?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292821" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/23">Post #22</a>
	                </div>
	            </div>
              <div id="likers-container-292821" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292821"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #22"></div>
  </section>
</div>
    <div class="postbit" id="292850" data-post-id="292850">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="jonatanklosko" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/jonatanklosko/120/37940_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  jonatanklosko
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Livebook</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>If you are just running it once for back-filling then <code>Nx.Serving.run/2</code> may be fine, but it runs right away so you want chunk the list and pass a list of inputs to <code>Nx.Serving.run/2</code> instead of <code>Task.async_stream</code> (in which case all <code>run</code>s are sequential anyway). Starting a serving under you app supervision tree and <code>batched_run</code> is mainly for long-running and handling concurrent requests.</p>
<blockquote>
<p>So <code>sequence_length</code> is the length of my entry?</p>
</blockquote>
<p>The input text is tokenized into a sequence of numbers (roughly one per word, sometimes many per word), the model needs a fixed-length sequence, so if the text is short we usually pad the sequence with zeros, if it’s too long it is truncated. The reason for fixed-length is basically so that we can compile the model upfront once with known input shape and run inference quickly. If you don’t set <code>:compile</code> then <code>:sequence_length</code> will effectively be the length of the input each time, but this means that the model is compiled multiple times (per each different input length).</p>
<blockquote>
<p>What is the upside of having a high batch_size on a CPU?</p>
</blockquote>
<p>Even though it doesn’t have as much parallel qualities as GPU, the XLA compiler can still do <em>some</em> parallelisation, so it could be the case that computation with <code>batch_size: 4</code> is just a bit slower than <code>batch_size: 1</code> (and not 4x slower), but it depends on model. It doesn’t hurt to have a big larger <code>:batch_size</code>. It depends on the model, but I would try like <code>8</code>, <code>16</code>.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292850" data-batch-url="/posts/batch_likers">
                        1
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/24">Post #23</a>
	                </div>
	            </div>
              <div id="likers-container-292850" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292850"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #23"></div>
  </section>
</div>
    <div class="postbit" id="292908" data-post-id="292908">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="aus" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/aus/120/40332_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  aus
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I’m using bumblebee to compute the embedding of user messages (I’m using HF sentence-transformers/paraphrase-multilingual-mpnet-base-v2), with the goal of semantically cache the response of a LLM and save CPU time (and money). Bumblebee needs on average 50% more time than the equivalent Python code, wrapped by a FastAPI server.</p>
<p>I went through this thread, but it’s not clear to me what I should to to improve Bumblebee’s performance. I’m compiling the model (<code>Axon.compile(model_info.model, template, %{}, compiler: EXLA)</code>), which increases the performance relative to the JIT compilation, but it’s still slow compared to Python.</p>
<p>Thanks!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292908" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/25">Post #24</a>
	                </div>
	            </div>
              <div id="likers-container-292908" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292908"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #24"></div>
  </section>
</div>
    <div class="postbit" id="292985" data-post-id="292985">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>It is hard to say without more information on how you are running the model. Per above, the results will vary depending if you are batching or not and if you are padding or not. Can you provide a snippet with more information on how you are starting the serving and calling it?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292985" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/26">Post #25</a>
	                </div>
	            </div>
              <div id="likers-container-292985" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292985"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #25"></div>
  </section>
</div>
    <div class="postbit" id="292996" data-post-id="292996">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="benonymus" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benonymus/120/31839_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  benonymus
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>For the <code>sequence_length</code>, to arrive at a number, how could I get exact sequence_lengths for string entries?</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="292996" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/27">Post #26</a>
	                </div>
	            </div>
              <div id="likers-container-292996" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="292996"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #26"></div>
  </section>
</div>
    <div class="postbit" id="293001" data-post-id="293001">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="aus" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/aus/120/40332_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  aus
                  </h3>
		          </div>
						
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Sure! Here are some more info:</p>
<p>I init the transformer in this way:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">template = %{
  "attention_mask" =&gt; Nx.template({1, 128}, :u32),
  "input_ids" =&gt; Nx.template({1, 128}, :u32),
  "token_type_ids" =&gt; Nx.template({1, 128}, :u32)
}

model_name = "sentence-transformers/paraphrase-multilingual-mpnet-base-v2"
{:ok, model_info} = Bumblebee.load_model({:hf, model_name})
{:ok, tokenizer} = Bumblebee.load_tokenizer({:hf, model_name})
{_init_fn, predict_fn} = Axon.compile(model_info.model, template, %{}, compiler: EXLA)
</code></pre>
<p><code>predict_fn</code> and the <code>tokenizer</code> are then stored in a GenServer’s state to be re-used.</p>
<p>To compute the embeddings, I do:</p>
<pre data-code-wrap="elixir"><code class="lang-elixir">inputs = Bumblebee.apply_tokenizer(tokenizer, text, length: 128)
result = predict_fn.(model_info.params, inputs)
input_mask_expanded = Nx.new_axis(inputs["attention_mask"], -1)
result.hidden_state
  |&gt; Nx.multiply(input_mask_expanded)
  |&gt; Nx.sum(axes: [1])
  |&gt; Nx.divide(Nx.sum(input_mask_expanded, axes: [1]))
</code></pre>
<p>I hope that helps, thank you!</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293001" data-batch-url="/posts/batch_likers">
                        0
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/28">Post #27</a>
	                </div>
	            </div>
              <div id="likers-container-293001" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293001"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #27"></div>
  </section>
</div>
    <div class="postbit" id="293003" data-post-id="293003">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Hi <a class="mention" href="/u/aus" rel="nofollow">@aus</a>, that looks good to me. Just make sure that <code>input_mask_expanded</code> and <code>result.hidden_state</code> are allocated on the EXLA Backend and not the binary backend. You can print them to the terminal to confirm.</p>
<p>At the end, this may still be slower than the Python version for two reasons:</p>
<ol>
<li>
<p>EXLA for CPU is not as fast as it should be</p>
</li>
<li>
<p>We don’t support dynamic shapes, which means you need to precompute/pad to 128. You could try passing larger inputs to both and ensure they both perform same at 128 entries or not</p>
</li>
</ol>
<aside class="quote no-group" data-username="benonymus" data-post="27" data-topic="56502" data-full="true">
<div class="title">
<div class="quote-controls"></div>
<img alt="" width="24" height="24" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/benonymus/48/31839_2.png" class="avatar"> benonymus:</div>
<blockquote>
<p>For the <code>sequence_length</code>, to arrive at a number, how could I get exact sequence_lengths for string entries?</p>
</blockquote>
</aside>
<p>I believe you can call the tokenizer without a length and the size of the tensor it returns.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293003" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/29">Post #28</a>
	                </div>
	            </div>
              <div id="likers-container-293003" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293003"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #28"></div>
  </section>
</div>
    <div class="postbit" id="293005" data-post-id="293005">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>Btw, folks can also try running <a href="https://github.com/elixir-nx/ortex" rel="nofollow">ONNX versions of the models</a> if the lack of dynamic shapes is being a hindrance.</p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="293005" data-batch-url="/posts/batch_likers">
                        2
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/30">Post #29</a>
	                </div>
	            </div>
              <div id="likers-container-293005" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="293005"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #29"></div>
  </section>
</div>
    <div class="postbit" id="295657" data-post-id="295657">
  <section>
    <div class="post-wrap">


					<div class="post-header">
		        <div class="user-avatar">
		          <img alt="josevalim" src="https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/josevalim/120/1787_2.png" width="120" height="120" />
		        </div>
					
						<div class="user-details">
		          <div class="user-name">
		            <h3>
                  josevalim
                  </h3>
		          </div>
						
			          <div class="user-title">
									<span>Creator of Elixir</span>
			          </div>
						</div>
					
					</div>

	        <div class="thread-main">
	            <div class="post-body" data-turbo="false">
								<p>I have implemented batch_keys in Nx (soon to be v0.6): <a href="https://github.com/elixir-nx/nx/pull/1268" class="inline-onebox" rel="nofollow">Support batch keys in Nx.Serving by josevalim · Pull Request #1268 · elixir-nx/nx · GitHub</a></p>
<p>We will later ship a new bumblebee version that supports multiple sequence lengths out of the box. <img src="https://forum.elixirforum.com/images/emoji/apple/slight_smile.png?v=15" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p> 
	            </div>

	            <div class="base-line">
	                <div class="thread-counters">
	                    <span class="thread-count count-likes js-likers-trigger" title="Likes" data-post-id="295657" data-batch-url="/posts/batch_likers">
                        5
                      </span>
                      <!-- <span class="thread-count js-solved-indicator" title="Marked as solution"></span> -->
	                </div>
	                <div class="go-to-post">
	                  <a title="Go to post" alt="Go to post" href="https://forum.elixirforum.com/t/nx-vs-python-performance-for-sentence-transformer-encoding/56502/31">Post #30</a>
	                </div>
	            </div>
              <div id="likers-container-295657" 
                   class="likers-container"
                   data-first-post="false"
                   data-batch-url="/posts/batch_likers">
                   <div class="likers-placeholder" 
                     data-likers-post-id="295657"
                     data-batch-url="/posts/batch_likers">
                  <div class="post-likers"></div>
                </div>
              </div>
	        </div>
			

    </div>

    <div class="triangle-top-right type-standard-post cat-standard-post" title="Post #30"></div>
  </section>
</div>
</template></turbo-stream><turbo-stream action="replace" target="load-more-container"><template><div id="load-more-container" class="load-more-container">
    <a class="load-more-button" data-turbo-stream="true" href="/topics/56502/load_more?page=4">Load more posts (7 remaining)</a>
</div></template></turbo-stream>