Skip to content

Commit

Permalink
add integration test
Browse files Browse the repository at this point in the history
add code_interpreter tools
  • Loading branch information
rauner committed Jan 30, 2024
1 parent bbe3d5c commit 7a289cf
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 64 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ serde_json = "1.0"

[dev-dependencies]
tokio-test = "0.4"
tower= "0.4"
Binary file modified sqlite.db
Binary file not shown.
11 changes: 7 additions & 4 deletions src/assistant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl Files {
}
Ok(())
}
pub async fn delete_files(&mut self) -> Result<(), AssistantError> {
pub async fn delete(&mut self) -> Result<(), AssistantError> {
let api_key = env::var("OPENAI_API_KEY")
.map_err(|_| AssistantError::OpenAIError("OPENAI_API_KEY not set".to_string()))?;
let client = Client::new();
Expand Down Expand Up @@ -258,7 +258,10 @@ impl Assistant {
let payload = json!({
"instructions": self.instructions,
"name": self.name,
"tools": [{"type": "code_interpreter"}],
"tools": [
{"type": "retrieval"},
{"type": "code_interpreter"}
],
"model": self.model,
});
let response = client
Expand Down Expand Up @@ -346,7 +349,7 @@ impl Assistant {
Ok(())
}
}

/// scrape urls and upload the resulting files to OpenAI
pub async fn create_files(folder_path: &str, scrape_urls: Vec<String>) -> Result<Files, AssistantError> {
// Initialize the Files struct directly
let mut files = Files {
Expand Down Expand Up @@ -731,7 +734,7 @@ pub async fn assistant_chat_handler(
run.create(&chat.id, &assistant_id).await?;
// Check the status of the run until it's completed or a timeout occurs
let start_time = std::time::Instant::now();
while start_time.elapsed().as_secs() < 30 {
while start_time.elapsed().as_secs() < 120 {
run.get_status(&chat.id).await?; // This sets the run.status field
if run.status == "completed" {
info!("Run completed, status: {}", run.status);
Expand Down
6 changes: 4 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ async fn main() {
// Create an assistant outside of the main function.
let assistant = match create_assistant(
"My Assistant",
"gpt-4-0125-preview",
"Your instructions here",
"gpt-4-1106-preview",
"On buycycle.com, users can buy and sell per-owned bicycles.
Help the users with how the website works, use the faq.html for refeeral links.
",
files,
)
.await
Expand Down
29 changes: 0 additions & 29 deletions tests/assistant_create.rs

This file was deleted.

79 changes: 50 additions & 29 deletions tests/assistant_integration.rs
Original file line number Diff line number Diff line change
@@ -1,52 +1,73 @@
use axum::{routing::post, Router};
use rust_bot::assistant::{assistant_chat_handler, create_assistant, DB};
use sqlx::{Executor, SqlitePool};
use std::net::SocketAddr;
use tokio::sync::oneshot;
use rust_bot::assistant::{assistant_chat_handler, create_assistant, teardown_assistant, create_files, DB}; // Replace `your_crate` with the actual crate name
use axum::{
extract::Extension,
body::Body,
http::{Request, StatusCode},
response::Response,
routing::post,
Router,
};

use tower::ServiceExt; // Import the `ServiceExt` trait
// Define a function to create the Axum app with the database pool and assistant.
async fn app(db_pool: SqlitePool, assistant_id: String) -> Router {
// ... (same as in your main file)
Router::new()
.route("/assistant", post(assistant_chat_handler)) // Updated route
.layer(Extension(db_pool))
.layer(Extension(assistant_id)) // Add the assistant ID as a layer
}
#[tokio::test]
async fn test_chat_endpoint() {
// Set up a temporary in-memory SQLite database for testing
let db_pool = SqlitePool::connect(":memory:").await.unwrap();
// Run database migrations here if necessary
// sqlx::migrate!("./migrations").run(&db_pool).await.unwrap();
let files = match create_files(
"context",
Vec::new(),
)
.await
{
Ok(files) => files,
Err(e) => {
eprintln!("Failed to create files: {:?}", e);
return;
}
};
// Create an assistant for testing
let assistant = create_assistant(
"Test Assistant",
"gpt-4",
"Your instructions here",
"/context",
files,
)
.await
.unwrap();
// Start the server using the `app` function
// Create the router
let router = app(db_pool.clone(), assistant.id).await;
let (tx, rx) = oneshot::channel::<()>();
let server = axum::Server::bind(&"127.0.0.1:0".parse::<SocketAddr>().unwrap())
.serve(router.into_make_service())
.with_graceful_shutdown(async {
rx.await.ok();
});
let (server, addr) = tokio::spawn(server).await.unwrap();
// Perform the test
let client = reqwest::Client::new();
let user_id = "test_user";
let response = client
.post(format!("http://{}/chat", addr))
.json(&serde_json::json!({
"user_id": user_id,
"message": "Hello, chatbot!"
}))
.send()
.await
// Create a mock request
let request = Request::builder()
.uri("/assistant")
.method("POST")
.header("content-type", "application/json")
.body(Body::from(
serde_json::json!({
"user_id": "user_123",
"message": "Can you help me?"
})
.to_string(),
))
.unwrap();
assert_eq!(response.status(), reqwest::StatusCode::OK);
let response_json: serde_json::Value = response.json().await.unwrap();
// ... (rest of your test assertions)
// Shut down the server
tx.send(()).unwrap();
server.await.unwrap();
// Call the service directly without a server
let response = router.oneshot(request).await.unwrap();
// Check the response
assert_eq!(response.status(), StatusCode::OK);
// You can also deserialize the response body if needed
// ...
// Clean up files and assistant
teardown_assistant(assistant).await.unwrap();
files.delete().await.unwrap();
}

0 comments on commit 7a289cf

Please sign in to comment.