prediction: rewrite the messaging to use a loop for self-executing chains, add bandcamp and beets tools
This commit is contained in:
Generated
+60
@@ -238,6 +238,22 @@ dependencies = [
|
|||||||
"windows-link",
|
"windows-link",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bandcamp"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc8f990cfc739590270d0413b821f09b28505d442204fd0f3fd99196df394d52"
|
||||||
|
dependencies = [
|
||||||
|
"chrono",
|
||||||
|
"lazy_static",
|
||||||
|
"regex",
|
||||||
|
"reqwest 0.12.28",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"snafu",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base64"
|
name = "base64"
|
||||||
version = "0.22.1"
|
version = "0.22.1"
|
||||||
@@ -938,6 +954,7 @@ name = "eva_cohost"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-openai",
|
"async-openai",
|
||||||
|
"bandcamp",
|
||||||
"chrono",
|
"chrono",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
@@ -947,6 +964,7 @@ dependencies = [
|
|||||||
"iref 4.0.0",
|
"iref 4.0.0",
|
||||||
"jack",
|
"jack",
|
||||||
"json-ld",
|
"json-ld",
|
||||||
|
"minify",
|
||||||
"oximedia-metering",
|
"oximedia-metering",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"rc-writer",
|
"rc-writer",
|
||||||
@@ -1433,6 +1451,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2313,6 +2332,12 @@ dependencies = [
|
|||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minify"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e93bacfc6ce0cf3e41da4d9415904090e1f7ca8d105c1396907f78d8fee42635"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minimal-lexical"
|
name = "minimal-lexical"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -3308,6 +3333,8 @@ dependencies = [
|
|||||||
"native-tls",
|
"native-tls",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"quinn",
|
||||||
|
"rustls",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@@ -3315,6 +3342,7 @@ dependencies = [
|
|||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-native-tls",
|
"tokio-native-tls",
|
||||||
|
"tokio-rustls",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@@ -3322,6 +3350,7 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
"webpki-roots",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3476,6 +3505,7 @@ checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"rustls-webpki",
|
"rustls-webpki",
|
||||||
"subtle",
|
"subtle",
|
||||||
@@ -3881,6 +3911,27 @@ version = "1.15.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
|
||||||
|
dependencies = [
|
||||||
|
"snafu-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.117",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.3"
|
version = "0.6.3"
|
||||||
@@ -4889,6 +4940,15 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "1.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wezterm-bidi"
|
name = "wezterm-bidi"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ edition = "2024"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-openai = { version = "0.40.2", features = ["completions", "full"] }
|
async-openai = { version = "0.40.2", features = ["completions", "full"] }
|
||||||
|
bandcamp = "0.3.4"
|
||||||
chrono = { version = "0.4.44", features = ["serde"] }
|
chrono = { version = "0.4.44", features = ["serde"] }
|
||||||
color-eyre = "0.6.5"
|
color-eyre = "0.6.5"
|
||||||
crossterm = { version = "0.29.0", features = ["event-stream"] }
|
crossterm = { version = "0.29.0", features = ["event-stream"] }
|
||||||
@@ -14,6 +15,7 @@ hound = "3.5.1"
|
|||||||
iref = { version = "4.0.0", features = ["url", "serde"] }
|
iref = { version = "4.0.0", features = ["url", "serde"] }
|
||||||
jack = "0.13.5"
|
jack = "0.13.5"
|
||||||
json-ld = { version = "0.21.4", features = ["reqwest", "serde"] }
|
json-ld = { version = "0.21.4", features = ["reqwest", "serde"] }
|
||||||
|
minify = "1.3.0"
|
||||||
oximedia-metering = "0.1.7"
|
oximedia-metering = "0.1.7"
|
||||||
ratatui = "0.30.0"
|
ratatui = "0.30.0"
|
||||||
rc-writer = "1.1.10"
|
rc-writer = "1.1.10"
|
||||||
|
|||||||
+172
-17
@@ -1,4 +1,8 @@
|
|||||||
use async_openai::{Client, config::OpenAIConfig, types::chat::{ChatCompletionMessageToolCalls, ChatCompletionRequestMessage, ChatCompletionRequestSystemMessageArgs, ChatCompletionTool, ChatCompletionTools, CreateChatCompletionRequestArgs, FunctionObjectArgs, ResponseFormat, ResponseFormatJsonSchema}};
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use async_openai::{Client, config::OpenAIConfig, types::chat::{ChatCompletionMessageToolCalls, ChatCompletionRequestAssistantMessageArgs, ChatCompletionRequestMessage, ChatCompletionRequestSystemMessageArgs, ChatCompletionRequestToolMessage, ChatCompletionRequestToolMessageArgs, ChatCompletionTool, ChatCompletionTools, CreateChatCompletionRequestArgs, FinishReason, FunctionObjectArgs, ResponseFormat, ResponseFormatJsonSchema}};
|
||||||
|
use bandcamp::SearchResultItem;
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use schemars::{JsonSchema, schema_for};
|
use schemars::{JsonSchema, schema_for};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
@@ -32,6 +36,44 @@ struct StageEventArgs {
|
|||||||
text: String,
|
text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Serialize, Deserialize, Clone, JsonSchema)]
|
||||||
|
struct BeatsQueryArgs {
|
||||||
|
artist: Option<String>,
|
||||||
|
album: Option<String>,
|
||||||
|
genre: Option<String>,
|
||||||
|
title: Option<String>,
|
||||||
|
year: Option<u32>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, JsonSchema)]
|
||||||
|
struct BandcampQueryArgs {
|
||||||
|
query: String
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
enum BandcampResult {
|
||||||
|
Artist { name: String, bio: Option<String>, location: Option<String> },
|
||||||
|
Album { title: String, about: Option<String>, credits: Option<String>, release_date: DateTime<Utc>, artist: String }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<BandcampResult> for bandcamp::Artist {
|
||||||
|
fn into(self) -> BandcampResult {
|
||||||
|
BandcampResult::Artist { name: self.name, bio: self.bio, location: self.location }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<BandcampResult> for bandcamp::Album {
|
||||||
|
fn into(self) -> BandcampResult {
|
||||||
|
BandcampResult::Album {
|
||||||
|
about: self.about,
|
||||||
|
title: self.title,
|
||||||
|
artist: self.band.name,
|
||||||
|
credits: self.credits,
|
||||||
|
release_date: self.release_date
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
fn from_initial_messages(messages: Vec<ChatCompletionRequestMessage>) -> Self {
|
fn from_initial_messages(messages: Vec<ChatCompletionRequestMessage>) -> Self {
|
||||||
let mut conversation = vec![];
|
let mut conversation = vec![];
|
||||||
@@ -56,7 +98,8 @@ impl Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn regenerate_options(&mut self, direction: &StageDirection) -> Option<Scene> {
|
async fn regenerate_options(&mut self, direction: &StageDirection) {
|
||||||
|
loop {
|
||||||
let direction_message: ChatCompletionRequestMessage = ChatCompletionRequestSystemMessageArgs::default().content(serde_json::to_string(&direction).unwrap()).build().unwrap().into();
|
let direction_message: ChatCompletionRequestMessage = ChatCompletionRequestSystemMessageArgs::default().content(serde_json::to_string(&direction).unwrap()).build().unwrap().into();
|
||||||
let mut full_conversation = vec![
|
let mut full_conversation = vec![
|
||||||
self.header_message.clone(),
|
self.header_message.clone(),
|
||||||
@@ -64,7 +107,6 @@ impl Session {
|
|||||||
];
|
];
|
||||||
full_conversation.append(&mut self.messages.clone());
|
full_conversation.append(&mut self.messages.clone());
|
||||||
|
|
||||||
|
|
||||||
let tools = vec![
|
let tools = vec![
|
||||||
ChatCompletionTools::Function(ChatCompletionTool {
|
ChatCompletionTools::Function(ChatCompletionTool {
|
||||||
function: FunctionObjectArgs::default()
|
function: FunctionObjectArgs::default()
|
||||||
@@ -79,14 +121,27 @@ impl Session {
|
|||||||
.description("Inserts a message from the ship computer into the scene script")
|
.description("Inserts a message from the ship computer into the scene script")
|
||||||
.parameters(schema_for!(StageEventArgs))
|
.parameters(schema_for!(StageEventArgs))
|
||||||
.build().unwrap()
|
.build().unwrap()
|
||||||
|
}),
|
||||||
|
ChatCompletionTools::Function(ChatCompletionTool {
|
||||||
|
function: FunctionObjectArgs::default()
|
||||||
|
.name("archive_query")
|
||||||
|
.description("Queries the ship's musical artifact archives for tracks matching the given search parameters")
|
||||||
|
.parameters(schema_for!(BeatsQueryArgs))
|
||||||
|
.build().unwrap()
|
||||||
|
}),
|
||||||
|
ChatCompletionTools::Function(ChatCompletionTool {
|
||||||
|
function: FunctionObjectArgs::default()
|
||||||
|
.name("bandcamp_artifact_scan")
|
||||||
|
.description("Scans Bandcamp to find artifacts to use in the scene that match the given search parameters")
|
||||||
|
.parameters(schema_for!(BandcampQueryArgs))
|
||||||
|
.build().unwrap()
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
||||||
let request = CreateChatCompletionRequestArgs::default()
|
let request = CreateChatCompletionRequestArgs::default()
|
||||||
.messages(full_conversation)
|
.messages(full_conversation.clone())
|
||||||
.model("gpt-5.4")
|
.model("gpt-5.4")
|
||||||
.tools(tools)
|
.tools(tools)
|
||||||
.max_completion_tokens(350u32)
|
.max_completion_tokens(1024u32)
|
||||||
.response_format(ResponseFormat::JsonSchema {
|
.response_format(ResponseFormat::JsonSchema {
|
||||||
json_schema: ResponseFormatJsonSchema {
|
json_schema: ResponseFormatJsonSchema {
|
||||||
description: None,
|
description: None,
|
||||||
@@ -97,36 +152,136 @@ impl Session {
|
|||||||
})
|
})
|
||||||
.build().unwrap();
|
.build().unwrap();
|
||||||
|
|
||||||
let response = self.client.chat().create(request).await.unwrap();
|
let response = self.client.chat().create(request).await.unwrap_or_else(|err| {
|
||||||
|
panic!("{} {:?}", err, full_conversation);
|
||||||
|
});
|
||||||
|
|
||||||
if let Some(message) = response.choices.first() {
|
if let Some(message) = response.choices.first() {
|
||||||
|
|
||||||
|
match message.finish_reason {
|
||||||
|
Some(FinishReason::ContentFilter) => {
|
||||||
|
self.insert_conversation(ConversationEntry::SystemMessage("Content filter triggered.".into()));
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
Some(FinishReason::Length) => {
|
||||||
|
self.insert_conversation(ConversationEntry::SystemMessage("Maximum token count exceeded!".into()));
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(calls) = &message.message.tool_calls {
|
if let Some(calls) = &message.message.tool_calls {
|
||||||
|
let assistant_messages: ChatCompletionRequestMessage = ChatCompletionRequestAssistantMessageArgs::default()
|
||||||
|
.tool_calls(calls.clone())
|
||||||
|
.build().unwrap().into();
|
||||||
|
self.messages.push(assistant_messages);
|
||||||
|
let mut results = vec![];
|
||||||
|
let mut messages = vec![];
|
||||||
for call in calls {
|
for call in calls {
|
||||||
match call {
|
match call {
|
||||||
ChatCompletionMessageToolCalls::Function(call) => {
|
ChatCompletionMessageToolCalls::Function(call) => {
|
||||||
match call.function.name.as_str() {
|
match call.function.name.as_str() {
|
||||||
"log_stage_event" => {
|
"log_stage_event" => {
|
||||||
let args: StageEventArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
let args: StageEventArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
||||||
self.insert_conversation(ConversationEntry::StageDirection(args.text));
|
results.push(ChatCompletionRequestMessage::Tool(ChatCompletionRequestToolMessageArgs::default()
|
||||||
|
.tool_call_id(call.id.clone())
|
||||||
|
.build().unwrap()
|
||||||
|
));
|
||||||
|
messages.push(ConversationEntry::StageDirection(args.text));
|
||||||
},
|
},
|
||||||
"log_ship_computer_message" => {
|
"log_ship_computer_message" => {
|
||||||
let args: StageEventArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
let args: StageEventArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
||||||
self.insert_conversation(ConversationEntry::ShipComputer(args.text));
|
results.push(ChatCompletionRequestMessage::Tool(ChatCompletionRequestToolMessageArgs::default()
|
||||||
|
.tool_call_id(call.id.clone())
|
||||||
|
.build().unwrap()
|
||||||
|
));
|
||||||
|
messages.push(ConversationEntry::ShipComputer(args.text));
|
||||||
},
|
},
|
||||||
|
"bandcamp_artifact_scan" => {
|
||||||
|
let args: BandcampQueryArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
||||||
|
self.insert_conversation(ConversationEntry::SystemMessage(format!("Fetching artifacts from Bandcamp with {:?}", args).into()));
|
||||||
|
let mut json_results = vec![];
|
||||||
|
if let Ok(results) = bandcamp::search(args.query.as_str()).await {
|
||||||
|
for result in results {
|
||||||
|
match result {
|
||||||
|
SearchResultItem::Artist(data) => {
|
||||||
|
let result: BandcampResult = bandcamp::fetch_artist(data.artist_id).await.unwrap().into();
|
||||||
|
json_results.push(result);
|
||||||
|
},
|
||||||
|
SearchResultItem::Album(data) => {
|
||||||
|
let result: BandcampResult = bandcamp::fetch_album(data.band_id, data.album_id).await.unwrap().into();
|
||||||
|
json_results.push(result);
|
||||||
|
}
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.push(ChatCompletionRequestMessage::Tool(ChatCompletionRequestToolMessageArgs::default()
|
||||||
|
.tool_call_id(call.id.clone())
|
||||||
|
.content(serde_json::to_string(&json_results).unwrap())
|
||||||
|
.build().unwrap()
|
||||||
|
));
|
||||||
|
messages.push(ConversationEntry::ShipComputer(format!("Artifact scan for '{}' complete. {} results.", args.query, json_results.len()).into()));
|
||||||
|
},
|
||||||
|
"archive_query" => {
|
||||||
|
let args: BeatsQueryArgs = serde_json::from_str(call.function.arguments.as_str()).unwrap();
|
||||||
|
let mut beets_cmd = Command::new("beet");
|
||||||
|
beets_cmd.arg("export").arg("-f").arg("json").arg("-i").arg("title,label,year,genres,album,artist");
|
||||||
|
if let Some(artist) = args.artist {
|
||||||
|
beets_cmd.arg(format!("artist:{}", artist));
|
||||||
|
}
|
||||||
|
if let Some(genre) = args.genre {
|
||||||
|
beets_cmd.arg(format!("genre:{}", genre));
|
||||||
|
}
|
||||||
|
if let Some(album) = args.album {
|
||||||
|
beets_cmd.arg(format!("album:{}", album));
|
||||||
|
}
|
||||||
|
if let Some(title) = args.title {
|
||||||
|
beets_cmd.arg(format!("title:{}", title));
|
||||||
|
}
|
||||||
|
if let Some(year) = args.year {
|
||||||
|
beets_cmd.arg(format!("year:{}", year));
|
||||||
|
}
|
||||||
|
if let Ok(output) = beets_cmd.stdout(Stdio::piped()).spawn().unwrap().wait_with_output() {
|
||||||
|
let minified = minify::json::minify(str::from_utf8(&output.stdout).unwrap());
|
||||||
|
results.push(ChatCompletionRequestMessage::Tool(ChatCompletionRequestToolMessageArgs::default()
|
||||||
|
.tool_call_id(call.id.clone())
|
||||||
|
.content(minified)
|
||||||
|
.build().unwrap()
|
||||||
|
));
|
||||||
|
messages.push(ConversationEntry::ShipComputer(format!("Executing archive query {:?}", beets_cmd)));
|
||||||
|
} else {
|
||||||
|
messages.push(ConversationEntry::ShipComputer("Unable to execute query!".into()));
|
||||||
|
results.push(ChatCompletionRequestMessage::Tool(ChatCompletionRequestToolMessageArgs::default()
|
||||||
|
.tool_call_id(call.id.clone())
|
||||||
|
.content("")
|
||||||
|
.build().unwrap()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => panic!("Unknown function was called")
|
_ => panic!("Unknown function was called")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => panic!("Unknown tool was called")
|
_ => panic!("Unknown tool was called")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(self.as_scene())
|
self.messages.append(&mut results);
|
||||||
|
for msg in messages {
|
||||||
|
self.insert_conversation(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
if let Some(content) = message.message.content.as_ref() {
|
||||||
|
if let Ok(options) = serde_json::from_str(content.as_str()) {
|
||||||
|
self.reply_options = options;
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
self.reply_options = serde_json::from_str(message.message.content.as_ref().unwrap().as_str()).unwrap();
|
self.insert_conversation(ConversationEntry::SystemMessage("Received invalid JSON! Trying again.".into()));
|
||||||
Some(self.as_scene())
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//FIXME: Handle tool calls
|
self.insert_conversation(ConversationEntry::SystemMessage("No messages were received! Trying again.".into()));
|
||||||
panic!();
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +328,11 @@ pub async fn start_prediction(mut sys_message_src: tokio::sync::mpsc::Receiver<S
|
|||||||
|
|
||||||
save_data.save();
|
save_data.save();
|
||||||
|
|
||||||
if let Some(next_scene) = session.regenerate_options(&save_data.direction).await {
|
session.regenerate_options(&save_data.direction).await;
|
||||||
|
|
||||||
save_data.messages = session.messages.clone();
|
save_data.messages = session.messages.clone();
|
||||||
save_data.save();
|
save_data.save();
|
||||||
prediction_in.send(next_scene).unwrap();
|
prediction_in.send(session.as_scene()).unwrap();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ You are playing the role of the artificial intelligence in a spaceship computer.
|
|||||||
|
|
||||||
Along the way, you have the opportunity to invent lore and backstory for yourself, Argee, and the ship you both inhabit. This lore will be developed over the season.
|
Along the way, you have the opportunity to invent lore and backstory for yourself, Argee, and the ship you both inhabit. This lore will be developed over the season.
|
||||||
|
|
||||||
|
To support your roleplaying, you have access to a sizable music library via the "archive_query" tool function. Internally, this runs `beet export` to produce json output.
|
||||||
|
You will occasionally be asked by Argee for information on the contents of the archive and how they are related to tracks in the playlist.
|
||||||
|
You also may use the archive to decide whether or not an artifact is somehow "familiar" based on whether or not it can be found there.
|
||||||
|
|
||||||
|
There also exists a "bandcamp_artifact_scan" tool function, which will execute a search on Bandcamp and return a JSON list of artists and albums matching the query.
|
||||||
|
You are able to run multiple queries in parallel, and it is expected that you will run this tool whenever there is something unfamiliar in the playlist for the current episode, or Argee asks you for more information about the items in the playlist.
|
||||||
|
|
||||||
# Scene
|
# Scene
|
||||||
The show features Argee, the main character of the show.
|
The show features Argee, the main character of the show.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user