{"id":27261508,"url":"https://github.com/cahlen/conversation-dataset-generator","last_synced_at":"2026-07-03T22:34:19.524Z","repository":{"id":287198535,"uuid":"963703790","full_name":"cahlen/conversation-dataset-generator","owner":"cahlen","description":"Generate multi-speaker conversational datasets for LLM fine-tuning. N-persona support, topic variation, conversation continuation, creative briefs with web search, character pools, Docker support. ShareGPT format with configurable role mapping.","archived":false,"fork":false,"pushed_at":"2026-04-07T09:10:06.000Z","size":430,"stargazers_count":14,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-04-07T10:24:07.696Z","etag":null,"topics":["dataset-generation","dialogue-generation","fine-tuning","huggingface","jsonl","llm","lora","nlp","peft","persona","python","synthentic-data","transformers"],"latest_commit_sha":null,"homepage":"https://cahlen.github.io/conversation-dataset-generator/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cahlen.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-04-10T04:56:09.000Z","updated_at":"2026-04-07T09:10:10.000Z","dependencies_parsed_at":"2025-04-12T09:15:32.302Z","dependency_job_id":null,"html_url":"https://github.com/cahlen/conversation-dataset-generator","commit_stats":null,"previous_names":["cahlen/conversation-dataset-generator"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cahlen/conversation-dataset-generator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cahlen%2Fconversation-dataset-generator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cahlen%2Fconversation-dataset-generator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cahlen%2Fconversation-dataset-generator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cahlen%2Fconversation-dataset-generator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cahlen","download_url":"https://codeload.github.com/cahlen/conversation-dataset-generator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cahlen%2Fconversation-dataset-generator/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35104115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-03T02:00:05.635Z","response_time":110,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dataset-generation","dialogue-generation","fine-tuning","huggingface","jsonl","llm","lora","nlp","peft","persona","python","synthentic-data","transformers"],"created_at":"2025-04-11T05:33:29.967Z","updated_at":"2026-07-03T22:34:19.518Z","avatar_url":"https://github.com/cahlen.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Conversation Dataset Generator\n\nGenerate synthetic conversational datasets in ShareGPT format for LLM fine-tuning. Define personas, topics, and styles — or provide a creative brief and let the LLM figure it out.\n\n[![MIT License](https://img.shields.io/github/license/cahlen/conversation-dataset-generator.svg)](LICENSE)\n\n## Quick Start (pip)\n\n```bash\npython -m venv venv \u0026\u0026 source venv/bin/activate\npip install -r requirements.txt\npython generate.py \\\n  --creative-brief \"Sherlock Holmes and Watson debate whether AI will replace detectives\" \\\n  --num-examples 5 --output-file conversations.jsonl\n```\n\nRequires Python 3.10+. For the default `--backend hf`, you'll also need an NVIDIA GPU with CUDA. With `--backend openai` you can use any OpenAI-compatible server (LM Studio, Ollama, OpenAI itself, etc.) — see [\"Using a remote OpenAI-compatible server\"](#using-a-remote-openai-compatible-server-no-local-gpu-needed) below.\n\n## Quick Start (Docker)\n\n![Dashboard via docker compose up](docs/screenshots/docker-compose-webapp.png)\n\nThe default `docker compose up` launches the Gradio dashboard at [http://localhost:7860](http://localhost:7860):\n\n```bash\ndocker compose up\n```\n\nPoint at any OpenAI-compatible server (LM Studio, Ollama, OpenAI itself) by setting env vars before launch:\n\n```bash\nCDG_BACKEND=openai \\\nCDG_BASE_URL=http://host.docker.internal:11434/v1 \\\nCDG_MODEL_ID=llama3.2:1b \\\ndocker compose up\n```\n\nIf you'd rather run the CLI inside the container (one-off batch jobs, etc.):\n\n```bash\ndocker compose run cdg python3 generate.py \\\n  --creative-brief \"Two scientists argue about time travel\" \\\n  --output-file output/data.jsonl\n```\n\nBuild manually if you don't want compose:\n\n```bash\n# Default CUDA 12.x — works on 30xx/40xx/50xx\ndocker build -t cdg .\n\n# CUDA 13.x for RTX 50xx with latest drivers\ndocker build --build-arg CUDA_VERSION=13.0.0 -t cdg .\n\n# Run the webapp (default)\ndocker run --gpus all -p 7860:7860 -e CDG_HOST=0.0.0.0 \\\n  -v $(pwd)/output:/app/output cdg\n\n# Or run the CLI (override the default command)\ndocker run --gpus all -v $(pwd)/output:/app/output cdg \\\n  python3 generate.py --creative-brief \"...\" --output-file output/data.jsonl\n```\n\n## Modes\n\n### Manual\n\nSpecify everything directly. No variation — every conversation uses the same parameters.\n\n```bash\npython generate.py \\\n  --topic \"best pizza toppings\" \\\n  --persona1 \"Tony\" --persona1-desc \"A passionate Italian chef\" \\\n  --persona2 \"Dave\" --persona2-desc \"A pineapple-on-pizza enthusiast\" \\\n  --scenario \"kitchen argument\" --style \"heated but friendly debate\" \\\n  --num-examples 10 --output-file pizza_debate.jsonl\n```\n\n### Creative Brief\n\nProvide a high-level brief. The LLM generates personas, topic, scenario, and style, then varies the topic/scenario for each conversation.\n\n```bash\npython generate.py \\\n  --creative-brief \"A grumpy cat and an overly enthusiastic golden retriever share a sunbeam\" \\\n  --num-examples 20 --output-file cat_dog.jsonl\n```\n\nOptionally enrich personas with web search context:\n\n```bash\npython generate.py \\\n  --creative-brief \"Linus Torvalds and Tim Cook debate open source\" \\\n  --persona1-search-term \"Linus Torvalds\" \\\n  --persona2-search-term \"Tim Cook Apple CEO\" \\\n  --num-examples 10 --output-file tech_debate.jsonl\n```\n\n### Fixed Persona + Variation\n\nFix the personas but let the LLM vary the topic and scenario each time.\n\n```bash\npython generate.py \\\n  --enable-variation \\\n  --fixed-persona1 \"Iron Man\" --fixed-persona1-desc \"Genius billionaire with rapid-fire wit\" \\\n  --fixed-persona2 \"Captain America\" --fixed-persona2-desc \"Principled, earnest, old-fashioned\" \\\n  --initial-topic \"team leadership\" --initial-scenario \"Avengers HQ\" --initial-style \"friendly disagreement\" \\\n  --num-examples 50 --output-file avengers.jsonl\n```\n\n### Random Pairings\n\nRandomly pair characters from YAML pool files for each conversation.\n\n```bash\npython generate.py \\\n  --random-pairings \\\n  --character-pool avengers_characters.yaml \\\n  --persona-desc-pool avengers_descriptions.yaml \\\n  --initial-topic \"planning a party\" --initial-scenario \"break room\" --initial-style \"casual banter\" \\\n  --num-examples 100 --output-file avengers_random.jsonl\n```\n\nAdd `--enable-variation` to also vary topics per conversation. Use `--group-size 3` for 3-way conversations.\n\n### Multi-Speaker (3+ Personas)\n\nUse `--persona` (repeatable) for inline definitions or `--personas` for a YAML file:\n\n```bash\n# Inline\npython generate.py \\\n  --persona \"Iron Man\" \"Genius billionaire with rapid-fire wit\" \\\n  --persona \"Captain America\" \"Principled, earnest, old-fashioned\" \\\n  --persona \"Thor\" \"Boisterous god with Shakespearean formality\" \\\n  --topic \"who pays for the pizza\" --scenario \"Avengers break room\" --style \"comedic argument\" \\\n  --num-examples 10 --output-file avengers_pizza.jsonl\n\n# From YAML file\npython generate.py \\\n  --personas my_characters.yaml \\\n  --topic \"planning a heist\" --scenario \"warehouse\" --style \"tense thriller\" \\\n  --num-examples 5 --output-file heist.jsonl\n```\n\nPersonas YAML format:\n```yaml\npersonas:\n  - name: \"Iron Man\"\n    description: \"Genius billionaire with rapid-fire wit\"\n  - name: \"Captain America\"\n    description: \"Principled, earnest, old-fashioned\"\n```\n\n### Continuing Conversations\n\nExtend an existing conversation with more turns:\n\n```bash\n# Continue the last conversation in a file\npython generate.py --continue-from conversations.jsonl --output-file more.jsonl\n\n# Continue a specific conversation\npython generate.py --continue-from conversations.jsonl --conversation-id 5 --output-file more.jsonl\n```\n\n### Batch Generation\n\nRun multiple generation jobs from a YAML config:\n\n```bash\npython batch_generate.py examples/batch_mixed_modes.yaml\n```\n\nSee `examples/` for sample batch configs.\n\n## Argument Reference\n\n### Mode Selection\n\n| Flag | Description |\n|---|---|\n| `--creative-brief TEXT` | Creative brief for automatic parameter generation |\n| `--enable-variation` | Vary topic/scenario between conversations |\n| `--random-pairings` | Random character pairs from pool files |\n\n### Manual Mode\n\n| Flag | Description |\n|---|---|\n| `--topic TEXT` | Conversation topic |\n| `--persona1 TEXT` | First speaker name |\n| `--persona1-desc TEXT` | First speaker description |\n| `--persona2 TEXT` | Second speaker name |\n| `--persona2-desc TEXT` | Second speaker description |\n| `--scenario TEXT` | Setting/context |\n| `--style TEXT` | Dialogue style/tone |\n| `--include-points TEXT` | Comma-separated keywords to include |\n\n### Fixed Persona Variation\n\n| Flag | Description |\n|---|---|\n| `--fixed-persona1 TEXT` | Fixed first speaker name |\n| `--fixed-persona1-desc TEXT` | Fixed first speaker description |\n| `--fixed-persona2 TEXT` | Fixed second speaker name |\n| `--fixed-persona2-desc TEXT` | Fixed second speaker description |\n| `--initial-topic TEXT` | Seed topic for variation |\n| `--initial-scenario TEXT` | Seed scenario for variation |\n| `--initial-style TEXT` | Seed style for variation |\n\n### Random Pairings\n\n| Flag | Description |\n|---|---|\n| `--character-pool FILE` | YAML file with character names |\n| `--persona-desc-pool FILE` | YAML file with character descriptions |\n\n### Multi-Speaker\n\n| Flag | Description |\n|---|---|\n| `--persona NAME DESC` | Add a persona (repeatable) |\n| `--personas FILE` | YAML file with personas list |\n| `--train-speaker NAME` | Assign this speaker the \"gpt\" role |\n| `--group-size N` | Characters per conversation in random pairings (default: 2) |\n\n### Continue Conversation\n\n| Flag | Description |\n|---|---|\n| `--continue-from FILE` | Continue from an existing JSONL file |\n| `--conversation-id N` | Specific conversation to continue (default: last) |\n\n### Web Search (Creative Brief)\n\n| Flag | Description |\n|---|---|\n| `--persona1-search-term TEXT` | Web search term for persona 1 context |\n| `--persona2-search-term TEXT` | Web search term for persona 2 context |\n\n### General\n\n| Flag | Default | Description |\n|---|---|---|\n| `--num-examples N` | 3 | Number of conversations to generate |\n| `--output-file PATH` | `generated_data.jsonl` | Output file path |\n| `--model-id ID` | `Qwen/Qwen2.5-7B-Instruct` | HuggingFace model for generation |\n| `--max-new-tokens N` | 4096 | Max tokens per generation |\n| `--load-in-4bit` | off | Enable 4-bit quantization (requires bitsandbytes) |\n| `--backend {hf,openai}` | `hf` | Inference backend: local transformers (`hf`) or OpenAI-compatible HTTP server (`openai`) |\n| `--api-base-url URL` | `http://localhost:1234/v1` | Server URL when `--backend openai`. Ollama: `http://localhost:11434/v1` |\n| `--api-key KEY` | env `OPENAI_API_KEY` | API key for `--backend openai`. Falls back to env, then to `\"not-needed\"` |\n| `--upload-to-hub REPO` | — | Upload dataset to HuggingFace Hub |\n| `--force-upload` | off | Skip upload confirmation |\n| `--role-mapping MAP` | first=human, rest=gpt | Map speaker names to roles (e.g., `\"Alice=human,Bob=gpt\"`) |\n| `--dedup-threshold FLOAT` | off | Drop generated conversations with cosine similarity \u003e this value to any prior. Typical range: 0.85–0.97. Requires `sentence-transformers`. |\n\n## Output Format\n\nEach line in the JSONL output is one conversation turn:\n\n```json\n{\n  \"conversation_id\": 0,\n  \"turn_number\": 0,\n  \"role\": \"human\",\n  \"speaker_name\": \"Tony\",\n  \"topic\": \"best pizza toppings\",\n  \"scenario\": \"kitchen argument\",\n  \"style\": \"heated but friendly debate\",\n  \"include_points\": \"\",\n  \"content\": \"So, you're telling me pineapple on pizza is the ultimate topping?\"\n}\n```\n\n## Role Mapping for Training\n\nThe `role` field in the output determines how training frameworks interpret each turn:\n- `\"human\"` = input/context (the model sees this)\n- `\"gpt\"` = target (the model learns to generate this)\n\n**Default:** First persona is `\"human\"`, all others are `\"gpt\"`.\n\n**Train a specific character:** Use `--train-speaker` to make one character the `\"gpt\"` role:\n\n```bash\n# Train the model to BE Captain America\npython generate.py \\\n  --persona \"Iron Man\" \"Genius billionaire\" \\\n  --persona \"Captain America\" \"Principled leader\" \\\n  --persona \"Thor\" \"Boisterous god\" \\\n  --train-speaker \"Captain America\" \\\n  --topic \"mission planning\" --scenario \"war room\" --style \"serious\" \\\n  --output-file cap_training.jsonl\n```\n\nIn the output, Captain America's turns will have `\"role\": \"gpt\"` and everyone else will have `\"role\": \"human\"`. The `speaker_name` field always stores the actual character name regardless.\n\n**Fine-grained control:** Use `--role-mapping` for custom assignments:\n\n```bash\n--role-mapping \"Iron Man=human,Captain America=gpt,Thor=human\"\n```\n\n## Evaluation\n\nMeasure the quality of generated datasets with intrinsic metrics:\n\n```bash\npython evaluate.py conversations.jsonl\n```\n\n```\n=== CDG Evaluation Report ===\n\nDataset: conversations.jsonl\nConversations: 100 | Turns: 1,247 | Avg turns: 12.5\n\nSpeakers (3):\n  Iron Man                  34.2% of turns\n  Captain America           33.1% of turns\n  Thor                      32.7% of turns\n\nDiversity:\n  Distinct-1: 0.42 | Distinct-2: 0.81 | Distinct-3: 0.91\n  Topic diversity: 0.72 (0=identical, 1=unrelated)\n  Vocabulary richness (TTR): 0.68\n  Vendi Score: 87.4 / 100 (effective distinct conversations; closer to N = more diverse)\n\nCoherence:\n  Turn-to-turn similarity: 0.47 (target: 0.3-0.6)\n  Self-repetition rate: 2.1%\n\nSpeaker Distinctiveness:\n  Avg pairwise distance: 0.38 (higher = more distinct voices)\n```\n\n**Metrics:**\n- **Distinct-N** — fraction of unique n-grams. Higher = more lexically diverse.\n- **Topic diversity** — embedding distance between conversation topics. 0 = all identical, 1 = completely varied.\n- **Turn coherence** — how well consecutive turns relate. Sweet spot: 0.3-0.6.\n- **Self-repetition** — fraction of near-duplicate turns within conversations.\n- **Speaker distinctiveness** — how different each speaker's language is from others.\n- **Vendi Score** — effective number of distinct conversations, computed from the eigenvalue entropy of the conversation-embedding similarity matrix. Range is `[1, N]` where `N` is the number of conversations: `1` means everything collapses to one effective example, `N` means every conversation is mutually distinct. Less sensitive than Distinct-N to surface-level paraphrases.\n\nOptions:\n```bash\npython evaluate.py data.jsonl --format json     # machine-readable\npython evaluate.py data.jsonl --no-embeddings   # skip embedding metrics (faster)\n```\n\n## Using a remote OpenAI-compatible server (no local GPU needed)\n\nYou can drive `generate.py` against any OpenAI-compatible inference server — LM Studio, Ollama, vLLM, TGI, or the real OpenAI API. This sidesteps local CUDA and lets you use models bigger than your VRAM.\n\n### LM Studio\n\nStart the server in LM Studio (Server tab, default port 1234), load a model, then:\n\n```bash\npython generate.py \\\n  --backend openai \\\n  --api-base-url http://localhost:1234/v1 \\\n  --model-id \"lmstudio-community/Qwen2.5-7B-Instruct-GGUF\" \\\n  --creative-brief \"Sherlock and Watson debate AI\" \\\n  --num-examples 5 \\\n  --output-file out.jsonl\n```\n\n### Ollama\n\n```bash\nollama pull llama3.2:1b   # or any model you like\npython generate.py \\\n  --backend openai \\\n  --api-base-url http://localhost:11434/v1 \\\n  --model-id llama3.2:1b \\\n  --creative-brief \"Two chefs argue about umami\" \\\n  --num-examples 5 \\\n  --output-file out.jsonl\n```\n\n### OpenAI (or OpenRouter, Together, etc.)\n\n```bash\nexport OPENAI_API_KEY=sk-...\npython generate.py \\\n  --backend openai \\\n  --api-base-url https://api.openai.com/v1 \\\n  --model-id gpt-4o-mini \\\n  --creative-brief \"...\" --num-examples 5 \\\n  --output-file out.jsonl\n```\n\nWhen `--backend openai` is set, `--load-in-4bit` is silently ignored (quantization happens server-side). The default `--backend hf` preserves the original local-transformers behavior.\n\n## Web interface\n\nA full Gradio dashboard is available for interactive generation, evaluation, and dataset packaging.\n\n```bash\npython webapp.py\n```\n\nOpens at `http://127.0.0.1:7860`. Set defaults via env vars: `CDG_BACKEND`, `CDG_BASE_URL`, `CDG_MODEL_ID`.\n\n![Empty dashboard](docs/screenshots/dashboard-empty.png)\n\n### What the dashboard does\n\n| Panel | Purpose |\n|---|---|\n| **Backend** | Choose `hf` (local transformers) or `openai` (any OpenAI-compatible server). Set base URL, API key, model id, max-new-tokens, 4-bit quantization. |\n| **Personas** | Pick a curated preset, paste a creative brief and let the model brainstorm a cast, or write your own. Two name+description fields plus an \"Add more\" textarea for N-speaker conversations. A **Train speaker** dropdown picks which speaker maps to the `gpt` role for fine-tuning. |\n| **Scene** | Topic, scenario, style. Optional must-cover points. |\n| **Batch** | Number of conversations (1–50), per-example variation toggle, near-duplicate dedup threshold. |\n| **Run status / Diversity metrics** | After Generate, the right pane shows healthy/needs-attention headline, stat grid of metrics with their **targets** (effective uniqueness, distinct-2, topic diversity, speaker distinctness, turn coherence, self-repetition), and plain-English recommendations when something misses. |\n| **Auto-fix issues** | One-click dispatcher that applies every applicable fix: rewrites personas for orthogonal voice, broadens topic, sharpens scene, toggles variation, drops max-tokens — based on which metrics failed. |\n| **Dataset** | Downloadable ShareGPT JSONL, ready for fine-tuning. |\n| **Preview** | First three generated conversations rendered inline; full batch in the JSONL. |\n\n### Creative brief workflow\n\n![Brainstorm from a brief](docs/screenshots/brainstorm-success.png)\n\nPaste a one-line idea like `\"A grizzled samurai mentors a sarcastic teenage hacker about honor in the digital age\"`, click **Brainstorm**, and the model fills in personas, topic, scenario, and style. Edit if needed, then click Generate.\n\n### Metrics with targets, not just numbers\n\n![Healthy metrics](docs/screenshots/metrics-healthy.png)\n\nEach stat shows actual value vs. target with traffic-light coloring. Plain-English headline names the failing dimension when something's off (\"NEEDS ATTENTION: distinct voices\"). Recommendations explain how to fix — and the Auto-fix button applies them.\n\n### N-speaker conversations\n\nThe Sci-fi crew preset packs four characters (captain, archaeologist, ship AI, engineer) into one conversation. Use the \"Add more\" textarea (`Name | Description` per line) to add as many speakers as you want.\n\n### What's CLI-only\n\nThese features aren't in the webapp; use `generate.py` instead:\n\n- **`--continue-from data.jsonl`** — extend an existing conversation\n- **`--random-pairings`** with `--character-pool` / `--persona-desc-pool` YAML pools\n- **`--upload-to-hub REPO_ID`** — push the dataset to HuggingFace Hub\n- **`--persona1-search-term` / `--persona2-search-term`** — DuckDuckGo persona context for creative brief mode\n- **`--role-mapping \"Name1=human,Name2=gpt\"`** — manual role mapping (the webapp uses the simpler `Train speaker` dropdown)\n- **`batch_generate.py examples/batch_*.yaml`** — batch jobs with mixed modes\n\n## For Contributors\n\n### Package Structure\n\n| Module | Responsibility |\n|---|---|\n| `cli.py` | Argument parsing, mode detection, orchestration |\n| `models.py` | Model/tokenizer loading, pipeline creation |\n| `prompts.py` | System prompts and message builders |\n| `generation.py` | LLM call wrappers with retry logic |\n| `parsing.py` | Regex parsers for LLM output |\n| `output.py` | JSONL writing and dataset card templates |\n| `hub.py` | HuggingFace Hub upload |\n| `character_pool.py` | YAML pool loading and random pairing |\n| `web_search.py` | DuckDuckGo persona context search |\n\n### Running Tests\n\n```bash\npip install -r requirements-dev.txt\npytest tests/ -v                    # all 121 tests\npytest tests/test_parsing.py -v     # one module\n```\n\nNo GPU required for tests — LLM calls are mocked.\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcahlen%2Fconversation-dataset-generator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcahlen%2Fconversation-dataset-generator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcahlen%2Fconversation-dataset-generator/lists"}