-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsimple_chat.rs
More file actions
89 lines (75 loc) · 2.8 KB
/
simple_chat.rs
File metadata and controls
89 lines (75 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
//! Simple chat example using the low-level `MessagesRequestBuilder` API.
//!
//! This example demonstrates the lower-level approach to building chat conversations
//! by manually managing message history and using the `MessagesRequestBuilder`.
//!
//! ## How to run
//!
//! ```shell
//! $ cargo run --example simple_chat --features reqwest-blocking -- config.toml
//! ```
//!
//! Requires a TOML configuration file with your Anthropic API key.
//!
//! Enter messages line by line. Press Ctrl+D (EOF) to exit.
use std::{
env, fs,
io::{self, Write},
};
use claus::{
anthropic::{Message, MessagesResponse, Role},
deserialize_response,
};
use serde::Deserialize;
/// Configuration structure for simple chat.
/// Only requires the Anthropic API key - other fields are ignored.
#[derive(Debug, Deserialize)]
struct Config {
/// Anthropic API key for Claude access
anthropic_api_key: String,
}
fn main() {
// Read config from first command line argument, panic if not provided.
let config_file = env::args()
.nth(1)
.expect("requires argument: path to TOML config file");
let client = reqwest::blocking::Client::new();
// Load configuration from TOML file
let config_content = fs::read_to_string(&config_file).expect("failed to read config file");
let config: Config = toml::from_str(&config_content).expect("failed to parse config TOML");
let api = claus::Api::new(config.anthropic_api_key);
// Messages will hold our conversation, it will include both user messages and model responses.
let mut messages = im::Vector::new();
while let Some(input) = read_next_line() {
messages.push_back(Message::from_text(Role::User, input));
// Build the request, then send it.
let http_req = claus::MessagesRequestBuilder::new()
.set_messages(messages.clone())
.build(&api);
let raw = client
.execute(http_req.into())
.expect("failed to execute request")
.text()
.expect("failed to fetch response text");
// Parse the response, then display and store it.
let response: MessagesResponse =
deserialize_response(&raw).expect("failed to parse response");
for content in &response.message {
println!("Claude: {}", content);
}
messages.push_back(response.message);
}
}
/// Helper function that shows a prompt and reads a line from stdin.
fn read_next_line() -> Option<String> {
let stdin = io::stdin();
let mut stdout = io::stdout();
let mut input = String::new();
stdout.write_all(b"You: ").expect("stdout failed to write");
stdout.flush().expect("stdout failed to flush");
if stdin.read_line(&mut input).expect("stdin failed to read") == 0 {
None
} else {
Some(input)
}
}