Skip to content

Commit 76e75da

Browse files
committed
add run steps
1 parent 75b85c7 commit 76e75da

File tree

13 files changed

+166
-22
lines changed

13 files changed

+166
-22
lines changed

examples/src/main/java/chat/StreamChatCompletionFunction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ public static ChatMessage handleToolCall(ToolCall call, List<Tool> validTools) {
101101
if (call.getType() != Tool.Type.FUNCTION)
102102
throw new HallucinationException("Unknown tool call type: " + call.getType());
103103

104-
FunctionCall function = call.getFunction();
104+
FunctionCall function = ((FunctionToolCall) call).getFunction();
105105
Map<String, JsonNode> arguments = function.tryParseArguments(validTools); // You can pass null here for less strict parsing
106106
String equation = arguments.get("equation").asText();
107107
double result = solveEquation(equation);

examples/src/main/kotlin/assistant/Thread.kt

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
11
package assistant
22

3+
import com.cjcrafter.openai.chat.tool.CodeInterpreterToolCall
4+
import com.cjcrafter.openai.chat.tool.FunctionToolCall
5+
import com.cjcrafter.openai.chat.tool.RetrievalToolCall
6+
import com.cjcrafter.openai.chat.tool.Tool
37
import com.cjcrafter.openai.openAI
48
import com.cjcrafter.openai.threads.create
9+
import com.cjcrafter.openai.threads.message.ImageContent
10+
import com.cjcrafter.openai.threads.message.TextContent
511
import com.cjcrafter.openai.threads.message.ThreadUser
12+
import com.cjcrafter.openai.threads.runs.MessageCreationDetails
13+
import com.cjcrafter.openai.threads.runs.ToolCallsDetails
614
import io.github.cdimascio.dotenv.dotenv
715

816
fun main() {
@@ -46,6 +54,47 @@ fun main() {
4654
Thread.sleep(2500)
4755
run = openai.threads.runs(thread).retrieve(run)
4856
}
49-
}
5057

58+
// Once the run stops, we want to retrieve the steps of the run. This
59+
// includes message outputs, function calls, code interpreters, etc.
60+
val steps = openai.threads.runs(thread).steps(run).list()
61+
steps.data.forEach { step ->
62+
when (val details = step.stepDetails) {
63+
is MessageCreationDetails -> {
64+
val messageId = details.messageCreation.messageId
65+
val message = openai.threads.messages(thread).retrieve(messageId)
66+
for (content in message.content) {
67+
68+
when (content) {
69+
is TextContent -> println(content.text.value)
70+
is ImageContent -> println(content.imageFile.fileId)
71+
else -> println("Unhandled content type: $content")
72+
}
73+
74+
}
75+
}
76+
77+
is ToolCallsDetails -> {
78+
for (toolCall in details.toolCalls) {
79+
when (toolCall) {
80+
is FunctionToolCall -> {
81+
82+
}
83+
is RetrievalToolCall -> {
84+
85+
}
86+
is CodeInterpreterToolCall -> {
87+
}
88+
}
89+
println(toolCall)
90+
}
91+
}
92+
93+
else -> {
94+
println("Unhandled step type: ${step.stepDetails.type}")
95+
}
96+
}
97+
println("Step: $step")
98+
}
99+
}
51100
}

