76 lines
3.1 KiB
Rust
76 lines
3.1 KiB
Rust
use async_openai::types::chat::*;
|
|
use chrono::Duration;
|
|
use crossterm::event::MediaKeyCode::Play;
|
|
use schemars::schema_for;
|
|
use serde::{Deserialize, Serialize};
|
|
use serde_json::Value;
|
|
use sqlite::OpenFlags;
|
|
|
|
use crate::GeneratedResponses;
|
|
|
|
const SYSTEM_PROMPT: &str = include_str!("system-prompt.txt");
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
pub enum ConversationEntry {
|
|
User(String),
|
|
Eva(String),
|
|
ShipComputer(String),
|
|
StageDirection(String),
|
|
SystemMessage(String)
|
|
}
|
|
|
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
|
pub struct StageDirection {
|
|
pub episode_number: u32,
|
|
pub time_remaining: Duration,
|
|
pub narrative: String,
|
|
pub artifacts: Vec<String>,
|
|
pub current_playlist: Vec<PlaylistEntry>
|
|
}
|
|
|
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
|
pub struct PlaylistEntry {
|
|
pub artist: String,
|
|
pub album: String,
|
|
pub title: String,
|
|
pub bpm: f64
|
|
}
|
|
|
|
|
|
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
|
pub struct Scene {
|
|
pub conversation: Vec<ConversationEntry>,
|
|
pub direction: StageDirection
|
|
}
|
|
|
|
impl Scene {
|
|
pub fn insert_conversation(&mut self, entry: ConversationEntry) {
|
|
self.conversation.push(entry);
|
|
}
|
|
}
|
|
|
|
impl Into<CreateChatCompletionRequest> for Scene {
|
|
fn into(self) -> CreateChatCompletionRequest {
|
|
let mut messages = vec![
|
|
ChatCompletionRequestMessage::System(ChatCompletionRequestSystemMessage { content: SYSTEM_PROMPT.into(), ..Default::default()}),
|
|
ChatCompletionRequestMessage::System(ChatCompletionRequestSystemMessage { content: serde_json::to_string(&self.direction).unwrap().into(), ..Default::default()}),
|
|
];
|
|
messages.extend(self.conversation.into_iter().filter(|x| if let ConversationEntry::SystemMessage(_) = x { false } else { true }).map(|entry| {
|
|
match entry {
|
|
ConversationEntry::User(text) => ChatCompletionRequestMessage::User(ChatCompletionRequestUserMessage { content: text.into(), ..Default::default()}),
|
|
ConversationEntry::Eva(text) => ChatCompletionRequestMessage::Assistant(ChatCompletionRequestAssistantMessage { content: Some(text.into()), ..Default::default()}),
|
|
ConversationEntry::ShipComputer(text) => ChatCompletionRequestMessage::System(ChatCompletionRequestSystemMessage { content: text.into(), name: Some("ship-computer".into()), ..Default::default() }),
|
|
ConversationEntry::StageDirection(text) => ChatCompletionRequestMessage::System(ChatCompletionRequestSystemMessage { content: text.into(), name: Some("stage-direction".into()), ..Default::default() }),
|
|
ConversationEntry::SystemMessage(_) => unreachable!()
|
|
}
|
|
}));
|
|
let response_schema: Value = schema_for!(GeneratedResponses).into();
|
|
CreateChatCompletionRequest {
|
|
model: "gpt-5.4".into(),
|
|
messages: messages,
|
|
max_completion_tokens: Some(350),
|
|
response_format: Some(ResponseFormat::JsonSchema { json_schema: ResponseFormatJsonSchema { description: None, name: "responses".into(), schema: response_schema, strict: None } }),
|
|
..Default::default()
|
|
}
|
|
}
|
|
} |