Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

green — conjoint and preference-study CLI

Expected Parrot choosing between premium and basic birdseed options in a conjoint price tradeoff

green is an agent-first CLI for conjoint analysis and discrete-choice experiments. The agent and user define attributes (e.g. brand, price, RAM) and their levels together; green builds a choice-task design, generates EDSL fielding code that runs the study, imports results back, fits MNL / hierarchical Bayes / latent-class models, and produces part-worths, willingness-to-pay, market-share simulations, and sensitivity / grid optimization. Project state lives under .green/ as an event log; CLI output is JSON envelopes by default.

Every generated design is checked for within-task attribute variation and conditional design-matrix rank. Green blocks fielding and estimation when requested effects are unidentified, so an aliased coefficient cannot silently surface as apparent zero preference.

Open the worked conjoint tutorial

The agent's role is to act as the analyst working the conjoint problem with the user — not to demand fully-formed inputs. Most users come in with a fuzzy task ("I want to understand laptop preferences") and need to be walked through what a conjoint study actually requires. Sections Inputs and elicitation and the worked example Walking a user from a fuzzy ask to a fitted model show how.

Copy and paste into Codex or Claude Code

Set up Green and help me run an auditable conjoint study in this repository.

Install the current Green and EDSL main branches as a managed uv tool. If uv
is not installed, first run `python -m pip install --upgrade uv`:

uv tool install --upgrade --force \
  --with-executables-from "edsl @ git+https://github.com/expectedparrot/edsl.git@main" \
  "green[fielding] @ git+https://github.com/expectedparrot/green.git@main"

Verify that both command-line tools resolve from uv's managed tool directory:

uv tool dir --bin
command -v green
command -v ep
green version
ep --help

If either command resolves outside the directory printed by `uv tool dir
--bin`, do not use that older installation. Run `uv tool update-shell`, verify
again, or invoke the commands by their absolute paths in the uv tool bin
directory.

Let EDSL manage repository-local authentication. Run `ep auth status`. If
authentication is missing, run `ep auth login` and follow its login flow. Do
not log in again when an existing EDSL profile is already configured. Never
display, copy, or commit API keys. Run `ep profiles current` to inspect the
redacted configuration and `ep check` before any paid model execution.

Then run:

green guide
green next

Treat `green guide` and every action returned by `green next` as the source of
truth. Run `green next` after every completed stage. Help me turn my research
question into attributes and realistic levels instead of requiring a complete
specification up front. Preserve Green's `.green/` provenance and inspect all
generated files under `green_jobs/`.

Before external fielding, show me the plan, selected model, respondent and
prediction counts, expected outputs, runtime range, and cost risk. Do not run
the approval-gated `ep run` command until I approve it. After execution,
normalize and import the returned results using the exact commands from
`green next`, continue through quality checks and estimation, and finish with
saved decision-ready reports. Never use `--force` without my explicit approval.

When to use this

  • The user wants to measure how customers trade off multiple product attributes (brand vs. price vs. features vs. delivery time).
  • A pricing study needs willingness-to-pay per attribute, not a single absolute price.
  • A new-product simulation is needed: given a proposed configuration and a competitive set, what share does it capture?
  • The deliverable is market-share prediction for candidate concepts, possibly under price changes.
  • The user wants to avoid stated-preference noise and can field a panel that answers 8–15 choice tasks.
  • The user needs to segment respondents by preference (latent class) or recover individual-level utilities for fine-grained simulation.

When this is a stretch (and how to adapt)

