Skip to content

Commit e0b4510

Browse files
committed
add support for llm message and tool calls
1 parent d76c94d commit e0b4510

File tree

1 file changed

+60
-5
lines changed

1 file changed

+60
-5
lines changed

dd-trace-core/src/main/java/datadog/trace/llmobs/writer/ddintake/LLMObsSpanMapper.java

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datadog.communication.serialization.Writable;
66
import datadog.trace.api.DDTags;
77
import datadog.trace.api.intake.TrackType;
8+
import datadog.trace.api.llmobs.LLMObs;
89
import datadog.trace.api.llmobs.LLMObsTags;
910
import datadog.trace.bootstrap.instrumentation.api.InternalSpanTypes;
1011
import datadog.trace.bootstrap.instrumentation.api.Tags;
@@ -63,6 +64,17 @@ public class LLMObsSpanMapper implements RemoteMapper {
6364
private static final byte[] METRICS = "metrics".getBytes(StandardCharsets.UTF_8);
6465
private static final byte[] TAGS = "tags".getBytes(StandardCharsets.UTF_8);
6566

67+
private static final byte[] LLM_MESSAGE_ROLE = "role".getBytes(StandardCharsets.UTF_8);
68+
private static final byte[] LLM_MESSAGE_CONTENT = "content".getBytes(StandardCharsets.UTF_8);
69+
private static final byte[] LLM_MESSAGE_TOOL_CALLS =
70+
"tool_calls".getBytes(StandardCharsets.UTF_8);
71+
72+
private static final byte[] LLM_TOOL_CALL_NAME = "name".getBytes(StandardCharsets.UTF_8);
73+
private static final byte[] LLM_TOOL_CALL_TYPE = "type".getBytes(StandardCharsets.UTF_8);
74+
private static final byte[] LLM_TOOL_CALL_TOOL_ID = "tool_id".getBytes(StandardCharsets.UTF_8);
75+
private static final byte[] LLM_TOOL_CALL_ARGUMENTS =
76+
"arguments".getBytes(StandardCharsets.UTF_8);
77+
6678
private final LLMObsSpanMapper.MetaWriter metaWriter = new MetaWriter();
6779
private final int size;
6880

@@ -242,8 +254,7 @@ public void accept(Metadata metadata) {
242254
for (Map.Entry<String, Object> tag : metadata.getTags().entrySet()) {
243255
String key = tag.getKey();
244256
Object value = tag.getValue();
245-
if (!tagsToRemapToMeta.containsKey(key)
246-
&& key.startsWith(LLMOBS_TAG_PREFIX)) {
257+
if (!tagsToRemapToMeta.containsKey(key) && key.startsWith(LLMOBS_TAG_PREFIX)) {
247258
writable.writeObject(key.substring(LLMOBS_TAG_PREFIX.length()) + ":" + value, null);
248259
}
249260
}
@@ -266,8 +277,52 @@ public void accept(Metadata metadata) {
266277
if (key.equals(INPUT) || key.equals(OUTPUT)) {
267278
if (!spanKind.equals(Tags.LLMOBS_LLM_SPAN_KIND)) {
268279
key += ".value";
280+
writable.writeString(key, null);
281+
writable.writeObject(val, null);
269282
} else {
283+
if (!(val instanceof List)) {
284+
LOGGER.warn(
285+
"unexpectedly found incorrect type for LLM span IO {}, expecting list",
286+
val.getClass().getName());
287+
continue;
288+
}
289+
// llm span kind must have llm objects
290+
List<LLMObs.LLMMessage> messages = (List<LLMObs.LLMMessage>) val;
270291
key += ".messages";
292+
writable.writeString(key, null);
293+
writable.startArray(messages.size());
294+
for (LLMObs.LLMMessage message : messages) {
295+
List<LLMObs.ToolCall> toolCalls = message.getToolCalls();
296+
boolean hasToolCalls = null != toolCalls && !toolCalls.isEmpty();
297+
writable.startMap(hasToolCalls ? 3 : 2);
298+
writable.writeUTF8(LLM_MESSAGE_ROLE);
299+
writable.writeString(message.getRole(), null);
300+
writable.writeUTF8(LLM_MESSAGE_CONTENT);
301+
writable.writeString(message.getContent(), null);
302+
if (hasToolCalls) {
303+
writable.writeUTF8(LLM_MESSAGE_TOOL_CALLS);
304+
writable.startArray(toolCalls.size());
305+
for (LLMObs.ToolCall toolCall : toolCalls) {
306+
Map<String, Object> arguments = toolCall.getArguments();
307+
boolean hasArguments = null != arguments && !arguments.isEmpty();
308+
writable.startMap(hasArguments ? 4 : 3);
309+
writable.writeUTF8(LLM_TOOL_CALL_NAME);
310+
writable.writeString(toolCall.getName(), null);
311+
writable.writeUTF8(LLM_TOOL_CALL_TYPE);
312+
writable.writeString(toolCall.getType(), null);
313+
writable.writeUTF8(LLM_TOOL_CALL_TOOL_ID);
314+
writable.writeString(toolCall.getToolID(), null);
315+
if (hasArguments) {
316+
writable.writeUTF8(LLM_TOOL_CALL_ARGUMENTS);
317+
writable.startMap(arguments.size());
318+
for (Map.Entry<String, Object> argument : arguments.entrySet()) {
319+
writable.writeString(argument.getKey(), null);
320+
writable.writeObject(argument.getValue(), null);
321+
}
322+
}
323+
}
324+
}
325+
}
271326
}
272327
} else if (key.equals(LLMObsTags.METADATA) && val instanceof Map) {
273328
Map<String, Object> metadataMap = (Map) val;
@@ -277,10 +332,10 @@ public void accept(Metadata metadata) {
277332
writable.writeString(entry.getKey(), null);
278333
writable.writeObject(entry.getValue(), null);
279334
}
280-
continue;
335+
} else {
336+
writable.writeString(key, null);
337+
writable.writeObject(val, null);
281338
}
282-
writable.writeString(key, null);
283-
writable.writeObject(val, null);
284339
}
285340
}
286341
}

0 commit comments

Comments
 (0)