use langchainrust::{
PromptTemplate,
FewShotPromptTemplate, ExampleSelector, LengthBasedExampleSelector,
};
use std::collections::HashMap;
fn make_example(input: &str, output: &str) -> HashMap<String, String> {
let mut map = HashMap::new();
map.insert("input".to_string(), input.to_string());
map.insert("output".to_string(), output.to_string());
map
}
#[test]
fn test_few_shot_basic_format() {
let examples = vec![
make_example("苹果", "水果"),
make_example("玫瑰", "花"),
];
let example_prompt = PromptTemplate::new("输入: {input} -> 类别: {output}");
let few_shot = FewShotPromptTemplate::new(
examples,
example_prompt,
"请将以下词语分类:",
"输入: {input} ->",
vec!["input".to_string()],
);
let mut vars = HashMap::new();
vars.insert("input", "太阳");
let result = few_shot.format(&vars).unwrap();
assert!(result.contains("请将以下词语分类"), "应包含前缀");
assert!(result.contains("苹果"), "应包含示例 1 的输入");
assert!(result.contains("水果"), "应包含示例 1 的输出");
assert!(result.contains("玫瑰"), "应包含示例 2 的输入");
assert!(result.contains("花"), "应包含示例 2 的输出");
assert!(result.contains("太阳"), "应包含用户输入");
}
#[test]
fn test_few_shot_missing_variable() {
let few_shot = FewShotPromptTemplate::new(
vec![],
PromptTemplate::new("{input} -> {output}"),
"",
"输入: {input}",
vec!["input".to_string(), "missing".to_string()],
);
let mut vars = HashMap::new();
vars.insert("input", "test");
let result = few_shot.format(&vars);
assert!(result.is_err());
assert!(result.unwrap_err().contains("missing"),
"应提示缺少的变量名");
}
#[test]
fn test_few_shot_empty_examples() {
let few_shot = FewShotPromptTemplate::new(
vec![],
PromptTemplate::new("{input} -> {output}"),
"Prefix",
"User: {input}",
vec!["input".to_string()],
);
let mut vars = HashMap::new();
vars.insert("input", "hello");
let result = few_shot.format(&vars).unwrap();
assert_eq!(result, "Prefix\n\nUser: hello");
}
#[test]
fn test_few_shot_custom_separator() {
let examples = vec![
make_example("a", "1"),
make_example("b", "2"),
make_example("c", "3"),
];
let few_shot = FewShotPromptTemplate::new(
examples,
PromptTemplate::new("{input}={output}"),
"",
"",
vec![],
).with_example_separator(" | ");
let vars = HashMap::new();
let result = few_shot.format(&vars).unwrap();
assert_eq!(result, "a=1 | b=2 | c=3");
}
#[test]
fn test_few_shot_add_example() {
let mut few_shot = FewShotPromptTemplate::new(
vec![make_example("old", "value")],
PromptTemplate::new("{input}={output}"),
"",
"",
vec![],
);
assert_eq!(few_shot.examples().len(), 1);
few_shot.add_example(make_example("new", "value2"));
assert_eq!(few_shot.examples().len(), 2);
let result = few_shot.format(&HashMap::new()).unwrap();
assert!(result.contains("old=value"));
assert!(result.contains("new=value2"));
}
#[test]
fn test_length_based_selector_new() {
let examples = vec![
make_example("a", "1"),
make_example("b", "2"),
];
let selector = LengthBasedExampleSelector::new(examples);
assert_eq!(selector.examples().len(), 2);
}
#[test]
fn test_length_based_selector_add() {
let mut selector = LengthBasedExampleSelector::new(vec![]);
assert!(selector.select_examples(&HashMap::new()).is_empty());
selector.add_example(make_example("x", "y"));
assert_eq!(selector.examples().len(), 1);
}
#[test]
fn test_few_shot_with_selector() {
let examples = vec![
make_example("q1", "a1"),
make_example("q2", "a2"),
];
let selector = Box::new(LengthBasedExampleSelector::new(examples.clone()));
let few_shot = FewShotPromptTemplate::new(
examples,
PromptTemplate::new("Q: {input}\nA: {output}"),
"Examples:",
"Q: {input}\nA:",
vec!["input".to_string()],
).with_example_selector(selector);
let mut vars = HashMap::new();
vars.insert("input", "my question");
let result = few_shot.format(&vars).unwrap();
assert!(result.contains("Examples:"));
assert!(result.contains("my question"));
}
#[test]
fn test_few_shot_no_input_vars() {
let few_shot = FewShotPromptTemplate::new(
vec![make_example("only", "example")],
PromptTemplate::new("{input}={output}"),
"Static prefix",
"",
vec![],
);
let vars = HashMap::new();
let result = few_shot.format(&vars).unwrap();
assert_eq!(result, "Static prefix\n\nonly=example");
}