If the agent has been called, the user wants this kind of analysis. The default move is to make it work. Common edge cases and adaptations:

  • Single attribute plus price. Still useful — run green with the one categorical attribute and a continuous price dimension; enable option-none and use --method full-factorial over a small price grid. The result reads as a Van Westendorp-style sensitivity curve. Don't bounce to a different tool.
  • Brand-dominated story ("Apple" carries meaning that "Dell with identical specs" cannot). Run green anyway with brand as a named categorical attribute and price + 1–2 features alongside; the brand effect will show up in the part-worths. If the user wants deeper decomposition of the brand effect, suggest pairing with a separate concept test fielded directly through EDSL.
  • Open-ended user feedback, no obvious attributes yet. Run bewley first to surface themes from the existing feedback corpus. Once a codebook emerges, attribute candidates fall out of it; come back to green with those.
  • Few attributes (1–2), short panel. MNL still works on tiny designs. Skip HB and latent-class; just MNL with full-factorial. Communicate to the user that the result is a baseline, not a high-resolution segmentation.
  • Internal / strategic decision with no respondent panel (vendor selection, location choice, project triage). This is one of the cases where pivoting really is the right call — there is nothing for green to estimate without a panel. Use mcda.

For every other shape of user request, the answer is "yes, here's how" not "no, use X."

Decision rule for the calling agent

Before dispatching to green, confirm:

  1. The user is interested in revealed preference (choice behavior), not stated importance ratings.
  2. There is some kind of respondent panel available — LLM-simulated agents (via EDSL), real humans (via Coop humanize()), or imported choice data.
  3. The product / service / proposition is decomposable into roughly 3–7 independent attributes (or can be made so by adapting, per When this is a stretch).
  4. The deliverable is a quantitative read on tradeoffs — WTP, importance, shares, sensitivity, segments — not a list of themes from open-ended feedback.

If yes (or yes-with-adaptation) on all four, green is the right method.

Inputs and elicitation

Most users will not arrive with attributes, levels, panel, and deliverable already pinned. The agent's job is to draw these out through a structured conversation. Each input below has a "How the agent elicits it" line — that's what to ask the user.

Attributes (3–7 product/service dimensions)

What it is. The set of dimensions over which respondents trade off. Typically 3–7 attributes; fewer than 3 collapses into a single-attribute study (still workable — see stretch), more than 7 strains respondent attention.

How the agent elicits this. Ask the user:

  • "What product, service, or proposition are we studying?"
  • "When customers choose one over another, what features seem to drive that choice? Try to land on 4–5 dimensions to start."

If the user offers more than 7 attributes, group or drop weakest two. If fewer than 3, probe specific axes: brand, price, a quality feature, a convenience feature, availability, support level, format, delivery time. For analogous studies suggest known starters:

  • Laptops / desktops — brand, price, RAM, screen size, weight.
  • SaaS pricing — brand, monthly cost, integration count, support tier.
  • Job offers — company, salary, remote-flexibility, role-level, equity grant.
  • Insurance plans — premium, deductible, copay, network breadth, brand.
  • Apartment rentals — rent, neighborhood, square footage, commute time, building amenities.

Default to suggest if the user is stuck: a 4-attribute starter — brand, price, one quality feature, one convenience feature. Confirm with the user before locking.

Fallback if the user genuinely can't articulate attributes: run a quick concept-elicitation pass via EDSL on existing customer feedback, or surface themes via bewley on a transcript corpus. Pull attribute candidates from the result and continue.

Levels per attribute (2–5 each)

What it is. The values each attribute can take in choice tasks.

How the agent elicits this. For each attribute, ask:

  • Categorical ("brand", "tier", "format"): "What are the 3–5 named options that matter?"
  • Continuous ("price", "weight", "battery hours"): "What range is realistic? Should we use 3 grid points or interpolate over the range?"

Push back if levels are not really comparable on the same axis ("Free vs. $1000" collapses to a binary; useful but not a 5-point continuum).

Default to suggest. For each categorical attribute: 3 levels — a clear winner, a clear loser, and a middle. For each continuous attribute: the user's expected range with 3 grid points.

Fallback. If the user names too many candidate brands or values, suggest dropping the least-distinguishing ones; if too few, suggest adding a "premium" or "budget" sentinel level to anchor the trade.

Constraints, prohibitions, and interactions (optional)

What it is. Rules that prune impossible combinations (prohibit add --when brand=Apple --when ram=4GB), monotonicity constraints (constraint add price --monotone decreasing), or expected interaction effects (interaction add brand price).

