diff --git a/crates/loopd/src/http.rs b/crates/loopd/src/http.rs new file mode 100644 index 0000000..fe35e0b --- /dev/null +++ b/crates/loopd/src/http.rs @@ -0,0 +1,423 @@ +//! A hand-written HTTP/1.1 client for talking to `inferproxy`. One request per connection; the +//! body is offered as a `std::io::Read`. Everything read from the socket is bounded and cannot +//! panic: numbers from the peer are parsed with `try_from`/`from_str_radix` and slices are taken +//! with `windows`, never indexing that can run off the end. + +use std::io::{self, ErrorKind, Read, Write}; +use std::os::unix::net::UnixStream; +use std::path::Path; +use std::time::Duration; + +pub const MAX_HEAD: usize = 16 * 1024; + +#[derive(Debug)] +pub enum HttpError { + Connect(std::io::Error), + Io(std::io::Error), + Timeout, + Closed, + TooLarge(&'static str), + Malformed(&'static str), +} + +impl std::fmt::Display for HttpError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HttpError::Connect(e) => write!(f, "could not connect: {e}"), + HttpError::Io(e) => write!(f, "io error: {e}"), + HttpError::Timeout => write!(f, "read timed out before the response arrived"), + HttpError::Closed => write!(f, "the peer closed the connection"), + HttpError::TooLarge(what) => write!(f, "{what} is larger than allowed"), + HttpError::Malformed(what) => write!(f, "{what} is malformed"), + } + } +} + +impl std::error::Error for HttpError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + HttpError::Connect(e) | HttpError::Io(e) => Some(e), + _ => None, + } + } +} + +/// True for the two error kinds a read timeout produces: WouldBlock and TimedOut. +pub fn is_timeout(e: &std::io::Error) -> bool { + matches!(e.kind(), ErrorKind::WouldBlock | ErrorKind::TimedOut) +} + +pub struct Request<'a> { + pub method: &'a str, + pub path: &'a str, + pub body: Option<&'a [u8]>, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Head { + pub status: u16, + pub headers: Vec<(String, String)>, +} + +impl Head { + pub fn header(&self, name: &str) -> Option<&str> { + let name = name.to_ascii_lowercase(); + self.headers + .iter() + .find(|(n, _)| *n == name) + .map(|(_, v)| v.as_str()) + } +} + +fn find_needle(haystack: &[u8], needle: &[u8]) -> Option { + if needle.is_empty() || haystack.len() < needle.len() { + return None; + } + haystack.windows(needle.len()).position(|w| w == needle) +} + +fn parse_status(line: &str) -> Result { + let mut parts = line.split_whitespace(); + let version = parts.next(); + let code = parts.next(); + if version != Some("HTTP/1.1") && version != Some("HTTP/1.0") { + return Err(HttpError::Malformed("status line")); + } + let code: u16 = code + .and_then(|c| c.parse::().ok()) + .ok_or(HttpError::Malformed("status line"))?; + if !(100..=599).contains(&code) { + return Err(HttpError::Malformed("status line")); + } + Ok(code) +} + +fn parse_head(bytes: &[u8]) -> Result { + let text = std::str::from_utf8(bytes).map_err(|_| HttpError::Malformed("head"))?; + let mut lines = text.split("\r\n"); + let status_line = lines.next().ok_or(HttpError::Malformed("head"))?; + let status = parse_status(status_line)?; + let mut headers = Vec::new(); + for line in lines { + let (name, value) = line + .split_once(':') + .ok_or(HttpError::Malformed("header line"))?; + if name.is_empty() || name.chars().any(char::is_whitespace) { + return Err(HttpError::Malformed("header line")); + } + headers.push((name.to_ascii_lowercase(), value.trim().to_string())); + } + Ok(Head { status, headers }) +} + +fn extend(out: &mut Vec, src: impl AsRef<[u8]>) { + out.extend_from_slice(src.as_ref()); +} + +pub struct Connection { + stream: UnixStream, + buf: Vec, + received: bool, +} + +impl Connection { + pub fn open(socket: &Path) -> Result { + let stream = UnixStream::connect(socket).map_err(HttpError::Connect)?; + Ok(Connection { + stream, + buf: Vec::new(), + received: false, + }) + } + + pub fn send(&mut self, req: &Request<'_>) -> Result<(), HttpError> { + let mut out: Vec = Vec::with_capacity(256); + extend( + &mut out, + format!("{} {} HTTP/1.1\r\n", req.method, req.path), + ); + extend(&mut out, "Host: localhost\r\n"); + extend(&mut out, "Connection: close\r\n"); + extend(&mut out, "Accept: */*\r\n"); + if let Some(body) = req.body { + extend(&mut out, "Content-Type: application/json\r\n"); + extend(&mut out, format!("Content-Length: {}\r\n", body.len())); + } + extend(&mut out, "\r\n"); + if let Some(body) = req.body { + extend(&mut out, body); + } + self.stream.write_all(&out).map_err(HttpError::Io) + } + + pub fn set_read_timeout(&self, timeout: Duration) -> Result<(), HttpError> { + self.stream + .set_read_timeout(Some(timeout)) + .map_err(HttpError::Io) + } + + pub fn received_any(&self) -> bool { + self.received + } + + pub fn read_head(&mut self) -> Result { + let mut tmp = [0u8; 8192]; + loop { + if let Some(pos) = find_needle(&self.buf, b"\r\n\r\n") { + let head = parse_head(&self.buf[..pos])?; + self.buf.drain(..pos + 4); + return Ok(head); + } + if self.buf.len() > MAX_HEAD { + return Err(HttpError::TooLarge("head")); + } + match self.stream.read(&mut tmp) { + Ok(0) => return Err(HttpError::Closed), + Ok(n) => { + self.received = true; + self.buf.extend_from_slice(&tmp[..n]); + } + Err(e) if is_timeout(&e) => return Err(HttpError::Timeout), + Err(e) => return Err(HttpError::Io(e)), + } + } + } + + pub fn body(&mut self, head: &Head) -> Result, HttpError> { + let framing = if head + .header("transfer-encoding") + .is_some_and(|v| v.eq_ignore_ascii_case("chunked")) + { + Framing::Chunked + } else if let Some(len) = head.header("content-length") { + Framing::Length(parse_length(len)?) + } else { + Framing::Close + }; + let buf = std::mem::take(&mut self.buf); + let stream = &mut self.stream; + Ok(Body { + stream, + buf, + framing, + phase: ChunkPhase::Size, + chunk_remaining: 0, + finished: false, + }) + } +} + +fn parse_length(value: &str) -> Result { + if value.is_empty() { + return Err(HttpError::Malformed("content-length")); + } + let n: u64 = value + .parse() + .map_err(|_| HttpError::Malformed("content-length"))?; + usize::try_from(n).map_err(|_| HttpError::TooLarge("content-length")) +} + +fn bad_chunk() -> io::Error { + io::Error::new(ErrorKind::InvalidData, "malformed chunk") +} + +fn parse_chunk_size(token: &[u8]) -> Result { + let semi = token.iter().position(|&b| b == b';').unwrap_or(token.len()); + let hex = &token[..semi]; + if hex.is_empty() { + return Err(bad_chunk()); + } + for &b in hex { + if !b.is_ascii_hexdigit() { + return Err(bad_chunk()); + } + } + let text = std::str::from_utf8(hex).map_err(|_| bad_chunk())?; + usize::from_str_radix(text, 16).map_err(|_| bad_chunk()) +} + +enum Framing { + Chunked, + Length(usize), + Close, +} + +enum ChunkPhase { + Size, + Data, + Crlf, + Trailers, +} + +pub struct Body<'a> { + stream: &'a mut UnixStream, + buf: Vec, + framing: Framing, + phase: ChunkPhase, + chunk_remaining: usize, + finished: bool, +} + +impl<'a> Body<'a> { + fn read_chunked(&mut self, buf: &mut [u8]) -> io::Result { + if self.finished { + return Ok(0); + } + let mut tmp = [0u8; 8192]; + let mut written = 0usize; + loop { + match self.phase { + ChunkPhase::Size => loop { + match find_needle(&self.buf, b"\r\n") { + Some(pos) => { + let size = + parse_chunk_size(&self.buf[..pos]).map_err(|_| bad_chunk())?; + self.buf.drain(..pos + 2); + if size == 0 { + self.phase = ChunkPhase::Trailers; + } else { + self.phase = ChunkPhase::Data; + self.chunk_remaining = size; + } + break; + } + None if self.buf.len() > 64 => return Err(bad_chunk()), + None => { + let k = self.stream.read(&mut tmp)?; + if k == 0 { + return Err(ErrorKind::UnexpectedEof.into()); + } + self.buf.extend_from_slice(&tmp[..k]); + } + } + }, + ChunkPhase::Data => { + if buf.len() - written == 0 { + return Ok(written); + } + if self.buf.is_empty() { + let k = self.stream.read(&mut tmp)?; + if k == 0 { + return Err(ErrorKind::UnexpectedEof.into()); + } + self.buf.extend_from_slice(&tmp[..k]); + } + let want = (buf.len() - written).min(self.chunk_remaining); + let take = self.buf.len().min(want); + buf[written..written + take].copy_from_slice(&self.buf[..take]); + self.buf.drain(..take); + written += take; + self.chunk_remaining -= take; + if self.chunk_remaining == 0 { + self.phase = ChunkPhase::Crlf; + } else if buf.len() - written == 0 { + return Ok(written); + } + } + ChunkPhase::Crlf => { + if self.buf.len() >= 2 { + if &self.buf[..2] == b"\r\n" { + self.buf.drain(..2); + self.phase = ChunkPhase::Size; + } else { + return Err(bad_chunk()); + } + } else { + let k = self.stream.read(&mut tmp)?; + if k == 0 { + return Err(ErrorKind::UnexpectedEof.into()); + } + self.buf.extend_from_slice(&tmp[..k]); + } + } + ChunkPhase::Trailers => loop { + match find_needle(&self.buf, b"\r\n") { + Some(pos) => { + if pos == 0 { + self.buf.drain(..2); + self.finished = true; + return Ok(written); + } + self.buf.drain(..pos + 2); + } + None if self.buf.len() > 512 => return Err(bad_chunk()), + None => { + let k = self.stream.read(&mut tmp)?; + if k == 0 { + return Err(ErrorKind::UnexpectedEof.into()); + } + self.buf.extend_from_slice(&tmp[..k]); + } + } + }, + } + } + } + + fn read_length(&mut self, buf: &mut [u8]) -> io::Result { + let Framing::Length(remaining) = self.framing else { + return Ok(0); + }; + if remaining == 0 { + return Ok(0); + } + let want = buf.len().min(remaining); + let from_buf = self.buf.len().min(want); + buf[..from_buf].copy_from_slice(&self.buf[..from_buf]); + self.buf.drain(..from_buf); + let mut got = from_buf; + if got < want { + let space = want - got; + let k = self.stream.read(&mut buf[got..got + space])?; + if k == 0 { + return Err(ErrorKind::UnexpectedEof.into()); + } + got += k; + } + self.framing = Framing::Length(remaining - got); + Ok(got) + } + + fn read_close(&mut self, buf: &mut [u8]) -> io::Result { + let take = self.buf.len().min(buf.len()); + buf[..take].copy_from_slice(&self.buf[..take]); + self.buf.drain(..take); + if take > 0 { + return Ok(take); + } + self.stream.read(buf) + } +} + +impl std::io::Read for Body<'_> { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match self.framing { + Framing::Chunked => self.read_chunked(buf), + Framing::Length(_) => self.read_length(buf), + Framing::Close => self.read_close(buf), + } + } +} + +pub fn read_capped(body: &mut impl Read, cap: usize) -> Result, HttpError> { + let mut out: Vec = Vec::new(); + let mut tmp = [0u8; 8192]; + loop { + let n = body.read(&mut tmp).map_err(|e| { + if is_timeout(&e) { + HttpError::Timeout + } else if e.kind() == ErrorKind::UnexpectedEof { + HttpError::Closed + } else { + HttpError::Io(e) + } + })?; + if n == 0 { + return Ok(out); + } + if out.len() + n > cap { + return Err(HttpError::TooLarge("body")); + } + out.extend_from_slice(&tmp[..n]); + } +} diff --git a/crates/loopd/src/lib.rs b/crates/loopd/src/lib.rs index ba0b25b..be1fafb 100644 --- a/crates/loopd/src/lib.rs +++ b/crates/loopd/src/lib.rs @@ -1,3 +1,4 @@ //! The agent loop: sessions, prompt assembly and memory. It holds no authority. pub mod config; +pub mod http; diff --git a/crates/loopd/tests/fixtures/http/bad_request.http b/crates/loopd/tests/fixtures/http/bad_request.http new file mode 100644 index 0000000..dd9bd4e --- /dev/null +++ b/crates/loopd/tests/fixtures/http/bad_request.http @@ -0,0 +1,13 @@ +HTTP/1.1 400 Bad Request +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: close + +64 +{"error":{"code":400,"message":"Expected 'messages' to be an array","type":"invalid_request_error"}} +0 + diff --git a/crates/loopd/tests/fixtures/http/capped.http b/crates/loopd/tests/fixtures/http/capped.http new file mode 100644 index 0000000..f9118f2 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/capped.http @@ -0,0 +1,525 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +214 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":70,"cache":15,"processed":15,"time_ms":6}} + + +238 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":51,"prompt_ms":173.924,"prompt_per_token_ms":3.4102745098039215,"prompt_per_second":293.2315264138359,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":70,"cache":15,"processed":66,"time_ms":173}} + + +238 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.471,"prompt_per_token_ms":4.154018181818182,"prompt_per_second":240.73077108254438,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":70,"cache":15,"processed":70,"time_ms":228}} + + +2f6 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"The"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" question"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":2,"predicted_ms":17.018,"predicted_per_token_ms":17.018,"predicted_per_second":58.76131155247385}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" asks"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":3,"predicted_ms":31.055,"predicted_per_token_ms":15.5275,"predicted_per_second":64.40186765416198}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" about"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":4,"predicted_ms":45.083,"predicted_per_token_ms":15.027666666666667,"predicted_per_second":66.5439300845108}} + + +1fb +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":5,"predicted_ms":59.122,"predicted_per_token_ms":14.7805,"predicted_per_second":67.65670985419979}} + + +1fb +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"8"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":6,"predicted_ms":73.101,"predicted_per_token_ms":14.6202,"predicted_per_second":68.39851712014884}} + + +208 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ro"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":7,"predicted_ms":87.106,"predicted_per_token_ms":14.517666666666665,"predicted_per_second":68.88159254241958}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"oks"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":8,"predicted_ms":101.658,"predicted_per_token_ms":14.522571428571428,"predicted_per_second":68.85832890672647}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" on"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":9,"predicted_ms":115.753,"predicted_per_token_ms":14.469125,"predicted_per_second":69.11267958497835}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" a"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":10,"predicted_ms":129.719,"predicted_per_token_ms":14.413222222222222,"predicted_per_second":69.38073836523563}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" chess"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":11,"predicted_ms":143.691,"predicted_per_token_ms":14.3691,"predicted_per_second":69.59378109972093}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"board"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":12,"predicted_ms":157.663,"predicted_per_token_ms":14.333,"predicted_per_second":69.76906439684643}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" that"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":13,"predicted_ms":171.689,"predicted_per_token_ms":14.307416666666667,"predicted_per_second":69.89381963899842}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" don"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":14,"predicted_ms":185.705,"predicted_per_token_ms":14.285,"predicted_per_second":70.00350017500875}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"'t"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":15,"predicted_ms":200.259,"predicted_per_token_ms":14.304214285714284,"predicted_per_second":69.90946723992431}} + + +20e +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" attack"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":16,"predicted_ms":214.525,"predicted_per_token_ms":14.301666666666668,"predicted_per_second":69.92192052208367}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" each"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":17,"predicted_ms":228.576,"predicted_per_token_ms":14.286,"predicted_per_second":69.99860002799944}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" other"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":18,"predicted_ms":242.603,"predicted_per_token_ms":14.270764705882353,"predicted_per_second":70.0733296785283}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":","}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":19,"predicted_ms":256.628,"predicted_per_token_ms":14.25711111111111,"predicted_per_second":70.14043674111944}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" with"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":20,"predicted_ms":270.638,"predicted_per_token_ms":14.244105263157893,"predicted_per_second":70.2044797848048}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" none"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":21,"predicted_ms":285.363,"predicted_per_token_ms":14.26815,"predicted_per_second":70.08617094717955}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" on"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":22,"predicted_ms":299.519,"predicted_per_token_ms":14.262809523809524,"predicted_per_second":70.11241356975684}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" the"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":23,"predicted_ms":313.597,"predicted_per_token_ms":14.25440909090909,"predicted_per_second":70.1537323380007}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" main"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":24,"predicted_ms":327.584,"predicted_per_token_ms":14.242782608695652,"predicted_per_second":70.21099931620593}} + + +210 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" diagonal"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":25,"predicted_ms":341.533,"predicted_per_token_ms":14.230541666666667,"predicted_per_second":70.27139397949831}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"."}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":26,"predicted_ms":355.541,"predicted_per_token_ms":14.22164,"predicted_per_second":70.31537853580882}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"\n\n"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":27,"predicted_ms":369.531,"predicted_per_token_ms":14.21273076923077,"predicted_per_second":70.35945563430403}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"R"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":28,"predicted_ms":383.51,"predicted_per_token_ms":14.204074074074073,"predicted_per_second":70.40233631456807}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"ooks"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":29,"predicted_ms":397.548,"predicted_per_token_ms":14.198142857142857,"predicted_per_second":70.43174660669906}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" that"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":30,"predicted_ms":412.093,"predicted_per_token_ms":14.210103448275863,"predicted_per_second":70.37246446797204}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" don"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":31,"predicted_ms":426.207,"predicted_per_token_ms":14.2069,"predicted_per_second":70.38833243001639}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"'t"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":32,"predicted_ms":440.396,"predicted_per_token_ms":14.206322580645162,"predicted_per_second":70.391193380503}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" attack"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":33,"predicted_ms":454.559,"predicted_per_token_ms":14.20496875,"predicted_per_second":70.39790214251614}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" each"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":34,"predicted_ms":468.592,"predicted_per_token_ms":14.199757575757575,"predicted_per_second":70.42373749445147}} + + +20d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" other"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":35,"predicted_ms":482.576,"predicted_per_token_ms":14.193411764705884,"predicted_per_second":70.45522363316866}} + + +20d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" means"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":36,"predicted_ms":496.525,"predicted_per_token_ms":14.186428571428571,"predicted_per_second":70.48990483862848}} + + +20f +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" exactly"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":37,"predicted_ms":510.648,"predicted_per_token_ms":14.184666666666667,"predicted_per_second":70.49866052545002}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" one"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":38,"predicted_ms":524.784,"predicted_per_token_ms":14.183351351351352,"predicted_per_second":70.50519832921735}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ro"}}],"created":1789675313,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":39,"predicted_ms":538.9,"predicted_per_token_ms":14.18157894736842,"predicted_per_second":70.51401002041196}} + + +208 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"ok"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":40,"predicted_ms":553.038,"predicted_per_token_ms":14.18046153846154,"predicted_per_second":70.51956646740369}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" per"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":41,"predicted_ms":567.155,"predicted_per_token_ms":14.178875,"predicted_per_second":70.52745722068923}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" row"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":42,"predicted_ms":581.119,"predicted_per_token_ms":14.173634146341463,"predicted_per_second":70.55353550649694}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" and"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":43,"predicted_ms":595.281,"predicted_per_token_ms":14.173357142857142,"predicted_per_second":70.55491440176992}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" one"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":44,"predicted_ms":609.304,"predicted_per_token_ms":14.169860465116278,"predicted_per_second":70.57232514475533}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ro"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":45,"predicted_ms":623.255,"predicted_per_token_ms":14.164886363636363,"predicted_per_second":70.59710712308765}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"ok"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":46,"predicted_ms":637.287,"predicted_per_token_ms":14.161933333333334,"predicted_per_second":70.61182795192747}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" per"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":47,"predicted_ms":651.242,"predicted_per_token_ms":14.157434782608695,"predicted_per_second":70.6342649890517}} + + +20e +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" column"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":48,"predicted_ms":665.265,"predicted_per_token_ms":14.154574468085107,"predicted_per_second":70.64853855230622}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"."}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":49,"predicted_ms":679.28,"predicted_per_token_ms":14.151666666666666,"predicted_per_second":70.66305499941114}} + + +20c +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" This"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":50,"predicted_ms":693.396,"predicted_per_token_ms":14.150938775510204,"predicted_per_second":70.66668974150413}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" is"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":51,"predicted_ms":707.413,"predicted_per_token_ms":14.14826,"predicted_per_second":70.68006949264432}} + + +210 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" equivalent"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":52,"predicted_ms":721.45,"predicted_per_token_ms":14.14607843137255,"predicted_per_second":70.69096957516112}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" to"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":53,"predicted_ms":735.58,"predicted_per_token_ms":14.14576923076923,"predicted_per_second":70.6925147502651}} + + +208 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" a"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":54,"predicted_ms":749.673,"predicted_per_token_ms":14.14477358490566,"predicted_per_second":70.69749077264355}} + + +212 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" permutation"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":55,"predicted_ms":763.702,"predicted_per_token_ms":14.14262962962963,"predicted_per_second":70.70820817544016}} + + +20d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" matrix"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":56,"predicted_ms":777.68,"predicted_per_token_ms":14.139636363636363,"predicted_per_second":70.72317662791895}} + + +206 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"."}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":57,"predicted_ms":791.78,"predicted_per_token_ms":14.13892857142857,"predicted_per_second":70.72671701735331}} + + +209 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" So"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":58,"predicted_ms":805.76,"predicted_per_token_ms":14.136140350877193,"predicted_per_second":70.74066719618746}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" the"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":59,"predicted_ms":819.948,"predicted_per_token_ms":14.13703448275862,"predicted_per_second":70.73619302687487}} + + +20d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" number"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":60,"predicted_ms":834.052,"predicted_per_token_ms":14.136474576271187,"predicted_per_second":70.7389946909785}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" of"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":61,"predicted_ms":848.101,"predicted_per_token_ms":14.135016666666667,"predicted_per_second":70.74629083092698}} + + +20b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ways"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":62,"predicted_ms":862.155,"predicted_per_token_ms":14.133688524590163,"predicted_per_second":70.7529388567021}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" to"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":63,"predicted_ms":876.321,"predicted_per_token_ms":14.134209677419355,"predicted_per_second":70.75033007311248}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"The"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":66,"predicted_ms":918.492,"predicted_per_token_ms":14.130646153846154,"predicted_per_second":70.76817217787416}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" number"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":67,"predicted_ms":932.589,"predicted_per_token_ms":14.130136363636364,"predicted_per_second":70.7707253677665}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" of"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":68,"predicted_ms":946.625,"predicted_per_token_ms":14.128731343283581,"predicted_per_second":70.7777631057705}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ways"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":69,"predicted_ms":960.683,"predicted_per_token_ms":14.127691176470588,"predicted_per_second":70.78297419648314}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" is"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":70,"predicted_ms":974.675,"predicted_per_token_ms":14.12572463768116,"predicted_per_second":70.79282837869033}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" the"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":71,"predicted_ms":988.81,"predicted_per_token_ms":14.125857142857143,"predicted_per_second":70.79216431872655}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" number"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":72,"predicted_ms":1002.867,"predicted_per_token_ms":14.124887323943662,"predicted_per_second":70.79702492952704}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" of"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":73,"predicted_ms":1016.819,"predicted_per_token_ms":14.12248611111111,"predicted_per_second":70.80906237983358}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" der"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":74,"predicted_ms":1030.918,"predicted_per_token_ms":14.122164383561643,"predicted_per_second":70.8106755338446}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"ang"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":75,"predicted_ms":1045.021,"predicted_per_token_ms":14.121905405405405,"predicted_per_second":70.81197411343888}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"ements"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":76,"predicted_ms":1059.04,"predicted_per_token_ms":14.120533333333332,"predicted_per_second":70.81885481190513}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" of"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":77,"predicted_ms":1073.065,"predicted_per_token_ms":14.119276315789474,"predicted_per_second":70.82515970607558}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":78,"predicted_ms":1087.054,"predicted_per_token_ms":14.117584415584417,"predicted_per_second":70.83364763847977}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"8"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":79,"predicted_ms":1101.088,"predicted_per_token_ms":14.11651282051282,"predicted_per_second":70.83902467377722}} + + +204 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" elements"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":80,"predicted_ms":1115.11,"predicted_per_token_ms":14.1153164556962,"predicted_per_second":70.84502874155913}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":","}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":81,"predicted_ms":1129.124,"predicted_per_token_ms":14.11405,"predicted_per_second":70.85138567597537}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" which"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":82,"predicted_ms":1143.084,"predicted_per_token_ms":14.11214814814815,"predicted_per_second":70.86093410458024}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" equals"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":83,"predicted_ms":1157.083,"predicted_per_token_ms":14.110768292682927,"predicted_per_second":70.86786341169994}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" **"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":84,"predicted_ms":1171.065,"predicted_per_token_ms":14.10921686746988,"predicted_per_second":70.8756559200386}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"4"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":85,"predicted_ms":1185.174,"predicted_per_token_ms":14.109214285714286,"predicted_per_second":70.87566888912515}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"0"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":86,"predicted_ms":1199.147,"predicted_per_token_ms":14.107611764705881,"predicted_per_second":70.88371984418924}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"3"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":87,"predicted_ms":1213.27,"predicted_per_token_ms":14.10779069767442,"predicted_per_second":70.88282080658057}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"2"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":88,"predicted_ms":1227.245,"predicted_per_token_ms":14.10626436781609,"predicted_per_second":70.8904904888592}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"0"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":89,"predicted_ms":1241.444,"predicted_per_token_ms":14.107318181818181,"predicted_per_second":70.88519498261702}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"**."}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":90,"predicted_ms":1255.669,"predicted_per_token_ms":14.108640449438203,"predicted_per_second":70.87855159281625}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" This"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":91,"predicted_ms":1269.736,"predicted_per_token_ms":14.10817777777778,"predicted_per_second":70.88087602462244}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" counts"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":92,"predicted_ms":1283.792,"predicted_per_token_ms":14.107604395604394,"predicted_per_second":70.88375687027182}} + + +20a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" permutations"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":93,"predicted_ms":1297.873,"predicted_per_token_ms":14.107315217391305,"predicted_per_second":70.8852098780081}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" of"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":94,"predicted_ms":1311.856,"predicted_per_token_ms":14.105978494623656,"predicted_per_second":70.89192716273737}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":95,"predicted_ms":1325.946,"predicted_per_token_ms":14.105808510638298,"predicted_per_second":70.89278145565507}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"8"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":96,"predicted_ms":1339.983,"predicted_per_token_ms":14.105084210526316,"predicted_per_second":70.89642182027683}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ro"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":97,"predicted_ms":1353.963,"predicted_per_token_ms":14.103781249999999,"predicted_per_second":70.90297149922118}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"oks"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":98,"predicted_ms":1368.053,"predicted_per_token_ms":14.103639175257733,"predicted_per_second":70.90368574901703}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ("}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":99,"predicted_ms":1382.062,"predicted_per_token_ms":14.102673469387755,"predicted_per_second":70.90854100611985}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"one"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":100,"predicted_ms":1396.044,"predicted_per_token_ms":14.101454545454546,"predicted_per_second":70.91467031125093}} + + +1f7 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" per"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":101,"predicted_ms":1410.024,"predicted_per_token_ms":14.10024,"predicted_per_second":70.920778653413}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" row"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":102,"predicted_ms":1424.204,"predicted_per_token_ms":14.101029702970296,"predicted_per_second":70.91680686193833}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" and"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":103,"predicted_ms":1438.367,"predicted_per_token_ms":14.101637254901961,"predicted_per_second":70.91375149735777}} + + +206 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" column"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":104,"predicted_ms":1452.392,"predicted_per_token_ms":14.100893203883496,"predicted_per_second":70.91749334890305}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":")"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":105,"predicted_ms":1466.597,"predicted_per_token_ms":14.101894230769231,"predicted_per_second":70.91245925090533}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" where"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":106,"predicted_ms":1480.643,"predicted_per_token_ms":14.101361904761905,"predicted_per_second":70.91513619420752}} + + +204 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" none"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":107,"predicted_ms":1494.784,"predicted_per_token_ms":14.101735849056604,"predicted_per_second":70.91325569446823}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" lands"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":108,"predicted_ms":1508.863,"predicted_per_token_ms":14.101523364485981,"predicted_per_second":70.91432422956888}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" on"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":109,"predicted_ms":1522.882,"predicted_per_token_ms":14.10075925925926,"predicted_per_second":70.9181670017769}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" the"}}],"created":1789675314,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":110,"predicted_ms":1537.028,"predicted_per_token_ms":14.101174311926606,"predicted_per_second":70.91607960297405}} + + +204 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" main"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":111,"predicted_ms":1551.029,"predicted_per_token_ms":14.100263636363636,"predicted_per_second":70.92065976845049}} + + +207 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" diagonal"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":112,"predicted_ms":1565.05,"predicted_per_token_ms":14.099549549549549,"predicted_per_second":70.92425162135396}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ("}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":113,"predicted_ms":1579.222,"predicted_per_token_ms":14.100196428571428,"predicted_per_second":70.9209978077813}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"a"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":114,"predicted_ms":1593.406,"predicted_per_token_ms":14.100938053097344,"predicted_per_second":70.91726778987905}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" fixed"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":115,"predicted_ms":1607.404,"predicted_per_token_ms":14.100035087719299,"predicted_per_second":70.92180932733775}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" point"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":116,"predicted_ms":1621.798,"predicted_per_token_ms":14.102591304347825,"predicted_per_second":70.90895413608847}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" would"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":117,"predicted_ms":1636.345,"predicted_per_token_ms":14.106422413793103,"predicted_per_second":70.88969624376278}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" place"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":118,"predicted_ms":1650.394,"predicted_per_token_ms":14.105931623931625,"predicted_per_second":70.89216271993233}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" a"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":119,"predicted_ms":1664.436,"predicted_per_token_ms":14.105389830508473,"predicted_per_second":70.89488571504101}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ro"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":120,"predicted_ms":1678.598,"predicted_per_token_ms":14.105865546218487,"predicted_per_second":70.8924948081673}} + + +1f8 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"ok"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":121,"predicted_ms":1692.759,"predicted_per_token_ms":14.106325,"predicted_per_second":70.89018578545439}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" on"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":122,"predicted_ms":1706.916,"predicted_per_token_ms":14.106743801652891,"predicted_per_second":70.88808119438801}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" the"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":123,"predicted_ms":1720.999,"predicted_per_token_ms":14.10654918032787,"predicted_per_second":70.88905920340453}} + + +208 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" diagonal"}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":124,"predicted_ms":1735.081,"predicted_per_token_ms":14.106349593495935,"predicted_per_second":70.89006219306188}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":")."}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":125,"predicted_ms":1749.154,"predicted_per_token_ms":14.10608064516129,"predicted_per_second":70.8914137920389}} + + +1ec +data: {"choices":[{"finish_reason":"stop","index":0,"delta":{}}],"created":1789675315,"id":"chatcmpl-1x092OMeEwmeoSzn7cE1GLkJlskrslR0","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":55,"prompt_ms":228.721,"prompt_per_token_ms":4.1585636363636365,"prompt_per_second":240.467643985467,"predicted_n":126,"predicted_ms":1763.228,"predicted_per_token_ms":14.105824,"predicted_per_second":70.89270360951618}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/control.http b/crates/loopd/tests/fixtures/http/control.http new file mode 100644 index 0000000..0df19b0 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/control.http @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: close + +10 +{"success":true} +0 + diff --git a/crates/loopd/tests/fixtures/http/plain.http b/crates/loopd/tests/fixtures/http/plain.http new file mode 100644 index 0000000..36cbb03 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/plain.http @@ -0,0 +1,97 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +212 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":46,"cache":0,"processed":0,"time_ms":11}} + + +227 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":15,"prompt_ms":62.46,"prompt_per_token_ms":4.164,"prompt_per_second":240.15369836695484,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":46,"cache":0,"processed":15,"time_ms":62}} + + +235 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":42,"prompt_ms":110.781,"prompt_per_token_ms":2.637642857142857,"prompt_per_second":379.1263844883148,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":46,"cache":0,"processed":42,"time_ms":110}} + + +236 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.137,"prompt_per_token_ms":5.350804347826087,"prompt_per_second":186.88779013313723,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":46,"cache":0,"processed":46,"time_ms":246}} + + +2ec +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"The"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" box"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":2,"predicted_ms":17.839,"predicted_per_token_ms":17.839,"predicted_per_second":56.05695386512697}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" is"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":3,"predicted_ms":32.208,"predicted_per_token_ms":16.104,"predicted_per_second":62.09637357178341}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" made"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":4,"predicted_ms":46.636,"predicted_per_token_ms":15.545333333333334,"predicted_per_second":64.3279869628613}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"."}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":5,"predicted_ms":61.039,"predicted_per_token_ms":15.25975,"predicted_per_second":65.53187306476187}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ("}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":6,"predicted_ms":75.194,"predicted_per_token_ms":15.0388,"predicted_per_second":66.49466712769636}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"run"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":7,"predicted_ms":89.347,"predicted_per_token_ms":14.891166666666665,"predicted_per_second":67.15390555922416}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":8,"predicted_ms":103.564,"predicted_per_token_ms":14.794857142857142,"predicted_per_second":67.5910548066896}} + + +1f1 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"6"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":9,"predicted_ms":117.664,"predicted_per_token_ms":14.708,"predicted_per_second":67.99020940984498}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"aac"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":10,"predicted_ms":131.848,"predicted_per_token_ms":14.649777777777778,"predicted_per_second":68.26042109095322}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"4"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":11,"predicted_ms":145.997,"predicted_per_token_ms":14.599700000000002,"predicted_per_second":68.49455810735836}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"7"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":12,"predicted_ms":160.522,"predicted_per_token_ms":14.59290909090909,"predicted_per_second":68.52643251392333}} + + +1f4 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"2"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":13,"predicted_ms":174.729,"predicted_per_token_ms":14.56075,"predicted_per_second":68.67778102089521}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"8"}}],"created":1789675304,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":14,"predicted_ms":189.019,"predicted_per_token_ms":14.539923076923078,"predicted_per_second":68.77615477809108}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":")"}}],"created":1789675305,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":15,"predicted_ms":203.221,"predicted_per_token_ms":14.515785714285714,"predicted_per_second":68.89051820431943}} + + +1f3 +data: {"choices":[{"finish_reason":"stop","index":0,"delta":{}}],"created":1789675305,"id":"chatcmpl-LMYge0IefEaKdgrXAjafeR0nrNUicPF2","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":46,"prompt_ms":246.429,"prompt_per_token_ms":5.357152173913043,"prompt_per_second":186.66634202955012,"predicted_n":16,"predicted_ms":217.376,"predicted_per_token_ms":14.491733333333334,"predicted_per_second":69.00485794199912}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/progress.http b/crates/loopd/tests/fixtures/http/progress.http new file mode 100644 index 0000000..a675c52 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/progress.http @@ -0,0 +1,81 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +216 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675307,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":15,"time_ms":6}} + + +23d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675308,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":2048,"prompt_ms":1243.164,"prompt_per_token_ms":0.607013671875,"prompt_per_second":1647.4093522656706,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":2063,"time_ms":1243}} + + +23d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675310,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":4096,"prompt_ms":2760.804,"prompt_per_token_ms":0.6740244140625,"prompt_per_second":1483.625784372958,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":4111,"time_ms":2760}} + + +240 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675311,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":6144,"prompt_ms":4317.25,"prompt_per_token_ms":0.7026774088541666,"prompt_per_second":1423.1281487057734,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":6159,"time_ms":4317}} + + +240 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675312,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":6513,"prompt_ms":4710.221,"prompt_per_token_ms":0.7232029786580684,"prompt_per_second":1382.737667723022,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":6528,"time_ms":4710}} + + +241 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675312,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7025,"prompt_ms":5045.515,"prompt_per_token_ms":0.7182227758007118,"prompt_per_second":1392.3256595213768,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":7040,"time_ms":5045}} + + +241 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.547,"prompt_per_token_ms":0.7849689856309574,"prompt_per_second":1273.9356819253194,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":7044,"cache":15,"processed":7044,"time_ms":5517}} + + +2ef +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"ok"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" ("}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":2,"predicted_ms":17.844,"predicted_per_token_ms":17.844,"predicted_per_second":56.04124635731898}} + + +1f4 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"run"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":3,"predicted_ms":32.64,"predicted_per_token_ms":16.32,"predicted_per_second":61.27450980392157}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":4,"predicted_ms":47.315,"predicted_per_token_ms":15.771666666666667,"predicted_per_second":63.404839902779244}} + + +1f6 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"6"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":5,"predicted_ms":61.947,"predicted_per_token_ms":15.48675,"predicted_per_second":64.57132710220027}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"aac"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":6,"predicted_ms":77.065,"predicted_per_token_ms":15.413,"predicted_per_second":64.8802958541491}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"4"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":7,"predicted_ms":91.683,"predicted_per_token_ms":15.280500000000002,"predicted_per_second":65.44288472235856}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"7"}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":8,"predicted_ms":106.25,"predicted_per_token_ms":15.178571428571429,"predicted_per_second":65.88235294117648}} + + +1f7 +data: {"choices":[{"finish_reason":"length","index":0,"delta":{}}],"created":1789675313,"id":"chatcmpl-l28a5WTzw2ZnKeMg92QlUvh4jZ1Tys3u","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":7029,"prompt_ms":5517.837,"prompt_per_token_ms":0.785010243277849,"prompt_per_second":1273.8687279091425,"predicted_n":8,"predicted_ms":106.25,"predicted_per_token_ms":15.178571428571429,"predicted_per_second":65.88235294117648}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/props.http b/crates/loopd/tests/fixtures/http/props.http new file mode 100644 index 0000000..279ae94 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/props.http @@ -0,0 +1,15 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: close + +f62 +{"default_generation_settings":{"params":{"seed":4294967295,"temperature":1.0,"dynatemp_range":0.0,"dynatemp_exponent":1.0,"top_k":20,"top_p":0.949999988079071,"min_p":0.05000000074505806,"top_n_sigma":-1.0,"xtc_probability":0.0,"xtc_threshold":0.10000000149011612,"typical_p":1.0,"repeat_last_n":64,"repeat_penalty":1.0,"presence_penalty":0.0,"frequency_penalty":0.0,"dry_multiplier":0.0,"dry_base":1.75,"dry_allowed_length":2,"dry_penalty_last_n":64,"mirostat":0,"mirostat_tau":5.0,"mirostat_eta":0.10000000149011612,"adaptive_target":-1.0,"adaptive_decay":0.8999999761581421,"max_tokens":-1,"n_predict":-1,"n_keep":0,"n_discard":0,"ignore_eos":false,"stream":false,"n_probs":0,"min_keep":0,"chat_format":"Content-only","reasoning_format":"none","reasoning_in_content":false,"generation_prompt":"","samplers":["penalties","dry","top_n_sigma","top_k","typ_p","top_p","min_p","xtc","temperature"],"speculative.types":"none","timings_per_token":false,"post_sampling_probs":false,"backend_sampling":false,"lora":[]},"n_ctx":131072},"total_slots":2,"model_alias":"ornith-1.5-35b-a3b","model_ftype":"Q4_K - Medium","model_path":"/var/lib/llama-server/huggingface/hub/models--ornith-ai--Ornith-1.5-35B-A3B-GGUF/snapshots/12393612fd4f730ff5aadc23e9b8f9648aa49ceb/Ornith-1.5-35B-Q4_K_M.gguf","modalities":{"vision":true,"video":true,"audio":false},"media_marker":"<__media_1NEgc2GobMPCrtOJSOjhswjzcmPq260o__>","endpoint_slots":true,"endpoint_props":false,"endpoint_metrics":false,"ui":true,"ui_settings":{},"chat_template":"{%- set image_count = namespace(value=0) %}\n{%- set video_count = namespace(value=0) %}\n{%- macro render_content(content, do_vision_count, is_system_content=false) %}\n {%- if content is string %}\n {{- content }}\n {%- elif content is iterable and content is not mapping %}\n {%- for item in content %}\n {%- if 'image' in item or 'image_url' in item or item.type == 'image' %}\n {%- if is_system_content %}\n {{- raise_exception('System message cannot contain images.') }}\n {%- endif %}\n {%- if do_vision_count %}\n {%- set image_count.value = image_count.value + 1 %}\n {%- endif %}\n {%- if add_vision_id %}\n {{- 'Picture ' ~ image_count.value ~ ': ' }}\n {%- endif %}\n {{- '<|vision_start|><|image_pad|><|vision_end|>' }}\n {%- elif 'video' in item or item.type == 'video' %}\n {%- if is_system_content %}\n {{- raise_exception('System message cannot contain videos.') }}\n {%- endif %}\n {%- if do_vision_count %}\n {%- set video_count.value = video_count.value + 1 %}\n {%- endif %}\n {%- if add_vision_id %}\n {{- 'Video ' ~ video_count.value ~ ': ' }}\n {%- endif %}\n {{- '<|vision_start|><|video_pad|><|vision_end|>' }}\n {%- elif 'text' in item %}\n {{- item.text }}\n {%- else %}\n {{- raise_exception('Unexpected item type in content.') }}\n {%- endif %}\n {%- endfor %}\n {%- elif content is none or content is undefined %}\n {{- '' }}\n {%- else %}\n {{- raise_exception('Unexpected content type.') }}\n {%- endif %}\n{%- endmacro %}\n{%- if not messages %}\n {{- raise_exception('No messages provided.') }}\n{%- endif %}\n{%- set num_sys = 0 %}\n{%- set merged_system = '' %}\n{%- if messages[0].role == 'system' or messages[0].role == 'developer' %}\n {%- set first = render_content(messages[0].content, false, true)|trim %}\n {%- if messages|length > 1 and (messages[1].role == 'system' or messages[1].role == 'developer') %}\n {%- set second = render_content(messages[1].content, false, true)|trim %}\n {%- set me +17c5 +rged_system = first + '\\n' + second %}\n {%- set num_sys = 2 %}\n {%- else %}\n {%- set merged_system = first %}\n {%- set num_sys = 1 %}\n {%- endif %}\n{%- endif %}\n{%- if tools and tools is iterable and tools is not mapping %}\n {{- '<|im_start|>system\\n' }}\n {{- \"# Tools\\n\\nYou have access to the following functions:\\n\\n\" }}\n {%- for tool in tools %}\n {{- \"\\n\" }}\n {{- tool | tojson }}\n {%- endfor %}\n {{- \"\\n\" }}\n {{- '\\n\\nIf you choose to call a function ONLY reply in the following format with NO suffix:\\n\\n\\n\\n\\nvalue_1\\n\\n\\nThis is the value for the second parameter\\nthat can span\\nmultiple lines\\n\\n\\n\\n\\n\\nReminder:\\n- Function calls MUST follow the specified format: an inner block must be nested within XML tags\\n- Required parameters MUST be specified\\n- You may provide optional reasoning for your function call in natural language BEFORE the function call, but NOT after\\n- If there is no function call available, answer the question like normal with your current knowledge and do not tell the user about function calls\\n' }}\n {%- if merged_system %}\n {{- '\\n\\n' + merged_system }}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n{%- else %}\n {%- if merged_system %}\n {{- '<|im_start|>system\\n' + merged_system + '<|im_end|>\\n' }}\n {%- endif %}\n{%- endif %}\n{%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}\n{%- for message in messages[::-1] %}\n {%- set index = (messages|length - 1) - loop.index0 %}\n {%- if ns.multi_step_tool and message.role == \"user\" %}\n {%- set content = render_content(message.content, false)|trim %}\n {%- if not(content.startswith('') and content.endswith('')) %}\n {%- set ns.multi_step_tool = false %}\n {%- set ns.last_query_index = index %}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- for message in messages %}\n {%- if loop.index0 >= num_sys and message.role != \"system\" and message.role != \"developer\" %}\n {%- set content = render_content(message.content, true)|trim %}\n {%- if message.role == \"user\" %}\n {{- '<|im_start|>' + message.role + '\\n' + content + '<|im_end|>' + '\\n' }}\n {%- elif message.role == \"assistant\" %}\n {%- set reasoning_content = '' %}\n {%- if message.reasoning_content is string %}\n {%- set reasoning_content = message.reasoning_content %}\n {%- else %}\n {%- if '' in content %}\n {%- set reasoning_content = content.split('')[0].rstrip('\\n').split('')[-1].lstrip('\\n') %}\n {%- set content = content.split('')[-1].lstrip('\\n') %}\n {%- endif %}\n {%- endif %}\n {%- set reasoning_content = reasoning_content|trim %}\n {{- '<|im_start|>' + message.role + '\\n\\n' + reasoning_content + '\\n\\n\\n' + content }}\n {%- if message.tool_calls and message.tool_calls is iterable and message.tool_calls is not mapping %}\n {%- for tool_call in message.tool_calls %}\n {%- if tool_call.function is defined %}\n {%- set tool_call = tool_call.function %}\n {%- endif %}\n {%- if loop.first %}\n {%- if content|trim %}\n {{- '\\n\\n\\n\\n' }}\n {%- else %}\n {{- '\\n\\n' }}\n {%- endif %}\n {%- else %}\n {{- '\\n\\n\\n' }}\n {%- endif %}\n {%- if tool_call.arguments is mapping %}\n {%- for args_name in tool_call.arguments %}\n {%- set args_value = tool_call.arguments[args_name] %}\n {{- '\\n' }}\n {%- set args_value = args_value | tojson | safe if args_value is mapping or (args_value is sequence and args_value is not string) else args_value | string %}\n {{- args_value }}\n {{- '\\n\\n' }}\n {%- endfor %}\n {%- endif %}\n {{- '\\n' }}\n {%- endfor %}\n {%- endif %}\n {{- '<|im_end|>\\n' }}\n {%- elif message.role == \"tool\" %}\n {%- if loop.previtem and loop.previtem.role != \"tool\" %}\n {{- '<|im_start|>user' }}\n {%- endif %}\n {{- '\\n\\n' }}\n {{- content }}\n {{- '\\n' }}\n {%- if not loop.last and loop.nextitem.role != \"tool\" %}\n {{- '<|im_end|>\\n' }}\n {%- elif loop.last %}\n {{- '<|im_end|>\\n' }}\n {%- endif %}\n {%- endif %}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|im_start|>assistant\\n' }}\n {%- if enable_thinking is defined and enable_thinking is false %}\n {{- '\\n\\n\\n\\n' }}\n {%- else %}\n {{- '\\n' }}\n {%- endif %}\n{%- endif %}\n{#- Unsloth fixes - developer role, tool calling #}","chat_template_caps":{"supports_object_arguments":true,"supports_parallel_tool_calls":true,"supports_preserve_reasoning":true,"supports_reasoning_effort":false,"supports_string_content":true,"supports_system_role":true,"supports_tool_calls":true,"supports_tools":true,"supports_typed_content":false},"bos_token":"<|endoftext|>","eos_token":"<|im_end|>","build_info":"b10809-5266f24","is_sleeping":false,"cors_proxy_enabled":false} +0 + diff --git a/crates/loopd/tests/fixtures/http/slots.http b/crates/loopd/tests/fixtures/http/slots.http new file mode 100644 index 0000000..e5a580e --- /dev/null +++ b/crates/loopd/tests/fixtures/http/slots.http @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: close + +a01 +[{"id":0,"n_ctx":131072,"speculative":false,"is_processing":false,"id_task":4323,"n_prompt_tokens":76,"n_prompt_tokens_processed":0,"n_prompt_tokens_cache":0,"params":{"seed":4294967295,"temperature":0.6000000238418579,"dynatemp_range":0.0,"dynatemp_exponent":1.0,"top_k":20,"top_p":0.949999988079071,"min_p":0.05000000074505806,"top_n_sigma":-1.0,"xtc_probability":0.0,"xtc_threshold":0.10000000149011612,"typical_p":1.0,"repeat_last_n":64,"repeat_penalty":1.0,"presence_penalty":0.0,"frequency_penalty":0.0,"dry_multiplier":0.0,"dry_base":1.75,"dry_allowed_length":2,"dry_penalty_last_n":64,"mirostat":0,"mirostat_tau":5.0,"mirostat_eta":0.10000000149011612,"adaptive_target":-1.0,"adaptive_decay":0.8999999761581421,"max_tokens":16,"n_predict":16,"n_keep":0,"n_discard":0,"ignore_eos":false,"stream":true,"n_probs":0,"min_keep":0,"chat_format":"peg-native","reasoning_format":"deepseek","reasoning_in_content":false,"generation_prompt":"<|im_start|>assistant\n\n\n\n\n","samplers":["penalties","dry","top_n_sigma","top_k","typ_p","top_p","min_p","xtc","temperature"],"speculative.types":"none","timings_per_token":true,"post_sampling_probs":false,"backend_sampling":false,"lora":[]},"next_token":[{"has_next_token":false,"has_new_line":false,"n_remain":-1,"n_decoded":0}]},{"id":1,"n_ctx":131072,"speculative":false,"is_processing":false,"id_task":1939,"n_prompt_tokens":1292,"n_prompt_tokens_processed":0,"n_prompt_tokens_cache":0,"params":{"seed":4294967295,"temperature":1.0,"dynatemp_range":0.0,"dynatemp_exponent":1.0,"top_k":20,"top_p":0.949999988079071,"min_p":0.05000000074505806,"top_n_sigma":-1.0,"xtc_probability":0.0,"xtc_threshold":0.10000000149011612,"typical_p":1.0,"repeat_last_n":64,"repeat_penalty":1.0,"presence_penalty":0.0,"frequency_penalty":0.0,"dry_multiplier":0.0,"dry_base":1.75,"dry_allowed_length":2,"dry_penalty_last_n":64,"mirostat":0,"mirostat_tau":5.0,"mirostat_eta":0.10000000149011612,"adaptive_target":-1.0,"adaptive_decay":0.8999999761581421,"max_tokens":16384,"n_predict":16384,"n_keep":0,"n_discard":0,"ignore_eos":false,"stream":true,"n_probs":0,"min_keep":0,"chat_format":"peg-native","reasoning_format":"deepseek","reasoning_in_content":false,"generation_prompt":"<|im_start|>assistant\n\n","samplers":["penalties","dry","top_n_sigma","top_k","typ_p","top_p","min_p","xtc","temperature"],"speculative.types":"none","timings_per_token":false,"post_sampling_probs":false,"backend_sampling":false,"lora":[]},"next_token":[{"has_next_token":false,"has_new_line":false,"n_remain":-1,"n_decoded":0}]}] +0 + diff --git a/crates/loopd/tests/fixtures/http/thinking.http b/crates/loopd/tests/fixtures/http/thinking.http new file mode 100644 index 0000000..d82d43f --- /dev/null +++ b/crates/loopd/tests/fixtures/http/thinking.http @@ -0,0 +1,277 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +214 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":55,"cache":15,"processed":15,"time_ms":6}} + + +238 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":36,"prompt_ms":151.463,"prompt_per_token_ms":4.207305555555555,"prompt_per_second":237.68181007902922,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":55,"cache":15,"processed":51,"time_ms":151}} + + +22f +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.379,"prompt_per_token_ms":5.109475,"prompt_per_second":195.71482393005152,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":55,"cache":15,"processed":55,"time_ms":204}} + + +2e9 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1ef +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"7"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":2,"predicted_ms":17.581,"predicted_per_token_ms":17.581,"predicted_per_second":56.87958591661453}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" *"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":3,"predicted_ms":31.917,"predicted_per_token_ms":15.9585,"predicted_per_second":62.662530939624645}} + + +1fb +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":4,"predicted_ms":46.043,"predicted_per_token_ms":15.347666666666667,"predicted_per_second":65.15648415611494}} + + +1ef +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"2"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":5,"predicted_ms":60.132,"predicted_per_token_ms":15.033,"predicted_per_second":66.52032195835828}} + + +1f0 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"3"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":6,"predicted_ms":74.214,"predicted_per_token_ms":14.8428,"predicted_per_second":67.37273290753765}} + + +1fa +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"."}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":7,"predicted_ms":88.451,"predicted_per_token_ms":14.741833333333332,"predicted_per_second":67.8341680704571}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" Let"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":8,"predicted_ms":102.733,"predicted_per_token_ms":14.676142857142858,"predicted_per_second":68.13779408758626}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" me"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":9,"predicted_ms":116.897,"predicted_per_token_ms":14.612125,"predicted_per_second":68.43631573094262}} + + +204 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" compute"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":10,"predicted_ms":130.975,"predicted_per_token_ms":14.552777777777777,"predicted_per_second":68.71540370299675}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":":"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":11,"predicted_ms":145.117,"predicted_per_token_ms":14.5117,"predicted_per_second":68.90991406933716}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":12,"predicted_ms":159.265,"predicted_per_token_ms":14.478636363636362,"predicted_per_second":69.06727780742787}} + + +1f1 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":13,"predicted_ms":173.31,"predicted_per_token_ms":14.4425,"predicted_per_second":69.24009001211702}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"7"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":14,"predicted_ms":187.424,"predicted_per_token_ms":14.41723076923077,"predicted_per_second":69.36144784019123}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" *"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":15,"predicted_ms":201.657,"predicted_per_token_ms":14.404071428571429,"predicted_per_second":69.42481540437475}} + + +1f1 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":16,"predicted_ms":216.105,"predicted_per_token_ms":14.407,"predicted_per_second":69.41070313042272}} + + +1f4 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"2"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":17,"predicted_ms":230.278,"predicted_per_token_ms":14.392375,"predicted_per_second":69.48123572377735}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"3"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":18,"predicted_ms":244.396,"predicted_per_token_ms":14.376235294117647,"predicted_per_second":69.55923992209367}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ="}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":19,"predicted_ms":258.485,"predicted_per_token_ms":14.360277777777778,"predicted_per_second":69.63653596920517}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":20,"predicted_ms":272.641,"predicted_per_token_ms":14.349526315789475,"predicted_per_second":69.68871152908036}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":21,"predicted_ms":286.727,"predicted_per_token_ms":14.33635,"predicted_per_second":69.75276133743945}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"7"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":22,"predicted_ms":300.787,"predicted_per_token_ms":14.323190476190476,"predicted_per_second":69.8168471376755}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" *"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":23,"predicted_ms":314.87,"predicted_per_token_ms":14.312272727272727,"predicted_per_second":69.87010512274907}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":24,"predicted_ms":328.974,"predicted_per_token_ms":14.303217391304347,"predicted_per_second":69.91433973505505}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"2"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":25,"predicted_ms":343.02,"predicted_per_token_ms":14.292499999999999,"predicted_per_second":69.96676578625154}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"0"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":26,"predicted_ms":357.078,"predicted_per_token_ms":14.283119999999998,"predicted_per_second":70.0127143089185}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" +"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":27,"predicted_ms":371.151,"predicted_per_token_ms":14.275038461538461,"predicted_per_second":70.05235066051283}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":28,"predicted_ms":385.265,"predicted_per_token_ms":14.269074074074073,"predicted_per_second":70.08163212334367}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":29,"predicted_ms":399.303,"predicted_per_token_ms":14.260821428571429,"predicted_per_second":70.12218791243743}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"7"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":30,"predicted_ms":413.34,"predicted_per_token_ms":14.253103448275862,"predicted_per_second":70.16015870711763}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" *"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":31,"predicted_ms":427.537,"predicted_per_token_ms":14.251233333333333,"predicted_per_second":70.16936545842816}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":32,"predicted_ms":441.571,"predicted_per_token_ms":14.244225806451613,"predicted_per_second":70.20388567183986}} + + +1f6 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"3"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":33,"predicted_ms":455.541,"predicted_per_token_ms":14.23565625,"predicted_per_second":70.24614688908353}} + + +1fe +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ="}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":34,"predicted_ms":469.487,"predicted_per_token_ms":14.226878787878789,"predicted_per_second":70.28948618385598}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":35,"predicted_ms":483.621,"predicted_per_token_ms":14.22414705882353,"predicted_per_second":70.30298518881521}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"3"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":36,"predicted_ms":497.817,"predicted_per_token_ms":14.223342857142857,"predicted_per_second":70.30696018818159}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"4"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":37,"predicted_ms":511.843,"predicted_per_token_ms":14.217861111111112,"predicted_per_second":70.33406728235025}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"0"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":38,"predicted_ms":525.825,"predicted_per_token_ms":14.211486486486487,"predicted_per_second":70.36561593686112}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" +"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":39,"predicted_ms":540.0,"predicted_per_token_ms":14.210526315789474,"predicted_per_second":70.37037037037037}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":40,"predicted_ms":554.023,"predicted_per_token_ms":14.205717948717949,"predicted_per_second":70.39418941090894}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"5"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":41,"predicted_ms":568.083,"predicted_per_token_ms":14.202074999999999,"predicted_per_second":70.41224609784135}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":42,"predicted_ms":582.132,"predicted_per_token_ms":14.198341463414632,"predicted_per_second":70.43076140806554}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" ="}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":43,"predicted_ms":596.24,"predicted_per_token_ms":14.196190476190477,"predicted_per_second":70.44143298000805}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":" "}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":44,"predicted_ms":610.366,"predicted_per_token_ms":14.194558139534884,"predicted_per_second":70.4495335585534}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"3"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":45,"predicted_ms":624.37,"predicted_per_token_ms":14.190227272727272,"predicted_per_second":70.47103480308151}} + + +1fc +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"9"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":46,"predicted_ms":638.436,"predicted_per_token_ms":14.187466666666667,"predicted_per_second":70.4847471007274}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"1"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":47,"predicted_ms":652.715,"predicted_per_token_ms":14.189456521739132,"predicted_per_second":70.47486268892243}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"."}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":48,"predicted_ms":666.873,"predicted_per_token_ms":14.188787234042554,"predicted_per_second":70.47818700112315}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"reasoning_content":"\n"}}],"created":1789675305,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":49,"predicted_ms":680.936,"predicted_per_token_ms":14.186166666666667,"predicted_per_second":70.4912062220238}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"1"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":52,"predicted_ms":723.201,"predicted_per_token_ms":14.180411764705882,"predicted_per_second":70.51981399362003}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"7"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":53,"predicted_ms":737.249,"predicted_per_token_ms":14.177865384615385,"predicted_per_second":70.53247952862601}} + + +1f4 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" *"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":54,"predicted_ms":751.363,"predicted_per_token_ms":14.176660377358491,"predicted_per_second":70.53847474522966}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":55,"predicted_ms":765.475,"predicted_per_token_ms":14.175462962962964,"predicted_per_second":70.54443319507496}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"2"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":56,"predicted_ms":779.545,"predicted_per_token_ms":14.173545454545454,"predicted_per_second":70.5539769994035}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"3"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":57,"predicted_ms":793.62,"predicted_per_token_ms":14.171785714285715,"predicted_per_second":70.56273783422796}} + + +1f9 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" equals"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":58,"predicted_ms":807.654,"predicted_per_token_ms":14.169368421052631,"predicted_per_second":70.57477583222519}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" "}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":59,"predicted_ms":821.65,"predicted_per_token_ms":14.166379310344826,"predicted_per_second":70.58966713320757}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"3"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":60,"predicted_ms":835.866,"predicted_per_token_ms":14.16722033898305,"predicted_per_second":70.58547661945813}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"9"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":61,"predicted_ms":850.108,"predicted_per_token_ms":14.168466666666665,"predicted_per_second":70.57926757541395}} + + +1f2 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"1"}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":62,"predicted_ms":864.085,"predicted_per_token_ms":14.16532786885246,"predicted_per_second":70.59490675107195}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"."}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":63,"predicted_ms":878.051,"predicted_per_token_ms":14.162112903225808,"predicted_per_second":70.61093262236476}} + + +1e8 +data: {"choices":[{"finish_reason":"stop","index":0,"delta":{}}],"created":1789675306,"id":"chatcmpl-oSb4bEgcGEBGNn7Bn6LXqGrh20qMbo4f","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":40,"prompt_ms":204.752,"prompt_per_token_ms":5.1188,"prompt_per_second":195.3582870985387,"predicted_n":64,"predicted_ms":892.097,"predicted_per_token_ms":14.160269841269841,"predicted_per_second":70.62012314804332}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/tokenize.http b/crates/loopd/tests/fixtures/http/tokenize.http new file mode 100644 index 0000000..912cfe5 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/tokenize.http @@ -0,0 +1,13 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: application/json; charset=utf-8 +Transfer-Encoding: chunked +Connection: close + +21 +{"tokens":[760,3618,369,1801,13]} +0 + diff --git a/crates/loopd/tests/fixtures/http/tool_call.http b/crates/loopd/tests/fixtures/http/tool_call.http new file mode 100644 index 0000000..6612eda --- /dev/null +++ b/crates/loopd/tests/fixtures/http/tool_call.http @@ -0,0 +1,121 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +212 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":312,"cache":0,"processed":0,"time_ms":7}} + + +238 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":278,"prompt_ms":370.003,"prompt_per_token_ms":1.3309460431654676,"prompt_per_second":751.345259362762,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":312,"cache":0,"processed":278,"time_ms":370}} + + +237 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":308,"prompt_ms":413.826,"prompt_per_token_ms":1.343590909090909,"prompt_per_second":744.274163537332,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":312,"cache":0,"processed":308,"time_ms":413}} + + +239 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":552.907,"prompt_per_token_ms":1.7721378205128206,"prompt_per_second":564.2901970855858,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":312,"cache":0,"processed":312,"time_ms":552}} + + +2eb +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"I"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1f3 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"'ll"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":2,"predicted_ms":16.527,"predicted_per_token_ms":16.527,"predicted_per_second":60.50704907121679}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" read"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":3,"predicted_ms":30.874,"predicted_per_token_ms":15.437,"predicted_per_second":64.77942605428517}} + + +200 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" the"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":4,"predicted_ms":45.026,"predicted_per_token_ms":15.008666666666668,"predicted_per_second":66.62817039044107}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" `/"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":5,"predicted_ms":59.061,"predicted_per_token_ms":14.76525,"predicted_per_second":67.72658776519192}} + + +1f4 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"etc"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":6,"predicted_ms":73.188,"predicted_per_token_ms":14.6376,"predicted_per_second":68.31721047166201}} + + +1fd +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"/"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":7,"predicted_ms":87.607,"predicted_per_token_ms":14.601166666666666,"predicted_per_second":68.48767792527994}} + + +205 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"hostname"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":8,"predicted_ms":101.729,"predicted_per_token_ms":14.532714285714286,"predicted_per_second":68.81027042436277}} + + +1f5 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"`"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":9,"predicted_ms":115.893,"predicted_per_token_ms":14.486625,"predicted_per_second":69.02919071902531}} + + +203 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" file"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":10,"predicted_ms":130.046,"predicted_per_token_ms":14.449555555555555,"predicted_per_second":69.20628085446688}} + + +201 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" for"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":11,"predicted_ms":144.156,"predicted_per_token_ms":14.415600000000001,"predicted_per_second":69.3692943755376}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":" you"}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":12,"predicted_ms":158.604,"predicted_per_token_ms":14.418545454545455,"predicted_per_second":69.35512345211974}} + + +1ff +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"."}}],"created":1789675306,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":13,"predicted_ms":172.624,"predicted_per_token_ms":14.385333333333334,"predicted_per_second":69.51524701084438}} + + +202 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"\n\n"}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":14,"predicted_ms":186.606,"predicted_per_token_ms":14.354307692307692,"predicted_per_second":69.66549842984683}} + + +274 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"id":"wgE8iFI58Zni4WCTiCMNp4TzCcM8ou7F","type":"function","function":{"name":"read_file","arguments":"{"}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":22,"predicted_ms":299.638,"predicted_per_token_ms":14.26847619047619,"predicted_per_second":70.0845687129136}} + + +232 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"path\":\""}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":27,"predicted_ms":370.16,"predicted_per_token_ms":14.236923076923079,"predicted_per_second":70.23989626107628}} + + +22b +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/etc"}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":28,"predicted_ms":384.27,"predicted_per_token_ms":14.232222222222221,"predicted_per_second":70.26309626044188}} + + +229 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"/"}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":29,"predicted_ms":398.284,"predicted_per_token_ms":14.224428571428572,"predicted_per_second":70.30159383756315}} + + +230 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"hostname"}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":30,"predicted_ms":412.404,"predicted_per_token_ms":14.220827586206896,"predicted_per_second":70.31939554417514}} + + +229 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\""}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":35,"predicted_ms":482.812,"predicted_per_token_ms":14.20035294117647,"predicted_per_second":70.42078490178372}} + + +228 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":39,"predicted_ms":538.943,"predicted_per_token_ms":14.18271052631579,"predicted_per_second":70.50838400350315}} + + +1f1 +data: {"choices":[{"finish_reason":"tool_calls","index":0,"delta":{}}],"created":1789675307,"id":"chatcmpl-e9aFhGwvvU0YGs2GTOy83IQWDpVtNvcP","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":0,"prompt_n":312,"prompt_ms":553.156,"prompt_per_token_ms":1.7729358974358973,"prompt_per_second":564.0361850906436,"predicted_n":41,"predicted_ms":566.991,"predicted_per_token_ms":14.174775,"predicted_per_second":70.54785702065817}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/turn1.http b/crates/loopd/tests/fixtures/http/turn1.http new file mode 100644 index 0000000..8da3c1b --- /dev/null +++ b/crates/loopd/tests/fixtures/http/turn1.http @@ -0,0 +1,37 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +214 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":44,"cache":15,"processed":15,"time_ms":6}} + + +22e +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":25,"prompt_ms":106.593,"prompt_per_token_ms":4.26372,"prompt_per_second":234.53697709980955,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":44,"cache":15,"processed":40,"time_ms":106}} + + +236 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":29,"prompt_ms":161.482,"prompt_per_token_ms":5.568344827586207,"prompt_per_second":179.586579309149,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":44,"cache":15,"processed":44,"time_ms":161}} + + +2ed +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"Blue"}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":29,"prompt_ms":161.813,"prompt_per_token_ms":5.579758620689654,"prompt_per_second":179.2192221885757,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1e5 +data: {"choices":[{"finish_reason":"stop","index":0,"delta":{}}],"created":1789675316,"id":"chatcmpl-1OEWBOVSZ1NthqfpaLOboUWbY9OJixgN","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":15,"prompt_n":29,"prompt_ms":161.813,"prompt_per_token_ms":5.579758620689654,"prompt_per_second":179.2192221885757,"predicted_n":2,"predicted_ms":17.197,"predicted_per_token_ms":17.197,"predicted_per_second":58.14967726929116}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/turn2.http b/crates/loopd/tests/fixtures/http/turn2.http new file mode 100644 index 0000000..1649560 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/turn2.http @@ -0,0 +1,41 @@ +HTTP/1.1 200 OK +Server: llama.cpp +Access-Control-Allow-Origin: +Connection: close +X-Accel-Buffering: no +Content-Type: text/event-stream +Transfer-Encoding: chunked +Connection: close + +214 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":0,"prompt_ms":0.0,"prompt_per_token_ms":0.0,"prompt_per_second":0.0,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":75,"cache":45,"processed":45,"time_ms":0}} + + +22a +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":2,"prompt_ms":32.846,"prompt_per_token_ms":16.423,"prompt_per_second":60.890214942458755,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":75,"cache":45,"processed":47,"time_ms":32}} + + +239 +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":26,"prompt_ms":114.273,"prompt_per_token_ms":4.3951153846153845,"prompt_per_second":227.52531219098125,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":75,"cache":45,"processed":71,"time_ms":114}} + + +22d +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":30,"prompt_ms":194.325,"prompt_per_token_ms":6.4775,"prompt_per_second":154.38054805094558,"predicted_n":0,"predicted_ms":0.0,"predicted_per_token_ms":0.0,"predicted_per_second":0.0},"prompt_progress":{"total":75,"cache":45,"processed":75,"time_ms":194}} + + +2ef +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"role":"assistant","content":null}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk"} + +data: {"choices":[{"finish_reason":null,"index":0,"delta":{"content":"Green"}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":30,"prompt_ms":194.635,"prompt_per_token_ms":6.487833333333333,"prompt_per_second":154.13466231664398,"predicted_n":1,"predicted_ms":0.001,"predicted_per_token_ms":0.0,"predicted_per_second":0.0}} + + +1e6 +data: {"choices":[{"finish_reason":"stop","index":0,"delta":{}}],"created":1789675316,"id":"chatcmpl-Po3MDTUPhb5xQOmzad8o6J8hupMG8HcE","model":"ornith-1.5-35b-a3b","system_fingerprint":"b10809-5266f24","object":"chat.completion.chunk","timings":{"cache_n":45,"prompt_n":30,"prompt_ms":194.635,"prompt_per_token_ms":6.487833333333333,"prompt_per_second":154.13466231664398,"predicted_n":2,"predicted_ms":17.301,"predicted_per_token_ms":17.301,"predicted_per_second":57.80012716027976}} + + +e +data: [DONE] + + +0 + diff --git a/crates/loopd/tests/fixtures/http/unknown_model.http b/crates/loopd/tests/fixtures/http/unknown_model.http new file mode 100644 index 0000000..c3875b4 --- /dev/null +++ b/crates/loopd/tests/fixtures/http/unknown_model.http @@ -0,0 +1,8 @@ +HTTP/1.1 400 Bad Request +Server: llama.cpp +Access-Control-Allow-Origin: +Content-Type: application/json; charset=utf-8 +Content-Length: 97 +Connection: close + +{"error":{"code":400,"message":"model 'no-such-model' not found","type":"invalid_request_error"}} \ No newline at end of file diff --git a/crates/loopd/tests/http.rs b/crates/loopd/tests/http.rs new file mode 100644 index 0000000..5f84a0a --- /dev/null +++ b/crates/loopd/tests/http.rs @@ -0,0 +1,310 @@ +//! Tests for the HTTP client, against the fake server. Do not edit. + +mod support; + +use loopd::http::{Connection, Head, HttpError, MAX_HEAD, Request, read_capped}; +use std::time::Duration; +use support::{FakeServer, Reply}; + +const GET_PROPS: Request<'static> = Request { + method: "GET", + path: "/props?model=m", + body: None, +}; + +fn get(server: &FakeServer) -> (Connection, Result) { + let mut conn = Connection::open(&server.socket).unwrap(); + conn.set_read_timeout(Duration::from_secs(5)).unwrap(); + conn.send(&GET_PROPS).unwrap(); + let head = conn.read_head(); + (conn, head) +} + +fn get_body(server: &FakeServer) -> Result, HttpError> { + let (mut conn, head) = get(server); + let head = head?; + let mut body = conn.body(&head)?; + read_capped(&mut body, 4 * 1024 * 1024) +} + +#[test] +fn reads_a_recorded_chunked_response() { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props")]); + let (mut conn, head) = get(&server); + let head = head.unwrap(); + assert_eq!(head.status, 200); + assert_eq!(head.header("transfer-encoding"), Some("chunked")); + assert_eq!( + head.header("content-type"), + Some("application/json; charset=utf-8") + ); + // The real server sends this header with an empty value, and `Connection` twice. + assert_eq!(head.header("access-control-allow-origin"), Some("")); + assert_eq!( + head.headers + .iter() + .filter(|(n, _)| n == "connection") + .count(), + 2 + ); + assert_eq!(head.header("x-missing"), None); + + let bytes = read_capped(&mut conn.body(&head).unwrap(), 4 * 1024 * 1024).unwrap(); + let props: serde_json::Value = serde_json::from_slice(&bytes).unwrap(); + let template = props["chat_template"].as_str().unwrap(); + // The hash recorded in docs/inference-contract.md. If the de-chunking were off by a byte, + // this would not match. + assert_eq!( + proto::sha256(template.as_bytes()).unwrap().to_hex(), + "f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b" + ); +} + +#[test] +fn the_result_does_not_depend_on_how_the_bytes_arrive() { + let whole = { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props")]); + get_body(&server).unwrap() + }; + for piece in [1, 2, 3, 7, 64, 1000] { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props").trickle(piece, 0)]); + assert_eq!(get_body(&server).unwrap(), whole, "in pieces of {piece}"); + } +} + +#[test] +fn reads_a_body_with_a_content_length() { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("unknown_model")]); + let (mut conn, head) = get(&server); + let head = head.unwrap(); + assert_eq!(head.status, 400); + assert_eq!(head.header("content-length"), Some("97")); + let bytes = read_capped(&mut conn.body(&head).unwrap(), 4096).unwrap(); + let body: serde_json::Value = serde_json::from_slice(&bytes).unwrap(); + assert_eq!(body["error"]["message"], "model 'no-such-model' not found"); +} + +#[test] +fn reads_a_body_that_runs_to_the_close() { + let server = FakeServer::start(); + server.route( + "/props", + vec![Reply::raw("HTTP/1.0 200 OK\r\nX-A: b\r\n\r\nto the end")], + ); + assert_eq!(get_body(&server).unwrap(), b"to the end"); +} + +#[test] +fn an_empty_body_is_empty_in_every_framing() { + for raw in [ + "HTTP/1.1 204 No Content\r\nContent-Length: 0\r\n\r\n", + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n0\r\n\r\n", + "HTTP/1.1 200 OK\r\n\r\n", + ] { + let server = FakeServer::start(); + server.route("/props", vec![Reply::raw(raw)]); + assert_eq!(get_body(&server).unwrap(), b"", "{raw:?}"); + } +} + +#[test] +fn chunk_extensions_and_trailers_are_skipped() { + let raw = "HTTP/1.1 200 OK\r\nTransfer-Encoding: Chunked\r\n\r\n\ + 5;ext=1\r\nhello\r\n1\r\n,\r\n6\r\n world\r\n0\r\nX-Trailer: t\r\n\r\n"; + let server = FakeServer::start(); + server.route("/props", vec![Reply::raw(raw)]); + assert_eq!(get_body(&server).unwrap(), b"hello, world"); +} + +#[test] +fn sends_a_well_formed_request() { + let server = FakeServer::start(); + server.route("/tokenize", vec![Reply::fixture("tokenize")]); + let mut conn = Connection::open(&server.socket).unwrap(); + let body = br#"{"content":"x"}"#; + conn.send(&Request { + method: "POST", + path: "/tokenize", + body: Some(body), + }) + .unwrap(); + conn.read_head().unwrap(); + let sent = &server.requests()[0]; + assert_eq!( + (sent.method.as_str(), sent.target.as_str()), + ("POST", "/tokenize") + ); + assert_eq!(sent.body, body); + let has = |line: &str| sent.headers.iter().any(|h| h.eq_ignore_ascii_case(line)); + assert!(has("Connection: close"), "{:?}", sent.headers); + assert!(has("Content-Type: application/json"), "{:?}", sent.headers); + assert!(has("Content-Length: 15"), "{:?}", sent.headers); + assert!( + sent.headers + .iter() + .any(|h| h.to_ascii_lowercase().starts_with("host:")) + ); + + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props")]); + let _ = get(&server); + let sent = &server.requests()[0]; + assert_eq!(sent.target, "/props?model=m"); + assert!( + !sent + .headers + .iter() + .any(|h| h.to_ascii_lowercase().starts_with("content-length")) + ); +} + +#[test] +fn a_timeout_before_the_first_byte_can_be_waited_out() { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props").head_delay(300)]); + let mut conn = Connection::open(&server.socket).unwrap(); + conn.set_read_timeout(Duration::from_millis(50)).unwrap(); + conn.send(&GET_PROPS).unwrap(); + let mut timeouts = 0; + let head = loop { + match conn.read_head() { + Ok(head) => break head, + Err(HttpError::Timeout) => { + assert!(!conn.received_any(), "nothing has arrived yet"); + timeouts += 1; + assert!(timeouts < 100); + } + Err(e) => panic!("{e}"), + } + }; + assert!( + timeouts >= 3, + "only {timeouts} timeouts in 300 ms at 50 ms each" + ); + assert!(conn.received_any()); + assert_eq!(head.status, 200); +} + +#[test] +fn a_timeout_in_the_middle_of_the_head_keeps_what_arrived() { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props").trickle(10, 120)]); + let mut conn = Connection::open(&server.socket).unwrap(); + conn.set_read_timeout(Duration::from_millis(40)).unwrap(); + conn.send(&GET_PROPS).unwrap(); + let mut saw_partial = false; + let head = loop { + match conn.read_head() { + Ok(head) => break head, + Err(HttpError::Timeout) => saw_partial |= conn.received_any(), + Err(e) => panic!("{e}"), + } + }; + assert!( + saw_partial, + "at least one timeout must have happened after some bytes arrived" + ); + assert_eq!(head.status, 200); + assert_eq!(head.header("server"), Some("llama.cpp")); +} + +#[test] +fn a_connection_closed_before_the_head_is_complete_is_closed() { + for cut in [0, 5, 40] { + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props").cut_after(cut)]); + let (_, head) = get(&server); + assert!( + matches!(head, Err(HttpError::Closed)), + "cut after {cut} bytes: {head:?}" + ); + } +} + +#[test] +fn a_body_cut_short_is_closed_in_both_framings() { + for name in ["props", "unknown_model"] { + let full = support::fixture_bytes("http", &format!("{name}.http")).len(); + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture(name).cut_after(full - 10)]); + let got = get_body(&server); + assert!(matches!(got, Err(HttpError::Closed)), "{name}: {got:?}"); + } +} + +#[test] +fn malformed_heads_are_rejected() { + for raw in [ + "HTTP/2 200 OK\r\n\r\n", + "HELLO\r\n\r\n", + "HTTP/1.1 abc OK\r\n\r\n", + "HTTP/1.1 99 Low\r\n\r\n", + "HTTP/1.1 200 OK\r\nno colon here\r\n\r\n", + "HTTP/1.1 200 OK\r\n: no name\r\n\r\n", + ] { + let server = FakeServer::start(); + server.route("/props", vec![Reply::raw(raw)]); + let (_, head) = get(&server); + assert!( + matches!(head, Err(HttpError::Malformed(_))), + "{raw:?}: {head:?}" + ); + } +} + +#[test] +fn malformed_framing_is_an_error_not_a_panic() { + for raw in [ + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\nzz\r\nhello\r\n0\r\n\r\n", + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nhelloXX0\r\n\r\n", + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\nffffffffffffffffffffffff\r\nx\r\n", + "HTTP/1.1 200 OK\r\nContent-Length: many\r\n\r\nhello", + "HTTP/1.1 200 OK\r\nContent-Length: -5\r\n\r\nhello", + ] { + let server = FakeServer::start(); + server.route("/props", vec![Reply::raw(raw)]); + assert!(get_body(&server).is_err(), "{raw:?}"); + } +} + +#[test] +fn everything_read_from_the_peer_is_bounded() { + // A head that never ends. + let server = FakeServer::start(); + let endless = format!("HTTP/1.1 200 OK\r\nX-Pad: {}\r\n", "a".repeat(2 * MAX_HEAD)); + server.route("/props", vec![Reply::raw(endless)]); + let (_, head) = get(&server); + assert!(matches!(head, Err(HttpError::TooLarge(_))), "{head:?}"); + + // A chunk-size line that never ends. + let server = FakeServer::start(); + let raw = format!( + "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n{}", + "1".repeat(10_000) + ); + server.route("/props", vec![Reply::raw(raw)]); + assert!(get_body(&server).is_err()); + + // A body larger than the caller allows. + let server = FakeServer::start(); + server.route("/props", vec![Reply::fixture("props")]); + let (mut conn, head) = get(&server); + let head = head.unwrap(); + let got = read_capped(&mut conn.body(&head).unwrap(), 1000); + assert!(matches!(got, Err(HttpError::TooLarge(_))), "{got:?}"); +} + +#[test] +fn a_missing_socket_is_a_connect_error() { + let missing = std::env::temp_dir().join("loopd-no-such-socket.sock"); + assert!(matches!( + Connection::open(&missing), + Err(HttpError::Connect(_)) + )); + let e: Box = Box::new(HttpError::Timeout); + assert!(!e.to_string().is_empty()); +} diff --git a/crates/loopd/tests/support/mod.rs b/crates/loopd/tests/support/mod.rs new file mode 100644 index 0000000..e2eb473 --- /dev/null +++ b/crates/loopd/tests/support/mod.rs @@ -0,0 +1,290 @@ +//! A scripted stand-in for `llama-server`, for tests. Do not edit. +//! +//! It listens on a Unix socket in a temporary directory. Each path has a list of replies that are +//! served in order; the last one repeats. A reply is raw bytes, normally a response recorded from +//! the real server (`tests/fixtures/http/*.http`), and can be delayed, sent in small pieces, cut +//! short, or left hanging. Every request is recorded. + +#![allow(dead_code)] // each test file uses a different part of this module + +use std::collections::VecDeque; +use std::io::{Read, Write}; +use std::os::unix::net::{UnixListener, UnixStream}; +use std::path::{Path, PathBuf}; +use std::sync::atomic::{AtomicU32, Ordering}; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::time::Duration; + +static NEXT: AtomicU32 = AtomicU32::new(0); + +pub fn fixture_path(kind: &str, name: &str) -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("tests/fixtures") + .join(kind) + .join(name) +} + +pub fn fixture_bytes(kind: &str, name: &str) -> Vec { + let path = fixture_path(kind, name); + std::fs::read(&path).unwrap_or_else(|e| panic!("{}: {e}", path.display())) +} + +/// A config that points at `socket`, with every limit short enough for a test. +pub fn test_config(socket: &Path) -> loopd::config::Config { + let text = format!( + r#" +[infer] +socket = "{}" +model = "test-model" +[slots] +main = 0 +background = 1 +[expect] +template_sha256 = "f55f52930aa8bf44ab5cb85f99370fcc3c56e9a85640b812086d5330bce5d86b" +n_ctx = 131072 +slots = 2 +[limits] +poll_ms = 40 +busy_wait_ms = 400 +load_wait_ms = 300 +idle_grace_ms = 200 +liveness_ms = 150 +retry_backoff_ms = [10, 20, 30] +retry_window_ms = 5000 +"#, + socket.display() + ); + loopd::config::Config::parse(&text).unwrap() +} + +/// What an independent script derived from a recorded stream: `tests/fixtures/expected/`. +pub fn expected(name: &str) -> serde_json::Value { + serde_json::from_slice(&fixture_bytes("expected", &format!("{name}.json"))).unwrap() +} + +#[derive(Clone)] +pub struct Reply { + bytes: Vec, + head_delay_ms: u64, + piece: usize, + piece_delay_ms: u64, + stop_after: Option, + hang_ms: u64, +} + +impl Reply { + /// Exactly these bytes, then close. + pub fn raw(bytes: impl Into>) -> Reply { + Reply { + bytes: bytes.into(), + head_delay_ms: 0, + piece: usize::MAX, + piece_delay_ms: 0, + stop_after: None, + hang_ms: 0, + } + } + + /// A response recorded from the real server: `tests/fixtures/http/.http`. + pub fn fixture(name: &str) -> Reply { + Reply::raw(fixture_bytes("http", &format!("{name}.http"))) + } + + /// A small JSON response with a content length. + pub fn json(status: u16, body: &str) -> Reply { + Reply::raw(format!( + "HTTP/1.1 {status} X\r\nContent-Type: application/json\r\nContent-Length: {}\r\n\r\n{body}", + body.len() + )) + } + + /// Wait this long before sending the first byte, as a queued request does. + pub fn head_delay(mut self, ms: u64) -> Reply { + self.head_delay_ms = ms; + self + } + + /// Send `piece` bytes at a time, waiting `delay_ms` before each piece after the first. + pub fn trickle(mut self, piece: usize, delay_ms: u64) -> Reply { + self.piece = piece.max(1); + self.piece_delay_ms = delay_ms; + self + } + + /// Send only the first `bytes` bytes, then close, as a server that dies does. + pub fn cut_after(mut self, bytes: usize) -> Reply { + self.stop_after = Some(bytes); + self + } + + /// Send only the first `bytes` bytes, then stay silent for `ms` before closing. + pub fn hang_after(mut self, bytes: usize, ms: u64) -> Reply { + self.stop_after = Some(bytes); + self.hang_ms = ms; + self + } + + /// The offset just after the `n`th `data:` line of the body, for use with `cut_after`. + pub fn offset_after_events(&self, n: usize) -> usize { + let mut seen = 0; + let mut at = 0; + while let Some(found) = find(&self.bytes[at..], b"\n\n") { + at += found + 2; + seen += 1; + if seen == n { + return at; + } + } + panic!("the reply has only {seen} events"); + } +} + +#[derive(Debug, Clone)] +pub struct Recorded { + pub method: String, + /// Path and query as sent. + pub target: String, + /// Header lines as sent, without the request line. + pub headers: Vec, + pub body: Vec, +} + +impl Recorded { + pub fn path(&self) -> &str { + self.target.split('?').next().unwrap_or("") + } + + pub fn json(&self) -> serde_json::Value { + serde_json::from_slice(&self.body).expect("request body is JSON") + } +} + +struct State { + routes: Mutex)>>, + requests: Mutex>, +} + +pub struct FakeServer { + pub socket: PathBuf, + state: Arc, +} + +impl FakeServer { + pub fn start() -> FakeServer { + let n = NEXT.fetch_add(1, Ordering::SeqCst); + let dir = std::env::temp_dir().join(format!("loopd-fake-{}-{n}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let socket = dir.join("infer.sock"); + let _ = std::fs::remove_file(&socket); + let listener = UnixListener::bind(&socket).unwrap(); + let state = Arc::new(State { + routes: Mutex::new(Vec::new()), + requests: Mutex::new(Vec::new()), + }); + let accept_state = Arc::clone(&state); + thread::spawn(move || { + for stream in listener.incoming() { + let Ok(stream) = stream else { break }; + let state = Arc::clone(&accept_state); + thread::spawn(move || serve(stream, &state)); + } + }); + FakeServer { socket, state } + } + + /// Replies for `path` (the query is ignored), served in order. The last one repeats. + pub fn route(&self, path: &str, replies: Vec) { + assert!(!replies.is_empty()); + let mut routes = self.state.routes.lock().unwrap(); + routes.retain(|(p, _)| p != path); + routes.push((path.to_string(), replies.into())); + } + + pub fn requests(&self) -> Vec { + self.state.requests.lock().unwrap().clone() + } + + pub fn requests_to(&self, path: &str) -> Vec { + self.requests() + .into_iter() + .filter(|r| r.path() == path) + .collect() + } +} + +fn find(haystack: &[u8], needle: &[u8]) -> Option { + haystack.windows(needle.len()).position(|w| w == needle) +} + +fn read_request(stream: &mut UnixStream) -> Option { + let mut buf = Vec::new(); + let mut chunk = [0u8; 4096]; + let head_end = loop { + if let Some(end) = find(&buf, b"\r\n\r\n") { + break end; + } + match stream.read(&mut chunk) { + Ok(0) | Err(_) => return None, + Ok(n) => buf.extend_from_slice(&chunk[..n]), + } + }; + let head = String::from_utf8_lossy(&buf[..head_end]).to_string(); + let mut lines = head.split("\r\n"); + let mut request_line = lines.next()?.split(' '); + let method = request_line.next()?.to_string(); + let target = request_line.next()?.to_string(); + let headers: Vec = lines.map(str::to_string).collect(); + let length = headers + .iter() + .filter_map(|h| h.split_once(':')) + .find(|(name, _)| name.eq_ignore_ascii_case("content-length")) + .and_then(|(_, v)| v.trim().parse::().ok()) + .unwrap_or(0); + let mut body = buf[head_end + 4..].to_vec(); + while body.len() < length { + match stream.read(&mut chunk) { + Ok(0) | Err(_) => return None, + Ok(n) => body.extend_from_slice(&chunk[..n]), + } + } + Some(Recorded { + method, + target, + headers, + body, + }) +} + +fn serve(mut stream: UnixStream, state: &State) { + let Some(request) = read_request(&mut stream) else { + return; + }; + let path = request.path().to_string(); + state.requests.lock().unwrap().push(request); + let reply = { + let mut routes = state.routes.lock().unwrap(); + match routes.iter_mut().find(|(p, _)| *p == path) { + Some((_, replies)) if replies.len() > 1 => replies.pop_front(), + Some((_, replies)) => replies.front().cloned(), + None => None, + } + }; + let reply = + reply.unwrap_or_else(|| Reply::json(404, r#"{"error":"no route in the fake server"}"#)); + thread::sleep(Duration::from_millis(reply.head_delay_ms)); + let end = reply + .stop_after + .unwrap_or(reply.bytes.len()) + .min(reply.bytes.len()); + for (i, piece) in reply.bytes[..end].chunks(reply.piece).enumerate() { + if i > 0 { + thread::sleep(Duration::from_millis(reply.piece_delay_ms)); + } + if stream.write_all(piece).is_err() { + return; // the client went away, which some tests do on purpose + } + let _ = stream.flush(); + } + thread::sleep(Duration::from_millis(reply.hang_ms)); +} diff --git a/docs/implementer-log.md b/docs/implementer-log.md index c2a5663..630c5bf 100644 --- a/docs/implementer-log.md +++ b/docs/implementer-log.md @@ -17,6 +17,7 @@ reviewer adds findings under "Reviews" once per milestone. | M2a/01-proto-sha256 | 2026-09-17 | done | 1 | pass | none | Added crates/proto/src/hash.rs wrapping emsha 1.0.4 (HashError, Sha256 with new/update/finish, sha256, Default); re-exported from lib.rs, added emsha workspace dep and dependencies.md row. One compile fix: finish needed `mut self` to call finalize. 4 hash tests pass, `make gate` prints `gate: ok`. | | M2a/02-inferproxy | 2026-09-17 | done | 3 | fail | none | Implemented Limits/TokenBucket/OpenGuard/serve/handle/forward in lib.rs (std only: the inference server's JSON is upstream's concern) and arg parsing + stale-socket handling in main.rs; TokenBucket counts thousandths of a token in u128 so partial refills stay additive and `saturating_duration_since` on an earlier `now` never underflows, capping at burst; serve refuses by rate-limit then open-connection limit; handle drops its OpenGuard before closing the client so a freshly-finished client is not refused on re-connect (rule 4). The scaffold `proto` dependency in `crates/inferproxy/Cargo.toml` was left untouched since the task's Modify/Copy lists cover only lib.rs, main.rs, the two test files and this log. First `make gate` failed on `clippy::map_clone` (`main.rs` used `.map(String::clone)`); switched to `.cloned()` and re-ran, then re-ran once more after restoring the proto scaffold — both pass. Hand test against straylight returned `{"status":"ok"}`; `forward.rs` passed 6/6 ten runs in a row. | | M2a/03-loopd-config | 2026-09-17 | done | 1 | pass | none | Wrote crates/loopd/src/config.rs: Config + Infer/Slots/Expect/Sampling/Limits with deny_unknown_fields on all six and struct-level `#[serde(deny_unknown_fields, default)]` on Sampling and Limits; manual Default impls for the two; hand-written Display/std::error::Error ConfigError named by file. Everywhere check: all six structs (Infer, Slots, Expect, Sampling, Limits, Config) carry deny_unknown_fields. One local fix: Display used `{path}` on a PathBuf and failed to build, switched to `path.display()`. 6 config tests pass; `make gate` prints `gate: ok`. | +| M2a/04-loopd-http | 2026-09-18 | done | 2 | fail | none | Added `pub mod http;` to crates/loopd/src/lib.rs and wrote crates/loopd/src/http.rs (423 lines): Request/Head/HttpError, send (exact header order, no `Content-Length` for GET), read_head (buffers across timeouts; `Timeout`/`Closed`/`TooLarge`/`Malformed`), parse_status+parse_head (`HTTP/1.1`/`HTTP/1.0`, status 100-599, lowercased names, duplicates kept, trimmed values), body (chunked/length/close; chunk extensions + trailers skipped), and read_capped. Two fixes: the chunk `Data` phase jumped to `Crlf` on `take==want`, but `want` was capped by the caller's buffer so it switched mid-chunk and returned `malformed chunk` on the recorded fixture — changed to switch on `chunk_remaining==0`; `read_length` reads straight into the caller buffer instead of an 8192 temp slice that would panic for readers larger than 8192. First gate failed on three clippy lints (needless borrows of `format!` results and `map_or` -> `is_some_and`), fixed on the second run. All 15 tests pass and `make gate` prints `gate: ok`. | ## Reviews