examples/src/main/kotlin/chat/StreamChatCompletionFunction.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package chat
33
import com.cjcrafter.openai.chat.*
44
import com.cjcrafter.openai.chat.ChatMessage.Companion.toSystemMessage
55
import com.cjcrafter.openai.chat.ChatMessage.Companion.toUserMessage
6+
import com.cjcrafter.openai.chat.tool.FunctionToolCall
67
import com.cjcrafter.openai.chat.tool.Tool
78
import com.cjcrafter.openai.chat.tool.ToolCall
89
import com.cjcrafter.openai.exception.HallucinationException
@@ -87,7 +88,7 @@ fun handleToolCall(call: ToolCall, validTools: List<Tool>?): ChatMessage {
8788
if (call.type !== Tool.Type.FUNCTION)
8889
throw HallucinationException("Unknown tool call type: " + call.type)
8990

90-
val function = call.function
91+
val function = (call as FunctionToolCall).function
9192
val arguments = function.tryParseArguments(validTools) // You can pass null here for less strict parsing
9293
val equation = arguments["equation"]!!.asText()
9394
val result = solveEquation(equation)

src/main/kotlin/com/cjcrafter/openai/chat/tool/CodeInterpreter.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ data class CodeInterpreter(
5555
* @property text The text output
5656
*/
5757
data class LogOutput(
58-
val text: String,
58+
@JsonProperty(required = true) val logs: String,
5959
) : Output() {
6060
override val type: Type = Type.LOGS
6161
}

src/main/kotlin/com/cjcrafter/openai/threads/message/ImageContent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ data class ImageContent(
66
@JsonProperty("image_file", required = true) val imageFile: ImageFile,
77
): ThreadMessageContent() {
88

9+
override val type = Type.IMAGE_FILE
10+
911
data class ImageFile(
1012
@JsonProperty("file_id", required = true) val fileId: String,
1113
)

src/main/kotlin/com/cjcrafter/openai/threads/message/TextContent.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ data class TextContent(
44
val text: Text
55
) : ThreadMessageContent() {
66

7+
override val type = Type.TEXT
8+
79
data class Text(
810
val value: String,
911
val annotations: List<TextAnnotation>

src/main/kotlin/com/cjcrafter/openai/threads/message/ThreadMessageContent.kt

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,35 @@ package com.cjcrafter.openai.threads.message
33
import com.fasterxml.jackson.annotation.JsonSubTypes
44
import com.fasterxml.jackson.annotation.JsonTypeInfo
55

6+
/**
7+
* A sealed class which represents a message in a thread.
8+
*/
69
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
710
@JsonSubTypes(
811
JsonSubTypes.Type(TextContent::class, name = "text"),
912
JsonSubTypes.Type(ImageContent::class, name = "image_file"),
1013
)
11-
abstract class ThreadMessageContent
14+
sealed class ThreadMessageContent {
15+
16+
/**
17+
* The type of content.
18+
*/
19+
abstract val type: Type
20+
21+
enum class Type {
22+
23+
/**
24+
* A message containing text, usually as a markdown string.
25+
*
26+
* @see TextContent
27+
*/
28+
TEXT,
29+
30+
/**
31+
* A message containing an image, stored as a file id.
32+
*
33+
* @see ImageContent
34+
*/
35+
IMAGE_FILE,
36+
}
37+
}
Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
11
package com.cjcrafter.openai.threads.runs
22

3-
class ListRunStepsResponse {
4-
}
3+
import com.fasterxml.jackson.annotation.JsonProperty
4+
5+
/**
6+
* A data class which represents a response from the OpenAI API containing a list of [RunStep]s.
7+
*
8+
* @property data The list of [RunStep]s
9+
* @property firstId The ID of the first [RunStep] in the list
10+
* @property lastId The ID of the last [RunStep] in the list
11+
* @property hasMore Whether there are more [RunStep]s to retrieve from the API
12+
*/
13+
data class ListRunStepsResponse(
14+
@JsonProperty(required = true) val data: List<RunStep>,
15+
@JsonProperty("first_id", required = true) val firstId: String,
16+
@JsonProperty("last_id", required = true) val lastId: String,
17+
@JsonProperty("has_more", required = true) val hasMore: Boolean,
18+
)

src/main/kotlin/com/cjcrafter/openai/threads/runs/RunHandler.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,16 @@ interface RunHandler {
7272
*/
7373
fun cancel(id: String): Run
7474

75+
/**
76+
* Gets the steps handler for the given run.
77+
*/
7578
fun steps(run: Run): RunStepHandler = steps(run.id)
7679

80+
/**
81+
*
82+
*
83+
* @param id
84+
* @return
85+
*/
7786
fun steps(id: String): RunStepHandler
7887
}

src/main/kotlin/com/cjcrafter/openai/threads/runs/RunHandlerImpl.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,11 @@ class RunHandlerImpl(
3636
val httpRequest = requestHelper.buildRequestNoBody("$endpoint/$id/cancel").addHeader("OpenAI-Beta", "assistants=v1").method("POST", null).build()
3737
return requestHelper.executeRequest(httpRequest, Run::class.java)
3838
}
39+
40+
private val stepHandlers = mutableMapOf<String, RunStepHandler>()
41+
override fun steps(id: String): RunStepHandler {
42+
return stepHandlers.getOrPut(id) {
43+
RunStepHandlerImpl(requestHelper, "$endpoint/$id/steps", threadId, id)
44+
}
45+
}
3946
}

0 commit comments

Comments
 (0)