adamrushy / OpenAISwift

This is a wrapper library around the ChatGPT and OpenAI HTTP API
MIT License
1.6k stars 242 forks source link

Add `usage` to `OpenAI` payload struct #46

Closed eastriverlee closed 1 year ago

eastriverlee commented 1 year ago

Hi, I enjoyed working with your library. but I wanted to know how many tokens I've used, so I made a very small change:

public struct OpenAI<T: Payload>: Codable {
    public let object: String
    public let model: String?
    public let choices: [T]
    public let usage: UsageResult
}

public struct UsageResult: Payload {
    public let prompt_tokens: Int
    public let completion_tokens: Int
    public let total_tokens: Int
}

This way, we can track tokens usage for sendEdits, sendCompletion, and sendChats without changing anything else.

bogdanf commented 1 year ago

I'd love to see this merged, but with better, swifter names for the members of UsageResult, like promptTokens instead of prompt_tokens.

eastriverlee commented 1 year ago

To get decoded by JsonDecoder, this is a must, since these are parameter names of the OpenAI's API result. If one wants to have more 'swifty' name, computed property extensions are possible, like:

public extension UsageResult {
    public var promptTokens: Int { prompt_tokens }
    ...
}

but I thought keeping changes to an absolute minimum was more important.

Maybe @adamrushy can merge with extra changes like the above.

arjun-dureja commented 1 year ago

@eastriverlee You can just create an enum that conforms to CodingKeys to set the correct parameter names: https://developer.apple.com/documentation/foundation/archives_and_serialization/encoding_and_decoding_custom_types#2904057

eastriverlee commented 1 year ago

That's good to know! Honestly I did not know that. In that case, I guess there is no reason to not change names.

I renamed properties and tested a new commit:

public struct UsageResult: Payload {
    public let promptTokens: Int
    public let completionTokens: Int
    public let totalTokens: Int

    enum CodingKeys: String, CodingKey {
        case promptTokens = "prompt_tokens"
        case completionTokens = "completion_tokens"
        case totalTokens = "total_tokens"
    }
}
bogdanf commented 1 year ago

@eastriverlee That's exactly what I had in mind.

bogdanf commented 1 year ago

One more thing, UsageResults should not conform to Payload but to Codable. Payload is intended to model one of the choices in the OpenAI struct, not anything else.

eastriverlee commented 1 year ago

Make sense. I wondered why Payload exist and just went it 🤭 without thinking too much.

ConfusedVorlon commented 1 year ago

nice - I was about to write this :)

adamrushy commented 1 year ago

Amazing extra! Great job @eastriverlee just awaiting GH Actions then will merge 🚀