Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I represent an account for the Anthropic Platform (https://console.anthropic.com). I hold information about the subscription state, account-specific rate limits, and track expenses from API calls.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
initialize-release
cleanUp: aggressive

aggressive ifTrue: [
self allSubInstancesDo: [:account |
account apiKey: nil].
self defaultAccount: nil].
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
defaultAccount: anAccount

DefaultAccount := anAccount.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
defaultAccount

^ DefaultAccount ifNil: [DefaultAccount := self new]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
preferences
defaultApiKey: aString

self defaultAccount apiKey: (aString ifEmpty: []).
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
preferences
defaultApiKey
<preference: 'Anthropic API Key' categoryList: #(SemanticText Anthropic) description: 'See https://console.anthropic.com/settings/keys' type: #String>

^ (DefaultAccount ifNotNil: [:account | account apiKey]) ifNil: ['']
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
preferences
defaultBaseUrl: aString

self defaultAccount baseUrl: (aString ifEmpty: []).
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
preferences
defaultBaseUrl
<preference: 'Anthropic API Base URL' categoryList: #(SemanticText Anthropic) description: 'If you are using AWS Bedrock, GCP Vertex or a proxy of the Anthropic API, you can enter your URL and port here.' type: #String>

^ (DefaultAccount ifNotNil: [:account | account baseUrl]) ifNil: ['']
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
constants
defaultRateLimitsPerTier
"See: https://platform.openai.com/docs/guides/rate-limits/usage-tiers"

| flat |
self flag: #modelConstants.
flat := Dictionary new
at: #free put:
(Dictionary new
at: 'gpt-3.5-turbo' put: #(3 200 40000 nil 200000);
at: 'text-embedding-3-large' put: #(3000 200 1000000 nil 3000000);
at: 'text-embedding-3-small' put: #(3000 200 1000000 nil 3000000);
at: 'text-embedding-ada-002' put: #(3000 200 1000000 nil 3000000);
at: 'whisper-1' put: #(3 200 nil nil nil);
at: 'tts-1' put: #(3 200 nil nil nil);
yourself);
at: 1 put:
(Dictionary new
at: 'gpt-4o' put: #(500 nil 30000 nil 90000);
at: 'gpt-4o-mini' put: #(500 10000 200000 nil 2000000);
at: 'gpt-4-turbo' put: #(500 nil 30000 nil 90000);
at: 'gpt-4' put: #(500 10000 10000 nil 100000);
at: 'gpt-3.5-turbo' put: #(3500 10000 200000 nil 2000000);
at: 'text-embedding-3-large' put: #(3000 nil 1000000 nil 3000000);
at: 'text-embedding-3-small' put: #(3000 nil 1000000 nil 3000000);
at: 'text-embedding-ada-002' put: #(3000 nil 1000000 nil 3000000);
at: 'whisper-1' put: #(500 nil nil nil nil);
at: 'tts-1' put: #(500 nil nil nil nil);
at: 'tts-1-hd' put: #(500 nil nil nil nil);
yourself);
at: 2 put:
(Dictionary new
at: 'gpt-4o' put: #(5000 nil 450000 nil 1350000);
at: 'gpt-4o-mini' put: #(5000 nil 2000000 nil 20000000);
at: 'gpt-4-turbo' put: #(5000 nil 450000 nil 1350000);
at: 'gpt-4' put: #(5000 nil 40000 nil 200000);
at: 'gpt-3.5-turbo' put: #(3500 nil 2000000 nil 5000000);
at: 'text-embedding-3-large' put: #(5000 nil 1000000 nil 20000000);
at: 'text-embedding-3-small' put: #(5000 nil 1000000 nil 20000000);
at: 'text-embedding-ada-002' put: #(5000 nil 1000000 nil 20000000);
at: 'whisper-1' put: #(2500 nil nil nil nil);
at: 'tts-1' put: #(2500 nil nil nil nil);
at: 'tts-1-hd' put: #(2500 nil nil nil nil);
yourself);
at: 3 put:
(Dictionary new
at: 'gpt-4o' put: #(5000 nil 800000 nil 50000000);
at: 'gpt-4o-mini' put: #(5000 nil 4000000 nil 40000000);
at: 'gpt-4-turbo' put: #(5000 nil 600000 nil 40000000);
at: 'gpt-4' put: #(5000 nil 80000 nil 5000000);
at: 'gpt-3.5-turbo' put: #(3500 nil 4000000 nil 100000000);
at: 'text-embedding-3-large' put: #(5000 nil 5000000 nil 100000000);
at: 'text-embedding-3-small' put: #(5000 nil 5000000 nil 100000000);
at: 'text-embedding-ada-002' put: #(5000 nil 5000000 nil 100000000);
at: 'whisper-1' put: #(5000 nil nil nil nil);
at: 'tts-1' put: #(5000 nil nil nil nil);
at: 'tts-1-hd' put: #(5000 nil nil nil nil);
yourself);
at: 4 put:
(Dictionary new
at: 'gpt-4o' put: #(10000 nil 2000000 nil 200000000);
at: 'gpt-4o-mini' put: #(10000 nil 10000000 nil 1000000000);
at: 'gpt-4-turbo' put: #(10000 nil 800000 nil 80000000);
at: 'gpt-4' put: #(10000 nil 300000 nil 30000000);
at: 'gpt-3.5-turbo' put: #(10000 nil 10000000 nil 1000000000);
at: 'text-embedding-3-large' put: #(10000 nil 5000000 nil 500000000);
at: 'text-embedding-3-small' put: #(10000 nil 5000000 nil 500000000);
at: 'text-embedding-ada-002' put: #(10000 nil 5000000 nil 500000000);
at: 'whisper-1' put: #(7500 nil nil nil nil);
at: 'tts-1' put: #(7500 nil nil nil nil);
at: 'tts-1-hd' put: #(7500 nil nil nil nil);
yourself);
at: 5 put:
(Dictionary new
at: 'gpt-4o' put: #(10000 nil 30000000 nil 5000000000);
at: 'gpt-4o-mini' put: #(30000 nil 150000000 nil 15000000000);
at: 'gpt-4-turbo' put: #(10000 nil 2000000 nil 300000000);
at: 'gpt-4' put: #(10000 nil 1000000 nil 150000000);
at: 'gpt-3.5-turbo' put: #(10000 nil 50000000 nil 10000000000);
at: 'text-embedding-3-large' put: #(10000 nil 10000000 nil 4000000000);
at: 'text-embedding-3-small' put: #(10000 nil 10000000 nil 4000000000);
at: 'text-embedding-ada-002' put: #(10000 nil 10000000 nil 4000000000);
at: 'whisper-1' put: #(10000 nil nil nil nil);
at: 'tts-1' put: #(10000 nil nil nil nil);
at: 'tts-1-hd' put: #(10000 nil nil nil nil);
yourself);
yourself.
^ flat collect: [:modelRateLimits |
modelRateLimits collect: [:rateLimits |
(self rateLimitsFromSpec: rateLimits)
collect: [:limit | limit ifNil: [Float infinity]]]]

"update and extend these constants based on the pasted tables below. do not change the formatting of the source code unless required (also keep the tab indentations)
the task is: output a new version of defaultRateLimitsPerTier based on the numbers provided in the tables. I'm sure you can find out the format on the numbers in the method yourself based on the tables. e.g., 3 rpm for gpt-3.5-turbo in tier free and so on. most numbers may not have changed, but some may have been added, changed, or removed in the screenshots, and I would like you to create a new version of the method that contains all numbers from the tables in the same format, and no other numbers that are not present in the tables.
exclude the dall-e models.

the tables:
"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
constants
isValidUsageTier: tier

^ tier = #free or:
[tier isInteger and: [tier strictlyPositive]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
support
openExpenseWatcher
"
AnthropicAccount openExpenseWatcher
"

^ self defaultAccount openExpenseWatcher
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
support
rateLimitsFromSpec: spec
"{requestsPerMinute. requestsPerDay. tokensPerMinute. tokensPerDay. batchQueueLimit}"

^ (#(rpm rpd tpm tpd batchQueueLimit) with: spec collect: [:key :limit |
key -> limit])
as: Dictionary
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
apiKey: aString

apiKey := aString.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
apiKey

^ apiKey
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
baseUrl: aStringOrNil

baseUrl := aStringOrNil.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing
baseUrl

^ baseUrl ifNil: [self defaultBaseUrl]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
connection
controlConnectionDuring: aBlock

self ignoreCertificate ifFalse: [^ aBlock value].

^ aBlock on: SqueakSSLCertificateError do: [:ex | ex resume]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - rate limits
customRateLimits

^ customRateLimits
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
initialize-release
defaultBaseUrl

^ 'https://api.anthropic.com'
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing - rate limits
defaultRateLimits

^ self class defaultRateLimitsPerTier at:
(self usageTier ifNil: [^ Dictionary new])
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
initialize-release
defaultUsageTier

^ #free
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
accessing - expenses
expensesPerModel

| expensesPerModel |
expensesPerModel := Dictionary new.
self expensesPerUser keysAndValuesDo: [:user :expensePerModel |
expensePerModel keysAndValuesDo: [:model :expense |
(expensesPerModel at: model ifAbsentPut: [Dictionary new])
at: user put: expense]].
^ expensesPerModel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing - expenses
expensesPerUser
"See https://openai.com/pricing for current prices and https://platform.openai.com/account/usage for your current usage."

^ expensesPerUser
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
testing
hasApiKey

^ self apiKey notNil
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing
ignoreCertificate: aBoolean
"If set to true, SSL certificates for the baseUrl will be ignored. WARNING: While this still ensures privacy (encryption), this opens the door to man-in-the-middle attacks (i.e., you cannot be sure that the remote host is what he say he is.)! Thus, use with caution."

ignoreCertificate := aBoolean.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing
ignoreCertificate
"If set to true, SSL certificates for the baseUrl will be ignored. WARNING: While this still ensures privacy (encryption), this opens the door to man-in-the-middle attacks (i.e., you cannot be sure that the remote host is what he say he is.)! Thus, use with caution."

^ ignoreCertificate
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
initialize-release
initialize

super initialize.

ignoreCertificate := false.
usageTier := self defaultUsageTier.
customRateLimits := Dictionary new.
self resetExpenses.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
accessing - expenses
noteExpense: expense forUser: userName model: modelName

| expensesPerModel |
expensesPerModel := expensesPerUser at: userName ifAbsentPut: [Dictionary new].
expensesPerModel at: modelName put:
(expensesPerModel at: modelName ifAbsent: [OpenAIAmount zero])
+ expense.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ui
openExpenseWatcher
"For the actual usage without estimations, see: https://platform.openai.com/account/usage"

| field inspector |
inspector := Inspector on: self.
field := inspector newCustomField valueGetter: [:account | account totalExpense].
inspector addCustomField: field.
field rememberInspector.
^ (World dropInspectorField: field event: self currentEvent)
in: [:answer |
answer = World ifFalse: "Morphic-ct.2143"
[answer openAsTool]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
accessing - rate limits
rateLimitForModel: modelName type: type ifUnknown: aBlock

| rateLimit |
rateLimit := self rateLimitsForModel: modelName ifUnknown: [^ aBlock value].
^ rateLimit at: type ifAbsent: aBlock
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
accessing - rate limits
rateLimits

| rateLimits |
rateLimits := self defaultRateLimits copy.
"merge"
self customRateLimits keysAndValuesDo: [:modelName :modelLimit |
rateLimits at: modelName put:
(rateLimits
at: modelName
ifPresent: [:defaultModelLimit |
defaultModelLimit , modelLimit]
ifAbsent: [modelLimit])].
^ rateLimits
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
accessing - rate limits
rateLimitsForModel: modelName ifUnknown: aBlock
"See: https://platform.openai.com/account/rate-limits. Hypothetically we could scrape this, in practice, users may enter relevant rate limits manually."

^ self rateLimits at: modelName ifAbsent:
["search for rate limits for more general model name (prefix, e.g., without version number/context size)"
| parts |
parts := modelName ifNotEmpty: [modelName splitBy: '-'].
parts ifNotEmpty:
[^ self
rateLimitsForModel: (parts allButLast joinSeparatedBy: '-')
ifUnknown: aBlock].
aBlock value]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - rate limits
requestsPerDayForModel: modelName ifUnknown: aBlock

^ self rateLimitForModel: modelName type: #rpd ifUnknown: aBlock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - rate limits
requestsPerMinuteForModel: modelName ifUnknown: aBlock

^ self rateLimitForModel: modelName type: #rpm ifUnknown: aBlock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - expenses
resetExpenses

expensesPerUser := Dictionary new.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
accessing - rate limits
setCustomRateLimitsForModel: modelName to: rateLimitsSpec
"rateLimitsSpec: {requestsPerMinute. requestsPerDay. tokensPerMinute. tokensPerDay. batchQueueLimit}
See: https://platform.openai.com/account/limits. Hypothetically we could scrape this, in practice, users may enter relevant rate limits manually."

self customRateLimits at: modelName put:
(self class rateLimitsFromSpec: rateLimitsSpec).
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - rate limits
tokensPerDayForModel: modelName ifUnknown: aBlock

^ self rateLimitForModel: modelName type: #tpd ifUnknown: aBlock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - rate limits
tokensPerMinuteForModel: modelName ifUnknown: aBlock

^ self rateLimitForModel: modelName type: #tpm ifUnknown: aBlock
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing - expenses
totalExpense

^ self expensesPerUser inject: OpenAIAmount zero into: [:sum :expenses |
expenses inject: OpenAIAmount zero into: [:userSum :expense | userSum + expense]]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - expenses
totalExpensePerModel

^ self expensesPerModel collect: [:expenses | expenses sum]
Loading