TheFireCo / genkit-plugins

Community Plugins for Genkit (OpenAI, Groq, Anthropic, Cohere, etc)
https://thefireco.github.io/genkit-plugins/
Apache License 2.0
90 stars 12 forks source link

Genkitx-openai `generate` response candidate not properly generated when `streamingCallback` is used #137

Open pedi opened 4 weeks ago

pedi commented 4 weeks ago

Affected plugin(s)

Describe the bug Using the sample flow generated by Genkit

const prompt =
      `Suggest an item for the menu of a ${subject} themed restaurant`;
    const llmResponse = await generate({
      model: gpt4o,
      prompt: prompt,
      config: {
        temperature: 1,
      },
      streamingCallback: streamingCallback,
    });

    console.log('history: ', llmResponse.toHistory());

The output of the history will be

history:  [
  { role: 'user', content: [ [Object] ] },
  { role: 'model', content: [] }
]

The user's original prompt is recorded but the model's response is empty

The issue is due to the following line https://github.com/TheFireCo/genkit-plugins/blob/main/plugins/openai/src/gpt.ts#L379

When calling

response = await stream.finalChatCompletion();

The response looks like below

response {
  role: 'assistant',
  content: 'Item: "The Exam Platter"\n' +
    '\n' +
    'Description: A sampler platter that offers a bit of everything to test your taste buds. It includes:\n' +
    '\n' +
    '- Pop Quiz Poppers: Bite-sized jalapeño poppers with a surprise spicy kick.\n' +
    '- Study Group Sliders: Mini beef, chicken, and veggie sliders, each with unique toppings to represent different study preferences.\n' +
    '- Multiple Choice Mozzarella Sticks: Classic mozzarella sticks served with a variety of dipping sauces - marinara, ranch, and spicy buffalo.\n' +
    '- Flashcard Fries: A generous portion of seasoned curly fries, waffle fries, and sweet potato fries for a mix-and-match experience.\n' +
    '- True/False Tenders: Chicken tenders served with an assortment of savory dips like honey mustard, BBQ, and buffalo.\n' +
    '\n' +
    'Perfect for those who love a bit of variety and want to ace the culinary experience!',
  refusal: null,
  parsed: null,
  tool_calls: []
}

Which contains an empty array of tool_calls.

The current code only check for truthiness of toolRequestParts, but we should also check its length instead.