Skip to content

Commit

Permalink
Merge pull request #12 from pascalfribi/main
Browse files Browse the repository at this point in the history
- ChatThread.addFunctionResponse is now public so it can be used
-Encoding of Arguments for assistant is now done, so it generates a String containing a JSON Dictionary. Otherwise it will not be accepted by OpenAI
- The content field is now encoded to "content: null" as it always needs to be present
  • Loading branch information
btfranklin committed Nov 4, 2023
2 parents e60ff23 + 216cacb commit 6ebaaad
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 10 deletions.
18 changes: 9 additions & 9 deletions Sources/CleverBird/chat/ChatMessage.swift
Expand Up @@ -37,22 +37,21 @@ public struct ChatMessage: Codable, Identifiable {
id: String? = nil,
functionCall: FunctionCall? = nil) throws {

// Validation: Name is required if role is function, and it should be the name of the function whose response is in the content.
if role == .function {
guard let functionCall = functionCall, let content = content, content.contains(functionCall.name) else {
throw CleverBirdError.invalidFunctionMessage
}
}

// Validation: Content is required for all messages except assistant messages with function calls.
if content == nil && !(role == .assistant && functionCall != nil) {
throw CleverBirdError.invalidMessageContent
}

self.role = role
self.content = content
self.functionCall = functionCall
self.name = functionCall?.name
if role == .function {
// Attention: if the role is function I need to set the functionCall to nil, otherwise this will
// be encoded into the message which leads to an error.
self.functionCall = nil
} else {
self.functionCall = functionCall
}

if let id = id {
self.id = id
Expand All @@ -79,7 +78,8 @@ public struct ChatMessage: Codable, Identifiable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.role, forKey: .role)
try container.encodeIfPresent(self.content, forKey: .content)
// The content field needs to be present even if it is nil, in this case encode it to Null
try container.encode(self.content, forKey: .content)
try container.encodeIfPresent(self.functionCall, forKey: .functionCall)
try container.encodeIfPresent(self.name, forKey: .name)
}
Expand Down
2 changes: 1 addition & 1 deletion Sources/CleverBird/chat/ChatThread.swift
Expand Up @@ -92,7 +92,7 @@ public class ChatThread {
}

@discardableResult
func addFunctionResponse(_ content: String, for functionCall: FunctionCall) -> ChatThread {
public func addFunctionResponse(_ content: String, for functionCall: FunctionCall) -> ChatThread {
do {
let responseMessage = try ChatMessage(role: .function,
content: content,
Expand Down
6 changes: 6 additions & 0 deletions Sources/CleverBird/chat/FunctionCall.swift
Expand Up @@ -59,4 +59,10 @@ public struct FunctionCall: Codable {
self.name = functionName
}

public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.name, forKey: .name)
let argumentsAsString = try String(data: JSONEncoder().encode(self.arguments), encoding: .utf8) ?? ""
try container.encode(argumentsAsString, forKey: .arguments)
}
}

0 comments on commit 6ebaaad

Please sign in to comment.