mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
feat(personality) introduce model_personality config (#9459)
## Summary Introduces the concept of a config model_personality. I would consider this an MVP for testing out the feature. There are a number of follow-ups to this PR: - More sophisticated templating with validation - In-product experience to manage this ## Testing - [x] Testing locally
This commit is contained in:
committed by
GitHub
Unverified
parent
46a4a03083
commit
714151eb4e
@@ -1,4 +1,5 @@
|
||||
use crate::client_common::tools::ToolSpec;
|
||||
use crate::config::types::Personality;
|
||||
use crate::error::Result;
|
||||
pub use codex_api::common::ResponseEvent;
|
||||
use codex_protocol::models::BaseInstructions;
|
||||
@@ -35,6 +36,9 @@ pub struct Prompt {
|
||||
|
||||
pub base_instructions: BaseInstructions,
|
||||
|
||||
/// Optionally specify the personality of the model.
|
||||
pub personality: Option<Personality>,
|
||||
|
||||
/// Optional the output schema for the model's response.
|
||||
pub output_schema: Option<Value>,
|
||||
}
|
||||
|
||||
@@ -2974,6 +2974,7 @@ async fn run_sampling_request(
|
||||
tools: router.specs(),
|
||||
parallel_tool_calls: model_supports_parallel,
|
||||
base_instructions,
|
||||
personality: None,
|
||||
output_schema: turn_context.final_output_json_schema.clone(),
|
||||
};
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ async fn run_remote_compact_task_inner_impl(
|
||||
tools: vec![],
|
||||
parallel_tool_calls: false,
|
||||
base_instructions: sess.get_base_instructions().await,
|
||||
personality: None,
|
||||
output_schema: None,
|
||||
};
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use crate::config::types::Notifications;
|
||||
use crate::config::types::OtelConfig;
|
||||
use crate::config::types::OtelConfigToml;
|
||||
use crate::config::types::OtelExporterKind;
|
||||
use crate::config::types::Personality;
|
||||
use crate::config::types::SandboxWorkspaceWrite;
|
||||
use crate::config::types::ScrollInputMode;
|
||||
use crate::config::types::ShellEnvironmentPolicy;
|
||||
@@ -127,6 +128,9 @@ pub struct Config {
|
||||
/// Info needed to make an API request to the model.
|
||||
pub model_provider: ModelProviderInfo,
|
||||
|
||||
/// Optionally specify the personality of the model
|
||||
pub model_personality: Option<Personality>,
|
||||
|
||||
/// Approval policy for executing commands.
|
||||
pub approval_policy: Constrained<AskForApproval>,
|
||||
|
||||
@@ -890,6 +894,10 @@ pub struct ConfigToml {
|
||||
/// Override to force-enable reasoning summaries for the configured model.
|
||||
pub model_supports_reasoning_summaries: Option<bool>,
|
||||
|
||||
/// EXPERIMENTAL
|
||||
/// Optionally specify a personality for the model
|
||||
pub model_personality: Option<Personality>,
|
||||
|
||||
/// Base URL for requests to ChatGPT (as opposed to the OpenAI API).
|
||||
pub chatgpt_base_url: Option<String>,
|
||||
|
||||
@@ -1474,6 +1482,7 @@ impl Config {
|
||||
notify: cfg.notify,
|
||||
user_instructions,
|
||||
base_instructions,
|
||||
model_personality: config_profile.model_personality.or(cfg.model_personality),
|
||||
developer_instructions,
|
||||
compact_prompt,
|
||||
// The config.toml omits "_mode" because it's a config file. However, "_mode"
|
||||
@@ -3605,6 +3614,7 @@ model_verbosity = "high"
|
||||
model_reasoning_summary: ReasoningSummary::Detailed,
|
||||
model_supports_reasoning_summaries: None,
|
||||
model_verbosity: None,
|
||||
model_personality: None,
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
@@ -3692,6 +3702,7 @@ model_verbosity = "high"
|
||||
model_reasoning_summary: ReasoningSummary::default(),
|
||||
model_supports_reasoning_summaries: None,
|
||||
model_verbosity: None,
|
||||
model_personality: None,
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
@@ -3794,6 +3805,7 @@ model_verbosity = "high"
|
||||
model_reasoning_summary: ReasoningSummary::default(),
|
||||
model_supports_reasoning_summaries: None,
|
||||
model_verbosity: None,
|
||||
model_personality: None,
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
@@ -3882,6 +3894,7 @@ model_verbosity = "high"
|
||||
model_reasoning_summary: ReasoningSummary::Detailed,
|
||||
model_supports_reasoning_summaries: None,
|
||||
model_verbosity: Some(Verbosity::High),
|
||||
model_personality: None,
|
||||
chatgpt_base_url: "https://chatgpt.com/backend-api/".to_string(),
|
||||
base_instructions: None,
|
||||
developer_instructions: None,
|
||||
|
||||
@@ -3,6 +3,7 @@ use schemars::JsonSchema;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
|
||||
use crate::config::types::Personality;
|
||||
use crate::protocol::AskForApproval;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
@@ -24,6 +25,7 @@ pub struct ConfigProfile {
|
||||
pub model_reasoning_effort: Option<ReasoningEffort>,
|
||||
pub model_reasoning_summary: Option<ReasoningSummary>,
|
||||
pub model_verbosity: Option<Verbosity>,
|
||||
pub model_personality: Option<Personality>,
|
||||
pub chatgpt_base_url: Option<String>,
|
||||
pub experimental_instructions_file: Option<AbsolutePathBuf>,
|
||||
pub experimental_compact_prompt_file: Option<AbsolutePathBuf>,
|
||||
|
||||
@@ -748,6 +748,14 @@ impl Default for ShellEnvironmentPolicy {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize, JsonSchema)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub enum Personality {
|
||||
Friendly,
|
||||
#[default]
|
||||
Pragmatic,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -9,6 +9,7 @@ use codex_protocol::openai_models::TruncationMode;
|
||||
use codex_protocol::openai_models::TruncationPolicyConfig;
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::config::types::Personality;
|
||||
use crate::truncate::approx_bytes_for_tokens;
|
||||
use tracing::warn;
|
||||
|
||||
@@ -88,6 +89,20 @@ pub(crate) fn with_config_overrides(mut model: ModelInfo, config: &Config) -> Mo
|
||||
}
|
||||
if let Some(base_instructions) = &config.base_instructions {
|
||||
model.base_instructions = base_instructions.clone();
|
||||
} else if model.slug.contains("gpt-5.2-codex")
|
||||
&& let Some(personality) = &config.model_personality
|
||||
{
|
||||
let template = include_str!(
|
||||
"../../templates/model_instructions/gpt-5.2-codex_instructions_template.md"
|
||||
);
|
||||
let personality_message = match personality {
|
||||
Personality::Friendly => include_str!("../../templates/personalities/friendly.md"),
|
||||
Personality::Pragmatic => {
|
||||
include_str!("../../templates/personalities/pragmatic.md")
|
||||
}
|
||||
};
|
||||
let instructions = template.replace("{{ personality_message }}", personality_message);
|
||||
model.base_instructions = instructions;
|
||||
}
|
||||
model
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user