Skip to content

Commit 67337d5

Browse files
committed
fix: 修正 OpenAI Langfuse 输入记录
1 parent b3c9af4 commit 67337d5

3 files changed

Lines changed: 48 additions & 6 deletions

File tree

src/services/api/openai/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ export async function* queryModelOpenAI(
400400
recordLLMObservation(options.langfuseTrace ?? null, {
401401
model: openaiModel,
402402
provider: 'openai',
403-
input: convertMessagesToLangfuse(messagesForAPI, systemPrompt),
403+
input: convertMessagesToLangfuse(openaiMessages),
404404
output: convertOutputToLangfuse(collectedMessages),
405405
usage: {
406406
input_tokens: usage.input_tokens,

src/services/langfuse/__tests__/langfuse.test.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,32 @@ describe('Langfuse integration', () => {
184184
})
185185
})
186186

187+
describe('convertMessagesToLangfuse', () => {
188+
test('preserves OpenAI-style messages including deferred tool announcements', async () => {
189+
const { convertMessagesToLangfuse } = await import('../convert.js')
190+
const result = convertMessagesToLangfuse([
191+
{
192+
role: 'system',
193+
content: 'system prompt',
194+
},
195+
{
196+
role: 'user',
197+
content:
198+
'<available-deferred-tools>\nmcp__wechat__send_message\n</available-deferred-tools>',
199+
},
200+
])
201+
202+
expect(result).toEqual([
203+
{ role: 'system', content: 'system prompt' },
204+
{
205+
role: 'user',
206+
content:
207+
'<available-deferred-tools>\nmcp__wechat__send_message\n</available-deferred-tools>',
208+
},
209+
])
210+
})
211+
})
212+
187213
// ── client tests ────────────────────────────────────────────────────────────
188214

189215
describe('isLangfuseEnabled', () => {

src/services/langfuse/convert.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ type LangfuseChatMessage = {
3030
tool_call_id?: string
3131
}
3232

33+
type LangfuseInputMessage =
34+
| UserMessage
35+
| AssistantMessage
36+
| LangfuseChatMessage
37+
3338
/** Normalize a content block into a LangfuseContentPart (non-tool_use, non-tool_result) */
3439
function toContentPart(block: Record<string, unknown>): LangfuseContentPart | null {
3540
const type = block.type as string | undefined
@@ -127,9 +132,9 @@ function toRole(msg: Message): 'user' | 'assistant' | 'system' {
127132
return 'user'
128133
}
129134

130-
/** Convert messagesForAPI (UserMessage | AssistantMessage)[] → Langfuse input format */
135+
/** Convert internal or OpenAI-style messages → Langfuse input format */
131136
export function convertMessagesToLangfuse(
132-
messages: (UserMessage | AssistantMessage)[],
137+
messages: LangfuseInputMessage[],
133138
systemPrompt?: readonly string[],
134139
): LangfuseChatMessage[] {
135140
const result: LangfuseChatMessage[] = []
@@ -139,12 +144,23 @@ export function convertMessagesToLangfuse(
139144
}
140145
}
141146
for (const msg of messages) {
142-
const inner = msg.message
147+
const inner = 'message' in msg ? msg.message : msg
143148
if (!inner) continue
144-
const role = (inner.role as 'user' | 'assistant' | undefined) ?? toRole(msg)
149+
const role =
150+
(inner.role as 'user' | 'assistant' | 'system' | 'tool' | undefined) ??
151+
('message' in msg ? toRole(msg) : 'user')
145152
const rawContent = inner.content
146153
if (typeof rawContent === 'string' || !Array.isArray(rawContent)) {
147-
result.push({ role, content: String(rawContent ?? '') })
154+
result.push({
155+
role,
156+
content: String(rawContent ?? ''),
157+
...('tool_call_id' in inner && typeof inner.tool_call_id === 'string'
158+
? { tool_call_id: inner.tool_call_id }
159+
: {}),
160+
...('tool_calls' in inner && Array.isArray(inner.tool_calls)
161+
? { tool_calls: inner.tool_calls as LangfuseToolCall[] }
162+
: {}),
163+
})
148164
continue
149165
}
150166

0 commit comments

Comments
 (0)