Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ categories = ["api-bindings", "asynchronous", "development-tools"]
[dependencies]
anyhow = "1"
base64 = "0.22"
lingua = { git = "https://github.com/braintrustdata/lingua.git" }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can't publish a crate with git deps, so we'll need to fix this before that happens.

bon = "3"
arc-swap = "1"
async-trait = "0.1"
Expand Down
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod json_merge;
mod log_queue;
mod logger;
mod logs3;
mod prompt;
mod span;
mod span_components;
mod stream;
Expand All @@ -21,12 +22,15 @@ pub use experiments::{
GitMetadataSettings, MetricSummary, ProjectMetadata, RepoInfo, ScoreSummary,
};
pub use extractors::{extract_anthropic_usage, extract_openai_usage};
pub use lingua::universal::{AssistantContent, TokenBudget, UserContent};
pub use lingua::{Message, UniversalParams, UniversalRequest};
pub use log_queue::LogQueueConfig;
pub use logger::{
BraintrustClient, BraintrustClientBuilder, LoginState, OrgInfo, DEFAULT_API_URL,
DEFAULT_APP_URL,
};
pub use logs3::{Logs3BatchUploader, Logs3UploadResult};
pub use prompt::{Prompt, PromptBuilder, PromptBuilderError};
pub use span::{SpanBuilder, SpanHandle, SpanLog, SpanLogBuilder, SpanLogBuilderError};
pub use span_components::SpanComponents;
pub use stream::{
Expand Down
66 changes: 66 additions & 0 deletions src/logger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::experiments::api::{
};
use crate::experiments::{BaseExperimentInfo, ExperimentBuilder};
use crate::log_queue::{LogQueue, LogQueueConfig};
use crate::prompt::{PromptBuilder, PromptFetchRequest, PromptFetchResponse, PromptFetcher};
use crate::span::SpanSubmitter;
use crate::types::{ParentSpanInfo, SpanPayload};

Expand Down Expand Up @@ -505,6 +506,13 @@ impl BraintrustClient {
crate::span::SpanBuilder::new(submitter, token, org_id)
}

/// Create a prompt builder with an explicit API token.
///
/// Use this if you already have the token and don't want to use the login state.
pub fn prompt_builder_with_credentials(&self, token: impl Into<String>) -> PromptBuilder<Self> {
PromptBuilder::new(Arc::new(self.clone()), token)
}

/// Perform login synchronously.
async fn perform_login(&self, api_key: &str, org_name: Option<&str>) -> Result<()> {
let login_url = self
Expand Down Expand Up @@ -910,6 +918,64 @@ impl ExperimentComparisonFetcher for BraintrustClient {
}
}

#[async_trait::async_trait]
impl PromptFetcher for BraintrustClient {
async fn fetch_prompt(
&self,
token: &str,
request: PromptFetchRequest,
) -> Result<PromptFetchResponse> {
let mut url = self
.inner
.api_url
.join("v1/prompt")
.map_err(|e| BraintrustError::InvalidConfig(e.to_string()))?;

{
let mut query = url.query_pairs_mut();
query.append_pair("slug", &request.slug);
if let Some(project_id) = &request.project_id {
query.append_pair("project_id", project_id);
}
if let Some(project_name) = &request.project_name {
query.append_pair("project_name", project_name);
}
if let Some(version) = &request.version {
query.append_pair("version", version);
}
if let Some(environment) = &request.environment {
query.append_pair("environment", environment);
}
}

let response = self
.inner
.http_client
.get(url)
.bearer_auth(token)
.send()
.await
.map_err(|e| BraintrustError::Network(e.to_string()))?;

if !response.status().is_success() {
let status = response.status();
let body = response.text().await.unwrap_or_default();
return Err(BraintrustError::Api {
status: status.as_u16(),
message: body,
});
}

response
.json::<PromptFetchResponse>()
.await
.map_err(|e| BraintrustError::Api {
status: 200,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should pick a better status than 200 for the error.

message: format!("Failed to parse prompt response: {}", e),
})
}
}

#[allow(dead_code)]
#[derive(Debug, Default)]
struct MutableSpanEvent {
Expand Down
Loading