diff --git a/.changeset/nine-carpets-jam.md b/.changeset/nine-carpets-jam.md
new file mode 100644
index 0000000000000000000000000000000000000000..67e2b248369e3c23628dd7449b15af897bfe1c74
--- /dev/null
+++ b/.changeset/nine-carpets-jam.md
@@ -0,0 +1,5 @@
+---
+"@llamaindex/openai": patch
+---
+
+fix: openai streaming with token usage and finish_reason
diff --git a/packages/llm/openai/src/llm.ts b/packages/llm/openai/src/llm.ts
index bcd6e494f5a1f93a4ca39b924521f6e2828efe05..a10f658db32593f0ad8a5a0c47fa867c5f0ef3fa 100644
--- a/packages/llm/openai/src/llm.ts
+++ b/packages/llm/openai/src/llm.ts
@@ -425,10 +425,25 @@ export class OpenAI extends ToolCallLLM<OpenAIAdditionalChatOptions> {
     let currentToolCall: PartialToolCall | null = null;
     const toolCallMap = new Map<string, PartialToolCall>();
     for await (const part of stream) {
-      if (part.choices.length === 0) continue;
+      if (part.choices.length === 0) {
+        if (part.usage) {
+          yield {
+            raw: part,
+            delta: "",
+          };
+        }
+        continue;
+      }
       const choice = part.choices[0]!;
       // skip parts that don't have any content
-      if (!(choice.delta.content || choice.delta.tool_calls)) continue;
+      if (
+        !(
+          choice.delta.content ||
+          choice.delta.tool_calls ||
+          choice.finish_reason
+        )
+      )
+        continue;
 
       let shouldEmitToolCall: PartialToolCall | null = null;
       if (