lenzcom's picture
Upload folder using huggingface_hub
e706de2 verified
/**
* Exercise 12: Composition and Pipelines
*
* Goal: Learn to compose LLM with other Runnables
*
* In this exercise, you'll:
* 1. Create helper Runnables to work with LLM
* 2. Build a pipeline by chaining operations
* 3. Create a reusable agent pipeline
* 4. See the power of composition
*
* This is where the Runnable pattern really shines!
*/
import {HumanMessage, SystemMessage, LlamaCppLLM, Runnable} from '../../../../src/index.js';
// TODO: Part 1 - Create a PromptFormatter Runnable
// This should:
// - Take a string input (user question)
// - Return an array of messages with a system prompt and the user question
// - System prompt: "You are a helpful assistant. Be concise."
class PromptFormatter extends Runnable {
async _call(input, config) {
// Your code here
return null;
}
}
// TODO: Part 2 - Create a ResponseParser Runnable
// This should:
// - Take an AIMessage input
// - Extract and return just the content string
// - Trim whitespace
class ResponseParser extends Runnable {
async _call(input, config) {
// Your code here
return null;
}
}
// TODO: Part 3 - Create an AnswerValidator Runnable
// This should:
// - Take a string input (the parsed response)
// - Check if it's longer than 10 characters
// - If too short, return "Error: Response too short"
// - Otherwise return the original response
class AnswerValidator extends Runnable {
async _call(input, config) {
// Your code here
return null;
}
}
async function exercise4() {
console.log('=== Exercise 4: Composition and Pipelines ===\n');
const llm = new LlamaCppLLM({
modelPath: './models/Meta-Llama-3.1-8B-Instruct-Q5_K_S.gguf',
temperature: 0.7,
maxTokens: 100
});
try {
// Part 1: Test individual components
console.log('Part 1: Testing individual components');
const formatter = new PromptFormatter();
const parser = new ResponseParser();
const validator = new AnswerValidator();
// TODO: Test the formatter
console.log('Testing formatter:');
const formatted = null; // await formatter.invoke("What is AI?")
console.log(formatted);
console.log();
// TODO: Test with LLM + parser
console.log('Testing LLM + parser:');
const llmResponse = null; // await llm.invoke(formatted)
const parsed = null; // await parser.invoke(llmResponse)
console.log('Parsed:', parsed);
console.log();
// TODO: Test validator with short input
console.log('Testing validator with short input:');
const shortResult = null; // await validator.invoke("Hi")
console.log(shortResult);
console.log();
// Part 2: Build a complete pipeline
console.log('Part 2: Complete pipeline');
// TODO: Chain all components together
// formatter -> llm -> parser -> validator
const pipeline = null; // Your code here
// TODO: Test the pipeline
const result1 = null; // await pipeline.invoke("What is machine learning?")
console.log('Result:', result1);
console.log();
// Part 3: Reusable agent pipeline
console.log('Part 3: Reusable agent pipeline');
// TODO: Create different pipelines for different tasks
// Creative pipeline: high temperature, no validator
const creativePipeline = null; // Your code here
// Factual pipeline: low temperature, with validator
const factualPipeline = null; // Your code here
// TODO: Test both pipelines
console.log('Creative (temp=0.9):');
const creative = null; // await creativePipeline.invoke("Describe a sunset")
console.log(creative);
console.log();
console.log('Factual (temp=0.1):');
const factual = null; // await factualPipeline.invoke("What is the capital of France?")
console.log(factual);
console.log();
// Part 4: Batch processing with pipelines
console.log('Part 4: Batch processing with pipeline');
// TODO: Use the pipeline with batch()
const questions = [
"What is Python?",
"What is JavaScript?",
"What is Rust?"
];
const answers = null; // await pipeline.batch(questions)
// TODO: Print results
// questions.forEach((q, i) => ...)
} finally {
await llm.dispose();
}
console.log('\n✓ Exercise 4 complete!');
}
// Run the exercise
exercise4().catch(console.error);
/**
* Expected Output:
* - Part 1: Each component works independently
* - Part 2: Full pipeline processes input -> output
* - Part 3: Different pipelines for different tasks
* - Part 4: Pipeline works with batch processing
*
* Learning Points:
* 1. Runnables are composable building blocks
* 2. .pipe() chains operations together
* 3. Pipelines are themselves Runnables
* 4. Easy to create specialized pipelines
* 5. Composition makes testing and reuse easy
*/