How the agent elicits this. Ask: "Are there combinations of attributes that would be obviously implausible — Apple at $300, Dell with no RAM at all? Does it matter if respondents see them?" Most users say no at first; gentle probing surfaces real constraints.

Default to suggest. Skip constraints unless an obvious one comes up. Add option-none if the choice context realistically allows "neither" (most retail does, most surveys do not).

Respondent population

What it is. Who answers the choice tasks. green supports three sources:

  • EDSL model-agents — LLM-simulated respondents (fast, cheap, noisier). Specify a model and an agent-list.
  • Coop humanize() — generate a URL the user can share with real humans (real, slow, requires recruiting).
  • External data import — pre-existing choice data in CSV/parquet.

How the agent elicits this. Ask: "Are we using LLM-simulated respondents to scope the study quickly, recruiting humans through Coop, or do you already have choice data we can import?"

Default to suggest. Start with EDSL model-agents for the first pass — cheap and fast. Once the design works, optionally upgrade to human respondents via Coop for the final read.

Fallback. If the user has neither LLM-agent infrastructure nor a panel, walk them through running a small EDSL job (an example agent list of 50 personas suffices for a pilot).

Deliverable

What it is. What the user wants out of the study. Determines which estimator and which reports.

How the agent elicits this. Ask: "Are you trying to..."

  • "...rank the importance of attributes overall?" → MNL + report importance.
  • "...measure willingness-to-pay for a specific feature?" → MNL + report wtp.
  • "...predict market share for a few candidate products?" → MNL or HB + market simulate.
  • "...find different customer segments and what each wants?" → latent-class + report segments.
  • "...screen high-value individuals for a follow-up study?" → HB for individual utilities.

Default to suggest. Start with MNL + report partworths + report importance. Almost every study wants these baseline numbers even if a richer analysis follows.

Fallback. If the user can't pick: run MNL first (cheap, fast), show them the part-worths, ask "is this enough or do you want individual-level / segment-level breakdowns?" — the artifact itself clarifies the question.

Outputs

All under .green/ (durable) or green_jobs/ (inspectable working code):

  • .green/designs/<name>/design.parquet — the choice-task design.
  • green_jobs/<name>/ — generated EDSL fielding code (inspect, dry-run, then run externally).
  • .green/data/<name>/ — imported response sets with quality reports.
  • .green/models/<name>/ — fitted MNL / HB / latent-class models with part-worths and diagnostics.
  • .green/reports/<name>/ — saved partworth, importance, WTP, and segment reports.
  • Market simulations are emitted as JSON; saved on demand.

Downstream consumers: messick can validate fitted model predictions; gutenberg can compile the analysis into a PDF report; tufte provides plot style

  • QA.

Workflow

Canonical sequence (the agent typically interleaves elicitation between each step in the early phases):

  1. green init --type generic-conjoint — create .green/ and the project. (Before this: elicit deliverable.)
  2. green dimension add / level add / prohibit add / constraint add / interaction add / reference-levels set — define the attribute space. (Before this: elicit attributes, levels, optional constraints.)
  3. green validate — confirm the conjoint definition is internally coherent.
  4. green design generate --method full-factorial — produce the choice-task design. (Before this: confirm tasks-per-respondent and alternatives-per-task with the user; defaults of 12 and 3 are reasonable.)
  5. green design codegen <design> — emit EDSL fielding code under green_jobs/<design>/. (Before this: elicit population — model, humans, or import.)
  6. Run the survey externally (python run_survey.py for LLM agents, or --humanize for a Coop URL).
  7. green data import-edsl <results-file> --design <design> --name <data> — bring results back into the project.
  8. green data quality <data> — sanity-check the import.
  9. green estimate {mnl|hb|latent-class} --data <data> --name <model> — fit a preference model. See Pick a model family below.
  10. green report partworths|importance|wtp|segments <model> — produce the deliverables.
  11. green market create / add-product / simulate / sensitivity / optimize — run share / WTP / what-if analyses if the deliverable is market shares.

