UNPKG

@sap-ai-sdk/orchestration

Version:

SAP Cloud SDK for AI is the official Software Development Kit (SDK) for **SAP AI Core**, **SAP Generative AI Hub**, and **Orchestration Service**.

168 lines 6.02 kB
import { createLogger } from '@sap-cloud-sdk/util'; const logger = createLogger({ package: 'orchestration', messageContext: 'stream-util' }); /** * @internal */ export function mergeStreamResponse(response, chunk) { const data = response._data; data.request_id = chunk.request_id; data.module_results = mergeModuleResults(data.module_results, chunk.module_results); data.orchestration_result = mergeLlmModule(data.orchestration_result, chunk.orchestration_result); } function mergeModuleResults(existing, incoming) { const mergedModuleResults = { ...existing }; for (const [moduleName, moduleResult] of Object.entries(incoming || {})) { switch (moduleName) { case 'llm': mergedModuleResults[moduleName] = mergeLlmModule(mergedModuleResults[moduleName], moduleResult); break; case 'output_unmasking': mergedModuleResults[moduleName] = mergeLlmChoices(mergedModuleResults[moduleName], moduleResult); break; default: mergedModuleResults[moduleName] = moduleResult; } } return mergedModuleResults; } function mergeLlmModule(existing, incoming) { if (!incoming) { return existing; } const mergedModuleResults = { ...incoming, usage: mergeTokenUsage(existing?.usage, incoming.usage), choices: mergeLlmChoices(existing?.choices, incoming?.choices) }; return mergedModuleResults; } function mergeTokenUsage(existing, incoming) { if (incoming) { logger.debug(`Token usage: ${JSON.stringify(incoming)}`); } return { prompt_tokens: incoming?.prompt_tokens ?? existing?.prompt_tokens ?? 0, completion_tokens: incoming?.completion_tokens ?? existing?.completion_tokens ?? 0, total_tokens: incoming?.total_tokens ?? existing?.total_tokens ?? 0 }; } function mergeLlmChoices(existing, incoming) { const mergedChoices = [...(existing ?? [])]; for (const choice of incoming ?? []) { const existingChoice = mergedChoices.find(c => c.index === choice.index); if (existingChoice) { // Merge existing choice with incoming choice existingChoice.finish_reason = handleFinishReason(existingChoice.finish_reason, choice.finish_reason, choice.index); existingChoice.logprobs = mergeLogProbs(existingChoice.logprobs, choice.logprobs); existingChoice.message = mergeMessage(existingChoice.message, choice.delta); } else { // Add new choice mergedChoices.push(transformStreamingChoice(choice)); } } return mergedChoices; } function mergeMessage(existing, incoming) { if (!incoming) { return existing; } return { role: existing.role, content: existing.content + (incoming.content ?? ''), tool_calls: mergeToolCalls(existing.tool_calls, incoming.tool_calls), refusal: incoming.refusal ?? existing.refusal }; } function mergeToolCalls(existing, incoming) { if (!incoming || incoming.length === 0) { return existing; } if (!existing || existing.length === 0) { return transformStreamingToolCalls(incoming); } const mergedToolCalls = [...existing]; for (const toolCall of incoming) { const existingToolCall = mergedToolCalls.find(tc => tc.index === toolCall.index); if (existingToolCall) { // Merge existing tool call with incoming tool call existingToolCall.function.name = toolCall.function?.name ?? existingToolCall.function.name; existingToolCall.function.arguments = existingToolCall.function.arguments + (toolCall.function?.arguments ?? ''); } else { // Add new tool call mergedToolCalls.push(transformStreamingToolCall(toolCall)); } } return mergedToolCalls; } function mergeLogProbs(existing, incoming) { if (!incoming) { return existing; } if (!existing) { return incoming; } return { content: [...(existing.content ?? []), ...(incoming.content ?? [])], refusal: [...(existing.refusal ?? []), ...(incoming.refusal ?? [])] }; } function handleFinishReason(existing, incoming, choiceIndex) { if (!incoming) { return existing ?? ''; } switch (incoming) { case 'content_filter': logger.error(`Choice ${choiceIndex}: Stream finished with content filter hit.`); break; case 'length': logger.error(`Choice ${choiceIndex}: Stream finished with token length exceeded.`); break; case 'stop': case 'tool_calls': case 'function_call': logger.debug(`Choice ${choiceIndex}: Stream finished.`); break; default: logger.error(`Choice ${choiceIndex}: Stream finished with unknown reason '${incoming}'.`); } return incoming; } function transformStreamingChoice(choice) { return { index: choice.index, message: { role: 'assistant', content: choice.delta.content, tool_calls: transformStreamingToolCalls(choice.delta.tool_calls), refusal: choice.delta.refusal }, finish_reason: choice.finish_reason ?? '', logprobs: choice.logprobs }; } function transformStreamingToolCalls(toolCalls) { if (!toolCalls || toolCalls.length === 0) { return undefined; } return toolCalls?.map(toolCall => transformStreamingToolCall(toolCall)); } function transformStreamingToolCall(toolCall) { return { index: toolCall.index, id: toolCall.id ?? '', type: toolCall.type ?? 'function', function: { name: toolCall.function?.name ?? '', arguments: toolCall.function?.arguments ?? '' } }; } //# sourceMappingURL=stream.js.map