Skip to content

Commit ec4663b

Browse files
committed
option 1: send in stream chunk
1 parent a716a13 commit ec4663b

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

src/handlers/handlerUtils.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,7 @@ export async function recursiveAfterRequestHookHandler(
11891189
responseJson: mappedResponseJson,
11901190
originalResponseJson,
11911191
} = await responseHandler(
1192+
c,
11921193
response,
11931194
isStreamingMode,
11941195
providerOption,
@@ -1198,7 +1199,8 @@ export async function recursiveAfterRequestHookHandler(
11981199
gatewayParams,
11991200
strictOpenAiCompliance,
12001201
c.req.url,
1201-
areSyncHooksAvailable
1202+
areSyncHooksAvailable,
1203+
hookSpanId
12021204
);
12031205

12041206
const arhResponse = await afterRequestHookHandler(

src/handlers/responseHandlers.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { HookSpan } from '../middlewares/hooks';
1818
import { env } from 'hono/adapter';
1919
import { OpenAIModelResponseJSONToStreamGenerator } from '../providers/open-ai-base/createModelResponse';
2020
import { anthropicMessagesJsonToStreamGenerator } from '../providers/anthropic-base/utils/streamGenerator';
21+
import { endpointStrings } from '../providers/types';
2122

2223
/**
2324
* Handles various types of responses based on the specified parameters
@@ -35,6 +36,7 @@ import { anthropicMessagesJsonToStreamGenerator } from '../providers/anthropic-b
3536
* @returns {Promise<{response: Response, json?: any}>} - The mapped response.
3637
*/
3738
export async function responseHandler(
39+
c: Context,
3840
response: Response,
3941
streamingMode: boolean,
4042
providerOptions: Options,
@@ -44,7 +46,8 @@ export async function responseHandler(
4446
gatewayRequest: Params,
4547
strictOpenAiCompliance: boolean,
4648
gatewayRequestUrl: string,
47-
areSyncHooksAvailable: boolean
49+
areSyncHooksAvailable: boolean,
50+
hookSpanId: string
4851
): Promise<{
4952
response: Response;
5053
responseJson: Record<string, any> | null;
@@ -110,14 +113,19 @@ export async function responseHandler(
110113
return { response: streamingResponse, responseJson: null };
111114
}
112115
if (streamingMode && isSuccessStatusCode) {
116+
const hooksManager = c.get('hooksManager');
117+
const span = hooksManager.getSpan(hookSpanId) as HookSpan;
118+
const hooksResult = span.getHooksResult();
113119
return {
114120
response: handleStreamingMode(
115121
response,
116122
provider,
117123
responseTransformerFunction,
118124
requestURL,
119125
strictOpenAiCompliance,
120-
gatewayRequest
126+
gatewayRequest,
127+
responseTransformer as endpointStrings,
128+
hooksResult
121129
),
122130
responseJson: null,
123131
};

src/handlers/services/responseService.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export class ResponseService {
8181
}> {
8282
const url = this.context.requestURL;
8383
return await responseHandler(
84+
this.context.honoContext,
8485
response,
8586
this.context.isStreaming,
8687
this.context.providerOption,
@@ -90,7 +91,8 @@ export class ResponseService {
9091
this.context.params,
9192
this.context.strictOpenAiCompliance,
9293
this.context.honoContext.req.url,
93-
this.hooksService.areSyncHooksAvailable
94+
this.hooksService.areSyncHooksAvailable,
95+
this.hooksService.hookSpan?.id as string
9496
);
9597
}
9698

src/handlers/streamHandler.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,11 @@ import {
88
PRECONDITION_CHECK_FAILED_STATUS_CODE,
99
GOOGLE_VERTEX_AI,
1010
} from '../globals';
11+
import { HookSpan } from '../middlewares/hooks';
1112
import { VertexLlamaChatCompleteStreamChunkTransform } from '../providers/google-vertex-ai/chatComplete';
1213
import { OpenAIChatCompleteResponse } from '../providers/openai/chatComplete';
1314
import { OpenAICompleteResponse } from '../providers/openai/complete';
15+
import { endpointStrings } from '../providers/types';
1416
import { Params } from '../types/requestBody';
1517
import { getStreamModeSplitPattern, type SplitPatternType } from '../utils';
1618

@@ -292,7 +294,9 @@ export function handleStreamingMode(
292294
responseTransformer: Function | undefined,
293295
requestURL: string,
294296
strictOpenAiCompliance: boolean,
295-
gatewayRequest: Params
297+
gatewayRequest: Params,
298+
fn: endpointStrings,
299+
hooksResult: HookSpan['hooksResult']
296300
): Response {
297301
const splitPattern = getStreamModeSplitPattern(proxyProvider, requestURL);
298302
// If the provider doesn't supply completion id,
@@ -311,6 +315,12 @@ export function handleStreamingMode(
311315
if (proxyProvider === BEDROCK) {
312316
(async () => {
313317
try {
318+
if (!strictOpenAiCompliance) {
319+
const hookResultChunk = constructHookResultChunk(hooksResult, fn);
320+
if (hookResultChunk) {
321+
await writer.write(encoder.encode(hookResultChunk));
322+
}
323+
}
314324
for await (const chunk of readAWSStream(
315325
reader,
316326
responseTransformer,
@@ -337,6 +347,12 @@ export function handleStreamingMode(
337347
} else {
338348
(async () => {
339349
try {
350+
if (!strictOpenAiCompliance) {
351+
const hookResultChunk = constructHookResultChunk(hooksResult, fn);
352+
if (hookResultChunk) {
353+
await writer.write(encoder.encode(hookResultChunk));
354+
}
355+
}
340356
for await (const chunk of readStream(
341357
reader,
342358
splitPattern,
@@ -434,3 +450,23 @@ export async function handleJSONToStreamResponse(
434450
statusText: response.statusText,
435451
});
436452
}
453+
454+
const constructHookResultChunk = (
455+
hooksResult: HookSpan['hooksResult'],
456+
fn: endpointStrings
457+
) => {
458+
if (fn === 'chatComplete' || fn === 'complete' || fn === 'embed') {
459+
return `data: ${JSON.stringify({
460+
hook_results: {
461+
before_request_hooks: hooksResult.beforeRequestHooksResult,
462+
},
463+
})}\n\n`;
464+
} else if (fn === 'messages') {
465+
return `event: hook_results\ndata: ${JSON.stringify({
466+
hook_results: {
467+
before_request_hooks: hooksResult.beforeRequestHooksResult,
468+
},
469+
})}\n\n`;
470+
}
471+
return null;
472+
};

0 commit comments

Comments
 (0)