If the agent loses track, run green status or green workflow phase to recover the current phase and recommended next steps.

Pick a model family (step 9)

Question Pick
Quick pooled baseline; small sample; one population? MNL
Need individual-level utilities for richer simulation? HB
Believe respondents fall into a few preference segments? latent-class
WTP and importance with minimum overhead? MNL
Reporting will lean on share-of-preference under many what-ifs? HB
Strategic question is "what kinds of customers are there?" latent-class

Start with MNL. It's cheap and produces interpretable part-worths and WTP in one shot. Upgrade to HB if simulation accuracy matters, or to latent-class if segmentation is the headline finding.

Worked examples

Walking a user from "study laptop preferences" to a fitted model

This example shows the agent doing the elicitation, then the resulting CLI. It's the typical shape of a real session.

User: "I want to figure out what makes people pick one laptop over another. Can you help me run a study?"

Agent: "Yes — green is the right tool for this. We'll set up a choice-based conjoint where respondents pick between laptop configurations and we recover what's actually driving choice. First, the attributes. A typical laptop study uses 4–5: brand, price, RAM, screen size, and weight. Does that fit, or are there features specific to your audience — battery life, GPU, port selection?"

User: "Brand, price, and battery life are the big ones for me."

Agent: "Three is workable but a little thin — choice models recover more reliable utilities with 4–5. Want me to add screen size as a fourth?"

User: "Sure, add screen size."

Agent: "Got it. Now levels. For brand, who are the candidates? I'd suggest Dell, Apple, and Lenovo as a baseline — should we add or swap?"

User: "Swap Lenovo for HP."

Agent: "Done. Price — what's the realistic range, and where are the natural breakpoints?"

User: "$800 to $2500."

Agent: "I'll use $800, $1500, $2500 as three grid points. For battery, are you thinking categorical buckets (short / medium / long) or a continuous range in hours?"

User: "Continuous, 4 to 14 hours."

Agent: "Great. Three grid points there too — 4, 9, 14 hours. Screen size — common laptops sit at 13", 15", 17"; works for you?"

User: "Yes."

Agent: "On respondents — quickest is to simulate with LLM agents through EDSL, then optionally validate against real humans through Coop later. Sound good?"

User: "Start with LLM agents."

Agent: "And the deliverable — are you mostly after which attributes matter most, willingness-to-pay for brand, predicted market shares, or all three?"

User: "Importance and WTP for brand."

Agent: "Perfect. I'll run MNL — that's the right estimator for those two outputs. Here's the sequence:"

green --project-dir ~/laptop-study init --type generic-conjoint
green --project-dir ~/laptop-study dimension add brand --type categorical
green --project-dir ~/laptop-study level add brand Dell Apple HP
green --project-dir ~/laptop-study dimension add price --type continuous \
  --range 800:2500 --unit USD --grid-count 3
green --project-dir ~/laptop-study constraint add price --monotone decreasing
green --project-dir ~/laptop-study dimension add battery --type continuous \
  --range 4:14 --unit hours --grid-count 3
green --project-dir ~/laptop-study dimension add screen --type categorical
green --project-dir ~/laptop-study level add screen 13in 15in 17in
green --project-dir ~/laptop-study validate
green --project-dir ~/laptop-study design generate --name main \
  --method full-factorial --tasks-per-respondent 12 --alternatives 3 --versions 1 --seed 42
green --project-dir ~/laptop-study design codegen main --job-name main \
  --model gpt-5.4-mini
cd ~/laptop-study/green_jobs/main && python run_survey.py
green --project-dir ~/laptop-study data import-edsl \
  green_jobs/main/results/results.json --design main --name field_run_1
green --project-dir ~/laptop-study estimate mnl \
  --data field_run_1 --name mnl_main
green --project-dir ~/laptop-study report partworths mnl_main
green --project-dir ~/laptop-study report importance mnl_main
green --project-dir ~/laptop-study report wtp mnl_main \
  --price-dimension price --attribute brand

