GRPO is the foundation for most reinforcement-learning objectives on Whitney.
Your code owns prompts, rewards, grouping, advantages, and the loss payload.
Whitney owns sampling, weight sync, and ordered primitive execution.Other algorithms in More algorithms extend this loop
with different advantage estimators, clipping, or distillation semantics.
Group completions by prompt and compute advantages (for standard GRPO: mean-center
within each group; optionally divide by standard deviation).
Build a forward JSON payload whose loss_function and loss_config encode your
policy-gradient objective for those advantages.
Each cycle calls your own build_loss(sample, cycle, request, ctx) -> dict —
so the only code you write is the reward function and the few lines below.
See The build_loss contract and
the ordered RL loop skeleton
for the surrounding loop:
def reward(tokens: list[int]) -> float: ... # your scoring function — decode tokens, grade the answer, return a scalardef build_loss(sample, cycle, request, ctx): prompt_tokens = request["prompt"]["token_ids"] sequences = sample["sequences"] rewards = [reward(sequence["tokens"]) for sequence in sequences] advantages = group_mean_advantages(rewards, normalize_std=True) if all_zero(advantages): raise ValueError(f"cycle {cycle}: reward is uniform across the group, no gradient signal") data = [ rl_datum(prompt_tokens, sequence["tokens"], sequence["logprobs"], advantage) for sequence, advantage in zip(sequences, advantages) ] return forward_backward_payload(data, "importance_sampling")
group_mean_advantages, all_zero, rl_datum, and forward_backward_payload
are the shared advantage and datum helpers.Never substitute generic GRPO when your algorithm requires a different estimator.
See More algorithms for variants — most of them are
one small change to build_loss over the same loop.
Use logprobs when your objective needs policy or reference log probabilities.
Do not infer them from generated text.Sample, logprobs, and forward bodies use the typed
JSON primitive contract.
On failure: cancel the run, poll until terminal, then close the session.
If the algorithm-specific loss cannot be represented in the current Whitney JSON and operation contract, stop before
creating a session. Never silently substitute generic GRPO.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Whitney","description":"Build caller-owned training loops with the Whitney HTTP API.","colors":{"primary":"#18181b","light":"#3f3f46","dark":"#fafafa"},"logo":{"light":"https://mintcdn.com/whitney-ai/31oF5lBZ51KYlN_v/logo.png?fit=max\u0026auto=format\u0026n=31oF5lBZ51KYlN_v\u0026q=85\u0026s=2834a6f45fc024ab73570b4179951fb9","dark":"https://mintcdn.com/whitney-ai/31oF5lBZ51KYlN_v/logo.png?fit=max\u0026auto=format\u0026n=31oF5lBZ51KYlN_v\u0026q=85\u0026s=2834a6f45fc024ab73570b4179951fb9","href":"/"},"api":{"playground":{"display":"interactive"},"examples":{"languages":["curl","python","javascript"]}},"footer":{"socials":{"x":"https://x.com/try_whitney","linkedin":"https://www.linkedin.com/company/whitney-ai"}},"seo":{"metatags":{"robots":"noindex, nofollow"}},"contextual":{"options":["copy","view","mcp","cursor","vscode","download-spec"],"display":"header"},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"whitney-ai","hasAudioNarration":false,"actualSubdomain":"whitney-ai","customDomains":["staging.docs.trywhitney.com"],"gitSource":{"type":"github","owner":"whitney-ai","repo":"lonepine","deployBranch":"main","contentDirectory":"docs","isPrivate":true,"mountPath":"","label":""},"chroma":{"latestBuiltDeploymentHistoryId":"6a9dff02b6b8641bb5563466","collectionId":"106bed20-47df-437d-85f6-8e8de33ded44","liveDeploymentHistoryId":"6a9dff02b6b8641bb5563466","schemaVersion":"v3"},"entitlements":{"AI_CHAT":{"status":"DISABLED"}},"buildId":"6a9dff02b6b8641bb5563466","clientVersion":"0.0.4044","searchFilterCounts":[{"language":"default","tag":"API Reference","count":28},{"language":"default","tag":"unified-training","count":28},{"language":"default","tag":"Guides","count":17},{"language":"default","tag":"Cookbooks","count":6},{"language":"default","tag":"Distillation","count":4},{"language":"default","tag":"How it works","count":3},{"language":"default","tag":"Get started","count":3},{"language":"default","tag":"Coding agents","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"cookbooks/grpo","slug":"/cookbooks/grpo","pageMetadata":{"title":"GRPO","description":"Run a caller-owned group-relative policy optimization loop.","href":"/cookbooks/grpo"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Run a caller-owned group-relative policy optimization loop.\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={a:`a`,code:`code`,li:`li`,ol:`ol`,p:`p`,pre:`pre`,span:`span`,..._provideComponents(),...props.components},{CodeBlock,Heading,Warning}=_components;if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);if(!Warning)_missingMdxReference(`Warning`,true);return _jsxs(_Fragment,{children:[_jsx(Heading,{level:`2`,id:`overview`,children:`Overview`}),`\n`,_jsx(_components.p,{children:`GRPO is the foundation for most reinforcement-learning objectives on Whitney.\nYour code owns prompts, rewards, grouping, advantages, and the loss payload.\nWhitney owns sampling, weight sync, and ordered primitive execution.`}),`\n`,_jsxs(_components.p,{children:[`Other algorithms in `,_jsx(_components.a,{href:`/cookbooks/algorithms`,children:`More algorithms`}),` extend this loop\nwith different advantage estimators, clipping, or distillation semantics.`]}),`\n`,_jsx(Heading,{level:`2`,id:`prerequisites`,children:`Prerequisites`}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsxs(_components.li,{children:[_jsx(_components.code,{children:`GET /v1/training/capabilities`}),` — confirm `,_jsx(_components.code,{children:`forward_backward`}),`, `,_jsx(_components.code,{children:`optim_step`}),`,\n`,_jsx(_components.code,{children:`save_weights_for_sampler`}),`, `,_jsx(_components.code,{children:`sample`}),`, and optionally `,_jsx(_components.code,{children:`logprobs`}),`.`]}),`\n`,_jsxs(_components.li,{children:[`Create a session and LoRA run (see `,_jsx(_components.a,{href:`/quickstart`,children:`Quickstart`}),`).`]}),`\n`]}),`\n`,_jsx(Heading,{level:`2`,id:`training-loop`,children:`Training loop`}),`\n`,_jsx(_components.p,{children:`For each cycle:`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`6`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`6`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`save_weights_for_sampler(version N)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` → sample(version N)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` → caller computes rewards and group advantages`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` → forward_backward(caller loss)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` → optim_step(explicit AdamW)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsx(_components.p,{children:`Run at least two full cycles so update, sync, and sample semantics are explicit.`}),`\n`,_jsx(Heading,{level:`3`,id:`caller-owned-math`,children:`Caller-owned math`}),`\n`,_jsxs(_components.p,{children:[`After `,_jsx(_components.code,{children:`sample`}),` returns:`]}),`\n`,_jsxs(_components.ol,{children:[`\n`,_jsx(_components.li,{children:`Score each completion with your reward function.`}),`\n`,_jsx(_components.li,{children:`Group completions by prompt and compute advantages (for standard GRPO: mean-center\nwithin each group; optionally divide by standard deviation).`}),`\n`,_jsxs(_components.li,{children:[`Build a forward JSON payload whose `,_jsx(_components.code,{children:`loss_function`}),` and `,_jsx(_components.code,{children:`loss_config`}),` encode your\npolicy-gradient objective for those advantages.`]}),`\n`]}),`\n`,_jsxs(_components.p,{children:[`Each cycle calls your own `,_jsx(_components.code,{children:`build_loss(sample, cycle, request, ctx) -> dict`}),` —\nso the only code you write is the reward function and the few lines below.\nSee `,_jsx(_components.a,{href:`/cookbooks/helpers#the-build_loss-contract`,children:`The build_loss contract`}),` and\nthe `,_jsx(_components.a,{href:`/cookbooks/helpers#ordered-rl-loop-skeleton`,children:`ordered RL loop skeleton`}),`\nfor the surrounding loop:`]}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`16`,language:`python`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`python`,children:_jsxs(_components.code,{language:`python`,numberOfLines:`16`,children:[_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` reward`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`tokens`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`: list[`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`int`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]) -> `}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:`float`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`:`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#D4D4D4`},children:` ...`}),_jsx(_components.span,{style:{color:`#6E7781`,\"--shiki-dark\":`#6A9955`},children:` # your scoring function — decode tokens, grade the answer, return a scalar`})]}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsx(_components.span,{className:`line`}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`def`}),_jsx(_components.span,{style:{color:`#8250DF`,\"--shiki-dark\":`#DCDCAA`},children:` build_loss`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`sample`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`cycle`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`request`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`, `}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#9CDCFE`},children:`ctx`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` prompt_tokens `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` request[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"prompt\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`][`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"token_ids\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sequences `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sample[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"sequences\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` rewards `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [reward(sequence[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"tokens\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`]) `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sequence `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sequences]`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` advantages `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` group_mean_advantages(rewards, `}),_jsx(_components.span,{style:{color:`#953800`,\"--shiki-dark\":`#9CDCFE`},children:`normalize_std`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#569CD6`},children:`True`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` if`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` all_zero(advantages):`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` raise`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#4EC9B0`},children:` ValueError`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`f`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"cycle `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`{`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`cycle`}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#569CD6`},children:`}`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`: reward is uniform across the group, no gradient signal\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` data `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#D4D4D4`},children:`=`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` [`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` rl_datum(prompt_tokens, sequence[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"tokens\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`], sequence[`}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"logprobs\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`], advantage)`})]}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` for`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` sequence, advantage `}),_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:`in`}),_jsx(_components.span,{style:{color:`#0550AE`,\"--shiki-dark\":`#DCDCAA`},children:` zip`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`(sequences, advantages)`})]}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` ]`})}),`\n`,_jsxs(_components.span,{className:`line`,children:[_jsx(_components.span,{style:{color:`#CF222E`,\"--shiki-dark\":`#C586C0`},children:` return`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:` forward_backward_payload(data, `}),_jsx(_components.span,{style:{color:`#0A3069`,\"--shiki-dark\":`#CE9178`},children:`\"importance_sampling\"`}),_jsx(_components.span,{style:{color:`#1F2328`,\"--shiki-dark\":`#D4D4D4`},children:`)`})]}),`\n`]})})}),`\n`,_jsxs(_components.p,{children:[_jsx(_components.code,{children:`group_mean_advantages`}),`, `,_jsx(_components.code,{children:`all_zero`}),`, `,_jsx(_components.code,{children:`rl_datum`}),`, and `,_jsx(_components.code,{children:`forward_backward_payload`}),`\nare the shared `,_jsx(_components.a,{href:`/cookbooks/helpers`,children:`advantage and datum helpers`}),`.`]}),`\n`,_jsxs(_components.p,{children:[`Never substitute generic GRPO when your algorithm requires a different estimator.\nSee `,_jsx(_components.a,{href:`/cookbooks/algorithms`,children:`More algorithms`}),` for variants — most of them are\none small change to `,_jsx(_components.code,{children:`build_loss`}),` over the same loop.`]}),`\n`,_jsx(Heading,{level:`3`,id:`log-probabilities`,children:`Log probabilities`}),`\n`,_jsxs(_components.p,{children:[`Use `,_jsx(_components.code,{children:`logprobs`}),` when your objective needs policy or reference log probabilities.\nDo not infer them from generated text.`]}),`\n`,_jsxs(_components.p,{children:[`Sample, logprobs, and forward bodies use the typed\n`,_jsx(_components.a,{href:`/concepts/json-primitives`,children:`JSON primitive contract`}),`.`]}),`\n`,_jsx(Heading,{level:`2`,id:`checkpoints`,children:`Checkpoints`}),`\n`,_jsx(CodeBlock,{filename:``,numberOfLines:`2`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`2`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`save_state → export_lora → finish → close session`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})}),`\n`,_jsxs(_components.p,{children:[`Optionally call `,_jsx(_components.code,{children:`save_weights_for_sampler`}),` before each sample cycle.`]}),`\n`,_jsx(Heading,{level:`2`,id:`cleanup`,children:`Cleanup`}),`\n`,_jsxs(_components.p,{children:[`On failure: `,_jsx(_components.code,{children:`cancel`}),` the run, poll until terminal, then `,_jsx(_components.code,{children:`close`}),` the session.`]}),`\n`,_jsx(Warning,{children:_jsx(_components.p,{children:`If the algorithm-specific loss cannot be represented in the current Whitney JSON and operation contract, stop before\ncreating a session. Never silently substitute generic GRPO.`})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"GRPO","description":"Run a caller-owned group-relative policy optimization loop.","href":"/cookbooks/grpo"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Overview","slug":"overview","depth":2,"children":[]},{"title":"Prerequisites","slug":"prerequisites","depth":2,"children":[]},{"title":"Training loop","slug":"training-loop","depth":2,"children":[{"title":"Caller-owned math","slug":"caller-owned-math","depth":3,"children":[]},{"title":"Log probabilities","slug":"log-probabilities","depth":3,"children":[]}]},{"title":"Checkpoints","slug":"checkpoints","depth":2,"children":[]},{"title":"Cleanup","slug":"cleanup","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"subdomain":"whitney-ai","siteName":"Whitney","title":"GRPO - Whitney","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-09-05T19:01:55.771Z","originalFileLocation":"cookbooks/grpo.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Run a caller-owned group-relative policy optimization loop.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Whitney\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003cmeta data-mint-head name=\"robots\" content=\"noindex, nofollow\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whitney-ai/_generated/favicon/apple-touch-icon.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whitney-ai/_generated/favicon/favicon-32x32.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whitney-ai/_generated/favicon/favicon-16x16.png?v=3\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/whitney-ai/_generated/favicon/favicon.ico?v=3\">\u003cmeta data-mint-head property=\"og:title\" content=\"GRPO - Whitney\">\u003cmeta data-mint-head property=\"og:description\" content=\"Run a caller-owned group-relative policy optimization loop.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Whitney\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://staging.docs.trywhitney.com/cookbooks/grpo\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://whitney-ai.mintlify.app/_mintlify/api/og/v2?division=Cookbooks\u0026amp;title=GRPO\u0026amp;description=Run+a+caller-owned+group-relative+policy+optimization+loop.\u0026amp;theme=72f845fa4fed9e550803d595\u0026amp;signature=59fa804bad50128c669328f0248fc55178280eb38f039538069a31a9cf2c8eb1\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"GRPO - Whitney\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Run a caller-owned group-relative policy optimization loop.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://whitney-ai.mintlify.app/_mintlify/api/og/v2?division=Cookbooks\u0026amp;title=GRPO\u0026amp;description=Run+a+caller-owned+group-relative+policy+optimization+loop.\u0026amp;theme=72f845fa4fed9e550803d595\u0026amp;signature=59fa804bad50128c669328f0248fc55178280eb38f039538069a31a9cf2c8eb1\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/whitney-ai/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Whitney\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#18181b\">\u003clink data-mint-head rel=\"canonical\" href=\"https://staging.docs.trywhitney.com/cookbooks/grpo\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/cookbooks/grpo.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://staging.docs.trywhitney.com/#organization\",\"name\":\"Whitney\",\"url\":\"https://staging.docs.trywhitney.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/whitney-ai/31oF5lBZ51KYlN_v/logo.png?fit=max\u0026auto=format\u0026n=31oF5lBZ51KYlN_v\u0026q=85\u0026s=2834a6f45fc024ab73570b4179951fb9\"}},{\"@type\":\"WebSite\",\"@id\":\"https://staging.docs.trywhitney.com#website\",\"name\":\"Whitney\",\"url\":\"https://staging.docs.trywhitney.com\",\"publisher\":{\"@id\":\"https://staging.docs.trywhitney.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://staging.docs.trywhitney.com/cookbooks/grpo#webpage\",\"url\":\"https://staging.docs.trywhitney.com/cookbooks/grpo\",\"name\":\"GRPO\",\"description\":\"Run a caller-owned group-relative policy optimization loop.\",\"dateModified\":\"2026-09-05T19:01:55.771Z\",\"isPartOf\":{\"@id\":\"https://staging.docs.trywhitney.com#website\"},\"breadcrumb\":{\"@id\":\"https://staging.docs.trywhitney.com/cookbooks/grpo#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://staging.docs.trywhitney.com/cookbooks/grpo#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Cookbooks\",\"item\":\"https://staging.docs.trywhitney.com/cookbooks/index\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GRPO\",\"item\":\"https://staging.docs.trywhitney.com/cookbooks/grpo\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://staging.docs.trywhitney.com/cookbooks/grpo#article\",\"headline\":\"GRPO\",\"name\":\"GRPO\",\"description\":\"Run a caller-owned group-relative policy optimization loop.\",\"url\":\"https://staging.docs.trywhitney.com/cookbooks/grpo\",\"mainEntityOfPage\":{\"@id\":\"https://staging.docs.trywhitney.com/cookbooks/grpo#webpage\"},\"dateModified\":\"2026-09-05T19:01:55.771Z\",\"publisher\":{\"@id\":\"https://staging.docs.trywhitney.com/#organization\"},\"isPartOf\":{\"@id\":\"https://staging.docs.trywhitney.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Whitney\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Whitney","nav":{"global":null,"tabs":[{"tab":"Guides","groups":[{"group":"Get started","pages":[{"title":"Whitney Training API","href":""},{"title":"Quickstart","href":"/quickstart"},{"title":"Supported models","href":"/models"}]},{"group":"How it works","pages":[{"title":"Sessions, runs, and operations","href":"/concepts/lifecycle"},{"title":"JSON primitives","href":"/concepts/json-primitives"},{"title":"Limits and expectations","href":"/concepts/limits"}]},{"group":"Cookbooks","pages":[{"title":"Algorithm cookbooks","href":"/cookbooks/index"},{"title":"Loop building blocks","href":"/cookbooks/helpers"},{"title":"Supervised fine-tuning","description":"Run a caller-owned cross-entropy SFT loop.","href":"/cookbooks/sft"},{"title":"GRPO","href":"/cookbooks/grpo"},{"title":"Evaluation","description":"Score model outputs with a caller-owned evaluation loop.","href":"/cookbooks/evaluation"},{"title":"More algorithms","href":"/cookbooks/algorithms"}]},{"group":"Distillation","pages":[{"title":"Distillation on Whitney","href":"/distillation/index"},{"title":"On-policy distillation (OPD)","href":"/distillation/opd"},{"title":"On-policy self-distillation (OPSD)","href":"/distillation/opsd"},{"title":"SDPO (Self-Distillation Policy Optimization)","href":"/distillation/sdpo"}]},{"group":"Coding agents","pages":[{"title":"Use Whitney with a coding agent","href":"/agents/coding-agents"}]}]},{"tab":"API Reference","pages":[{"title":"API Reference","href":"/api-reference/unified-training/list-supported-providermodel-pairs-and-primitive-capabilities"}]}]},"basePath":"","title":"GRPO - Whitney","buildId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","deploymentId":"dpl_DeHjVRGfFnhYQwHnfC2pjeXXv8h9","dynamics":[],"chunks":[]}