langchain
Version:
Typescript bindings for langchain
1 lines • 3.83 kB
Source Map (JSON)
{"version":3,"file":"modelRefusal.cjs","names":["ModelRefusalError","MiddlewareError","StructuredOutputParsingError","createMiddleware","AIMessage"],"sources":["../../../src/agents/middleware/modelRefusal.ts"],"sourcesContent":["import { ModelRefusalError } from \"@langchain/core/errors\";\nimport {\n AIMessage,\n type BaseMessage,\n type ContentBlock,\n} from \"@langchain/core/messages\";\n\nimport { MiddlewareError, StructuredOutputParsingError } from \"../errors.js\";\nimport { createMiddleware } from \"../middleware.js\";\n\nfunction throwIfRefused(message: BaseMessage | undefined): void {\n if (!message) return;\n for (const block of message.contentBlocks) {\n if (block.type === \"refusal\") {\n throw ModelRefusalError.fromRefusal(\n block as ContentBlock.Refusal,\n message\n );\n }\n }\n}\n\n/**\n * The `StructuredOutputParsingError` behind `error`, if any.\n *\n * Middleware listed after this one wraps errors in `MiddlewareError`, so the\n * parsing error can sit further down the `cause` chain.\n */\nfunction parsingError(\n error: unknown\n): StructuredOutputParsingError | undefined {\n let current = error;\n while (MiddlewareError.isInstance(current)) current = current.cause;\n return current instanceof StructuredOutputParsingError ? current : undefined;\n}\n\n/**\n * Middleware that throws {@link ModelRefusalError} when the model refuses.\n *\n * Providers report a refusal, such as a safety-policy refusal, as a successful\n * response, so without this middleware the agent run ends as if it succeeded.\n * The middleware checks each model response for a `refusal` content block,\n * including refusals that fail to parse under a structured `responseFormat`.\n * It does not detect refusals the model writes as ordinary text.\n *\n * List it after {@link modelFallbackMiddleware} so the fallback catches the\n * error and retries the request on the next model. `modelRetryMiddleware` does\n * not retry refusals.\n *\n * @example\n * ```ts\n * import {\n * createAgent,\n * modelFallbackMiddleware,\n * modelRefusalMiddleware,\n * } from \"langchain\";\n *\n * const agent = createAgent({\n * model: \"anthropic:claude-sonnet-5-5\",\n * tools: [],\n * middleware: [\n * modelFallbackMiddleware(\"openai:gpt-6.1-sol\"),\n * modelRefusalMiddleware(),\n * ],\n * });\n * ```\n */\nexport function modelRefusalMiddleware() {\n return createMiddleware({\n name: \"modelRefusalMiddleware\",\n wrapModelCall: async (request, handler) => {\n let response;\n try {\n response = await handler(request);\n } catch (error) {\n throwIfRefused(parsingError(error)?.aiMessage);\n throw error;\n }\n // A parsed structured response comes back as `{ structuredResponse, messages }`.\n const messages: unknown[] = AIMessage.isInstance(response)\n ? [response]\n : ((response as { messages?: unknown[] }).messages ?? []);\n for (const message of messages) {\n if (AIMessage.isInstance(message)) throwIfRefused(message);\n }\n return response;\n },\n });\n}\n"],"mappings":";;;;;AAUA,SAAS,eAAe,SAAwC;CAC9D,IAAI,CAAC,SAAS;CACd,KAAK,MAAM,SAAS,QAAQ,eAC1B,IAAI,MAAM,SAAS,WACjB,MAAMA,uBAAAA,kBAAkB,YACtB,OACA,OACF;AAGN;;;;;;;AAQA,SAAS,aACP,OAC0C;CAC1C,IAAI,UAAU;CACd,OAAOC,eAAAA,gBAAgB,WAAW,OAAO,GAAG,UAAU,QAAQ;CAC9D,OAAO,mBAAmBC,eAAAA,+BAA+B,UAAU,KAAA;AACrE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,yBAAyB;CACvC,OAAOC,mBAAAA,iBAAiB;EACtB,MAAM;EACN,eAAe,OAAO,SAAS,YAAY;GACzC,IAAI;GACJ,IAAI;IACF,WAAW,MAAM,QAAQ,OAAO;GAClC,SAAS,OAAO;IACd,eAAe,aAAa,KAAK,CAAC,EAAE,SAAS;IAC7C,MAAM;GACR;GAEA,MAAM,WAAsBC,yBAAAA,UAAU,WAAW,QAAQ,IACrD,CAAC,QAAQ,IACP,SAAsC,YAAY,CAAC;GACzD,KAAK,MAAM,WAAW,UACpB,IAAIA,yBAAAA,UAAU,WAAW,OAAO,GAAG,eAAe,OAAO;GAE3D,OAAO;EACT;CACF,CAAC;AACH"}