Output: per-attribute part-worths, an importance ranking, and a brand WTP table in USD. Saved model under .green/models/mnl_main/.

Market simulation under a price change (CLI-first)

User already has a fitted model (mnl_main from the previous example or from another run). Wants to predict how Dell's market share moves as Dell's price varies from $1000 to $2000.

green --project-dir ~/laptop-study market create laptop_market
green --project-dir ~/laptop-study market add-product laptop_market dell_16 \
  brand=Dell ram=16GB price=1000
green --project-dir ~/laptop-study market add-product laptop_market apple_32 \
  brand=Apple ram=32GB price=1500
green --project-dir ~/laptop-study market simulate mnl_main \
  --market laptop_market --rule share
green --project-dir ~/laptop-study market sensitivity mnl_main \
  --market laptop_market --vary dell_16.price --range 1000:2000:250

Output: predicted shares per product, then a price-sensitivity curve for dell_16 across the swept range.

Latent-class segmentation (CLI-first)

User already knows they want segmentation. Discover preference segments and label them by a respondent trait.

green --project-dir ~/laptop-study estimate latent-class \
  --data field_run_1 --name lc_main --classes auto --covariates segment --seed 42
green --project-dir ~/laptop-study report segments lc_main --trait segment

Output: number of classes (auto-selected by BIC), per-class part-worths, and a class-by-trait summary table.

Quick command reference

For full options, run green <subcommand> --help.

Group Commands
Project init, guide, next, status, validate, version, show, log, describe, diff
Workflow guide, next (canonical); workflow phase, workflow checklist (inspection)
Definition dimension add/list/remove, level add/list/rename/remove, option none --enable/--disable, prohibit add/list/remove, constraint add/list/remove, interaction add/list/remove, reference-levels set
Agents agent-list create/list/show/clone/delete, agent add/remove
Design + fielding design generate/inspect/validate/codegen/delete, plan field, simulate stub
Data data import, data import-edsl, data quality (blocking gate), data export, data delete
Estimation plan estimate, estimate mnl/hb/latent-class/diagnose/delete (--missing-choice-policy drop-task is explicit)
Reports report partworths/importance/wtp/segments/save/list/delete, validate --require-report
Markets market create, market add-product, market simulate/sensitivity/optimize
Docs docs list, docs show <topic>, docs search <query>

Common pitfalls

  • Don't skip green validate before design generate. Definition errors (uncovered constraints, malformed levels) otherwise surface as opaque design failures.
  • HB needs more tasks per respondent than MNL. 8 tasks/respondent is fine for MNL; HB starves below 12–15.
  • --classes auto for latent-class can pick more classes than are interpretable. Always run report segments and sanity-check before reporting.
  • design codegen writes inspectable code; the canonical state stays in .green/. Editing green_jobs/<name>/ directly will be overwritten on the next codegen.
  • After any external fielding run, data import-edsl first. The import step normalizes schema and runs quality checks; estimation errors before import are usually really import errors.
  • Default design generator is full-factorial. Fine for small attribute spaces, explosive otherwise. Keep total levels modest or pre-prune via prohibitions until D-optimal designs land.
  • Don't lock attributes too quickly during elicitation. It's cheap to suggest a 4-attribute starter, get the user nodding, then realize on probing that one of the four collapses to a near-binary. Validate the trade-space before green init.

Cross-references

  • Pipeline neighbors.
    • Upstream: build a calibrated agent panel via saldana (transcripts → AgentList) or manning (calibrate to a target distribution) before fielding LLM-simulated respondents.
    • Downstream: validate the fitted model's predictions against held-out humans via messick; compile the analysis via gutenberg and style its plots via tufte.
  • Method-space neighbors.
    • sinclair — for general survey-building workflows that are not conjoint.
    • mcda — for internal multi-criteria decisions without a customer panel.
    • voting — for group preference aggregation over a fixed alternative set.
    • bewley — surface attribute candidates from open-ended feedback before defining the conjoint, when the user can't articulate attributes directly.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages