-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
feat(core): Add byte size limit and oldest first truncation for gen_ai messages #17863
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 5 commits
29e4eda
bf1003e
c50ad1b
18265ac
f1b468f
50d1d6d
7df9993
c91de63
bbea7cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export function getByteSize(str: string): number { | ||
return new TextEncoder().encode(str).length; | ||
} | ||
|
||
export function truncateMessagesByBytes(messages: unknown[], maxBytes: number): unknown[] { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add JSDocs for this files?
RulaKhaled marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (!Array.isArray(messages) || messages.length === 0) { | ||
return messages; | ||
} | ||
|
||
const messagesJson = JSON.stringify(messages); | ||
const totalBytes = getByteSize(messagesJson); | ||
RulaKhaled marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
if (totalBytes <= maxBytes) { | ||
return messages; | ||
} | ||
|
||
let truncatedMessages = [...messages]; | ||
RulaKhaled marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
while (truncatedMessages.length > 0) { | ||
const truncatedJson = JSON.stringify(truncatedMessages); | ||
const truncatedBytes = getByteSize(truncatedJson); | ||
|
||
if (truncatedBytes <= maxBytes) { | ||
break; | ||
} | ||
|
||
truncatedMessages.shift(); | ||
RulaKhaled marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
return truncatedMessages; | ||
cursor[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
export const DEFAULT_GEN_AI_MESSAGES_BYTE_LIMIT = 100000; | ||
RulaKhaled marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
export function truncateGenAiMessages(messages: unknown[]): unknown[] { | ||
return truncateMessagesByBytes(messages, DEFAULT_GEN_AI_MESSAGES_BYTE_LIMIT); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,7 @@ import { | |
GEN_AI_USAGE_OUTPUT_TOKENS_ATTRIBUTE, | ||
GEN_AI_USAGE_TOTAL_TOKENS_ATTRIBUTE, | ||
} from '../ai/gen-ai-attributes'; | ||
import { truncateGenAiMessages } from '../ai/messageTruncation'; | ||
import { buildMethodPath, getFinalOperationName, getSpanOperation } from '../ai/utils'; | ||
import { handleCallbackErrors } from '../handleCallbackErrors'; | ||
import { CHAT_PATH, CHATS_CREATE_METHOD, GOOGLE_GENAI_SYSTEM_NAME } from './constants'; | ||
|
@@ -128,25 +129,23 @@ function extractRequestAttributes( | |
return attributes; | ||
} | ||
|
||
/** | ||
* Add private request attributes to spans. | ||
* This is only recorded if recordInputs is true. | ||
* Handles different parameter formats for different Google GenAI methods. | ||
*/ | ||
function addPrivateRequestAttributes(span: Span, params: Record<string, unknown>): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you also revert back this JSDoc comment? |
||
// For models.generateContent: ContentListUnion: Content | Content[] | PartUnion | PartUnion[] | ||
if ('contents' in params) { | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(params.contents) }); | ||
const contents = params.contents; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you revert the comment removal to help others understand the request structure? this could also be a string |
||
const truncatedContents = truncateGenAiMessages(contents as unknown[]); | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedContents) }); | ||
} | ||
|
||
// For chat.sendMessage: message can be string or Part[] | ||
if ('message' in params) { | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(params.message) }); | ||
const message = params.message; | ||
RulaKhaled marked this conversation as resolved.
Show resolved
Hide resolved
|
||
const truncatedMessage = truncateGenAiMessages(message as unknown[]); | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedMessage) }); | ||
|
||
} | ||
|
||
// For chats.create: history contains the conversation history | ||
if ('history' in params) { | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(params.history) }); | ||
const history = params.history; | ||
const truncatedHistory = truncateGenAiMessages(history as unknown[]); | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedHistory) }); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,6 +19,7 @@ import { | |
GEN_AI_RESPONSE_TOOL_CALLS_ATTRIBUTE, | ||
GEN_AI_SYSTEM_ATTRIBUTE, | ||
} from '../ai/gen-ai-attributes'; | ||
import { truncateGenAiMessages } from '../ai/messageTruncation'; | ||
import { OPENAI_INTEGRATION_NAME } from './constants'; | ||
import { instrumentStream } from './streaming'; | ||
import type { | ||
|
@@ -188,13 +189,16 @@ function addResponseAttributes(span: Span, result: unknown, recordOutputs?: bool | |
} | ||
} | ||
|
||
// Extract and record AI request inputs, if present. This is intentionally separate from response attributes. | ||
function addRequestAttributes(span: Span, params: Record<string, unknown>): void { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can you also revert back this JSDoc comment? |
||
if ('messages' in params) { | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(params.messages) }); | ||
const messages = params.messages; | ||
const truncatedMessages = truncateGenAiMessages(messages as unknown[]); | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedMessages) }); | ||
} | ||
if ('input' in params) { | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(params.input) }); | ||
const input = params.input; | ||
const truncatedInput = truncateGenAiMessages(input as unknown[]); | ||
span.setAttributes({ [GEN_AI_REQUEST_MESSAGES_ATTRIBUTE]: JSON.stringify(truncatedInput) }); | ||
cursor[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you mind adding tests for this? You can use the files under
dev-packages/node-integration-tests/suites/tracing