Skip to main content

oransim-causal-marketing-twin

Causal digital twin for marketing simulation — predict campaign ROI, run counterfactual KOL swaps, and audit causal graphs before spending a dollar.

Zur Installation springen

Quellinformationen

Repository
reason-machines/trending-skills
Letzte Quellaktivität
22. April 2026 um 05:48
Erkannte Sprache von SKILL.md
Englisch
Sterne
82
Forks
15

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
oransim-causal-marketing-twin
description
Causal digital twin for marketing simulation — predict campaign ROI, run counterfactual KOL swaps, and audit causal graphs before spending a dollar.
triggers
["simulate marketing campaign ROI","run counterfactual campaign analysis","predict KOL performance before launch","swap KOL mid-campaign simulation","causal marketing twin","oransim predict campaign","what if I change my marketing budget","pre-launch ROI ranking for creatives"]
# Oransim — Causal Digital Twin for Marketing > Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection. Oransim is an open-source causal simulation engine for marketing teams. It lets you predict campaign ROI, run counterfactual "what if" scenarios (swap KOLs, reallocate budget, change platforms), and audit every prediction through a transparent 64-node causal graph — before spending a dollar. **Core capabilities:** - **Pre-launch ROI ranking** across creative × KOL × budget combinations - **Mid-campaign `do()`-operator rollouts** (e.g. swap KOL on day 3, see 14-day path diff) - **Post-mortem counterfactuals** (what if we'd spent on 小红书 instead of 抖音?) - LLM-backed "soul personas" for 1M+ virtual consumer agents - Causal Neural Hawkes Process for temporal cascade simulation - Per-arm counterfactual heads (TARNet / Dragonnet architecture) --- ## Installation ```bash git clone https://github.com/OranAi-Ltd/oransim.git cd oransim pip install -e '.[dev]' ``` ### Backend (mock mode — no API key needed) ```bash LLM_MODE=mock python -m uvicorn oransim.api:app --port 8001 ``` ### Backend (real LLM pipeline) ```bash LLM_MODE=api \ LLM_API_KEY=$YOUR_LLM_API_KEY \ LLM_MODEL=gpt-4o \ python -m uvicorn oransim.api:app --port 8001 ``` ### Frontend ```bash python -m http.server 8090 --directory frontend # Open http://localhost:8090 ``` --- ## Configuration All config via environment variables (see `.env.example`): ```bash # LLM mode: "mock" (deterministic stubs) or "api" (real LLM) LLM_MODE=api # Provider: openai (default), anthropic, gemini, qwen LLM_PROVIDER=openai # API key (also accepts provider-specific: OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.) LLM_API_KEY=sk-... # Model LLM_MODEL=gpt-4o # Custom base URL (DeepSeek, vLLM, etc.) LLM_BASE_URL=https://api.deepseek.com/v1 ``` ### Provider quick-reference | Provider | `LLM_PROVIDER` | `LLM_BASE_URL` | Example model | |---|---|---|---| | OpenAI | `openai` | `https://api.openai.com/v1` | `gpt-4o` | | DeepSeek | `openai` | `https://api.deepseek.com/v1` | `deepseek-chat` | | vLLM (local) | `openai` | `http://localhost:8000/v1` | any | | Anthropic | `anthropic` | *(default)* | `claude-sonnet-4-6` | | Gemini | `gemini` | *(default)* | `gemini-2.5-flash` | | Qwen | `qwen` | *(default)* | `qwen-plus` | --- ## Key API Endpoints All endpoints served at `http://localhost:8001`. ### POST `/api/predict` — Run a campaign simulation ```python import httpx payload = { "campaign": { "name": "Summer Beauty Launch", "platform": "xhs", # xhs | douyin | tiktok "budget": 500000, # CNY "duration_days": 14, "creatives": [ {"id": "vid_A", "type": "video", "duration_sec": 30}, {"id": "vid_B", "type": "video", "duration_sec": 60}, ], "kols": [ {"id": "kol_001", "tier": "mid", "vertical": "beauty", "fans": 250000}, {"id": "kol_002", "tier": "koc", "vertical": "skincare", "fans": 45000}, ], "budget_split": {"xhs": 0.6, "douyin": 0.4}, }, "mode": "fast", # "fast" (quantile baseline) | "full" (LLM agent simulation) "n_simulations": 100, } response = httpx.post("http://localhost:8001/api/predict", json=payload, timeout=120) result = response.json() print(result["roi"]["p50"]) # median ROI print(result["roi"]["p35"]) # lower confidence band print(result["roi"]["p65"]) # upper confidence band print(result["causal_path"]) # which nodes drove the prediction ``` ### GET `/api/graph/inspect` — Audit the causal graph ```python import httpx, json graph = httpx.get("http://localhost:8001/api/graph/inspect").json() print(f"Nodes: {len(graph['nodes'])}") # 64 nodes print(f"Edges: {len(graph['edges'])}") # 117 edges # Find all paths from budget allocation to purchase intent for edge in graph["edges"]: if edge["source"] == "budget_allocation": print(edge) ``` ### POST `/api/sandbox/counterfactual` — Mid-campaign KOL swap ```python import httpx # Scenario: campaign running, day 3, swap KOL counterfactual = httpx.post( "http://localhost:8001/api/sandbox/counterfactual", json={ "base_campaign_id": "campaign_abc123", "intervention": { "do": { "kol": {"remove": ["kol_001"], "add": ["kol_003"]}, "day": 3, "budget_realloc": {"kol_001_budget": "kol_003"}, } }, "rollout_days": 14, }, timeout=120, ).json() print(counterfactual["roi_diff"]) # ROI change from intervention print(counterfactual["trajectory_diff"]) # day-by-day path difference print(counterfactual["attribution"]) # which causal nodes shifted ``` ### POST `/api/sandbox/postmortem` — Platform counterfactual ```python import httpx postmortem = httpx.post( "http://localhost:8001/api/sandbox/postmortem", json={ "actuals": { "campaign_id": "q2_campaign", "spend": {"xhs": 200000, "douyin": 300000}, "observed_roi": 1.4, }, "counterfactual_alloc": {"xhs": 1.0, "douyin": 0.0}, # what if all on XHS? }, timeout=120, ).json() print(postmortem["counterfactual_roi"]) # what ROI would have been print(postmortem["delta"]) # difference from actuals ``` ### GET `/api/adapters` — List available platform adapters ```python import httpx adapters = httpx.get("http://localhost:8001/api/adapters").json() # Returns: ["xhs_v1", "tiktok_agent", "douyin", ...] ``` --- ## Python SDK Usage (Direct Engine) For programmatic use without the HTTP layer: ```python from oransim.world_model import AgentSociety from oransim.causal import CausalGraph, do_operator from oransim.diffusion import HawkesRollout # 1. Build the causal graph graph = CausalGraph.from_config("configs/default_graph.yaml") # 2. Initialize virtual consumer society society = AgentSociety( n_agents=10_000, # scale down from 1M for local dev vertical="beauty", platform="xhs", llm_mode="mock", # "mock" | "api" ) # 3. Define campaign campaign = { "budget": 200_000, "kols": [{"id": "kol_001", "tier": "mid", "fans": 150_000}], "creative_ids": ["vid_A"], "duration_days": 14, } # 4. Run baseline simulation baseline = HawkesRollout(graph=graph, society=society) result = baseline.run(campaign, n_simulations=50) print(f"P50 ROI: {result.roi.p50:.2f}") # 5. Apply do()-operator intervention with do_operator(graph) as intervened_graph: intervened_graph.set("kol_assignment", "kol_002") intervened_graph.set("intervention_day", 3) counterfactual = HawkesRollout(graph=intervened_graph, society=society) cf_result = counterfactual.run(campaign, n_simulations=50) print(f"Counterfactual P50 ROI: {cf_result.roi.p50:.2f}") print(f"Delta: {cf_result.roi.p50 - result.roi.p50:.2f}") ``` --- ## Pre-launch ROI Ranking (All Combinations) ```python from itertools import product from oransim.world_model import AgentSociety from oransim.causal import CausalGraph from oransim.diffusion import HawkesRollout import pandas as pd graph = CausalGraph.from_config("configs/default_graph.yaml") society = AgentSociety(n_agents=5_000, vertical="beauty", platform="xhs", llm_mode="mock") creatives = ["vid_A", "vid_B", "vid_C", "vid_D"] kol_lists = [["kol_001"], ["kol_002"], ["kol_003"]] budgets = [200_000, 500_000] results = [] for creative, kols, budget in product(creatives, kol_lists, budgets): campaign = {"budget": budget, "kols": kols, "creative_ids": [creative], "duration_days": 14} rollout = HawkesRollout(graph=graph, society=society) r = rollout.run(campaign, n_simulations=30) results.append({ "creative": creative, "kol": kols[0], "budget": budget, "roi_p35": r.roi.p35, "roi_p50": r.roi.p50, "roi_p65": r.roi.p65, }) df = pd.DataFrame(results).sort_values("roi_p50", ascending=False) print(df.head(5).to_string()) # top 5 combinations ``` --- ## Common Patterns ### Pattern 1: Mock mode for CI / testing ```python import os os.environ["LLM_MODE"] = "mock" from oransim.world_model import AgentSociety society = AgentSociety(n_agents=100, vertical="beauty", platform="xhs", llm_mode="mock") # All LLM calls return deterministic stubs — fast, free, reproducible ``` ### Pattern 2: Check if backend is in mock mode ```python import httpx health = httpx.get("http://localhost:8001/health").json() if health.get("llm_mode") == "mock": print("WARNING: Running in mock mode — LLM features are stubs") ``` ### Pattern 3: Inspect a prediction's causal path ```python result = httpx.post("http://localhost:8001/api/predict", json=payload).json() # Every prediction includes which causal nodes fired for node in result["causal_path"]: print(f"{node['id']:30s} weight={node['weight']:.3f} layer={node['layer']}") ``` ### Pattern 4: Load the LightGBM quantile baseline (fast mode) ```python import pickle, numpy as np with open("models/lgbm_quantile_baseline.pkl", "rb") as f: model = pickle.load(f) # Feature vector: [budget, n_kols, avg_fans, duration_days, platform_enc] X = np.array([[500_000, 2, 150_000, 14, 0]]) # 0=xhs, 1=douyin p35, p50, p65 = model.predict(X) print(f"ROI P35={p35[0]:.2f} P50={p50[0]:.2f} P65={p65[0]:.2f}") ``` --- ## Project Structure ``` oransim/ ├── oransim/ │ ├── api.py # FastAPI app + god-file (being refactored to api_routers/) │ ├── api_routers/ # Split routers: predict, sandbox, graph, adapters
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen