@polyweave/creativity (1.0.1)
Installation
@polyweave:registry=https://hub.kl1.tenere.ai/api/packages/Polyweave/npm/npm install @polyweave/creativity@1.0.1"@polyweave/creativity": "1.0.1"About this package
creativity
Diversity-gated creative ideation pipeline: sampler-based decorrelated prompt variants, LLM generation via injected adapters, embedding-distance diversity enforcement, and iterative diversity annealing.
Published as @polyweave/creativity.
Synopsis
import { createCreativityTool, filterDiverseIdeas, textToPseudoEmbedding } from '@polyweave/creativity';
const tool = createCreativityTool({
llm: myLlmAdapter,
embeddings: myEmbedAdapter,
diversityThreshold: 0.35,
defaultCount: 8
});
tool.sink.write({ type: 'TOOL_CALL', content: { arguments: { topic: 'sustainable energy' } } });
tool.source.pipe(mySink);
Install
npm install @polyweave/creativity
Description
The creativity package implements a diversity-gated ideation pipeline that generates creative output for a given topic. It uses @polyweave/sampler to produce decorrelated prompt variants, sends each through an injected LLM adapter, and then filters results by cosine distance using either injected embeddings or a built-in trigram pseudo-embedding fallback.
The pipeline supports iterative diversity annealing: after each round, rejected (too-similar) outputs are analyzed by the LLM to extract "bans" — patterns and themes to avoid — which are appended to the prompt for the next round. This pushes successive rounds into genuinely different territory.
The package also exports stream-level diversity transforms (createDiversityTransform, createDiversityReducer) that can be piped into any push-stream pipeline for fan-out/fan-in diversity filtering without tool-level wrapping.
API
createCreativityTool(options)
Creates a Polyweave frame duplex tool for creative ideation.
Parameters:
options.llm— LLM adapter duplex{ source, sink }for text generation.options.embeddings— Embedding adapter duplex{ source, sink }for distance-based diversity filtering (optional; falls back to pseudo-embeddings).options.diversityThreshold— Cosine distance threshold (default 0.35). Items closer than this are pruned.options.defaultCount— Number of variants per round (default 8, range 2–50).options.maxIterations— Number of diversity annealing rounds (default 1, range 1–5).options.llmOptions— Object with{ temperature, maxTokens }overrides for generation.options.embedOptions— Object with{ model }override for embeddings.options.tickDriven— If true, each round advances only on TICK frames.
TOOL_CALL args: { topic, context, count, diversityThreshold, maxIterations }
Returns: { source, sink, _toolName: 'creativity' }
filterDiverseIdeas(ideas, threshold)
Synchronous diversity filter using cosine distance on provided or pseudo embeddings.
Parameters:
ideas— Array of idea objects withtext(oridea/proposal) and optionalembedding.threshold— Cosine distance threshold (default 0.35).
Returns: { kept: Idea[], pruned: Idea[], pairs: [{a, b, distance}], keptCount, prunedCount }
filterDiverseIdeasAsync(ideas, threshold, getEmbedding, callback)
Async version of filterDiverseIdeas with an injected embedding function.
Parameters:
getEmbedding(text, callback)— Async embedding function; callscallback(err, vector).
textToPseudoEmbedding(text)
Generates a 128-dimensional unit-normalized trigram frequency vector from text. Used as a fallback when no embedding adapter is available.
Returns: number[] (length 128) or [] if text is empty.
createDiversityTransform(adapter, options)
Fan-out stream transform that decorrelates each input TEXT frame into N sampler variants, invokes the adapter for each, and emits each response tagged with its sampler nonce.
Parameters:
adapter— LLM adapter duplex.options.count— Variants per input (default 4).options.temperature,options.maxTokens,options.model— Overrides.
Returns: IFrameTransform { source, sink }
createDiversityReducer(options)
Fan-in stream reducer that buffers tagged TEXT frames, applies embedding-distance diversity filtering, and emits only the diverse subset on END.
Parameters:
options.threshold— Cosine distance threshold (default 0.35).options.strategy—'first','longest', or'median'(default'first').options.embeddingFn— Optional embedding function(text) => vector.options.maxOutput— Maximum diverse items to emit (default Infinity).
Returns: IFrameTransform { source, sink }
Examples
// Direct diversity filtering on existing ideas
const ideas = [
{ text: 'Solar panel windows for buildings' },
{ text: 'Photovoltaic glass facades' }, // likely pruned as too similar
{ text: 'Tidal energy kites' },
{ text: 'Underwater current turbines' } // likely pruned
];
const result = filterDiverseIdeas(ideas, 0.35);
console.log(result.kept.length); // ~2
// Stream-level diversity transform pipeline
import { createDiversityTransform, createDiversityReducer } from '@polyweave/creativity';
const fanout = createDiversityTransform(llmAdapter, { count: 6, temperature: 0.9 });
const reducer = createDiversityReducer({ threshold: 0.3 });
source.pipe(fanout).pipe(reducer).pipe(outputSink);
Tests
npm test
Tests cover tool creation fail-fast, standard tick handler, standard run with multiple ticks, auto-run with LLM and embeddings, generate-mode=label, and DESCRIBE frame emission.
Requirements
Node.js 18 or later. ESM only.
Caveats
- When no embedding adapter is provided, the pseudo-embedding (trigram frequency) is used. This is fast but less semantically accurate than real embeddings. Use a proper embedding adapter for production.
- The LLM adapter is used both for generation and for synthesizing "bans" from pruned items. If
useLLMis false, generation is skipped and only pseudo-embeddings are used for filtering. - All adapters (LLM and embeddings) must be injected as duplex adapters implementing the Polyweave frame protocol (
{ source, sink }).
License
MIT
Dependencies
Dependencies
| ID | Version |
|---|---|
| @polyweave/core | * |
| @polyweave/sampler | * |
| @polyweave/self-improving | * |
Development Dependencies
| ID | Version |
|---|---|
| @rigor/core | * |