mirror of
https://github.com/mii443/openai-api-rs.git
synced 2025-08-22 15:15:34 +00:00
Add realtime api
This commit is contained in:
1
examples/realtime/.gitignore
vendored
Normal file
1
examples/realtime/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
target
|
1543
examples/realtime/Cargo.lock
generated
Normal file
1543
examples/realtime/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
13
examples/realtime/Cargo.toml
Normal file
13
examples/realtime/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "realtime"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
openai-api-rs = { path = "../../../openai-api-rs" }
|
||||
serde = { version = "1.0.210", features = ["derive"] }
|
||||
serde_json = "1.0.128"
|
||||
tokio = { version = "1.40.0", features = ["full"] }
|
||||
tokio-tungstenite = { version = "0.24.0", features = ["connect", "native-tls"] }
|
||||
futures-util = { version = "0.3.31", features = ["sink", "std"] }
|
||||
futures-channel = "0.3.31"
|
91
examples/realtime/src/main.rs
Normal file
91
examples/realtime/src/main.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::process::exit;
|
||||
use std::env;
|
||||
|
||||
use futures_util::{future, pin_mut, StreamExt};
|
||||
use openai_api_rs::realtime::api::RealtimeClient;
|
||||
use openai_api_rs::realtime::client_event::{ConversationItemCreate, ResponseCreate};
|
||||
use openai_api_rs::realtime::server_event::ServerEvent;
|
||||
use openai_api_rs::realtime::types::Item;
|
||||
use tokio::io::AsyncReadExt;
|
||||
use tokio_tungstenite::tungstenite::protocol::Message;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
let api_key = env::var("OPENAI_API_KEY").unwrap().to_string();
|
||||
let model = "gpt-4o-realtime-preview-2024-10-01".to_string();
|
||||
|
||||
let (stdin_tx, stdin_rx) = futures_channel::mpsc::unbounded();
|
||||
tokio::spawn(read_stdin(stdin_tx));
|
||||
|
||||
let realtime_client = RealtimeClient::new(api_key, model);
|
||||
|
||||
let (write, read) = realtime_client.connect().await.unwrap();
|
||||
println!("WebSocket handshake complete");
|
||||
|
||||
let stdin_to_ws = stdin_rx.map(Ok).forward(write);
|
||||
|
||||
let ws_to_stdout = {
|
||||
read.for_each(|message| async {
|
||||
let message = message.unwrap();
|
||||
match message {
|
||||
Message::Text(_) => {
|
||||
let data = message.clone().into_data();
|
||||
let server_event: ServerEvent = serde_json::from_slice(&data).unwrap();
|
||||
match server_event {
|
||||
ServerEvent::ResponseOutputItemDone(_event) => {
|
||||
eprintln!();
|
||||
}
|
||||
ServerEvent::ResponseAudioTranscriptDelta(event) => {
|
||||
eprint!("{}", event.delta.trim());
|
||||
}
|
||||
ServerEvent::Error(e) => {
|
||||
eprint!("{e:?}");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Message::Close(_) => {
|
||||
eprintln!("Close");
|
||||
exit(0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
pin_mut!(stdin_to_ws, ws_to_stdout);
|
||||
future::select(stdin_to_ws, ws_to_stdout).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn read_stdin(tx: futures_channel::mpsc::UnboundedSender<Message>) {
|
||||
let mut stdin = tokio::io::stdin();
|
||||
loop {
|
||||
let mut buf = vec![0; 2048];
|
||||
let n = match stdin.read(&mut buf).await {
|
||||
Err(_) | Ok(0) => break,
|
||||
Ok(n) => n,
|
||||
};
|
||||
buf.truncate(n);
|
||||
let text = String::from_utf8_lossy(&buf).into_owned();
|
||||
let item = Item::try_from(serde_json::json!({
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"type": "input_text",
|
||||
"text": text.trim()
|
||||
}
|
||||
]
|
||||
}))
|
||||
.unwrap();
|
||||
let event = ConversationItemCreate {
|
||||
item,
|
||||
..Default::default()
|
||||
};
|
||||
let message: Message = event.into();
|
||||
tx.unbounded_send(message).unwrap();
|
||||
tx.unbounded_send(ResponseCreate::default().into()).unwrap();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user