Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/agents/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod optimizer;
45 changes: 45 additions & 0 deletions src/agents/optimizer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use crate::error::{Result, ScribeError, map_provider_error};
use crate::types::{Artifact, Intent, MODEL};
use crate::tools::{deconstructor::Deconstructor, prompt_reviewer::PromptReviewer, web_searcher::WebSearcher};
use crate::utilities::require_env;
use rig::providers::gemini::Client;
use rig::prelude::*;
use rig::completion::Prompt;

pub async fn optimizer(prompt: Intent) -> Result<Artifact> {
require_env("GEMINI_API_KEY")?;
let client = Client::new(require_env("GEMINI_API_KEY")?)?;
let system_prompt_json = include_str!("../../data/optimizer.json");
let artifact: Artifact = serde_json::from_str(system_prompt_json)
.map_err(|e| ScribeError::Validation(format!("Failed to parse embedded optimizer.json: {}", e)))?;
let system_prompt = artifact.system_prompt;

let prompt_officer = client
.agent(MODEL)
.preamble(system_prompt.as_str())
.tool(Deconstructor)
.tool(PromptReviewer)
.tool(WebSearcher)
.build();

let input = format!(
"Follow this workflow to optimize the prompt:
1. Use the Deconstructor tool to analyze the goal and constraints of: '{}'
2. Use the PromptReviewer to check and refine the draft.
3. Use the WebSearcher to find the best practice related task/goal.
4. Finally, provide the optimized system prompt.

Constraint: The final output must be the system prompt only, but you MUST use your tools first to arrive at that result.",
prompt.text
);
let optimized_prompt = prompt_officer
.prompt(input)
.await
.map_err(map_provider_error)?;
let artifact = Artifact {
system_prompt: optimized_prompt,
signed_by: "".to_string(),
};

Ok(artifact)
}
3 changes: 3 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pub enum ScribeError {

#[error("Extraction failed: {0}")]
Extraction(#[from] rig::extractor::ExtractionError),

#[error("Client error: {0}")]
ClientError(#[from] rig::http_client::Error),
}

pub fn map_provider_error(e: rig::completion::PromptError) -> ScribeError {
Expand Down
5 changes: 3 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
mod error;
pub mod pipline;
pub mod agents;
pub mod tools;
mod types;
pub mod utilities;

use std::path::PathBuf;

pub use error::{Result, ScribeError};
use pipline::optimizer;
use agents::optimizer::optimizer;

pub use types::{Artifact, Intent, ScopeId, Specification};

Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ async fn main() -> Result<()> {
// create caching path
let cache_path = PathBuf::from("./.prompts_perssitense_cache");
let scribe = RigScribe::new(cache_path);
let id = ScopeId(2028);
let id = ScopeId(2031);
// Input: The raw, often vague user intent.
let raw_prompt = "write a python fonction";
eprintln!("\n\nOptimizing ...\n\n");
Expand Down
168 changes: 0 additions & 168 deletions src/pipline.rs

This file was deleted.

52 changes: 52 additions & 0 deletions src/tools/deconstructor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
use crate::types::{Intent, Specification, MODEL};
use crate::error::{Result, ScribeError};
use crate::utilities::require_env;
use rig::completion::ToolDefinition;
use rig::tool::Tool;
use rig::providers::gemini::Client;
use serde::{Deserialize, Serialize};
use rig::completion::Prompt;
use rig::client::ProviderClient;
use rig::prelude::*; // Needed for .prompt() method

#[derive(Serialize, Deserialize)]
pub struct Deconstructor;

impl Tool for Deconstructor {
const NAME: &'static str = "Deconstructor";

type Error = ScribeError;
type Args = Intent;
type Output = Specification;

async fn definition(&self, _prompt: String) -> ToolDefinition {
let schema = schemars::schema_for!(Intent);
let parameters = serde_json::to_value(schema).unwrap();
ToolDefinition {
name: "Deconstructor".to_string(),
description: "this tools take a raw prompte and give back it Specification include goal and constrian".to_string(),
parameters: parameters,
}
}

async fn call(&self, args: Self::Args) -> Result<Self::Output> {
println!("[Tool Calling]-> Deconstructor!");
require_env("GEMINI_API_KEY")?;
let client = Client::from_env();
let architect = client
.agent(MODEL)
.preamble(
"
Role: Senior Solution Architect\n\
Task: Extract constraints and risks and main goal of given request\n\
Output: A short bullet list, no prose
",
)
.build();
let repons = architect.prompt(args.text.clone()).await?;
let spec_extractor = client.extractor::<Specification>(MODEL).build();
let spec = spec_extractor.extract(repons).await;

Ok(spec?)
}
}
3 changes: 3 additions & 0 deletions src/tools/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod deconstructor;
pub mod prompt_reviewer;
pub mod web_searcher;
60 changes: 60 additions & 0 deletions src/tools/prompt_reviewer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::types::{Intent, Specification, Artifact, MODEL};
use crate::error::{Result, ScribeError};
use crate::utilities::require_env;
use rig::completion::ToolDefinition;
use rig::tool::Tool;
use rig::providers::gemini::Client;
use serde::{Deserialize, Serialize};
use schemars::JsonSchema;
use rig::completion::Prompt;
use rig::client::ProviderClient;
use rig::prelude::*;

#[derive(Deserialize, Debug, Clone, Serialize, JsonSchema)]
pub struct PromptReviewerArgs {
intent: Intent,
spec: Specification,
}

#[derive(Serialize, Deserialize)]
pub struct PromptReviewer;

impl Tool for PromptReviewer {
const NAME: &'static str = "PromptReviewer";

type Error = ScribeError;
type Args = PromptReviewerArgs;
type Output = Artifact;

async fn definition(&self, _prompt: String) -> ToolDefinition {
let schema = schemars::schema_for!(PromptReviewerArgs);
let parameters = serde_json::to_value(schema).unwrap();
ToolDefinition {
name: "PromptReviewer".to_string(),
description: "this tools take a raw prompte it will evelaute that given promte wiuth its Specification include goal and constrian".to_string(),
parameters,
}
}

async fn call(&self, args: Self::Args) -> Result<Self::Output> {
println!("[Tool Calling]-> PromptReviewer!");
require_env("GEMINI_API_KEY")?;
let client = Client::from_env();
let system_prompt_json = include_str!("../../data/prompt_officer.json");
let artifact: Artifact = serde_json::from_str(system_prompt_json)
.map_err(|e| ScribeError::Validation(format!("Failed to parse embedded prompt_officer.json: {}", e)))?;
let system_prompt = artifact.system_prompt;
let prompt_reviewer = client.agent(MODEL).preamble(system_prompt.as_str()).build();
let input = format!("
Critisize following prompt base on given property:
Goal:\n{}\n\nConstraints:\n{}\n\nDraft:\n{}\n\n\
Instruction: Be highly cretical and persimiste and find every defit or any point which could be better. and use all best practice and if needed use websearch. \n",
args.spec.goal, args.spec.constraints, args.intent.text);

let repons = prompt_reviewer.prompt(input).await?;
let artifact_extractor = client.extractor::<Artifact>(MODEL).build();
let artifact = artifact_extractor.extract(repons).await;

Ok(artifact?)
}
}
Loading