Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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,7 @@
constants
defaultRateLimitsPerTier
"Not implemented"

self flag: #modelConstants.
self flag: #todo.
^ nil
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
"Not implemented"
self flag: #todo.
^ 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]
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
accessing - expenses
totalExpensePerUser

^ self expensesPerUser collect: [:expenses | expenses sum]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing
usageTier: tier
"Rate and usage limits depend on the usage tier of your account, which is assigned by based on the duration of your subscription and the magnitude of your payments. Must be #free or a positive integer. You can find your current tier here: https://platform.openai.com/account/limits"

usageTier := tier.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
accessing
usageTier
"Rate and usage limits depend on the usage tier of your account, which is assigned by based on the duration of your subscription and the magnitude of your payments. Must be #free or a positive integer. You can find your current tier here: https://platform.openai.com/account/limits"

^ usageTier
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"class" : {
"cleanUp:" : "ct 8/20/2023 12:56",
"defaultAccount" : "ct 8/20/2023 12:52",
"defaultAccount:" : "ct 8/20/2023 12:52",
"defaultApiKey" : "zakkor 1/10/2025 12:49",
"defaultApiKey:" : "ct 10/15/2023 22:20",
"defaultBaseUrl" : "zakkor 1/10/2025 12:49",
"defaultBaseUrl:" : "ct 12/1/2023 23:30",
"defaultRateLimitsPerTier" : "zakkor 1/15/2025 21:54",
"isValidUsageTier:" : "ct 11/28/2023 12:39",
"openExpenseWatcher" : "zakkor 1/10/2025 12:50",
"rateLimitsFromSpec:" : "ct 6/20/2024 00:00" },
"instance" : {
"apiKey" : "ct 8/20/2023 12:55",
"apiKey:" : "ct 8/20/2023 12:55",
"baseUrl" : "ct 12/1/2023 23:29",
"baseUrl:" : "ct 12/1/2023 23:31",
"controlConnectionDuring:" : "ct 12/11/2023 18:35",
"customRateLimits" : "ct 11/28/2023 13:27",
"defaultBaseUrl" : "zakkor 1/10/2025 12:54",
"defaultRateLimits" : "zakkor 1/13/2025 22:33",
"defaultUsageTier" : "ct 11/28/2023 14:54",
"expensesPerModel" : "ct 8/20/2023 20:15",
"expensesPerUser" : "ct 8/27/2023 20:57",
"hasApiKey" : "ct 10/15/2023 21:44",
"ignoreCertificate" : "ct 12/11/2023 18:44",
"ignoreCertificate:" : "ct 12/11/2023 18:44",
"initialize" : "ct 12/11/2023 18:33",
"noteExpense:forUser:model:" : "ct 8/20/2023 19:11",
"openExpenseWatcher" : "ct 11/26/2023 21:56",
"rateLimitForModel:type:ifUnknown:" : "ct 11/28/2023 18:46",
"rateLimits" : "ct 2/21/2024 15:12",
"rateLimitsForModel:ifUnknown:" : "ct 2/21/2024 15:12",
"requestsPerDayForModel:ifUnknown:" : "ct 11/28/2023 18:46",
"requestsPerMinuteForModel:ifUnknown:" : "ct 11/28/2023 13:33",
"resetExpenses" : "ct 8/20/2023 21:04",
"setCustomRateLimitsForModel:to:" : "ct 4/27/2024 22:13",
"tokensPerDayForModel:ifUnknown:" : "ct 11/28/2023 13:33",
"tokensPerMinuteForModel:ifUnknown:" : "ct 11/28/2023 13:33",
"totalExpense" : "ct 8/20/2023 20:17",
"totalExpensePerModel" : "ct 8/20/2023 19:03",
"totalExpensePerUser" : "ct 8/20/2023 18:52",
"usageTier" : "ct 11/28/2023 14:56",
"usageTier:" : "ct 11/28/2023 14:56" } }
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"category" : "SemanticText-Providers-Anthropic",
"classinstvars" : [
],
"classvars" : [
"DefaultAccount" ],
"commentStamp" : "Ed 1/10/2025 12:45",
"instvars" : [
"baseUrl",
"apiKey",
"ignoreCertificate",
"usageTier",
"customRateLimits",
"expensesPerUser" ],
"name" : "AnthropicAccount",
"pools" : [
],
"super" : "Object",
"type" : "normal" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
I generate answers for a SemanticConversation using a large language model (LLM) such as GPT (Generative Pre-Trained Transformer) from the OpenAI API. Colloquially also referred to as ChatGPT, which however is a different service with additional features.
Loading