gproxy-protocol 4.1.7

GPROXY v4 connection modelling, operation declarations, vendor wire types and pairwise conversion
Documentation
use crate::{
    transform::TransformError,
    wire::openai::chat::{response as r, stream as s},
};

pub(crate) fn append(
    old: &mut Option<r::Logprobs>,
    source: s::ChunkLogprobs,
) -> Result<(), TransformError> {
    let old = old.get_or_insert_with(|| r::Logprobs::builder(None, None).build());
    if let Some(Some(content)) = source.content {
        old.content.get_or_insert_with(Vec::new).extend(
            content
                .into_iter()
                .map(collect)
                .collect::<Result<Vec<_>, _>>()?,
        );
    }
    if let Some(Some(refusal)) = source.refusal {
        old.refusal.get_or_insert_with(Vec::new).extend(
            refusal
                .into_iter()
                .map(collect)
                .collect::<Result<Vec<_>, _>>()?,
        );
    }
    Ok(())
}

fn collect(source: s::ChunkTokenLogprob) -> Result<r::TokenLogprob, TransformError> {
    let mut top = Vec::new();
    for value in source.top_logprobs {
        top.push(
            r::TokenLogprobTop::builder(value.token, value.bytes.flatten(), value.logprob).build(),
        );
    }
    Ok(r::TokenLogprob::builder(source.token, source.bytes.flatten(), source.logprob, top).build())
}

pub(crate) fn synthesize(input: r::Logprobs) -> Result<s::ChunkLogprobs, TransformError> {
    let content = input
        .content
        .map(|v| {
            v.into_iter()
                .map(synthesize_token)
                .collect::<Result<Vec<_>, _>>()
        })
        .map(crate::transform::optional)
        .transpose()?
        .flatten();
    let refusal = input
        .refusal
        .map(|v| {
            v.into_iter()
                .map(synthesize_token)
                .collect::<Result<Vec<_>, _>>()
        })
        .map(crate::transform::optional)
        .transpose()?
        .flatten();
    let mut out = s::ChunkLogprobs::builder().build();
    out.content = content.map(Some);
    out.refusal = refusal.map(Some);
    Ok(out)
}

fn synthesize_token(input: r::TokenLogprob) -> Result<s::ChunkTokenLogprob, TransformError> {
    let mut top = Vec::new();
    for v in input.top_logprobs {
        let mut item = s::ChunkTopLogprob::builder(v.token, v.logprob).build();
        item.bytes = Some(v.bytes);
        top.push(item);
    }
    let mut out = s::ChunkTokenLogprob::builder(input.token, input.logprob, top).build();
    out.bytes = Some(input.bytes);
    Ok(out)
}