diff --git a/.stats.yml b/.stats.yml index afb44f9e..f18d6148 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ -configured_endpoints: 76 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai%2Fopenai-b26121d5df6eb5d3032a45a267473798b15fcfec76dd44a3256cf1238be05fa4.yml +configured_endpoints: 80 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/openai-c8579861bc21d4d2155a5b9e8e7d54faee8083730673c4d32cbbe573d7fb4116.yml diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 52104571..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,830 +0,0 @@ -# Changelog - -## 0.1.0-alpha.66 (2025-03-20) - -Full Changelog: [v0.1.0-alpha.65...v0.1.0-alpha.66](https://github.com/openai/openai-go/compare/v0.1.0-alpha.65...v0.1.0-alpha.66) - -### Features - -* **api:** o1-pro now available through the API ([#296](https://github.com/openai/openai-go/issues/296)) ([c3265ab](https://github.com/openai/openai-go/commit/c3265ab62826e475a61bb951115913a9acdc6947)) - - -### Bug Fixes - -* **api:** correct some Responses types ([#295](https://github.com/openai/openai-go/issues/295)) ([9ec5b48](https://github.com/openai/openai-go/commit/9ec5b4821800f1312660de85043fe1755f80375f)) -* **types:** improve responses type names ([ffc93bb](https://github.com/openai/openai-go/commit/ffc93bb7b7a9020032693728bd33b6675057a618)) - - -### Chores - -* **internal:** codegen related update ([#292](https://github.com/openai/openai-go/issues/292)) ([81e7895](https://github.com/openai/openai-go/commit/81e789545a3c6eac8bc56687f8131308735ac8fc)) - -## 0.1.0-alpha.65 (2025-03-17) - -Full Changelog: [v0.1.0-alpha.64...v0.1.0-alpha.65](https://github.com/openai/openai-go/compare/v0.1.0-alpha.64...v0.1.0-alpha.65) - -### Bug Fixes - -* **ci:** add workflow back in ([f695f00](https://github.com/openai/openai-go/commit/f695f0013d805623548b42c346a167ee15dd9405)) -* revert bad update ([e1ebde6](https://github.com/openai/openai-go/commit/e1ebde6c189d93efd9bae193a8686242446b86f3)) - -## 0.1.0-alpha.64 (2025-03-15) - -Full Changelog: [v0.1.0-alpha.63...v0.1.0-alpha.64](https://github.com/openai/openai-go/compare/v0.1.0-alpha.63...v0.1.0-alpha.64) - -### ⚠ BREAKING CHANGES - -* **client:** improve naming of some variants ([#89](https://github.com/openai/openai-go/issues/89)) - -### Features - -* add azure, examples, and message constructors ([fb2df0f](https://github.com/openai/openai-go/commit/fb2df0fe22002f1826bfaa1cb008c45db375885c)) -* add SKIP_BREW env var to ./scripts/bootstrap ([#255](https://github.com/openai/openai-go/issues/255)) ([151c5e7](https://github.com/openai/openai-go/commit/151c5e7106b467174703089ca21845780f121c03)) -* add support for error property in stream ([#29](https://github.com/openai/openai-go/issues/29)) ([0c7d6e5](https://github.com/openai/openai-go/commit/0c7d6e5fc62fd0ed686d5fd254376ff35eb9903a)) -* **api:** add chatgpt-4o-latest model ([#24](https://github.com/openai/openai-go/issues/24)) ([110d1f0](https://github.com/openai/openai-go/commit/110d1f025a3e9259ae87b8ed7c4824de32d489fb)) -* **api:** add file search result details to run steps ([#32](https://github.com/openai/openai-go/issues/32)) ([c1862bd](https://github.com/openai/openai-go/commit/c1862bda1d70ce21d4af85583f975a3aa9cc1e1f)) -* **api:** add gpt-4.5-preview ([#242](https://github.com/openai/openai-go/issues/242)) ([961bf16](https://github.com/openai/openai-go/commit/961bf16109133c94298241f1240d2c0203c8ead7)) -* **api:** add gpt-4o-2024-11-20 model ([#131](https://github.com/openai/openai-go/issues/131)) ([8fe1011](https://github.com/openai/openai-go/commit/8fe1011b33c5d05a14fe249e520894eec7c74334)) -* **api:** add gpt-4o-audio-preview model for chat completions ([#88](https://github.com/openai/openai-go/issues/88)) ([f4a76d0](https://github.com/openai/openai-go/commit/f4a76d0aff1127efe4faa8052334a39f6303cada)) -* **api:** add new, expressive voices for Realtime and Audio in Chat Completions ([#101](https://github.com/openai/openai-go/issues/101)) ([f946acc](https://github.com/openai/openai-go/commit/f946acc71a92f885bed87f0d4e724fb40cae0f14)) -* **api:** add o1 models ([#49](https://github.com/openai/openai-go/issues/49)) ([698a0c9](https://github.com/openai/openai-go/commit/698a0c9c09ffc8b070a796bf4b10b4ba39a17815)) -* **api:** add o3-mini ([#195](https://github.com/openai/openai-go/issues/195)) ([1dc8887](https://github.com/openai/openai-go/commit/1dc888754d531b7d18768b17a44c5415fa6bf3ea)) -* **api:** add omni-moderation model ([#63](https://github.com/openai/openai-go/issues/63)) ([7402f24](https://github.com/openai/openai-go/commit/7402f24732a207c67c98248d58431520081bc324)) -* **api:** add support for predicted outputs ([#110](https://github.com/openai/openai-go/issues/110)) ([73c798a](https://github.com/openai/openai-go/commit/73c798a65bd0aa7d241d5a2fa21eb8c880f8e769)) -* **api:** add support for storing chat completions ([#228](https://github.com/openai/openai-go/issues/228)) ([3da23d8](https://github.com/openai/openai-go/commit/3da23d8f861f8c73c91a7d1443a35ea20475f91e)) -* **api:** new o1 and GPT-4o models + preference fine-tuning ([#142](https://github.com/openai/openai-go/issues/142)) ([a9e2f35](https://github.com/openai/openai-go/commit/a9e2f35573f21296a452955d6ded82385812f649)) -* **api:** support storing chat completions, enabling evals and model distillation in the dashboard ([#72](https://github.com/openai/openai-go/issues/72)) ([b0eae50](https://github.com/openai/openai-go/commit/b0eae50c466a7f6628da792ecbef97a398489a69)) -* **api:** update enum values, comments, and examples ([#181](https://github.com/openai/openai-go/issues/181)) ([29e5479](https://github.com/openai/openai-go/commit/29e547924355b3d0cd64bfed807418b7cacc179e)) -* **api:** updates ([#138](https://github.com/openai/openai-go/issues/138)) ([525573e](https://github.com/openai/openai-go/commit/525573e0d8bb0d69b183e418ded2b987f7da7c73)) -* **api:** updates ([#259](https://github.com/openai/openai-go/issues/259)) ([aa5cb47](https://github.com/openai/openai-go/commit/aa5cb47722c42f17808a15cf15dd58a7a3cfa17f)) -* **api:** updates ([#5](https://github.com/openai/openai-go/issues/5)) ([f92a25c](https://github.com/openai/openai-go/commit/f92a25c87da861702e1792b6799b6601861d4d01)) -* **assistants:** add polling helpers and examples ([#84](https://github.com/openai/openai-go/issues/84)) ([eaa9194](https://github.com/openai/openai-go/commit/eaa91946e78c278f0eacffd6f19c4691d9e23eeb)) -* **client:** accept RFC6838 JSON content types ([#256](https://github.com/openai/openai-go/issues/256)) ([9a8f472](https://github.com/openai/openai-go/commit/9a8f472bc60a208f446d5a56a60a3b824e486786)) -* **client:** allow custom baseurls without trailing slash ([#254](https://github.com/openai/openai-go/issues/254)) ([32b7eb4](https://github.com/openai/openai-go/commit/32b7eb453c7d8a7e2982877baff56c46e3e47c50)) -* **client:** improve default client options support ([0c621c0](https://github.com/openai/openai-go/commit/0c621c0572cedf1b2d7976020d037d688c9956b7)) -* **client:** improve default client options support ([#266](https://github.com/openai/openai-go/issues/266)) ([e68b1cd](https://github.com/openai/openai-go/commit/e68b1cd08f7ed7f008b9b006fc3f9ccb2497fa27)) -* **client:** improve naming of some variants ([#89](https://github.com/openai/openai-go/issues/89)) ([6bb0f75](https://github.com/openai/openai-go/commit/6bb0f75b9b00fcdeffa9c19aa5de0cc48e12c168)) -* **client:** send `X-Stainless-Timeout` header ([#204](https://github.com/openai/openai-go/issues/204)) ([72405f0](https://github.com/openai/openai-go/commit/72405f00fbb168f85b9b8b40aee8a0dbadce67f3)) -* **client:** send retry count header ([#60](https://github.com/openai/openai-go/issues/60)) ([01ed6ab](https://github.com/openai/openai-go/commit/01ed6ab70bae02e882cd4ffd4e0455f0ab03511e)) -* **examples/structure-outputs:** created an example for using structured outputs ([d4303e8](https://github.com/openai/openai-go/commit/d4303e8f8c4cfd7f260681ebed600749b6262028)) -* extract out `ImageModel`, `AudioModel`, `SpeechModel` ([#3](https://github.com/openai/openai-go/issues/3)) ([4b90869](https://github.com/openai/openai-go/commit/4b90869569ec034cb78995d9c56720cad5920577)) -* make enums not nominal ([#4](https://github.com/openai/openai-go/issues/4)) ([a559359](https://github.com/openai/openai-go/commit/a55935938f21c2a4b1d682538bd3481861a126a3)) -* move pagination package from internal to packages ([#81](https://github.com/openai/openai-go/issues/81)) ([c7476f7](https://github.com/openai/openai-go/commit/c7476f78f69b23044436236081f0faf405c98b1c)) -* **pagination:** avoid fetching when has_more: false ([#218](https://github.com/openai/openai-go/issues/218)) ([978707d](https://github.com/openai/openai-go/commit/978707dd3b64230c7835e83548167c8617444462)) -* publish ([c329601](https://github.com/openai/openai-go/commit/c329601324226e28ff18d6ccecfdde41cedd3b5a)) -* simplify content union ([#18](https://github.com/openai/openai-go/issues/18)) ([b228103](https://github.com/openai/openai-go/commit/b2281035a6d6abeb02a912a3543c98ac70ff456f)) -* **stream-accumulators:** added streaming accumulator helpers and example ([ecfdb64](https://github.com/openai/openai-go/commit/ecfdb64214f4a8d75bff6a29d068c55357ed7815)) -* support assistants stream ([7c00c63](https://github.com/openai/openai-go/commit/7c00c6340ffed1557b5763bba1790fb0f55c8530)) -* support deprecated markers ([#178](https://github.com/openai/openai-go/issues/178)) ([2c21e34](https://github.com/openai/openai-go/commit/2c21e3404639defedcad990acc1f530bbcb2781f)) -* **vector store:** improve chunking strategy type names ([#40](https://github.com/openai/openai-go/issues/40)) ([5d0740f](https://github.com/openai/openai-go/commit/5d0740f77b32c89fc2bebfea98fe8b939d78a155)) - - -### Bug Fixes - -* **api/types:** correct audio duration & role types ([#209](https://github.com/openai/openai-go/issues/209)) ([f480273](https://github.com/openai/openai-go/commit/f480273953cb9eef9b367867dfc9a3b4af3ea858)) -* **api:** add missing file rank enum + more metadata ([#248](https://github.com/openai/openai-go/issues/248)) ([a47089e](https://github.com/openai/openai-go/commit/a47089e5d9ce08ba0fc6461e3d4bb8941ca79291)) -* **api:** add missing reasoning effort + model enums ([#215](https://github.com/openai/openai-go/issues/215)) ([5b53a1d](https://github.com/openai/openai-go/commit/5b53a1d531a05599d8d517b3c1e98c8c8e40ccbd)) -* **api:** escape key values when encoding maps ([#116](https://github.com/openai/openai-go/issues/116)) ([a29c08e](https://github.com/openai/openai-go/commit/a29c08e27eb6fb403cfca60247bf1d23d82ec26e)) -* **audio:** correct response_format translations type ([#62](https://github.com/openai/openai-go/issues/62)) ([c46777b](https://github.com/openai/openai-go/commit/c46777ba01b6d0f3be506521ed5c7420f1fd0f20)) -* **beta:** pass beta header by default ([#75](https://github.com/openai/openai-go/issues/75)) ([e0a5caa](https://github.com/openai/openai-go/commit/e0a5caa65f645c3531bc2a9795b0571949305dbd)) -* **client:** don't truncate manually specified filenames ([#230](https://github.com/openai/openai-go/issues/230)) ([86febfc](https://github.com/openai/openai-go/commit/86febfce3ae78704595e4450cb4e1373e7932a78)) -* **client:** no panic on missing BaseURL ([#121](https://github.com/openai/openai-go/issues/121)) ([9e252ee](https://github.com/openai/openai-go/commit/9e252ee90db5549d910d46dd998fd499dac60b22)) -* correct required fields for flattened unions ([#120](https://github.com/openai/openai-go/issues/120)) ([9d6e6f2](https://github.com/openai/openai-go/commit/9d6e6f2ace15ac7c843b0585265b1cea1e46e78d)) -* deserialization of struct unions that implement json.Unmarshaler ([#11](https://github.com/openai/openai-go/issues/11)) ([7c0847a](https://github.com/openai/openai-go/commit/7c0847aa2ae15b4442ab0625d8a780ed684c275e)) -* do not call path.Base on ContentType ([#225](https://github.com/openai/openai-go/issues/225)) ([e1c1a55](https://github.com/openai/openai-go/commit/e1c1a55e7de733fa70194a3475bcf943c0568ba7)) -* **examples/fine-tuning:** used an old constant name ([#34](https://github.com/openai/openai-go/issues/34)) ([fb78f1d](https://github.com/openai/openai-go/commit/fb78f1df84dc5a5187157eeeb9a21b3853c328f6)) -* **example:** use correct model ([#86](https://github.com/openai/openai-go/issues/86)) ([0f3578d](https://github.com/openai/openai-go/commit/0f3578d2c3e4f40bfeea511e385d5c74d2b06e4e)) -* fix apijson.Port for embedded structs ([#174](https://github.com/openai/openai-go/issues/174)) ([13ecf6c](https://github.com/openai/openai-go/commit/13ecf6c0b82085e54e56807cb7dcd981768c50ca)) -* fix apijson.Port for embedded structs ([#177](https://github.com/openai/openai-go/issues/177)) ([1820b25](https://github.com/openai/openai-go/commit/1820b2592eee7aa55212c3b0bcfc3077c5d7f3a7)) -* fix early cancel when RequestTimeout is provided for streaming requests ([#221](https://github.com/openai/openai-go/issues/221)) ([08320be](https://github.com/openai/openai-go/commit/08320be359825fbceb4642aa6a60142ceec8ce2e)) -* fix unicode encoding for json ([#193](https://github.com/openai/openai-go/issues/193)) ([4a905a7](https://github.com/openai/openai-go/commit/4a905a7a596d7e1a7f0de9bec7f49c1026d36621)) -* flush stream response when done event is sent ([#172](https://github.com/openai/openai-go/issues/172)) ([cf1a6a5](https://github.com/openai/openai-go/commit/cf1a6a5b384fbd3de948494d50a1b19cfba79fdd)) -* **requestconfig:** copy over more fields when cloning ([#44](https://github.com/openai/openai-go/issues/44)) ([3c7aa48](https://github.com/openai/openai-go/commit/3c7aa48609798b665b61a222067af0f8bbdc0f40)) -* **responses:** correct computer use enum value ([#261](https://github.com/openai/openai-go/issues/261)) ([73d820b](https://github.com/openai/openai-go/commit/73d820bd96debf858adee674ec330f7b9d477342)) -* **responses:** correct reasoning output type ([#262](https://github.com/openai/openai-go/issues/262)) ([a636da3](https://github.com/openai/openai-go/commit/a636da379ea7f41ed73e320fa85f06219a71e8ac)) -* **stream:** ensure .Close() doesn't panic ([#194](https://github.com/openai/openai-go/issues/194)) ([71821a8](https://github.com/openai/openai-go/commit/71821a8938562f79d859d8939b9d20b2ef2ad3ca)) -* **stream:** ensure .Close() doesn't panic ([#201](https://github.com/openai/openai-go/issues/201)) ([a75c812](https://github.com/openai/openai-go/commit/a75c812270296b3c308b4f044e2b81071bdb8f8b)) -* **streaming:** correctly accumulate tool calls and roles ([#55](https://github.com/openai/openai-go/issues/55)) ([321ff9e](https://github.com/openai/openai-go/commit/321ff9e778b3c70addac90abbbc5e06e63581de2)) -* **types:** correct metadata type + other fixes ([1dc8887](https://github.com/openai/openai-go/commit/1dc888754d531b7d18768b17a44c5415fa6bf3ea)) -* update stream error handling ([#213](https://github.com/openai/openai-go/issues/213)) ([b2a763d](https://github.com/openai/openai-go/commit/b2a763dcde75cc6de5ee2b7d5e18fdcda1aaa90c)) - - -### Chores - -* add back custom code that was reverted ([4b46d02](https://github.com/openai/openai-go/commit/4b46d02aa506b9b521c88abcd5ea78ffe5083088)) -* **api:** bump spec version ([#154](https://github.com/openai/openai-go/issues/154)) ([4fc775f](https://github.com/openai/openai-go/commit/4fc775fa9bd22a0a0df370e2ef20f6485a11f3e3)) -* **api:** delete deprecated method ([#208](https://github.com/openai/openai-go/issues/208)) ([dcb01cc](https://github.com/openai/openai-go/commit/dcb01cc7ba479e486b6bc57c73b46b634f316dca)) -* bump Go to v1.21 ([#12](https://github.com/openai/openai-go/issues/12)) ([e4c3228](https://github.com/openai/openai-go/commit/e4c322840f7ea441a78dd723e46e27b048d16c1e)) -* bump license year ([#151](https://github.com/openai/openai-go/issues/151)) ([5e724f9](https://github.com/openai/openai-go/commit/5e724f9816b2d9697970c56c62adab3a62f2b6cd)) -* bump openapi url ([#136](https://github.com/openai/openai-go/issues/136)) ([b9bf99d](https://github.com/openai/openai-go/commit/b9bf99dbf047cb3a32efafa7bcf6979ac7ba15ab)) -* **ci:** bump prism mock server version ([#10](https://github.com/openai/openai-go/issues/10)) ([00f9455](https://github.com/openai/openai-go/commit/00f9455692c52fb37544d3f657090b216667d8ec)) -* **ci:** codeowners file ([#9](https://github.com/openai/openai-go/issues/9)) ([be41ac2](https://github.com/openai/openai-go/commit/be41ac2ce87efacf17748cb9dd2d3b1b4a43180e)) -* **docs:** add docstring explaining streaming pattern ([#205](https://github.com/openai/openai-go/issues/205)) ([bfabf9d](https://github.com/openai/openai-go/commit/bfabf9d23191c2050dde7844da06bab321b5a361)) -* **docs:** fix maxium typo ([#69](https://github.com/openai/openai-go/issues/69)) ([29dfb56](https://github.com/openai/openai-go/commit/29dfb56cb755fce02e0d923bcd742f9d780151b7)) -* **docs:** remove some duplicative api.md entries ([#65](https://github.com/openai/openai-go/issues/65)) ([532c9a0](https://github.com/openai/openai-go/commit/532c9a05d7637d891aa76a9ef2ec3254c0f20942)) -* **examples:** minor formatting changes ([#14](https://github.com/openai/openai-go/issues/14)) ([85aaaa5](https://github.com/openai/openai-go/commit/85aaaa5af7242ca6a2d12a61a127d4b1ae08f7d9)) -* fix GetNextPage docstring ([#78](https://github.com/openai/openai-go/issues/78)) ([a736116](https://github.com/openai/openai-go/commit/a736116b2544976afe6a4f95ceb066fc959ece67)) -* **internal:** fix devcontainers setup ([#236](https://github.com/openai/openai-go/issues/236)) ([25b0137](https://github.com/openai/openai-go/commit/25b0137b0d161554ed9ce0cab2b71c60aa7a17e0)) -* **internal:** remove CI condition ([#271](https://github.com/openai/openai-go/issues/271)) ([c61ef3a](https://github.com/openai/openai-go/commit/c61ef3a83a5ac7cf810331c1f5c8b4bffd385b19)) -* **internal:** remove extra empty newlines ([#268](https://github.com/openai/openai-go/issues/268)) ([df22608](https://github.com/openai/openai-go/commit/df2260865fb588c84707a067128ff03561cccef6)) -* **internal:** rename `streaming.go` ([#176](https://github.com/openai/openai-go/issues/176)) ([fb192c6](https://github.com/openai/openai-go/commit/fb192c675b008273962f88ca599dd84f5ddf7823)) -* **internal:** spec update ([#130](https://github.com/openai/openai-go/issues/130)) ([7fd444a](https://github.com/openai/openai-go/commit/7fd444a5724bdeef6cdc4b9e9db4f445eaa020e2)) -* **internal:** spec update ([#145](https://github.com/openai/openai-go/issues/145)) ([b8ba547](https://github.com/openai/openai-go/commit/b8ba547746107d6c2081bc66e746b82114ac9b44)) -* **internal:** spec update ([#146](https://github.com/openai/openai-go/issues/146)) ([d4bcfc0](https://github.com/openai/openai-go/commit/d4bcfc0fd6906d50c2e522e18d3d7cc154b0cc71)) -* **internal:** spec update ([#158](https://github.com/openai/openai-go/issues/158)) ([fd7fe8c](https://github.com/openai/openai-go/commit/fd7fe8c49e12cf2bee9b96b1af0ad509ee745fa0)) -* **internal:** streaming refactors ([#165](https://github.com/openai/openai-go/issues/165)) ([2fbb02c](https://github.com/openai/openai-go/commit/2fbb02c1c18b92e966266b3340ee15deaf408d34)) -* **internal:** update spec link ([#53](https://github.com/openai/openai-go/issues/53)) ([4915187](https://github.com/openai/openai-go/commit/4915187abeec2e3a1e6290004fc4c18a7f1129ca)) -* **internal:** update spec version ([#95](https://github.com/openai/openai-go/issues/95)) ([ba37fcc](https://github.com/openai/openai-go/commit/ba37fcc41ef1c5d63a218b9bf9139029264bc274)) -* **internal:** updates ([#2](https://github.com/openai/openai-go/issues/2)) ([103d454](https://github.com/openai/openai-go/commit/103d454b1d1fab5032c6af54e62ffe65f0cacb35)) -* **internal:** updates ([#6](https://github.com/openai/openai-go/issues/6)) ([316e623](https://github.com/openai/openai-go/commit/316e6231c27728f4031f822287389c67e914739a)) -* move ChatModel type to shared ([#250](https://github.com/openai/openai-go/issues/250)) ([304ec6b](https://github.com/openai/openai-go/commit/304ec6b670cfea141177e098b622d517c2aa3a9d)) -* refactor client tests ([#187](https://github.com/openai/openai-go/issues/187)) ([b956e3a](https://github.com/openai/openai-go/commit/b956e3a350d27965407154319a30eef09131fc3c)) -* **tests:** limit array example length ([#128](https://github.com/openai/openai-go/issues/128)) ([45fa490](https://github.com/openai/openai-go/commit/45fa4909359bbcda7acc6a72a1cf2f1e709c7cf1)) -* **types:** define FilePurpose enum ([#22](https://github.com/openai/openai-go/issues/22)) ([1daff0f](https://github.com/openai/openai-go/commit/1daff0f73ce40ae61e2d4b217d22811cbb373c27)) -* **types:** improve type name for embedding models ([#57](https://github.com/openai/openai-go/issues/57)) ([57736f9](https://github.com/openai/openai-go/commit/57736f9c857865e5a26c62b8cfba3c064a784e7b)) -* **types:** rename vector store chunking strategy ([#169](https://github.com/openai/openai-go/issues/169)) ([6076a58](https://github.com/openai/openai-go/commit/6076a584b57291ae915dd0596c2b6a4331a4f080)) - - -### Documentation - -* add missing docs for some enums ([#114](https://github.com/openai/openai-go/issues/114)) ([3d9fbd8](https://github.com/openai/openai-go/commit/3d9fbd85098e8ff5ee89872846c8151028179299)) -* document raw responses ([#197](https://github.com/openai/openai-go/issues/197)) ([9d06d7a](https://github.com/openai/openai-go/commit/9d06d7a1a78431ba01e6018fe6c2a9a4b75c3db6)) -* **examples:** fix typo ([#207](https://github.com/openai/openai-go/issues/207)) ([bf8afc3](https://github.com/openai/openai-go/commit/bf8afc3a81676b7675c314aa1c1e7e4941e9430f)) -* improve and reference contributing documentation ([#73](https://github.com/openai/openai-go/issues/73)) ([cd4dcc1](https://github.com/openai/openai-go/commit/cd4dcc17fd18353730c74e9993700423d9df2e0d)) -* **readme:** add an alpha warning ([#27](https://github.com/openai/openai-go/issues/27)) ([42ecbf8](https://github.com/openai/openai-go/commit/42ecbf8bd79d2469896e872b4c97f30cd9b203d8)) -* **readme:** added some examples to readme ([#39](https://github.com/openai/openai-go/issues/39)) ([a714dde](https://github.com/openai/openai-go/commit/a714dde3784397e902208b9b47cf45a83307aa74)) -* **readme:** fix example snippet ([#118](https://github.com/openai/openai-go/issues/118)) ([2af88cb](https://github.com/openai/openai-go/commit/2af88cbdf2fa07f59d7bf929f3df4aac35a579b0)) -* **readme:** fix misplaced period ([#156](https://github.com/openai/openai-go/issues/156)) ([42bbc45](https://github.com/openai/openai-go/commit/42bbc454ba50b88844cac58abfd254f889b56790)) -* **readme:** fix typo ([#148](https://github.com/openai/openai-go/issues/148)) ([07d3e40](https://github.com/openai/openai-go/commit/07d3e40f2e5f605b10818b97b580ebd46589b9b2)) -* **readme:** smaller readme snippets with links to examples ([#46](https://github.com/openai/openai-go/issues/46)) ([082e6ae](https://github.com/openai/openai-go/commit/082e6aedc9b3a80402511c062f3331c90be6d4d0)) -* update CONTRIBUTING.md ([#51](https://github.com/openai/openai-go/issues/51)) ([871b758](https://github.com/openai/openai-go/commit/871b7580fe8da75cc4c2525612a094006cc8bcf8)) -* update URLs from stainlessapi.com to stainless.com ([#243](https://github.com/openai/openai-go/issues/243)) ([fcb72c5](https://github.com/openai/openai-go/commit/fcb72c51429536374d2017e4303c7d90ded7a7b8)) - - -### Refactors - -* sort fields for squashed union structs ([#111](https://github.com/openai/openai-go/issues/111)) ([e927fb0](https://github.com/openai/openai-go/commit/e927fb06a76a9ad5e6061a24cf78ee2f43b9cb26)) - -## 0.1.0-alpha.63 (2025-03-12) - -Full Changelog: [v0.1.0-alpha.62...v0.1.0-alpha.63](https://github.com/openai/openai-go/compare/v0.1.0-alpha.62...v0.1.0-alpha.63) - -### Features - -* add SKIP_BREW env var to ./scripts/bootstrap ([#255](https://github.com/openai/openai-go/issues/255)) ([175ff8a](https://github.com/openai/openai-go/commit/175ff8a9fd945152693a873b20beaa1c4a4b0fc7)) -* **api:** updates ([#259](https://github.com/openai/openai-go/issues/259)) ([b95257b](https://github.com/openai/openai-go/commit/b95257b2950d77f5a634aa08a82925300c318031)) -* **client:** accept RFC6838 JSON content types ([#256](https://github.com/openai/openai-go/issues/256)) ([5941c83](https://github.com/openai/openai-go/commit/5941c838786018b77fdd8a72eaef5e798b95f81a)) -* **client:** allow custom baseurls without trailing slash ([#254](https://github.com/openai/openai-go/issues/254)) ([de1216a](https://github.com/openai/openai-go/commit/de1216a51301e6aeb987bdbff707d2f85b374593)) - - -### Bug Fixes - -* **responses:** correct computer use enum value ([#261](https://github.com/openai/openai-go/issues/261)) ([e5a07c6](https://github.com/openai/openai-go/commit/e5a07c6dbd762d567de2049bb218330b480ae35e)) -* **responses:** correct reasoning output type ([#262](https://github.com/openai/openai-go/issues/262)) ([ecad35d](https://github.com/openai/openai-go/commit/ecad35dce6297a7905af3f4760e46c482ac9f89f)) - - -### Chores - -* move ChatModel type to shared ([#250](https://github.com/openai/openai-go/issues/250)) ([34fbacc](https://github.com/openai/openai-go/commit/34fbacc8308683c2dca3368ad0d42cca3aee8deb)) - - -### Refactors - -* tidy up dependencies ([#257](https://github.com/openai/openai-go/issues/257)) ([d367e14](https://github.com/openai/openai-go/commit/d367e141c63b2585feb57670a9d7e762dfc7ca75)) - -## 0.1.0-alpha.62 (2025-03-05) - -Full Changelog: [v0.1.0-alpha.61...v0.1.0-alpha.62](https://github.com/openai/openai-go/compare/v0.1.0-alpha.61...v0.1.0-alpha.62) - -### Bug Fixes - -* **api:** add missing file rank enum + more metadata ([#248](https://github.com/openai/openai-go/issues/248)) ([78e98d1](https://github.com/openai/openai-go/commit/78e98d18b319bc0de2c00543d75771166a42db73)) - -## 0.1.0-alpha.61 (2025-02-27) - -Full Changelog: [v0.1.0-alpha.60...v0.1.0-alpha.61](https://github.com/openai/openai-go/compare/v0.1.0-alpha.60...v0.1.0-alpha.61) - -### Documentation - -* update URLs from stainlessapi.com to stainless.com ([#243](https://github.com/openai/openai-go/issues/243)) ([98019cf](https://github.com/openai/openai-go/commit/98019cf8c6b51e0b00ce8e58aca3b438f225f48f)) - -## 0.1.0-alpha.60 (2025-02-27) - -Full Changelog: [v0.1.0-alpha.59...v0.1.0-alpha.60](https://github.com/openai/openai-go/compare/v0.1.0-alpha.59...v0.1.0-alpha.60) - -### Features - -* **api:** add gpt-4.5-preview ([#242](https://github.com/openai/openai-go/issues/242)) ([0a7488c](https://github.com/openai/openai-go/commit/0a7488ce04a50e513d1dfe805540ddf84914bd50)) - - -### Chores - -* **internal:** fix devcontainers setup ([#236](https://github.com/openai/openai-go/issues/236)) ([b27a9db](https://github.com/openai/openai-go/commit/b27a9db77dc86b57312831f6c0e22a1bcb4967ed)) - -## 0.1.0-alpha.59 (2025-02-15) - -Full Changelog: [v0.1.0-alpha.58...v0.1.0-alpha.59](https://github.com/openai/openai-go/compare/v0.1.0-alpha.58...v0.1.0-alpha.59) - -### Bug Fixes - -* **client:** don't truncate manually specified filenames ([#230](https://github.com/openai/openai-go/issues/230)) ([853b748](https://github.com/openai/openai-go/commit/853b7483c07dc6f3b820f28bf3c5f097c3d440ad)) - -## 0.1.0-alpha.58 (2025-02-13) - -Full Changelog: [v0.1.0-alpha.57...v0.1.0-alpha.58](https://github.com/openai/openai-go/compare/v0.1.0-alpha.57...v0.1.0-alpha.58) - -### Features - -* **api:** add support for storing chat completions ([#228](https://github.com/openai/openai-go/issues/228)) ([e3cb85e](https://github.com/openai/openai-go/commit/e3cb85ea8020c774557a8b2283f41f146b7efd94)) - -## 0.1.0-alpha.57 (2025-02-10) - -Full Changelog: [v0.1.0-alpha.56...v0.1.0-alpha.57](https://github.com/openai/openai-go/compare/v0.1.0-alpha.56...v0.1.0-alpha.57) - -### Bug Fixes - -* do not call path.Base on ContentType ([#225](https://github.com/openai/openai-go/issues/225)) ([7dda9a8](https://github.com/openai/openai-go/commit/7dda9a8792c5d0725614d8867d42db45cb408a91)) - -## 0.1.0-alpha.56 (2025-02-07) - -Full Changelog: [v0.1.0-alpha.55...v0.1.0-alpha.56](https://github.com/openai/openai-go/compare/v0.1.0-alpha.55...v0.1.0-alpha.56) - -### Features - -* **pagination:** avoid fetching when has_more: false ([#218](https://github.com/openai/openai-go/issues/218)) ([22dfd12](https://github.com/openai/openai-go/commit/22dfd12bd06caaa6750b54c934b970288f43c67f)) - - -### Bug Fixes - -* fix early cancel when RequestTimeout is provided for streaming requests ([#221](https://github.com/openai/openai-go/issues/221)) ([4843296](https://github.com/openai/openai-go/commit/48432968fbb130a60d2a678df4e19bcc41d4a5e1)) - -## 0.1.0-alpha.55 (2025-02-05) - -Full Changelog: [v0.1.0-alpha.54...v0.1.0-alpha.55](https://github.com/openai/openai-go/compare/v0.1.0-alpha.54...v0.1.0-alpha.55) - -### Bug Fixes - -* **api:** add missing reasoning effort + model enums ([#215](https://github.com/openai/openai-go/issues/215)) ([a2345e6](https://github.com/openai/openai-go/commit/a2345e67316c4571354ab8587a94aa477fadf81b)) -* update stream error handling ([#213](https://github.com/openai/openai-go/issues/213)) ([2f82244](https://github.com/openai/openai-go/commit/2f82244b2c6c8584c4e8a91db8863a4cd0b41a2b)) - -## 0.1.0-alpha.54 (2025-02-05) - -Full Changelog: [v0.1.0-alpha.53...v0.1.0-alpha.54](https://github.com/openai/openai-go/compare/v0.1.0-alpha.53...v0.1.0-alpha.54) - -### Bug Fixes - -* **streaming:** correctly decode assistant events ([38ded46](https://github.com/openai/openai-go/commit/38ded4694480071a768eb4d2790ba4552e001506)) - - -### Chores - -* add UnionUnmarshaler for responses that are interfaces ([#211](https://github.com/openai/openai-go/issues/211)) ([185d848](https://github.com/openai/openai-go/commit/185d848cd3e9efb48f7468acc06a8b78f3a7b785)) - -## 0.1.0-alpha.53 (2025-02-05) - -Full Changelog: [v0.1.0-alpha.52...v0.1.0-alpha.53](https://github.com/openai/openai-go/compare/v0.1.0-alpha.52...v0.1.0-alpha.53) - -### Bug Fixes - -* **api/types:** correct audio duration & role types ([#209](https://github.com/openai/openai-go/issues/209)) ([bb8cc1a](https://github.com/openai/openai-go/commit/bb8cc1a938ba142068261170d7c82a445c2f0c6c)) - - -### Chores - -* **api:** delete deprecated method ([#208](https://github.com/openai/openai-go/issues/208)) ([0a927ba](https://github.com/openai/openai-go/commit/0a927ba16dfc5cde2a368e8a1040f5ba3cda7708)) -* **docs:** add docstring explaining streaming pattern ([#205](https://github.com/openai/openai-go/issues/205)) ([0bdb37f](https://github.com/openai/openai-go/commit/0bdb37f7efd9b338c32a1a83b90cecdb74f8ecce)) - - -### Documentation - -* **examples:** fix typo ([#207](https://github.com/openai/openai-go/issues/207)) ([05796de](https://github.com/openai/openai-go/commit/05796de39d3c1c88251fc42674bec1a53730c3d2)) - -## 0.1.0-alpha.52 (2025-02-03) - -Full Changelog: [v0.1.0-alpha.51...v0.1.0-alpha.52](https://github.com/openai/openai-go/compare/v0.1.0-alpha.51...v0.1.0-alpha.52) - -### Features - -* **client:** send `X-Stainless-Timeout` header ([#204](https://github.com/openai/openai-go/issues/204)) ([4ccf9c9](https://github.com/openai/openai-go/commit/4ccf9c9be331773407ec062c9da563d5b20831fe)) - - -### Bug Fixes - -* **stream:** ensure .Close() doesn't panic ([#194](https://github.com/openai/openai-go/issues/194)) ([02983a3](https://github.com/openai/openai-go/commit/02983a322b264af40105b7c742e6fe24cbb396d3)) -* **stream:** ensure .Close() doesn't panic ([#201](https://github.com/openai/openai-go/issues/201)) ([2df52a9](https://github.com/openai/openai-go/commit/2df52a9c7ec4839f104c0f30edfda183693fce8c)) - - -### Documentation - -* document raw responses ([#197](https://github.com/openai/openai-go/issues/197)) ([8400879](https://github.com/openai/openai-go/commit/8400879b1c226a62dc95feedc97a9c2718c8210f)) - -## 0.1.0-alpha.51 (2025-01-31) - -Full Changelog: [v0.1.0-alpha.50...v0.1.0-alpha.51](https://github.com/openai/openai-go/compare/v0.1.0-alpha.50...v0.1.0-alpha.51) - -### Features - -* **api:** add o3-mini ([#195](https://github.com/openai/openai-go/issues/195)) ([c5689d0](https://github.com/openai/openai-go/commit/c5689d01773a7ac0c10e95c1c8badadde251924e)) - - -### Bug Fixes - -* fix unicode encoding for json ([#193](https://github.com/openai/openai-go/issues/193)) ([3bd3c60](https://github.com/openai/openai-go/commit/3bd3c60561b1213dc4a5fe8b27c30ddef8234726)) -* **types:** correct metadata type + other fixes ([c5689d0](https://github.com/openai/openai-go/commit/c5689d01773a7ac0c10e95c1c8badadde251924e)) - -## 0.1.0-alpha.50 (2025-01-29) - -Full Changelog: [v0.1.0-alpha.49...v0.1.0-alpha.50](https://github.com/openai/openai-go/compare/v0.1.0-alpha.49...v0.1.0-alpha.50) - -### Chores - -* refactor client tests ([#187](https://github.com/openai/openai-go/issues/187)) ([2752c07](https://github.com/openai/openai-go/commit/2752c076dcc87e7c08d6785ba0a00ec9eba5a0c1)) - -## 0.1.0-alpha.49 (2025-01-22) - -Full Changelog: [v0.1.0-alpha.48...v0.1.0-alpha.49](https://github.com/openai/openai-go/compare/v0.1.0-alpha.48...v0.1.0-alpha.49) - -### Features - -* **api:** update enum values, comments, and examples ([#181](https://github.com/openai/openai-go/issues/181)) ([a074981](https://github.com/openai/openai-go/commit/a07498136304d74bd706684341fb9dcce6e8075c)) -* Minor text change: Update readme to say beta instead of alpha ([2b766ab](https://github.com/openai/openai-go/commit/2b766ab7054cb649d40db0e7ac50c370e070043f)) -* support deprecated markers ([#178](https://github.com/openai/openai-go/issues/178)) ([3d6f52f](https://github.com/openai/openai-go/commit/3d6f52f0f5b30f1f064cfbba8f61d28c1094bb0a)) - -## 0.1.0-alpha.48 (2025-01-21) - -Full Changelog: [v0.1.0-alpha.47...v0.1.0-alpha.48](https://github.com/openai/openai-go/compare/v0.1.0-alpha.47...v0.1.0-alpha.48) - -### Bug Fixes - -* fix apijson.Port for embedded structs ([#174](https://github.com/openai/openai-go/issues/174)) ([b9bc4bf](https://github.com/openai/openai-go/commit/b9bc4bf94438100057c9c95a199e82ec6a48e12e)) -* fix apijson.Port for embedded structs ([#177](https://github.com/openai/openai-go/issues/177)) ([a85df33](https://github.com/openai/openai-go/commit/a85df33a9fe89dffb5ce00ee297d173bb40018ed)) - - -### Chores - -* **internal:** rename `streaming.go` ([#176](https://github.com/openai/openai-go/issues/176)) ([8c54a3b](https://github.com/openai/openai-go/commit/8c54a3bfe8ed07346c2eade2cabfff1f6d97a7d8)) - -## 0.1.0-alpha.47 (2025-01-20) - -Full Changelog: [v0.1.0-alpha.46...v0.1.0-alpha.47](https://github.com/openai/openai-go/compare/v0.1.0-alpha.46...v0.1.0-alpha.47) - -### Bug Fixes - -* flush stream response when done event is sent ([#172](https://github.com/openai/openai-go/issues/172)) ([fa793de](https://github.com/openai/openai-go/commit/fa793de4e849c5e3ba23fbe4d6fd1533f08d9fe6)) - -## 0.1.0-alpha.46 (2025-01-17) - -Full Changelog: [v0.1.0-alpha.45...v0.1.0-alpha.46](https://github.com/openai/openai-go/compare/v0.1.0-alpha.45...v0.1.0-alpha.46) - -### Chores - -* **internal:** streaming refactors ([#165](https://github.com/openai/openai-go/issues/165)) ([168a030](https://github.com/openai/openai-go/commit/168a0305dc423cb09cefbfe0ad7c9c240a6a41b8)) -* **types:** rename vector store chunking strategy ([#169](https://github.com/openai/openai-go/issues/169)) ([2dc79a6](https://github.com/openai/openai-go/commit/2dc79a62b58e78275a68ee19d85b9be7873a3491)) - -## 0.1.0-alpha.45 (2025-01-09) - -Full Changelog: [v0.1.0-alpha.44...v0.1.0-alpha.45](https://github.com/openai/openai-go/compare/v0.1.0-alpha.44...v0.1.0-alpha.45) - -### Chores - -* **internal:** spec update ([#158](https://github.com/openai/openai-go/issues/158)) ([0ca04bd](https://github.com/openai/openai-go/commit/0ca04bdb233cf8fc5ea9ff497363a466bb95759a)) - -## 0.1.0-alpha.44 (2025-01-08) - -Full Changelog: [v0.1.0-alpha.43...v0.1.0-alpha.44](https://github.com/openai/openai-go/compare/v0.1.0-alpha.43...v0.1.0-alpha.44) - -### Documentation - -* **readme:** fix misplaced period ([#156](https://github.com/openai/openai-go/issues/156)) ([438fe84](https://github.com/openai/openai-go/commit/438fe84825a5d73a649d72c64ba52bf2f59e8847)) - -## 0.1.0-alpha.43 (2025-01-03) - -Full Changelog: [v0.1.0-alpha.42...v0.1.0-alpha.43](https://github.com/openai/openai-go/compare/v0.1.0-alpha.42...v0.1.0-alpha.43) - -### Chores - -* **api:** bump spec version ([#154](https://github.com/openai/openai-go/issues/154)) ([e55cffe](https://github.com/openai/openai-go/commit/e55cffe979c1e573ca2fe713365f31c62bb00b0e)) - -## 0.1.0-alpha.42 (2025-01-02) - -Full Changelog: [v0.1.0-alpha.41...v0.1.0-alpha.42](https://github.com/openai/openai-go/compare/v0.1.0-alpha.41...v0.1.0-alpha.42) - -### Chores - -* bump license year ([#151](https://github.com/openai/openai-go/issues/151)) ([c3e375e](https://github.com/openai/openai-go/commit/c3e375eca1eaece3b73b6918e5c07474717decc5)) - -## 0.1.0-alpha.41 (2024-12-21) - -Full Changelog: [v0.1.0-alpha.40...v0.1.0-alpha.41](https://github.com/openai/openai-go/compare/v0.1.0-alpha.40...v0.1.0-alpha.41) - -### Chores - -* **internal:** spec update ([#146](https://github.com/openai/openai-go/issues/146)) ([a9a67ba](https://github.com/openai/openai-go/commit/a9a67ba2f487d23adc7238c1151cab76a7fd9f01)) - - -### Documentation - -* **readme:** fix typo ([#148](https://github.com/openai/openai-go/issues/148)) ([1bb2322](https://github.com/openai/openai-go/commit/1bb23222e794c8439a56f765dee0c8d4e0db6eac)) - -## 0.1.0-alpha.40 (2024-12-17) - -Full Changelog: [v0.1.0-alpha.39...v0.1.0-alpha.40](https://github.com/openai/openai-go/compare/v0.1.0-alpha.39...v0.1.0-alpha.40) - -### Features - -* **api:** new o1 and GPT-4o models + preference fine-tuning ([#142](https://github.com/openai/openai-go/issues/142)) ([9207561](https://github.com/openai/openai-go/commit/920756111c0f7725eb5746b22c1393e327dc2990)) - - -### Chores - -* **internal:** spec update ([#145](https://github.com/openai/openai-go/issues/145)) ([bc0dba4](https://github.com/openai/openai-go/commit/bc0dba40f69294f460b3d448a6a093e487509dca)) - -## 0.1.0-alpha.39 (2024-12-05) - -Full Changelog: [v0.1.0-alpha.38...v0.1.0-alpha.39](https://github.com/openai/openai-go/compare/v0.1.0-alpha.38...v0.1.0-alpha.39) - -### Features - -* **api:** updates ([#138](https://github.com/openai/openai-go/issues/138)) ([67badff](https://github.com/openai/openai-go/commit/67badffd9f6b24979e52a71548437516b8d97e6f)) - - -### Chores - -* bump openapi url ([#136](https://github.com/openai/openai-go/issues/136)) ([179a1cd](https://github.com/openai/openai-go/commit/179a1cd7104d13c2014fa9fe3b1551e4b8829d71)) - -## 0.1.0-alpha.38 (2024-11-20) - -Full Changelog: [v0.1.0-alpha.37...v0.1.0-alpha.38](https://github.com/openai/openai-go/compare/v0.1.0-alpha.37...v0.1.0-alpha.38) - -### Features - -* **api:** add gpt-4o-2024-11-20 model ([#131](https://github.com/openai/openai-go/issues/131)) ([8dabbd3](https://github.com/openai/openai-go/commit/8dabbd3d3f338986470049c1a3842e47a7194c1e)) - - -### Chores - -* **internal:** spec update ([#130](https://github.com/openai/openai-go/issues/130)) ([23476d8](https://github.com/openai/openai-go/commit/23476d8131b009e38f7f22024d925fd7fe76e4db)) -* **tests:** limit array example length ([#128](https://github.com/openai/openai-go/issues/128)) ([5560e6b](https://github.com/openai/openai-go/commit/5560e6ba5f77e774d6be40e71628c1b62f8b3005)) - -## 0.1.0-alpha.37 (2024-11-12) - -Full Changelog: [v0.1.0-alpha.36...v0.1.0-alpha.37](https://github.com/openai/openai-go/compare/v0.1.0-alpha.36...v0.1.0-alpha.37) - -### Bug Fixes - -* **client:** no panic on missing BaseURL ([#121](https://github.com/openai/openai-go/issues/121)) ([1a8b841](https://github.com/openai/openai-go/commit/1a8b8415caabf9e4f33fc2b095b31dd926376b47)) - -## 0.1.0-alpha.36 (2024-11-11) - -Full Changelog: [v0.1.0-alpha.35...v0.1.0-alpha.36](https://github.com/openai/openai-go/compare/v0.1.0-alpha.35...v0.1.0-alpha.36) - -### Bug Fixes - -* correct required fields for flattened unions ([#120](https://github.com/openai/openai-go/issues/120)) ([8fe865b](https://github.com/openai/openai-go/commit/8fe865b5cb230bdac498ae295b16a7388cfdde6c)) - - -### Documentation - -* **readme:** fix example snippet ([#118](https://github.com/openai/openai-go/issues/118)) ([7f1803b](https://github.com/openai/openai-go/commit/7f1803b44183e8796a40eab6dee440cf16813e3c)) - -## 0.1.0-alpha.35 (2024-11-10) - -Full Changelog: [v0.1.0-alpha.34...v0.1.0-alpha.35](https://github.com/openai/openai-go/compare/v0.1.0-alpha.34...v0.1.0-alpha.35) - -### Bug Fixes - -* **api:** escape key values when encoding maps ([#116](https://github.com/openai/openai-go/issues/116)) ([a2bcd73](https://github.com/openai/openai-go/commit/a2bcd7394f725ea0e653d7d4c145f3f48b36c1c3)) - -## 0.1.0-alpha.34 (2024-11-07) - -Full Changelog: [v0.1.0-alpha.33...v0.1.0-alpha.34](https://github.com/openai/openai-go/compare/v0.1.0-alpha.33...v0.1.0-alpha.34) - -### Documentation - -* add missing docs for some enums ([#114](https://github.com/openai/openai-go/issues/114)) ([f01913f](https://github.com/openai/openai-go/commit/f01913f1432a64304de9232bd36624c9506e02ab)) - -## 0.1.0-alpha.33 (2024-11-05) - -Full Changelog: [v0.1.0-alpha.32...v0.1.0-alpha.33](https://github.com/openai/openai-go/compare/v0.1.0-alpha.32...v0.1.0-alpha.33) - -### Features - -* **api:** add support for predicted outputs ([#110](https://github.com/openai/openai-go/issues/110)) ([ab88fa9](https://github.com/openai/openai-go/commit/ab88fa960917bedd15d2ffdf50d0d7169afd661a)) - - -### Refactors - -* sort fields for squashed union structs ([#111](https://github.com/openai/openai-go/issues/111)) ([f7e4ac8](https://github.com/openai/openai-go/commit/f7e4ac83cd345e58c824a489a2883bd4ef7717f6)) - -## 0.1.0-alpha.32 (2024-10-30) - -Full Changelog: [v0.1.0-alpha.31...v0.1.0-alpha.32](https://github.com/openai/openai-go/compare/v0.1.0-alpha.31...v0.1.0-alpha.32) - -### Features - -* **api:** add new, expressive voices for Realtime and Audio in Chat Completions ([#101](https://github.com/openai/openai-go/issues/101)) ([f946acc](https://github.com/openai/openai-go/commit/f946acc71a92f885bed87f0d4e724fb40cae0f14)) - -## 0.1.0-alpha.31 (2024-10-23) - -Full Changelog: [v0.1.0-alpha.30...v0.1.0-alpha.31](https://github.com/openai/openai-go/compare/v0.1.0-alpha.30...v0.1.0-alpha.31) - -### Chores - -* **internal:** update spec version ([#95](https://github.com/openai/openai-go/issues/95)) ([0cb6f6a](https://github.com/openai/openai-go/commit/0cb6f6abd428a5bd314902708ab12bc12a1b978f)) - -## 0.1.0-alpha.30 (2024-10-22) - -Full Changelog: [v0.1.0-alpha.29...v0.1.0-alpha.30](https://github.com/openai/openai-go/compare/v0.1.0-alpha.29...v0.1.0-alpha.30) - -### ⚠ BREAKING CHANGES - -* **client:** improve naming of some variants ([#89](https://github.com/openai/openai-go/issues/89)) - -### Features - -* **client:** improve naming of some variants ([#89](https://github.com/openai/openai-go/issues/89)) ([12ac070](https://github.com/openai/openai-go/commit/12ac070611061e98ae2aaaeefa8eb661ff7f995f)) - -## 0.1.0-alpha.29 (2024-10-17) - -Full Changelog: [v0.1.0-alpha.28...v0.1.0-alpha.29](https://github.com/openai/openai-go/compare/v0.1.0-alpha.28...v0.1.0-alpha.29) - -### Features - -* **api:** add gpt-4o-audio-preview model for chat completions ([#88](https://github.com/openai/openai-go/issues/88)) ([03da9c9](https://github.com/openai/openai-go/commit/03da9c984e6b0fdb0d8da7a8e4fde29fc45b784d)) -* **assistants:** add polling helpers and examples ([#84](https://github.com/openai/openai-go/issues/84)) ([eab25dd](https://github.com/openai/openai-go/commit/eab25dde95f7dd50b712326714ce55e93432b4dc)) - - -### Bug Fixes - -* **example:** use correct model ([#86](https://github.com/openai/openai-go/issues/86)) ([6dad9b2](https://github.com/openai/openai-go/commit/6dad9b256b86b069ec9445ae86bfb2f2c3764b66)) - -## 0.1.0-alpha.28 (2024-10-16) - -Full Changelog: [v0.1.0-alpha.27...v0.1.0-alpha.28](https://github.com/openai/openai-go/compare/v0.1.0-alpha.27...v0.1.0-alpha.28) - -### Features - -* move pagination package from internal to packages ([#81](https://github.com/openai/openai-go/issues/81)) ([8875bdc](https://github.com/openai/openai-go/commit/8875bdc847467b322bd9b6c54c027d97a79c5f16)) - -## 0.1.0-alpha.27 (2024-10-14) - -Full Changelog: [v0.1.0-alpha.26...v0.1.0-alpha.27](https://github.com/openai/openai-go/compare/v0.1.0-alpha.26...v0.1.0-alpha.27) - -### Chores - -* fix GetNextPage docstring ([#78](https://github.com/openai/openai-go/issues/78)) ([490f8f0](https://github.com/openai/openai-go/commit/490f8f0ae34cc6769a7555cf77fef0192963ad06)) - -## 0.1.0-alpha.26 (2024-10-08) - -Full Changelog: [v0.1.0-alpha.25...v0.1.0-alpha.26](https://github.com/openai/openai-go/compare/v0.1.0-alpha.25...v0.1.0-alpha.26) - -### Bug Fixes - -* **beta:** pass beta header by default ([#75](https://github.com/openai/openai-go/issues/75)) ([cb66b47](https://github.com/openai/openai-go/commit/cb66b474fb86646501314456fce6acc4b31a2026)) - -## 0.1.0-alpha.25 (2024-10-02) - -Full Changelog: [v0.1.0-alpha.24...v0.1.0-alpha.25](https://github.com/openai/openai-go/compare/v0.1.0-alpha.24...v0.1.0-alpha.25) - -### Documentation - -* improve and reference contributing documentation ([#73](https://github.com/openai/openai-go/issues/73)) ([03a8261](https://github.com/openai/openai-go/commit/03a8261970011b2be7e101ec095a0eb93b361a04)) - -## 0.1.0-alpha.24 (2024-10-01) - -Full Changelog: [v0.1.0-alpha.23...v0.1.0-alpha.24](https://github.com/openai/openai-go/compare/v0.1.0-alpha.23...v0.1.0-alpha.24) - -### Features - -* **api:** support storing chat completions, enabling evals and model distillation in the dashboard ([#72](https://github.com/openai/openai-go/issues/72)) ([1e50f54](https://github.com/openai/openai-go/commit/1e50f549ef135d7494c9260c4638c6054fe06c74)) - - -### Chores - -* **docs:** fix maxium typo ([#69](https://github.com/openai/openai-go/issues/69)) ([3a5c6a6](https://github.com/openai/openai-go/commit/3a5c6a657ac8d821e95e07b442f00140b5332c93)) - -## 0.1.0-alpha.23 (2024-09-29) - -Full Changelog: [v0.1.0-alpha.22...v0.1.0-alpha.23](https://github.com/openai/openai-go/compare/v0.1.0-alpha.22...v0.1.0-alpha.23) - -### Chores - -* **docs:** remove some duplicative api.md entries ([#65](https://github.com/openai/openai-go/issues/65)) ([13a1ca2](https://github.com/openai/openai-go/commit/13a1ca2eb6320c797d6e278bfe258e1e7f27e031)) - -## 0.1.0-alpha.22 (2024-09-26) - -Full Changelog: [v0.1.0-alpha.21...v0.1.0-alpha.22](https://github.com/openai/openai-go/compare/v0.1.0-alpha.21...v0.1.0-alpha.22) - -### Features - -* **api:** add omni-moderation model ([#63](https://github.com/openai/openai-go/issues/63)) ([9ca9ebb](https://github.com/openai/openai-go/commit/9ca9ebb1f40c056642d987445ea0cc8d60a1d15f)) - -## 0.1.0-alpha.21 (2024-09-25) - -Full Changelog: [v0.1.0-alpha.20...v0.1.0-alpha.21](https://github.com/openai/openai-go/compare/v0.1.0-alpha.20...v0.1.0-alpha.21) - -### Features - -* **client:** send retry count header ([#60](https://github.com/openai/openai-go/issues/60)) ([8797500](https://github.com/openai/openai-go/commit/87975004c4917be6b59c34b1252b6a393412a754)) - - -### Bug Fixes - -* **audio:** correct response_format translations type ([#62](https://github.com/openai/openai-go/issues/62)) ([4b8df65](https://github.com/openai/openai-go/commit/4b8df6595d2d416c3589d6a270ebdf247bbe18af)) - -## 0.1.0-alpha.20 (2024-09-20) - -Full Changelog: [v0.1.0-alpha.19...v0.1.0-alpha.20](https://github.com/openai/openai-go/compare/v0.1.0-alpha.19...v0.1.0-alpha.20) - -### Chores - -* **types:** improve type name for embedding models ([#57](https://github.com/openai/openai-go/issues/57)) ([05fe24e](https://github.com/openai/openai-go/commit/05fe24eec2797848bbe866ad3c4bfa8da4a61b77)) - -## 0.1.0-alpha.19 (2024-09-18) - -Full Changelog: [v0.1.0-alpha.18...v0.1.0-alpha.19](https://github.com/openai/openai-go/compare/v0.1.0-alpha.18...v0.1.0-alpha.19) - -### Features - -* fix(streaming): correctly accumulate tool calls and roles ([#55](https://github.com/openai/openai-go/issues/55)) ([89651e4](https://github.com/openai/openai-go/commit/89651e4ebb80179b2fcc92d3c573679683a39201)) - -## 0.1.0-alpha.18 (2024-09-16) - -Full Changelog: [v0.1.0-alpha.17...v0.1.0-alpha.18](https://github.com/openai/openai-go/compare/v0.1.0-alpha.17...v0.1.0-alpha.18) - -### Chores - -* **internal:** update spec link ([#53](https://github.com/openai/openai-go/issues/53)) ([0fefed1](https://github.com/openai/openai-go/commit/0fefed1b392ea99ce2fa68e22a9ee53f60476037)) - - -### Documentation - -* update CONTRIBUTING.md ([#51](https://github.com/openai/openai-go/issues/51)) ([fe2d656](https://github.com/openai/openai-go/commit/fe2d656eaee480a87c4bf00eb5937fb167018ec9)) - -## 0.1.0-alpha.17 (2024-09-12) - -Full Changelog: [v0.1.0-alpha.16...v0.1.0-alpha.17](https://github.com/openai/openai-go/compare/v0.1.0-alpha.16...v0.1.0-alpha.17) - -### Features - -* **api:** add o1 models ([#49](https://github.com/openai/openai-go/issues/49)) ([37d160c](https://github.com/openai/openai-go/commit/37d160cef58d3aca3f8dfc8c50b0eb8b516c1bcb)) - - -### Documentation - -* **readme:** smaller readme snippets with links to examples ([#46](https://github.com/openai/openai-go/issues/46)) ([dcea342](https://github.com/openai/openai-go/commit/dcea34213655ce8f9d84979d2f3d9dfa1f7459a3)) - -## 0.1.0-alpha.16 (2024-09-10) - -Full Changelog: [v0.1.0-alpha.15...v0.1.0-alpha.16](https://github.com/openai/openai-go/compare/v0.1.0-alpha.15...v0.1.0-alpha.16) - -### Bug Fixes - -* **requestconfig:** copy over more fields when cloning ([#44](https://github.com/openai/openai-go/issues/44)) ([6e02130](https://github.com/openai/openai-go/commit/6e02130c086c21e7f0895d18d6ed98fefb56f4d0)) - -## 0.1.0-alpha.15 (2024-09-05) - -Full Changelog: [v0.1.0-alpha.14...v0.1.0-alpha.15](https://github.com/openai/openai-go/compare/v0.1.0-alpha.14...v0.1.0-alpha.15) - -### Features - -* **vector store:** improve chunking strategy type names ([#40](https://github.com/openai/openai-go/issues/40)) ([4932cca](https://github.com/openai/openai-go/commit/4932ccac47b4b7976366244aab5810fa44292350)) - -## 0.1.0-alpha.14 (2024-09-03) - -Full Changelog: [v0.1.0-alpha.13...v0.1.0-alpha.14](https://github.com/openai/openai-go/compare/v0.1.0-alpha.13...v0.1.0-alpha.14) - -### Features - -* **examples/structure-outputs:** created an example for using structured outputs ([7d1e71e](https://github.com/openai/openai-go/commit/7d1e71e72b8c55d5b7228b72d967e4cae8165280)) -* **stream-accumulators:** added streaming accumulator helpers and example ([29e80e7](https://github.com/openai/openai-go/commit/29e80e7dfb4571e93e616981ddc950e3058b6203)) - - -### Bug Fixes - -* **examples/fine-tuning:** used an old constant name ([#34](https://github.com/openai/openai-go/issues/34)) ([5d9ec26](https://github.com/openai/openai-go/commit/5d9ec26407b15c7effceb999bba3dfbeefc0adf2)) - - -### Documentation - -* **readme:** added some examples to readme ([#39](https://github.com/openai/openai-go/issues/39)) ([2dbfa62](https://github.com/openai/openai-go/commit/2dbfa62ffc89ead88e0fed586684a6b757836752)) - -## 0.1.0-alpha.13 (2024-08-29) - -Full Changelog: [v0.1.0-alpha.12...v0.1.0-alpha.13](https://github.com/openai/openai-go/compare/v0.1.0-alpha.12...v0.1.0-alpha.13) - -### Features - -* **api:** add file search result details to run steps ([#32](https://github.com/openai/openai-go/issues/32)) ([f6a1f12](https://github.com/openai/openai-go/commit/f6a1f12acbaf158af8009debcc2019d1b9e19104)) - -## 0.1.0-alpha.12 (2024-08-23) - -Full Changelog: [v0.1.0-alpha.11...v0.1.0-alpha.12](https://github.com/openai/openai-go/compare/v0.1.0-alpha.11...v0.1.0-alpha.12) - -### Features - -* support assistants stream ([0647f03](https://github.com/openai/openai-go/commit/0647f03c55fe8ec654f6a8fd98d77384d9df6b9d)) - -## 0.1.0-alpha.11 (2024-08-22) - -Full Changelog: [v0.1.0-alpha.10...v0.1.0-alpha.11](https://github.com/openai/openai-go/compare/v0.1.0-alpha.10...v0.1.0-alpha.11) - -### Features - -* add support for error property in stream ([#29](https://github.com/openai/openai-go/issues/29)) ([73f9342](https://github.com/openai/openai-go/commit/73f93429e1319387f1a95208166b3e871ce4e03a)) - -## 0.1.0-alpha.10 (2024-08-21) - -Full Changelog: [v0.1.0-alpha.9...v0.1.0-alpha.10](https://github.com/openai/openai-go/compare/v0.1.0-alpha.9...v0.1.0-alpha.10) - -### Documentation - -* **readme:** add an alpha warning ([#27](https://github.com/openai/openai-go/issues/27)) ([3f1cc3b](https://github.com/openai/openai-go/commit/3f1cc3bbf19daa48e83aacb6906b9776726d7154)) - -## 0.1.0-alpha.9 (2024-08-16) - -Full Changelog: [v0.1.0-alpha.8...v0.1.0-alpha.9](https://github.com/openai/openai-go/compare/v0.1.0-alpha.8...v0.1.0-alpha.9) - -### Features - -* **api:** add chatgpt-4o-latest model ([#24](https://github.com/openai/openai-go/issues/24)) ([112c7f3](https://github.com/openai/openai-go/commit/112c7f31917596b6c029a1f00643647375e8c8c8)) - -## 0.1.0-alpha.8 (2024-08-15) - -Full Changelog: [v0.1.0-alpha.7...v0.1.0-alpha.8](https://github.com/openai/openai-go/compare/v0.1.0-alpha.7...v0.1.0-alpha.8) - -### Chores - -* **types:** define FilePurpose enum ([#22](https://github.com/openai/openai-go/issues/22)) ([2a7c699](https://github.com/openai/openai-go/commit/2a7c699e4fb21f848aa5d260da9d2a5c471866d1)) - -## 0.1.0-alpha.7 (2024-08-12) - -Full Changelog: [v0.1.0-alpha.6...v0.1.0-alpha.7](https://github.com/openai/openai-go/compare/v0.1.0-alpha.6...v0.1.0-alpha.7) - -### Chores - -* add back custom code that was reverted ([2557bd8](https://github.com/openai/openai-go/commit/2557bd8b5f1748adf67d9208ceaeea3250d93b14)) - -## 0.1.0-alpha.6 (2024-08-12) - -Full Changelog: [v0.1.0-alpha.5...v0.1.0-alpha.6](https://github.com/openai/openai-go/compare/v0.1.0-alpha.5...v0.1.0-alpha.6) - -### Features - -* Adding in Azure support ([3225b7c](https://github.com/openai/openai-go/commit/3225b7c6028c0c5ab9420416b6bb8b31a5383218)) - -## 0.1.0-alpha.5 (2024-08-12) - -Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/openai/openai-go/compare/v0.1.0-alpha.4...v0.1.0-alpha.5) - -### Features - -* simplify content union ([#18](https://github.com/openai/openai-go/issues/18)) ([51877bf](https://github.com/openai/openai-go/commit/51877bf8f16e348a531aa54f0f49e9d71390a485)) - -## 0.1.0-alpha.4 (2024-08-12) - -Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/openai/openai-go/compare/v0.1.0-alpha.3...v0.1.0-alpha.4) - -### Chores - -* **examples:** minor formatting changes ([#14](https://github.com/openai/openai-go/issues/14)) ([8d4490b](https://github.com/openai/openai-go/commit/8d4490b78dcc0edee3264448e3fa3f3781d04258)) - -## 0.1.0-alpha.3 (2024-08-12) - -Full Changelog: [v0.1.0-alpha.2...v0.1.0-alpha.3](https://github.com/openai/openai-go/compare/v0.1.0-alpha.2...v0.1.0-alpha.3) - -### Chores - -* bump Go to v1.21 ([#12](https://github.com/openai/openai-go/issues/12)) ([db5efda](https://github.com/openai/openai-go/commit/db5efdaad3848b8f130f279e6760d9d525e02bda)) - -## 0.1.0-alpha.2 (2024-08-10) - -Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/openai/openai-go/compare/v0.1.0-alpha.1...v0.1.0-alpha.2) - -### Bug Fixes - -* deserialization of struct unions that implement json.Unmarshaler ([#11](https://github.com/openai/openai-go/issues/11)) ([7c0847a](https://github.com/openai/openai-go/commit/7c0847aa2ae15b4442ab0625d8a780ed684c275e)) - - -### Chores - -* **ci:** bump prism mock server version ([#10](https://github.com/openai/openai-go/issues/10)) ([00f9455](https://github.com/openai/openai-go/commit/00f9455692c52fb37544d3f657090b216667d8ec)) -* **ci:** codeowners file ([#9](https://github.com/openai/openai-go/issues/9)) ([be41ac2](https://github.com/openai/openai-go/commit/be41ac2ce87efacf17748cb9dd2d3b1b4a43180e)) -* **internal:** updates ([#6](https://github.com/openai/openai-go/issues/6)) ([316e623](https://github.com/openai/openai-go/commit/316e6231c27728f4031f822287389c67e914739a)) - -## 0.1.0-alpha.1 (2024-08-06) - -Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/openai/openai-go/compare/v0.0.1-alpha.0...v0.1.0-alpha.1) - -### Features - -* add azure, examples, and message constructors ([fb2df0f](https://github.com/openai/openai-go/commit/fb2df0fe22002f1826bfaa1cb008c45db375885c)) -* **api:** updates ([#5](https://github.com/openai/openai-go/issues/5)) ([9f525e8](https://github.com/openai/openai-go/commit/9f525e85d8fe13cce2a18a1a48179bc5a6d1f094)) -* extract out `ImageModel`, `AudioModel`, `SpeechModel` ([#3](https://github.com/openai/openai-go/issues/3)) ([f085893](https://github.com/openai/openai-go/commit/f085893d109a9e841d1df13df4c71cae06018758)) -* make enums not nominal ([#4](https://github.com/openai/openai-go/issues/4)) ([9f77005](https://github.com/openai/openai-go/commit/9f77005474b8a38cbfc09f22ec3b81d1de62d3c3)) -* publish ([c329601](https://github.com/openai/openai-go/commit/c329601324226e28ff18d6ccecfdde41cedd3b5a)) - - -### Chores - -* **internal:** updates ([#2](https://github.com/openai/openai-go/issues/2)) ([5976d8d](https://github.com/openai/openai-go/commit/5976d8d8b9a94cd78e4d86f704137f4b43224a08)) diff --git a/README.md b/README.md index f08c1a11..342463d0 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,6 @@ Go Reference -> [!WARNING] -> **This release is currently in beta**. Minor breaking changes may occur. - The OpenAI Go library provides convenient access to [the OpenAI REST API](https://platform.openai.com/docs) from applications written in Go. The full API of this library can be found in [api.md](api.md). @@ -38,8 +35,6 @@ This library requires Go 1.18+. The full API of this library can be found in [api.md](api.md). -See the [examples](./examples/) directory for complete and runnable examples. - ```go package main @@ -57,10 +52,10 @@ func main() { option.WithAPIKey("My API Key"), // defaults to os.LookupEnv("OPENAI_API_KEY") ) chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ - openai.UserMessage("Say this is a test"), - }), - Model: openai.F(openai.ChatModelGPT4o), + Messages: []openai.ChatCompletionMessageParamUnion{ + openai.UserMessage("Say this is a test"), + }, + Model: openai.ChatModelGPT4o, }) if err != nil { panic(err.Error()) @@ -70,23 +65,22 @@ func main() { ``` -
Conversations ```go param := openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage("What kind of houseplant is easy to take care of?"), - }), + }, Seed: openai.Int(1), - Model: openai.F(openai.ChatModelGPT4o), + Model: openai.ChatModelGPT4o, } completion, err := client.Chat.Completions.New(ctx, param) -param.Messages.Value = append(param.Messages.Value, completion.Choices[0].Message) -param.Messages.Value = append(param.Messages.Value, openai.UserMessage("How big are those?")) +param.Messages = append(param.Messages, completion.Choices[0].Message.ToParam()) +param.Messages = append(param.Messages, openai.UserMessage("How big are those?")) // continue the conversation completion, err = client.Chat.Completions.New(ctx, param) @@ -101,11 +95,11 @@ completion, err = client.Chat.Completions.New(ctx, param) question := "Write an epic" stream := client.Chat.Completions.NewStreaming(ctx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), + }, Seed: openai.Int(0), - Model: openai.F(openai.ChatModelGPT4o), + Model: openai.ChatModelGPT4o, }) // optionally, an accumulator helper can be used @@ -134,15 +128,15 @@ for stream.Next() { } } -if err := stream.Err(); err != nil { - panic(err) +if stream.Err() != nil { + panic(stream.Err()) } // After the stream is finished, acc can be used like a ChatCompletion _ = acc.Choices[0].Message.Content ``` -> See the [full streaming and accumulation example](./examples/chat-completion-accumulating/main.go) +> See the [full streaming and accumulation example]./examples/chat-completion-accumulating/main.go)
@@ -160,16 +154,15 @@ import ( question := "What is the weather in New York City?" params := openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), - Tools: openai.F([]openai.ChatCompletionToolParam{ + }, + Tools: []openai.ChatCompletionToolParam{ { - Type: openai.F(openai.ChatCompletionToolTypeFunction), - Function: openai.F(openai.FunctionDefinitionParam{ - Name: openai.String("get_weather"), + Function: openai.FunctionDefinitionParam{ + Name: "get_weather", Description: openai.String("Get weather at the given location"), - Parameters: openai.F(openai.FunctionParameters{ + Parameters: openai.FunctionParameters{ "type": "object", "properties": map[string]interface{}{ "location": map[string]string{ @@ -177,32 +170,39 @@ params := openai.ChatCompletionNewParams{ }, }, "required": []string{"location"}, - }), - }), + }, + }, }, - }), - Model: openai.F(openai.ChatModelGPT4o), + }, + Model: openai.ChatModelGPT4o, } -// chat completion request with tool calls -completion, _ := client.Chat.Completions.New(ctx, params) - -for _, toolCall := range completion.Choices[0].Message.ToolCalls { +// If there is a was a function call, continue the conversation +params.Messages = append(params.Messages, completion.Choices[0].Message.ToParam()) +for _, toolCall := range toolCalls { if toolCall.Function.Name == "get_weather" { - // extract the location from the function call arguments + // Extract the location from the function call arguments var args map[string]interface{} - _ := json.Unmarshal([]byte(toolCall.Function.Arguments), &args) + err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args) + if err != nil { + panic(err) + } + location := args["location"].(string) + + // Simulate getting weather data + weatherData := getWeather(location) + + // Print the weather data + fmt.Printf("Weather in %s: %s\n", location, weatherData) - // call a weather API with the arguments requested by the model - weatherData := getWeather(args["location"].(string)) - params.Messages.Value = append(params.Messages.Value, openai.ToolMessage(toolCall.ID, weatherData)) + params.Messages = append(params.Messages, openai.ToolMessage(weatherData, toolCall.ID)) } } // ... continue the conversation with the information provided by the tool ``` -> See the [full tool calling example](./examples/chat-completion-tool-calling/main.go) +> See the [full tool calling example]./examples/chat-completion-tool-calling/main.go) @@ -220,6 +220,7 @@ import ( type HistoricalComputer struct { Origin Origin `json:"origin" jsonschema_description:"The origin of the computer"` Name string `json:"full_name" jsonschema_description:"The name of the device model"` + Legacy string `json:"legacy" jsonschema:"enum=positive,enum=neutral,enum=negative" jsonschema_description:"Its influence on the field of computing"` NotableFacts []string `json:"notable_facts" jsonschema_description:"A few key facts about the computer"` } @@ -229,6 +230,8 @@ type Origin struct { } func GenerateSchema[T any]() interface{} { + // Structured Outputs uses a subset of JSON schema + // These flags are necessary to comply with the subset reflector := jsonschema.Reflector{ AllowAdditionalProperties: false, DoNotReference: true, @@ -248,26 +251,25 @@ func main() { question := "What computer ran the first neural network?" schemaParam := openai.ResponseFormatJSONSchemaJSONSchemaParam{ - Name: openai.F("biography"), - Description: openai.F("Notable information about a person"), - Schema: openai.F(HistoricalComputerResponseSchema), + Name: "historical_computer", + Description: openai.String("Notable information about a computer"), + Schema: HistoricalComputerResponseSchema, Strict: openai.Bool(true), } chat, _ := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{ // ... - ResponseFormat: openai.F[openai.ChatCompletionNewParamsResponseFormatUnion]( - openai.ResponseFormatJSONSchemaParam{ - Type: openai.F(openai.ResponseFormatJSONSchemaTypeJSONSchema), - JSONSchema: openai.F(schemaParam), + ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{ + OfJSONSchema: &openai.ResponseFormatJSONSchemaParam{ + JSONSchema: schemaParam, }, - ), + }, // only certain models can perform structured outputs - Model: openai.F(openai.ChatModelGPT4o2024_08_06), + Model: openai.ChatModelGPT4o2024_08_06, }) // extract into a well-typed struct - historicalComputer := HistoricalComputer{} + var historicalComputer HistoricalComputer _ = json.Unmarshal([]byte(chat.Choices[0].Message.Content), &historicalComputer) historicalComputer.Name @@ -283,33 +285,85 @@ func main() { + ### Request fields -All request parameters are wrapped in a generic `Field` type, -which we use to distinguish zero values from null or omitted fields. +The openai library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson) +semantics from the Go 1.24+ `encoding/json` release for request fields. + +Required primitive fields (`int64`, `string`, etc.) feature the tag \`json:...,required\`. These +fields are always serialized, even their zero values. + +Optional primitive types are wrapped in a `param.Opt[T]`. Use the provided constructors set `param.Opt[T]` fields such as `openai.String(string)`, `openai.Int(int64)`, etc. -This prevents accidentally sending a zero value if you forget a required parameter, -and enables explicitly sending `null`, `false`, `''`, or `0` on optional parameters. -Any field not specified is not sent. +Optional primitives, maps, slices and structs and string enums (represented as `string`) always feature the +tag \`json:"...,omitzero"\`. Their zero values are considered omitted. -To construct fields with values, use the helpers `String()`, `Int()`, `Float()`, or most commonly, the generic `F[T]()`. -To send a null, use `Null[T]()`, and to send a nonconforming value, use `Raw[T](any)`. For example: +Any non-nil slice of length zero will serialize as an empty JSON array, `"[]"`. Similarly, any non-nil map with length zero with serialize as an empty JSON object, `"{}"`. + +To send `null` instead of an `param.Opt[T]`, use `param.NullOpt[T]()`. +To send `null` instead of a struct, use `param.NullObj[T]()`, where `T` is a struct. +To send a custom value instead of a struct, use `param.OverrideObj[T](value)`. + +To override request structs contain a `.WithExtraFields(map[string]any)` method which can be used to +send non-conforming fields in the request body. Extra fields take higher precedence than normal +fields. ```go params := FooParams{ - Name: openai.F("hello"), + ID: "id_xxx", // required property + Name: openai.String("hello"), // optional property + Description: param.NullOpt[string](), // explicit null property + + Point: openai.Point{ + X: 0, // required field will serialize as 0 + Y: openai.Int(1), // optional field will serialize as 1 + // ... omitted non-required fields will not be serialized + }), - // Explicitly send `"description": null` - Description: openai.Null[string](), + Origin: openai.Origin{}, // the zero value of [Origin] is considered omitted +} - Point: openai.F(openai.Point{ - X: openai.Int(0), - Y: openai.Int(1), +// In cases where the API specifies a given type, +// but you want to send something else, use [WithExtraFields]: +params.WithExtraFields(map[string]any{ + "x": 0.01, // send "x" as a float instead of int +}) - // In cases where the API specifies a given type, - // but you want to send something else, use `Raw`: - Z: openai.Raw[int64](0.01), // sends a float - }), +// Send a number instead of an object +custom := param.OverrideObj[openai.FooParams](12) +``` + +When available, use the `.IsPresent()` method to check if an optional parameter is not omitted or `null`. +Otherwise, the `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field. + +### Request unions + +Unions are represented as a struct with fields prefixed by "Of" for each of it's variants, +only one field can be non-zero. The non-zero field will be serialized. + +Properties can be accessed via getters on the union struct. These getters return a mutable +pointer to the underlying data, if present. + +```go +// Only one field can be non-zero, use param.IsOmitted() to check if a field is set +type AnimalUnionParam struct { + OfCat *Cat `json:",omitzero,inline` + OfDog *Dog `json:",omitzero,inline` +} + +animal := AnimalUnionParam{ + OfCat: &Cat{ + Name: "Whiskers", + Owner: PersonParam{ + Address: AddressParam{Street: "3333 Coyote Hill Rd", Zip: 0}, + }, + }, +} + +// Mutating a field +if address := animal.GetOwner().GetAddress(); address != nil { + address.ZipCode = 94304 } ``` @@ -325,14 +379,14 @@ information about each property, which you can use like so: ```go if res.Name == "" { - // true if `"name"` is either not present or explicitly null - res.JSON.Name.IsNull() + // true if `"name"` was unmarshalled successfully + res.JSON.Name.IsPresent() - // true if the `"name"` key was not present in the response JSON at all - res.JSON.Name.IsMissing() + res.JSON.Name.IsExplicitNull() // true if `"name"` is explicitly null + res.JSON.Name.Raw() == "" // true if `"name"` field does not exist // When the API returns data that cannot be coerced to the expected type: - if res.JSON.Name.IsInvalid() { + if !res.JSON.Name.IsPresent() && res.JSON.Name.Raw() != "" { raw := res.JSON.Name.Raw() legacyName := struct{ @@ -345,7 +399,7 @@ if res.Name == "" { } ``` -These `.JSON` structs also include an `Extras` map containing +These `.JSON` structs also include an `ExtraFields` map containing any properties in the json response that were not specified in the struct. This can be useful for API features not yet present in the SDK. @@ -354,6 +408,49 @@ present in the SDK. body := res.JSON.ExtraFields["my_unexpected_field"].Raw() ``` +### Response Unions + +In responses, unions are represented by a flattened struct containing all possible fields from each of the +object variants. +To convert it to a variant use the `.AsFooVariant()` method or the `.AsAny()` method if present. + +If a response value union contains primitive values, primitive fields will be alongside +the properties but prefixed with `Of` and feature the tag `json:"...,inline"`. + +```go +type AnimalUnion struct { + OfString string `json:",inline"` + Name string `json:"name"` + Owner Person `json:"owner"` + // ... + JSON struct { + OfString resp.Field + Name resp.Field + Owner resp.Field + // ... + } +} + +// If animal variant +if animal.Owner.Address.JSON.ZipCode == "" { + panic("missing zip code") +} + +// If string variant +if !animal.OfString == "" { + panic("expected a name") +} + +// Switch on the variant +switch variant := animalOrName.AsAny().(type) { +case string: +case Dog: +case Cat: +default: + panic("unexpected type") +} +``` + ### RequestOptions This library uses the functional options pattern. Functions defined in the @@ -385,7 +482,7 @@ You can use `.ListAutoPaging()` methods to iterate through items across all page ```go iter := client.FineTuning.Jobs.ListAutoPaging(context.TODO(), openai.FineTuningJobListParams{ - Limit: openai.F(int64(20)), + Limit: openai.Int(20), }) // Automatically fetches more pages as needed. for iter.Next() { @@ -402,7 +499,7 @@ with additional helper methods like `.GetNextPage()`, e.g.: ```go page, err := client.FineTuning.Jobs.List(context.TODO(), openai.FineTuningJobListParams{ - Limit: openai.F(int64(20)), + Limit: openai.Int(20), }) for page != nil { for _, job := range page.Data { @@ -426,8 +523,8 @@ To handle errors, we recommend that you use the `errors.As` pattern: ```go _, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{ - Model: openai.F(openai.FineTuningJobNewParamsModelBabbage002), - TrainingFile: openai.F("file-abc123"), + Model: "babbage-002", + TrainingFile: "file-abc123", }) if err != nil { var apierr *openai.Error @@ -456,10 +553,14 @@ defer cancel() client.Chat.Completions.New( ctx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ - openai.UserMessage("Say this is a test"), - }), - Model: openai.F(openai.ChatModelGPT4o), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("How can I list all files in a directory using Python?"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }, // This sets the per-retry timeout option.WithRequestTimeout(20*time.Second), @@ -469,7 +570,7 @@ client.Chat.Completions.New( ### File uploads Request parameters that correspond to file uploads in multipart requests are typed as -`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form +`io.Reader`. The contents of the `io.Reader` will by default be sent as a multipart form part with the file name of "anonymous_file" and content-type of "application/octet-stream". The file name and content-type can be customized by implementing `Name() string` or `ContentType() @@ -484,19 +585,19 @@ which can be used to wrap any `io.Reader` with the appropriate file name and con file, err := os.Open("input.jsonl") openai.FileNewParams{ File: openai.F[io.Reader](file), - Purpose: openai.F(openai.FilePurposeFineTune), + Purpose: openai.FilePurposeFineTune, } // A file from a string openai.FileNewParams{ File: openai.F[io.Reader](strings.NewReader("my file contents")), - Purpose: openai.F(openai.FilePurposeFineTune), + Purpose: openai.FilePurposeFineTune, } // With a custom filename and contentType openai.FileNewParams{ File: openai.FileParam(strings.NewReader(`{"hello": "foo"}`), "file.go", "application/json"), - Purpose: openai.F(openai.FilePurposeFineTune), + Purpose: openai.FilePurposeFineTune, } ``` @@ -518,10 +619,14 @@ client := openai.NewClient( client.Chat.Completions.New( context.TODO(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ - openai.UserMessage("Say this is a test"), - }), - Model: openai.F(openai.ChatModelGPT4o), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("How can I get the name of the current day in JavaScript?"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }, option.WithMaxRetries(5), ) @@ -538,11 +643,14 @@ var response *http.Response chatCompletion, err := client.Chat.Completions.New( context.TODO(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F([]openai.ChatCompletionContentPartUnionParam{openai.ChatCompletionContentPartTextParam{Text: openai.F("text"), Type: openai.F(openai.ChatCompletionContentPartTextTypeText)}}), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }, option.WithResponseInto(&response), ) @@ -588,10 +696,10 @@ or the `option.WithJSONSet()` methods. ```go params := FooNewParams{ - ID: openai.F("id_xxxx"), - Data: openai.F(FooNewParamsData{ - FirstName: openai.F("John"), - }), + ID: "id_xxxx", + Data: FooNewParamsData{ + FirstName: openai.String("John"), + }, } client.Foo.New(context.Background(), params, option.WithJSONSet("data.last_name", "Doe")) ``` @@ -643,7 +751,7 @@ middleware has been applied. ## Microsoft Azure OpenAI -To use this library with [Azure OpenAI](https://learn.microsoft.com/azure/ai-services/openai/overview), use the option.RequestOption functions in the `azure` package. +To use this library with [Azure OpenAI]https://learn.microsoft.com/azure/ai-services/openai/overview), use the ption.RequestOption functions in the `azure` package. ```go package main @@ -658,7 +766,7 @@ func main() { const azureOpenAIEndpoint = "https://.openai.azure.com" // The latest API versions, including previews, can be found here: - // https://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versioning + // ttps://learn.microsoft.com/en-us/azure/ai-services/openai/reference#rest-api-versionng const azureOpenAIAPIVersion = "2024-06-01" tokenCredential, err := azidentity.NewDefaultAzureCredential(nil) @@ -678,6 +786,7 @@ func main() { } ``` + ## Semantic versioning This package generally follows [SemVer](https://semver.org/spec/v2.0.0.html) conventions, though certain backwards-incompatible changes may be released as minor versions: diff --git a/aliases.go b/aliases.go index bb7c52e9..3a0f505d 100644 --- a/aliases.go +++ b/aliases.go @@ -4,148 +4,156 @@ package openai import ( "github.com/openai/openai-go/internal/apierror" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" ) +// aliased to make [param.APIUnion] private when embedding +type paramUnion = param.APIUnion + +// aliased to make [param.APIObject] private when embedding +type paramObj = param.APIObject + type Error = apierror.Error // This is an alias to an internal type. type ChatModel = shared.ChatModel -// This is an alias to an internal value. +// Equals "o3-mini" const ChatModelO3Mini = shared.ChatModelO3Mini -// This is an alias to an internal value. +// Equals "o3-mini-2025-01-31" const ChatModelO3Mini2025_01_31 = shared.ChatModelO3Mini2025_01_31 -// This is an alias to an internal value. +// Equals "o1" const ChatModelO1 = shared.ChatModelO1 -// This is an alias to an internal value. +// Equals "o1-2024-12-17" const ChatModelO1_2024_12_17 = shared.ChatModelO1_2024_12_17 -// This is an alias to an internal value. +// Equals "o1-preview" const ChatModelO1Preview = shared.ChatModelO1Preview -// This is an alias to an internal value. +// Equals "o1-preview-2024-09-12" const ChatModelO1Preview2024_09_12 = shared.ChatModelO1Preview2024_09_12 -// This is an alias to an internal value. +// Equals "o1-mini" const ChatModelO1Mini = shared.ChatModelO1Mini -// This is an alias to an internal value. +// Equals "o1-mini-2024-09-12" const ChatModelO1Mini2024_09_12 = shared.ChatModelO1Mini2024_09_12 -// This is an alias to an internal value. +// Equals "gpt-4o" const ChatModelGPT4o = shared.ChatModelGPT4o -// This is an alias to an internal value. +// Equals "gpt-4o-2024-11-20" const ChatModelGPT4o2024_11_20 = shared.ChatModelGPT4o2024_11_20 -// This is an alias to an internal value. +// Equals "gpt-4o-2024-08-06" const ChatModelGPT4o2024_08_06 = shared.ChatModelGPT4o2024_08_06 -// This is an alias to an internal value. +// Equals "gpt-4o-2024-05-13" const ChatModelGPT4o2024_05_13 = shared.ChatModelGPT4o2024_05_13 -// This is an alias to an internal value. +// Equals "gpt-4o-audio-preview" const ChatModelGPT4oAudioPreview = shared.ChatModelGPT4oAudioPreview -// This is an alias to an internal value. +// Equals "gpt-4o-audio-preview-2024-10-01" const ChatModelGPT4oAudioPreview2024_10_01 = shared.ChatModelGPT4oAudioPreview2024_10_01 -// This is an alias to an internal value. +// Equals "gpt-4o-audio-preview-2024-12-17" const ChatModelGPT4oAudioPreview2024_12_17 = shared.ChatModelGPT4oAudioPreview2024_12_17 -// This is an alias to an internal value. +// Equals "gpt-4o-mini-audio-preview" const ChatModelGPT4oMiniAudioPreview = shared.ChatModelGPT4oMiniAudioPreview -// This is an alias to an internal value. +// Equals "gpt-4o-mini-audio-preview-2024-12-17" const ChatModelGPT4oMiniAudioPreview2024_12_17 = shared.ChatModelGPT4oMiniAudioPreview2024_12_17 -// This is an alias to an internal value. +// Equals "gpt-4o-search-preview" const ChatModelGPT4oSearchPreview = shared.ChatModelGPT4oSearchPreview -// This is an alias to an internal value. +// Equals "gpt-4o-mini-search-preview" const ChatModelGPT4oMiniSearchPreview = shared.ChatModelGPT4oMiniSearchPreview -// This is an alias to an internal value. +// Equals "gpt-4o-search-preview-2025-03-11" const ChatModelGPT4oSearchPreview2025_03_11 = shared.ChatModelGPT4oSearchPreview2025_03_11 -// This is an alias to an internal value. +// Equals "gpt-4o-mini-search-preview-2025-03-11" const ChatModelGPT4oMiniSearchPreview2025_03_11 = shared.ChatModelGPT4oMiniSearchPreview2025_03_11 -// This is an alias to an internal value. +// Equals "chatgpt-4o-latest" const ChatModelChatgpt4oLatest = shared.ChatModelChatgpt4oLatest -// This is an alias to an internal value. +// Equals "gpt-4o-mini" const ChatModelGPT4oMini = shared.ChatModelGPT4oMini -// This is an alias to an internal value. +// Equals "gpt-4o-mini-2024-07-18" const ChatModelGPT4oMini2024_07_18 = shared.ChatModelGPT4oMini2024_07_18 -// This is an alias to an internal value. +// Equals "gpt-4-turbo" const ChatModelGPT4Turbo = shared.ChatModelGPT4Turbo -// This is an alias to an internal value. +// Equals "gpt-4-turbo-2024-04-09" const ChatModelGPT4Turbo2024_04_09 = shared.ChatModelGPT4Turbo2024_04_09 -// This is an alias to an internal value. +// Equals "gpt-4-0125-preview" const ChatModelGPT4_0125Preview = shared.ChatModelGPT4_0125Preview -// This is an alias to an internal value. +// Equals "gpt-4-turbo-preview" const ChatModelGPT4TurboPreview = shared.ChatModelGPT4TurboPreview -// This is an alias to an internal value. +// Equals "gpt-4-1106-preview" const ChatModelGPT4_1106Preview = shared.ChatModelGPT4_1106Preview -// This is an alias to an internal value. +// Equals "gpt-4-vision-preview" const ChatModelGPT4VisionPreview = shared.ChatModelGPT4VisionPreview -// This is an alias to an internal value. +// Equals "gpt-4" const ChatModelGPT4 = shared.ChatModelGPT4 -// This is an alias to an internal value. +// Equals "gpt-4-0314" const ChatModelGPT4_0314 = shared.ChatModelGPT4_0314 -// This is an alias to an internal value. +// Equals "gpt-4-0613" const ChatModelGPT4_0613 = shared.ChatModelGPT4_0613 -// This is an alias to an internal value. +// Equals "gpt-4-32k" const ChatModelGPT4_32k = shared.ChatModelGPT4_32k -// This is an alias to an internal value. +// Equals "gpt-4-32k-0314" const ChatModelGPT4_32k0314 = shared.ChatModelGPT4_32k0314 -// This is an alias to an internal value. +// Equals "gpt-4-32k-0613" const ChatModelGPT4_32k0613 = shared.ChatModelGPT4_32k0613 -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo" const ChatModelGPT3_5Turbo = shared.ChatModelGPT3_5Turbo -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-16k" const ChatModelGPT3_5Turbo16k = shared.ChatModelGPT3_5Turbo16k -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-0301" const ChatModelGPT3_5Turbo0301 = shared.ChatModelGPT3_5Turbo0301 -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-0613" const ChatModelGPT3_5Turbo0613 = shared.ChatModelGPT3_5Turbo0613 -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-1106" const ChatModelGPT3_5Turbo1106 = shared.ChatModelGPT3_5Turbo1106 -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-0125" const ChatModelGPT3_5Turbo0125 = shared.ChatModelGPT3_5Turbo0125 -// This is an alias to an internal value. +// Equals "gpt-3.5-turbo-16k-0613" const ChatModelGPT3_5Turbo16k0613 = shared.ChatModelGPT3_5Turbo16k0613 // A filter used to compare a specified attribute key to a given value using a // defined comparison operation. // // This is an alias to an internal type. -type ComparisonFilterParam = shared.ComparisonFilterParam +type ComparisonFilter = shared.ComparisonFilter // Specifies the comparison operator: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`. // @@ -159,24 +167,36 @@ type ComparisonFilterParam = shared.ComparisonFilterParam // This is an alias to an internal type. type ComparisonFilterType = shared.ComparisonFilterType -// This is an alias to an internal value. +// Equals "eq" const ComparisonFilterTypeEq = shared.ComparisonFilterTypeEq -// This is an alias to an internal value. +// Equals "ne" const ComparisonFilterTypeNe = shared.ComparisonFilterTypeNe -// This is an alias to an internal value. +// Equals "gt" const ComparisonFilterTypeGt = shared.ComparisonFilterTypeGt -// This is an alias to an internal value. +// Equals "gte" const ComparisonFilterTypeGte = shared.ComparisonFilterTypeGte -// This is an alias to an internal value. +// Equals "lt" const ComparisonFilterTypeLt = shared.ComparisonFilterTypeLt -// This is an alias to an internal value. +// Equals "lte" const ComparisonFilterTypeLte = shared.ComparisonFilterTypeLte +// The value to compare against the attribute key; supports string, number, or +// boolean types. +// +// This is an alias to an internal type. +type ComparisonFilterValueUnion = shared.ComparisonFilterValueUnion + +// A filter used to compare a specified attribute key to a given value using a +// defined comparison operation. +// +// This is an alias to an internal type. +type ComparisonFilterParam = shared.ComparisonFilterParam + // The value to compare against the attribute key; supports string, number, or // boolean types. // @@ -186,19 +206,24 @@ type ComparisonFilterValueUnionParam = shared.ComparisonFilterValueUnionParam // Combine multiple filters using `and` or `or`. // // This is an alias to an internal type. -type CompoundFilterParam = shared.CompoundFilterParam +type CompoundFilter = shared.CompoundFilter // Type of operation: `and` or `or`. // // This is an alias to an internal type. type CompoundFilterType = shared.CompoundFilterType -// This is an alias to an internal value. +// Equals "and" const CompoundFilterTypeAnd = shared.CompoundFilterTypeAnd -// This is an alias to an internal value. +// Equals "or" const CompoundFilterTypeOr = shared.CompoundFilterTypeOr +// Combine multiple filters using `and` or `or`. +// +// This is an alias to an internal type. +type CompoundFilterParam = shared.CompoundFilterParam + // This is an alias to an internal type. type ErrorObject = shared.ErrorObject @@ -239,6 +264,37 @@ type Metadata = shared.Metadata // This is an alias to an internal type. type MetadataParam = shared.MetadataParam +// **o-series models only** +// +// Configuration options for +// [reasoning models](https://platform.openai.com/docs/guides/reasoning). +// +// This is an alias to an internal type. +type Reasoning = shared.Reasoning + +// **computer_use_preview only** +// +// A summary of the reasoning performed by the model. This can be useful for +// debugging and understanding the model's reasoning process. One of `concise` or +// `detailed`. +// +// This is an alias to an internal type. +type ReasoningGenerateSummary = shared.ReasoningGenerateSummary + +// Equals "concise" +const ReasoningGenerateSummaryConcise = shared.ReasoningGenerateSummaryConcise + +// Equals "detailed" +const ReasoningGenerateSummaryDetailed = shared.ReasoningGenerateSummaryDetailed + +// **o-series models only** +// +// Configuration options for +// [reasoning models](https://platform.openai.com/docs/guides/reasoning). +// +// This is an alias to an internal type. +type ReasoningParam = shared.ReasoningParam + // **o-series models only** // // Constrains effort on reasoning for @@ -249,13 +305,13 @@ type MetadataParam = shared.MetadataParam // This is an alias to an internal type. type ReasoningEffort = shared.ReasoningEffort -// This is an alias to an internal value. +// Equals "low" const ReasoningEffortLow = shared.ReasoningEffortLow -// This is an alias to an internal value. +// Equals "medium" const ReasoningEffortMedium = shared.ReasoningEffortMedium -// This is an alias to an internal value. +// Equals "high" const ReasoningEffortHigh = shared.ReasoningEffortHigh // JSON object response format. An older method of generating JSON responses. Using @@ -265,14 +321,6 @@ const ReasoningEffortHigh = shared.ReasoningEffortHigh // This is an alias to an internal type. type ResponseFormatJSONObject = shared.ResponseFormatJSONObject -// The type of response format being defined. Always `json_object`. -// -// This is an alias to an internal type. -type ResponseFormatJSONObjectType = shared.ResponseFormatJSONObjectType - -// This is an alias to an internal value. -const ResponseFormatJSONObjectTypeJSONObject = shared.ResponseFormatJSONObjectTypeJSONObject - // JSON object response format. An older method of generating JSON responses. Using // `json_schema` is recommended for models that support it. Note that the model // will not generate JSON without a system or user message instructing it to do so. @@ -292,14 +340,6 @@ type ResponseFormatJSONSchema = shared.ResponseFormatJSONSchema // This is an alias to an internal type. type ResponseFormatJSONSchemaJSONSchema = shared.ResponseFormatJSONSchemaJSONSchema -// The type of response format being defined. Always `json_schema`. -// -// This is an alias to an internal type. -type ResponseFormatJSONSchemaType = shared.ResponseFormatJSONSchemaType - -// This is an alias to an internal value. -const ResponseFormatJSONSchemaTypeJSONSchema = shared.ResponseFormatJSONSchemaTypeJSONSchema - // JSON Schema response format. Used to generate structured JSON responses. Learn // more about // [Structured Outputs](https://platform.openai.com/docs/guides/structured-outputs). @@ -317,15 +357,32 @@ type ResponseFormatJSONSchemaJSONSchemaParam = shared.ResponseFormatJSONSchemaJS // This is an alias to an internal type. type ResponseFormatText = shared.ResponseFormatText -// The type of response format being defined. Always `text`. -// -// This is an alias to an internal type. -type ResponseFormatTextType = shared.ResponseFormatTextType - -// This is an alias to an internal value. -const ResponseFormatTextTypeText = shared.ResponseFormatTextTypeText - // Default response format. Used to generate text responses. // // This is an alias to an internal type. type ResponseFormatTextParam = shared.ResponseFormatTextParam + +// This is an alias to an internal type. +type ResponsesModel = shared.ResponsesModel + +// Equals "o1-pro" +const ResponsesModelO1Pro = shared.ResponsesModelO1Pro + +// Equals "o1-pro-2025-03-19" +const ResponsesModelO1Pro2025_03_19 = shared.ResponsesModelO1Pro2025_03_19 + +// Equals "computer-use-preview" +const ResponsesModelComputerUsePreview = shared.ResponsesModelComputerUsePreview + +// Equals "computer-use-preview-2025-03-11" +const ResponsesModelComputerUsePreview2025_03_11 = shared.ResponsesModelComputerUsePreview2025_03_11 + +func toParam[T comparable](value T, meta resp.Field) param.Opt[T] { + if meta.IsPresent() { + return param.NewOpt(value) + } + if meta.IsExplicitNull() { + return param.NullOpt[T]() + } + return param.Opt[T]{} +} diff --git a/api.md b/api.md index 20a62f98..6c341462 100644 --- a/api.md +++ b/api.md @@ -6,20 +6,28 @@ - shared.FunctionDefinitionParam - shared.FunctionParameters - shared.MetadataParam +- shared.ReasoningParam - shared.ReasoningEffort - shared.ResponseFormatJSONObjectParam - shared.ResponseFormatJSONSchemaParam - shared.ResponseFormatTextParam +- shared.ResponsesModel # Shared Response Types +- shared.ChatModel +- shared.ComparisonFilter +- shared.CompoundFilter - shared.ErrorObject - shared.FunctionDefinition - shared.FunctionParameters - shared.Metadata +- shared.Reasoning +- shared.ReasoningEffort - shared.ResponseFormatJSONObject - shared.ResponseFormatJSONSchema - shared.ResponseFormatText +- shared.ResponsesModel # Completions @@ -145,9 +153,16 @@ Params Types: ## Transcriptions +Params Types: + +- openai.TranscriptionInclude + Response Types: - openai.Transcription +- openai.TranscriptionStreamEventUnion +- openai.TranscriptionTextDeltaEvent +- openai.TranscriptionTextDoneEvent Methods: @@ -244,7 +259,7 @@ Params Types: Response Types: -- openai.FileChunkingStrategy +- openai.FileChunkingStrategyUnion - openai.OtherFileChunkingStrategyObject - openai.StaticFileChunkingStrategy - openai.StaticFileChunkingStrategyObject @@ -306,8 +321,8 @@ Response Types: - openai.Assistant - openai.AssistantDeleted -- openai.AssistantStreamEvent -- openai.AssistantTool +- openai.AssistantStreamEventUnion +- openai.AssistantToolUnion - openai.CodeInterpreterTool - openai.FileSearchTool - openai.FunctionTool @@ -324,10 +339,12 @@ Methods: Params Types: +- openai.AssisstantVectorStoreChunkingStrategyUnionParam - openai.AssistantResponseFormatOptionUnionParam - openai.AssistantToolChoiceParam - openai.AssistantToolChoiceFunctionParam - openai.AssistantToolChoiceOptionUnionParam +- openai.AssistantToolResourcesParam Response Types: @@ -384,8 +401,8 @@ Response Types: - openai.RunStepDelta - openai.RunStepDeltaEvent - openai.RunStepDeltaMessageDelta -- openai.ToolCall -- openai.ToolCallDelta +- openai.ToolCallUnion +- openai.ToolCallDeltaUnion - openai.ToolCallDeltaObject - openai.ToolCallsStepDetails @@ -407,8 +424,8 @@ Params Types: Response Types: -- openai.Annotation -- openai.AnnotationDelta +- openai.AnnotationUnion +- openai.AnnotationDeltaUnion - openai.FileCitationAnnotation - openai.FileCitationDeltaAnnotation - openai.FilePathAnnotation @@ -422,8 +439,8 @@ Response Types: - openai.ImageURLDelta - openai.ImageURLDeltaBlock - openai.Message -- openai.MessageContent -- openai.MessageContentDelta +- openai.MessageContentUnion +- openai.MessageContentDeltaUnion - openai.MessageDeleted - openai.MessageDelta - openai.MessageDeltaEvent @@ -478,3 +495,125 @@ Response Types: Methods: - client.Uploads.Parts.New(ctx context.Context, uploadID string, body openai.UploadPartNewParams) (openai.UploadPart, error) + +# Responses + +Params Types: + +- responses.ComputerToolParam +- responses.EasyInputMessageParam +- responses.FileSearchToolParam +- responses.FunctionToolParam +- responses.ResponseComputerToolCallParam +- responses.ResponseComputerToolCallOutputScreenshotParam +- responses.ResponseFileSearchToolCallParam +- responses.ResponseFormatTextConfigUnionParam +- responses.ResponseFormatTextJSONSchemaConfigParam +- responses.ResponseFunctionToolCallParam +- responses.ResponseFunctionWebSearchParam +- responses.ResponseIncludable +- responses.ResponseInputParam +- responses.ResponseInputContentUnionParam +- responses.ResponseInputFileParam +- responses.ResponseInputImageParam +- responses.ResponseInputItemUnionParam +- responses.ResponseInputMessageContentListParam +- responses.ResponseInputTextParam +- responses.ResponseOutputMessageParam +- responses.ResponseOutputRefusalParam +- responses.ResponseOutputTextParam +- responses.ResponseReasoningItemParam +- responses.ResponseTextConfigParam +- responses.ToolUnionParam +- responses.ToolChoiceFunctionParam +- responses.ToolChoiceOptions +- responses.ToolChoiceTypesParam +- responses.WebSearchToolParam + +Response Types: + +- responses.ComputerTool +- responses.FileSearchTool +- responses.FunctionTool +- responses.Response +- responses.ResponseAudioDeltaEvent +- responses.ResponseAudioDoneEvent +- responses.ResponseAudioTranscriptDeltaEvent +- responses.ResponseAudioTranscriptDoneEvent +- responses.ResponseCodeInterpreterCallCodeDeltaEvent +- responses.ResponseCodeInterpreterCallCodeDoneEvent +- responses.ResponseCodeInterpreterCallCompletedEvent +- responses.ResponseCodeInterpreterCallInProgressEvent +- responses.ResponseCodeInterpreterCallInterpretingEvent +- responses.ResponseCodeInterpreterToolCall +- responses.ResponseCompletedEvent +- responses.ResponseComputerToolCall +- responses.ResponseComputerToolCallOutputItem +- responses.ResponseComputerToolCallOutputScreenshot +- responses.ResponseContentPartAddedEvent +- responses.ResponseContentPartDoneEvent +- responses.ResponseCreatedEvent +- responses.ResponseError +- responses.ResponseErrorEvent +- responses.ResponseFailedEvent +- responses.ResponseFileSearchCallCompletedEvent +- responses.ResponseFileSearchCallInProgressEvent +- responses.ResponseFileSearchCallSearchingEvent +- responses.ResponseFileSearchToolCall +- responses.ResponseFormatTextConfigUnion +- responses.ResponseFormatTextJSONSchemaConfig +- responses.ResponseFunctionCallArgumentsDeltaEvent +- responses.ResponseFunctionCallArgumentsDoneEvent +- responses.ResponseFunctionToolCall +- responses.ResponseFunctionToolCallItem +- responses.ResponseFunctionToolCallOutputItem +- responses.ResponseFunctionWebSearch +- responses.ResponseInProgressEvent +- responses.ResponseIncompleteEvent +- responses.ResponseInputContentUnion +- responses.ResponseInputFile +- responses.ResponseInputImage +- responses.ResponseInputMessageContentList +- responses.ResponseInputMessageItem +- responses.ResponseInputText +- responses.ResponseItemUnion +- responses.ResponseOutputItemUnion +- responses.ResponseOutputItemAddedEvent +- responses.ResponseOutputItemDoneEvent +- responses.ResponseOutputMessage +- responses.ResponseOutputRefusal +- responses.ResponseOutputText +- responses.ResponseReasoningItem +- responses.ResponseRefusalDeltaEvent +- responses.ResponseRefusalDoneEvent +- responses.ResponseStatus +- responses.ResponseStreamEventUnion +- responses.ResponseTextAnnotationDeltaEvent +- responses.ResponseTextConfig +- responses.ResponseTextDeltaEvent +- responses.ResponseTextDoneEvent +- responses.ResponseUsage +- responses.ResponseWebSearchCallCompletedEvent +- responses.ResponseWebSearchCallInProgressEvent +- responses.ResponseWebSearchCallSearchingEvent +- responses.ToolUnion +- responses.ToolChoiceFunction +- responses.ToolChoiceOptions +- responses.ToolChoiceTypes +- responses.WebSearchTool + +Methods: + +- client.Responses.New(ctx context.Context, body responses.ResponseNewParams) (responses.Response, error) +- client.Responses.Get(ctx context.Context, responseID string, query responses.ResponseGetParams) (responses.Response, error) +- client.Responses.Delete(ctx context.Context, responseID string) error + +## InputItems + +Response Types: + +- responses.ResponseItemList + +Methods: + +- client.Responses.InputItems.List(ctx context.Context, responseID string, query responses.InputItemListParams) (pagination.CursorPage[responses.ResponseItemUnion], error) diff --git a/audio.go b/audio.go index 9728598b..9cd3e19d 100644 --- a/audio.go +++ b/audio.go @@ -14,16 +14,16 @@ import ( // the [NewAudioService] method instead. type AudioService struct { Options []option.RequestOption - Transcriptions *AudioTranscriptionService - Translations *AudioTranslationService - Speech *AudioSpeechService + Transcriptions AudioTranscriptionService + Translations AudioTranslationService + Speech AudioSpeechService } // NewAudioService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewAudioService(opts ...option.RequestOption) (r *AudioService) { - r = &AudioService{} +func NewAudioService(opts ...option.RequestOption) (r AudioService) { + r = AudioService{} r.Options = opts r.Transcriptions = NewAudioTranscriptionService(opts...) r.Translations = NewAudioTranslationService(opts...) @@ -34,11 +34,14 @@ func NewAudioService(opts ...option.RequestOption) (r *AudioService) { type AudioModel = string const ( - AudioModelWhisper1 AudioModel = "whisper-1" + AudioModelWhisper1 AudioModel = "whisper-1" + AudioModelGPT4oTranscribe AudioModel = "gpt-4o-transcribe" + AudioModelGPT4oMiniTranscribe AudioModel = "gpt-4o-mini-transcribe" ) // The format of the output, in one of these options: `json`, `text`, `srt`, -// `verbose_json`, or `vtt`. +// `verbose_json`, or `vtt`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, +// the only supported format is `json`. type AudioResponseFormat string const ( @@ -48,11 +51,3 @@ const ( AudioResponseFormatVerboseJSON AudioResponseFormat = "verbose_json" AudioResponseFormatVTT AudioResponseFormat = "vtt" ) - -func (r AudioResponseFormat) IsKnown() bool { - switch r { - case AudioResponseFormatJSON, AudioResponseFormatText, AudioResponseFormatSRT, AudioResponseFormatVerboseJSON, AudioResponseFormatVTT: - return true - } - return false -} diff --git a/audiospeech.go b/audiospeech.go index 38f6f743..aef19cc4 100644 --- a/audiospeech.go +++ b/audiospeech.go @@ -6,10 +6,9 @@ import ( "context" "net/http" - "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" ) // AudioSpeechService contains methods and other services that help with @@ -25,8 +24,8 @@ type AudioSpeechService struct { // NewAudioSpeechService generates a new service that applies the given options to // each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewAudioSpeechService(opts ...option.RequestOption) (r *AudioSpeechService) { - r = &AudioSpeechService{} +func NewAudioSpeechService(opts ...option.RequestOption) (r AudioSpeechService) { + r = AudioSpeechService{} r.Options = opts return } @@ -43,31 +42,46 @@ func (r *AudioSpeechService) New(ctx context.Context, body AudioSpeechNewParams, type SpeechModel = string const ( - SpeechModelTTS1 SpeechModel = "tts-1" - SpeechModelTTS1HD SpeechModel = "tts-1-hd" + SpeechModelTTS1 SpeechModel = "tts-1" + SpeechModelTTS1HD SpeechModel = "tts-1-hd" + SpeechModelGPT4oMiniTTS SpeechModel = "gpt-4o-mini-tts" ) type AudioSpeechNewParams struct { // The text to generate audio for. The maximum length is 4096 characters. - Input param.Field[string] `json:"input,required"` + Input string `json:"input,required"` // One of the available [TTS models](https://platform.openai.com/docs/models#tts): - // `tts-1` or `tts-1-hd` - Model param.Field[SpeechModel] `json:"model,required"` + // `tts-1`, `tts-1-hd` or `gpt-4o-mini-tts`. + Model SpeechModel `json:"model,omitzero,required"` // The voice to use when generating the audio. Supported voices are `alloy`, `ash`, // `coral`, `echo`, `fable`, `onyx`, `nova`, `sage` and `shimmer`. Previews of the // voices are available in the // [Text to speech guide](https://platform.openai.com/docs/guides/text-to-speech#voice-options). - Voice param.Field[AudioSpeechNewParamsVoice] `json:"voice,required"` - // The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, - // `wav`, and `pcm`. - ResponseFormat param.Field[AudioSpeechNewParamsResponseFormat] `json:"response_format"` + // + // Any of "alloy", "ash", "coral", "echo", "fable", "onyx", "nova", "sage", + // "shimmer". + Voice AudioSpeechNewParamsVoice `json:"voice,omitzero,required"` + // Control the voice of your generated audio with additional instructions. Does not + // work with `tts-1` or `tts-1-hd`. + Instructions param.Opt[string] `json:"instructions,omitzero"` // The speed of the generated audio. Select a value from `0.25` to `4.0`. `1.0` is // the default. - Speed param.Field[float64] `json:"speed"` + Speed param.Opt[float64] `json:"speed,omitzero"` + // The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, + // `wav`, and `pcm`. + // + // Any of "mp3", "opus", "aac", "flac", "wav", "pcm". + ResponseFormat AudioSpeechNewParamsResponseFormat `json:"response_format,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AudioSpeechNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r AudioSpeechNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow AudioSpeechNewParams + return param.MarshalObject(r, (*shadow)(&r)) } // The voice to use when generating the audio. Supported voices are `alloy`, `ash`, @@ -88,14 +102,6 @@ const ( AudioSpeechNewParamsVoiceShimmer AudioSpeechNewParamsVoice = "shimmer" ) -func (r AudioSpeechNewParamsVoice) IsKnown() bool { - switch r { - case AudioSpeechNewParamsVoiceAlloy, AudioSpeechNewParamsVoiceAsh, AudioSpeechNewParamsVoiceCoral, AudioSpeechNewParamsVoiceEcho, AudioSpeechNewParamsVoiceFable, AudioSpeechNewParamsVoiceOnyx, AudioSpeechNewParamsVoiceNova, AudioSpeechNewParamsVoiceSage, AudioSpeechNewParamsVoiceShimmer: - return true - } - return false -} - // The format to audio in. Supported formats are `mp3`, `opus`, `aac`, `flac`, // `wav`, and `pcm`. type AudioSpeechNewParamsResponseFormat string @@ -108,11 +114,3 @@ const ( AudioSpeechNewParamsResponseFormatWAV AudioSpeechNewParamsResponseFormat = "wav" AudioSpeechNewParamsResponseFormatPCM AudioSpeechNewParamsResponseFormat = "pcm" ) - -func (r AudioSpeechNewParamsResponseFormat) IsKnown() bool { - switch r { - case AudioSpeechNewParamsResponseFormatMP3, AudioSpeechNewParamsResponseFormatOpus, AudioSpeechNewParamsResponseFormatAAC, AudioSpeechNewParamsResponseFormatFLAC, AudioSpeechNewParamsResponseFormatWAV, AudioSpeechNewParamsResponseFormatPCM: - return true - } - return false -} diff --git a/audiospeech_test.go b/audiospeech_test.go index 4672869f..72c71753 100644 --- a/audiospeech_test.go +++ b/audiospeech_test.go @@ -27,11 +27,12 @@ func TestAudioSpeechNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) resp, err := client.Audio.Speech.New(context.TODO(), openai.AudioSpeechNewParams{ - Input: openai.F("input"), - Model: openai.F(openai.SpeechModelTTS1), - Voice: openai.F(openai.AudioSpeechNewParamsVoiceAlloy), - ResponseFormat: openai.F(openai.AudioSpeechNewParamsResponseFormatMP3), - Speed: openai.F(0.250000), + Input: "input", + Model: openai.SpeechModelTTS1, + Voice: openai.AudioSpeechNewParamsVoiceAlloy, + Instructions: openai.String("instructions"), + ResponseFormat: openai.AudioSpeechNewParamsResponseFormatMP3, + Speed: openai.Float(0.25), }) if err != nil { var apierr *openai.Error diff --git a/audiotranscription.go b/audiotranscription.go index 15f5bd6a..28441950 100644 --- a/audiotranscription.go +++ b/audiotranscription.go @@ -5,15 +5,19 @@ package openai import ( "bytes" "context" + "encoding/json" "io" "mime/multipart" "net/http" "github.com/openai/openai-go/internal/apiform" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" + "github.com/openai/openai-go/packages/ssestream" + "github.com/openai/openai-go/shared/constant" ) // AudioTranscriptionService contains methods and other services that help with @@ -29,8 +33,8 @@ type AudioTranscriptionService struct { // NewAudioTranscriptionService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewAudioTranscriptionService(opts ...option.RequestOption) (r *AudioTranscriptionService) { - r = &AudioTranscriptionService{} +func NewAudioTranscriptionService(opts ...option.RequestOption) (r AudioTranscriptionService) { + r = AudioTranscriptionService{} r.Options = opts return } @@ -43,62 +47,319 @@ func (r *AudioTranscriptionService) New(ctx context.Context, body AudioTranscrip return } +// Transcribes audio into the input language. +func (r *AudioTranscriptionService) NewStreaming(ctx context.Context, body AudioTranscriptionNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[TranscriptionStreamEventUnion]) { + var ( + raw *http.Response + err error + ) + opts = append(r.Options[:], opts...) + opts = append([]option.RequestOption{option.WithJSONSet("stream", true)}, opts...) + path := "audio/transcriptions" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...) + return ssestream.NewStream[TranscriptionStreamEventUnion](ssestream.NewDecoder(raw), err) +} + // Represents a transcription response returned by model, based on the provided // input. type Transcription struct { // The transcribed text. - Text string `json:"text,required"` - JSON transcriptionJSON `json:"-"` + Text string `json:"text,required"` + // The log probabilities of the tokens in the transcription. Only returned with the + // models `gpt-4o-transcribe` and `gpt-4o-mini-transcribe` if `logprobs` is added + // to the `include` array. + Logprobs []TranscriptionLogprob `json:"logprobs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Text resp.Field + Logprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// transcriptionJSON contains the JSON metadata for the struct [Transcription] -type transcriptionJSON struct { - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field +// Returns the unmodified JSON received from the API +func (r Transcription) RawJSON() string { return r.JSON.raw } +func (r *Transcription) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type TranscriptionLogprob struct { + // The token in the transcription. + Token string `json:"token"` + // The bytes of the token. + Bytes []float64 `json:"bytes"` + // The log probability of the token. + Logprob float64 `json:"logprob"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Token resp.Field + Bytes resp.Field + Logprob resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -func (r *Transcription) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r TranscriptionLogprob) RawJSON() string { return r.JSON.raw } +func (r *TranscriptionLogprob) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r transcriptionJSON) RawJSON() string { - return r.raw +type TranscriptionInclude string + +const ( + TranscriptionIncludeLogprobs TranscriptionInclude = "logprobs" +) + +// TranscriptionStreamEventUnion contains all possible properties and values from +// [TranscriptionTextDeltaEvent], [TranscriptionTextDoneEvent]. +// +// Use the [TranscriptionStreamEventUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type TranscriptionStreamEventUnion struct { + // This field is from variant [TranscriptionTextDeltaEvent]. + Delta string `json:"delta"` + // Any of "transcript.text.delta", "transcript.text.done". + Type string `json:"type"` + // This field is a union of [[]TranscriptionTextDeltaEventLogprob], + // [[]TranscriptionTextDoneEventLogprob] + Logprobs TranscriptionStreamEventUnionLogprobs `json:"logprobs"` + // This field is from variant [TranscriptionTextDoneEvent]. + Text string `json:"text"` + JSON struct { + Delta resp.Field + Type resp.Field + Logprobs resp.Field + Text resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := TranscriptionStreamEventUnion.AsAny().(type) { +// case TranscriptionTextDeltaEvent: +// case TranscriptionTextDoneEvent: +// default: +// fmt.Errorf("no variant present") +// } +func (u TranscriptionStreamEventUnion) AsAny() any { + switch u.Type { + case "transcript.text.delta": + return u.AsTranscriptTextDelta() + case "transcript.text.done": + return u.AsTranscriptTextDone() + } + return nil +} + +func (u TranscriptionStreamEventUnion) AsTranscriptTextDelta() (v TranscriptionTextDeltaEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u TranscriptionStreamEventUnion) AsTranscriptTextDone() (v TranscriptionTextDoneEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u TranscriptionStreamEventUnion) RawJSON() string { return u.JSON.raw } + +func (r *TranscriptionStreamEventUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// TranscriptionStreamEventUnionLogprobs is an implicit subunion of +// [TranscriptionStreamEventUnion]. TranscriptionStreamEventUnionLogprobs provides +// convenient access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [TranscriptionStreamEventUnion]. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfTranscriptionTextDeltaEventLogprobs +// OfTranscriptionTextDoneEventLogprobs] +type TranscriptionStreamEventUnionLogprobs struct { + // This field will be present if the value is a + // [[]TranscriptionTextDeltaEventLogprob] instead of an object. + OfTranscriptionTextDeltaEventLogprobs []TranscriptionTextDeltaEventLogprob `json:",inline"` + // This field will be present if the value is a + // [[]TranscriptionTextDoneEventLogprob] instead of an object. + OfTranscriptionTextDoneEventLogprobs []TranscriptionTextDoneEventLogprob `json:",inline"` + JSON struct { + OfTranscriptionTextDeltaEventLogprobs resp.Field + OfTranscriptionTextDoneEventLogprobs resp.Field + raw string + } `json:"-"` +} + +func (r *TranscriptionStreamEventUnionLogprobs) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Emitted when there is an additional text delta. This is also the first event +// emitted when the transcription starts. Only emitted when you +// [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) +// with the `Stream` parameter set to `true`. +type TranscriptionTextDeltaEvent struct { + // The text delta that was additionally transcribed. + Delta string `json:"delta,required"` + // The type of the event. Always `transcript.text.delta`. + Type constant.TranscriptTextDelta `json:"type,required"` + // The log probabilities of the delta. Only included if you + // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) + // with the `include[]` parameter set to `logprobs`. + Logprobs []TranscriptionTextDeltaEventLogprob `json:"logprobs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Delta resp.Field + Type resp.Field + Logprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TranscriptionTextDeltaEvent) RawJSON() string { return r.JSON.raw } +func (r *TranscriptionTextDeltaEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type TranscriptionTextDeltaEventLogprob struct { + // The token that was used to generate the log probability. + Token string `json:"token"` + // The bytes that were used to generate the log probability. + Bytes []interface{} `json:"bytes"` + // The log probability of the token. + Logprob float64 `json:"logprob"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Token resp.Field + Bytes resp.Field + Logprob resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TranscriptionTextDeltaEventLogprob) RawJSON() string { return r.JSON.raw } +func (r *TranscriptionTextDeltaEventLogprob) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Emitted when the transcription is complete. Contains the complete transcription +// text. Only emitted when you +// [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) +// with the `Stream` parameter set to `true`. +type TranscriptionTextDoneEvent struct { + // The text that was transcribed. + Text string `json:"text,required"` + // The type of the event. Always `transcript.text.done`. + Type constant.TranscriptTextDone `json:"type,required"` + // The log probabilities of the individual tokens in the transcription. Only + // included if you + // [create a transcription](https://platform.openai.com/docs/api-reference/audio/create-transcription) + // with the `include[]` parameter set to `logprobs`. + Logprobs []TranscriptionTextDoneEventLogprob `json:"logprobs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Text resp.Field + Type resp.Field + Logprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TranscriptionTextDoneEvent) RawJSON() string { return r.JSON.raw } +func (r *TranscriptionTextDoneEvent) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type TranscriptionTextDoneEventLogprob struct { + // The token that was used to generate the log probability. + Token string `json:"token"` + // The bytes that were used to generate the log probability. + Bytes []interface{} `json:"bytes"` + // The log probability of the token. + Logprob float64 `json:"logprob"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Token resp.Field + Bytes resp.Field + Logprob resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TranscriptionTextDoneEventLogprob) RawJSON() string { return r.JSON.raw } +func (r *TranscriptionTextDoneEventLogprob) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } type AudioTranscriptionNewParams struct { // The audio file object (not file name) to transcribe, in one of these formats: // flac, mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. - File param.Field[io.Reader] `json:"file,required" format:"binary"` - // ID of the model to use. Only `whisper-1` (which is powered by our open source - // Whisper V2 model) is currently available. - Model param.Field[AudioModel] `json:"model,required"` + File io.Reader `json:"file,required" format:"binary"` + // ID of the model to use. The options are `gpt-4o-transcribe`, + // `gpt-4o-mini-transcribe`, and `whisper-1` (which is powered by our open source + // Whisper V2 model). + Model AudioModel `json:"model,omitzero,required"` // The language of the input audio. Supplying the input language in // [ISO-639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) (e.g. `en`) // format will improve accuracy and latency. - Language param.Field[string] `json:"language"` + Language param.Opt[string] `json:"language,omitzero"` // An optional text to guide the model's style or continue a previous audio // segment. The // [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) // should match the audio language. - Prompt param.Field[string] `json:"prompt"` - // The format of the output, in one of these options: `json`, `text`, `srt`, - // `verbose_json`, or `vtt`. - ResponseFormat param.Field[AudioResponseFormat] `json:"response_format"` + Prompt param.Opt[string] `json:"prompt,omitzero"` // The sampling temperature, between 0 and 1. Higher values like 0.8 will make the // output more random, while lower values like 0.2 will make it more focused and // deterministic. If set to 0, the model will use // [log probability](https://en.wikipedia.org/wiki/Log_probability) to // automatically increase the temperature until certain thresholds are hit. - Temperature param.Field[float64] `json:"temperature"` + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // Additional information to include in the transcription response. `logprobs` will + // return the log probabilities of the tokens in the response to understand the + // model's confidence in the transcription. `logprobs` only works with + // response_format set to `json` and only with the models `gpt-4o-transcribe` and + // `gpt-4o-mini-transcribe`. + Include []TranscriptionInclude `json:"include,omitzero"` + // The format of the output, in one of these options: `json`, `text`, `srt`, + // `verbose_json`, or `vtt`. For `gpt-4o-transcribe` and `gpt-4o-mini-transcribe`, + // the only supported format is `json`. + // + // Any of "json", "text", "srt", "verbose_json", "vtt". + ResponseFormat AudioResponseFormat `json:"response_format,omitzero"` // The timestamp granularities to populate for this transcription. // `response_format` must be set `verbose_json` to use timestamp granularities. // Either or both of these options are supported: `word`, or `segment`. Note: There // is no additional latency for segment timestamps, but generating word timestamps // incurs additional latency. - TimestampGranularities param.Field[[]AudioTranscriptionNewParamsTimestampGranularity] `json:"timestamp_granularities"` + TimestampGranularities []string `json:"timestamp_granularities,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AudioTranscriptionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r AudioTranscriptionNewParams) MarshalMultipart() (data []byte, contentType string, err error) { buf := bytes.NewBuffer(nil) writer := multipart.NewWriter(buf) @@ -113,18 +374,3 @@ func (r AudioTranscriptionNewParams) MarshalMultipart() (data []byte, contentTyp } return buf.Bytes(), writer.FormDataContentType(), nil } - -type AudioTranscriptionNewParamsTimestampGranularity string - -const ( - AudioTranscriptionNewParamsTimestampGranularityWord AudioTranscriptionNewParamsTimestampGranularity = "word" - AudioTranscriptionNewParamsTimestampGranularitySegment AudioTranscriptionNewParamsTimestampGranularity = "segment" -) - -func (r AudioTranscriptionNewParamsTimestampGranularity) IsKnown() bool { - switch r { - case AudioTranscriptionNewParamsTimestampGranularityWord, AudioTranscriptionNewParamsTimestampGranularitySegment: - return true - } - return false -} diff --git a/audiotranscription_test.go b/audiotranscription_test.go index 3547baa0..d0a09ee2 100644 --- a/audiotranscription_test.go +++ b/audiotranscription_test.go @@ -28,13 +28,14 @@ func TestAudioTranscriptionNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Audio.Transcriptions.New(context.TODO(), openai.AudioTranscriptionNewParams{ - File: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Model: openai.F(openai.AudioModelWhisper1), - Language: openai.F("language"), - Prompt: openai.F("prompt"), - ResponseFormat: openai.F(openai.AudioResponseFormatJSON), - Temperature: openai.F(0.000000), - TimestampGranularities: openai.F([]openai.AudioTranscriptionNewParamsTimestampGranularity{openai.AudioTranscriptionNewParamsTimestampGranularityWord}), + File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Model: openai.AudioModelWhisper1, + Include: []openai.TranscriptionInclude{openai.TranscriptionIncludeLogprobs}, + Language: openai.String("language"), + Prompt: openai.String("prompt"), + ResponseFormat: openai.AudioResponseFormatJSON, + Temperature: openai.Float(0), + TimestampGranularities: []string{"word"}, }) if err != nil { var apierr *openai.Error diff --git a/audiotranslation.go b/audiotranslation.go index 6b423f0f..abdd4ddb 100644 --- a/audiotranslation.go +++ b/audiotranslation.go @@ -11,9 +11,10 @@ import ( "github.com/openai/openai-go/internal/apiform" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" ) // AudioTranslationService contains methods and other services that help with @@ -29,8 +30,8 @@ type AudioTranslationService struct { // NewAudioTranslationService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewAudioTranslationService(opts ...option.RequestOption) (r *AudioTranslationService) { - r = &AudioTranslationService{} +func NewAudioTranslationService(opts ...option.RequestOption) (r AudioTranslationService) { + r = AudioTranslationService{} r.Options = opts return } @@ -44,48 +45,52 @@ func (r *AudioTranslationService) New(ctx context.Context, body AudioTranslation } type Translation struct { - Text string `json:"text,required"` - JSON translationJSON `json:"-"` + Text string `json:"text,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Text resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// translationJSON contains the JSON metadata for the struct [Translation] -type translationJSON struct { - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Translation) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r Translation) RawJSON() string { return r.JSON.raw } +func (r *Translation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r translationJSON) RawJSON() string { - return r.raw -} - type AudioTranslationNewParams struct { // The audio file object (not file name) translate, in one of these formats: flac, // mp3, mp4, mpeg, mpga, m4a, ogg, wav, or webm. - File param.Field[io.Reader] `json:"file,required" format:"binary"` + File io.Reader `json:"file,required" format:"binary"` // ID of the model to use. Only `whisper-1` (which is powered by our open source // Whisper V2 model) is currently available. - Model param.Field[AudioModel] `json:"model,required"` + Model AudioModel `json:"model,omitzero,required"` // An optional text to guide the model's style or continue a previous audio // segment. The // [prompt](https://platform.openai.com/docs/guides/speech-to-text#prompting) // should be in English. - Prompt param.Field[string] `json:"prompt"` - // The format of the output, in one of these options: `json`, `text`, `srt`, - // `verbose_json`, or `vtt`. - ResponseFormat param.Field[AudioResponseFormat] `json:"response_format"` + Prompt param.Opt[string] `json:"prompt,omitzero"` // The sampling temperature, between 0 and 1. Higher values like 0.8 will make the // output more random, while lower values like 0.2 will make it more focused and // deterministic. If set to 0, the model will use // [log probability](https://en.wikipedia.org/wiki/Log_probability) to // automatically increase the temperature until certain thresholds are hit. - Temperature param.Field[float64] `json:"temperature"` + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // The format of the output, in one of these options: `json`, `text`, `srt`, + // `verbose_json`, or `vtt`. + // + // Any of "json", "text", "srt", "verbose_json", "vtt". + ResponseFormat AudioTranslationNewParamsResponseFormat `json:"response_format,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AudioTranslationNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r AudioTranslationNewParams) MarshalMultipart() (data []byte, contentType string, err error) { buf := bytes.NewBuffer(nil) writer := multipart.NewWriter(buf) @@ -100,3 +105,15 @@ func (r AudioTranslationNewParams) MarshalMultipart() (data []byte, contentType } return buf.Bytes(), writer.FormDataContentType(), nil } + +// The format of the output, in one of these options: `json`, `text`, `srt`, +// `verbose_json`, or `vtt`. +type AudioTranslationNewParamsResponseFormat string + +const ( + AudioTranslationNewParamsResponseFormatJSON AudioTranslationNewParamsResponseFormat = "json" + AudioTranslationNewParamsResponseFormatText AudioTranslationNewParamsResponseFormat = "text" + AudioTranslationNewParamsResponseFormatSRT AudioTranslationNewParamsResponseFormat = "srt" + AudioTranslationNewParamsResponseFormatVerboseJSON AudioTranslationNewParamsResponseFormat = "verbose_json" + AudioTranslationNewParamsResponseFormatVTT AudioTranslationNewParamsResponseFormat = "vtt" +) diff --git a/audiotranslation_test.go b/audiotranslation_test.go index ae277373..75bc5903 100644 --- a/audiotranslation_test.go +++ b/audiotranslation_test.go @@ -28,11 +28,11 @@ func TestAudioTranslationNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Audio.Translations.New(context.TODO(), openai.AudioTranslationNewParams{ - File: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Model: openai.F(openai.AudioModelWhisper1), - Prompt: openai.F("prompt"), - ResponseFormat: openai.F(openai.AudioResponseFormatJSON), - Temperature: openai.F(0.000000), + File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Model: openai.AudioModelWhisper1, + Prompt: openai.String("prompt"), + ResponseFormat: openai.AudioTranslationNewParamsResponseFormatJSON, + Temperature: openai.Float(0), }) if err != nil { var apierr *openai.Error diff --git a/azure/azure_test.go b/azure/azure_test.go index f5b9043a..4c3e3757 100644 --- a/azure/azure_test.go +++ b/azure/azure_test.go @@ -12,11 +12,11 @@ import ( func TestJSONRoute(t *testing.T) { chatCompletionParams := openai.ChatCompletionNewParams{ - Model: openai.F(openai.ChatModel("arbitraryDeployment")), - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Model: openai.ChatModel("arbitraryDeployment"), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.AssistantMessage("You are a helpful assistant"), openai.UserMessage("Can you tell me another word for the universe?"), - }), + }, } serializedBytes, err := apijson.MarshalRoot(chatCompletionParams) @@ -86,11 +86,11 @@ func TestGetAudioMultipartRoute(t *testing.T) { func TestNoRouteChangeNeeded(t *testing.T) { chatCompletionParams := openai.ChatCompletionNewParams{ - Model: openai.F(openai.ChatModel("arbitraryDeployment")), - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Model: openai.ChatModel("arbitraryDeployment"), + Messages: []openai.ChatCompletionMessageParamUnion{ openai.AssistantMessage("You are a helpful assistant"), openai.UserMessage("Can you tell me another word for the universe?"), - }), + }, } serializedBytes, err := apijson.MarshalRoot(chatCompletionParams) diff --git a/batch.go b/batch.go index 60b6c6c2..9d09c2cb 100644 --- a/batch.go +++ b/batch.go @@ -11,11 +11,13 @@ import ( "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" ) // BatchService contains methods and other services that help with interacting with @@ -31,8 +33,8 @@ type BatchService struct { // NewBatchService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewBatchService(opts ...option.RequestOption) (r *BatchService) { - r = &BatchService{} +func NewBatchService(opts ...option.RequestOption) (r BatchService) { + r = BatchService{} r.Options = opts return } @@ -105,8 +107,11 @@ type Batch struct { // The ID of the input file for the batch. InputFileID string `json:"input_file_id,required"` // The object type, which is always `batch`. - Object BatchObject `json:"object,required"` + Object constant.Batch `json:"object,required"` // The current status of the batch. + // + // Any of "validating", "failed", "in_progress", "finalizing", "completed", + // "expired", "cancelling", "cancelled". Status BatchStatus `json:"status,required"` // The Unix timestamp (in seconds) for when the batch was cancelled. CancelledAt int64 `json:"cancelled_at"` @@ -138,58 +143,40 @@ type Batch struct { OutputFileID string `json:"output_file_id"` // The request counts for different statuses within the batch. RequestCounts BatchRequestCounts `json:"request_counts"` - JSON batchJSON `json:"-"` -} - -// batchJSON contains the JSON metadata for the struct [Batch] -type batchJSON struct { - ID apijson.Field - CompletionWindow apijson.Field - CreatedAt apijson.Field - Endpoint apijson.Field - InputFileID apijson.Field - Object apijson.Field - Status apijson.Field - CancelledAt apijson.Field - CancellingAt apijson.Field - CompletedAt apijson.Field - ErrorFileID apijson.Field - Errors apijson.Field - ExpiredAt apijson.Field - ExpiresAt apijson.Field - FailedAt apijson.Field - FinalizingAt apijson.Field - InProgressAt apijson.Field - Metadata apijson.Field - OutputFileID apijson.Field - RequestCounts apijson.Field - raw string - ExtraFields map[string]apijson.Field + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CompletionWindow resp.Field + CreatedAt resp.Field + Endpoint resp.Field + InputFileID resp.Field + Object resp.Field + Status resp.Field + CancelledAt resp.Field + CancellingAt resp.Field + CompletedAt resp.Field + ErrorFileID resp.Field + Errors resp.Field + ExpiredAt resp.Field + ExpiresAt resp.Field + FailedAt resp.Field + FinalizingAt resp.Field + InProgressAt resp.Field + Metadata resp.Field + OutputFileID resp.Field + RequestCounts resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -func (r *Batch) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r Batch) RawJSON() string { return r.JSON.raw } +func (r *Batch) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r batchJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `batch`. -type BatchObject string - -const ( - BatchObjectBatch BatchObject = "batch" -) - -func (r BatchObject) IsKnown() bool { - switch r { - case BatchObjectBatch: - return true - } - return false -} - // The current status of the batch. type BatchStatus string @@ -204,37 +191,26 @@ const ( BatchStatusCancelled BatchStatus = "cancelled" ) -func (r BatchStatus) IsKnown() bool { - switch r { - case BatchStatusValidating, BatchStatusFailed, BatchStatusInProgress, BatchStatusFinalizing, BatchStatusCompleted, BatchStatusExpired, BatchStatusCancelling, BatchStatusCancelled: - return true - } - return false -} - type BatchErrors struct { Data []BatchError `json:"data"` // The object type, which is always `list`. - Object string `json:"object"` - JSON batchErrorsJSON `json:"-"` + Object string `json:"object"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// batchErrorsJSON contains the JSON metadata for the struct [BatchErrors] -type batchErrorsJSON struct { - Data apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *BatchErrors) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r BatchErrors) RawJSON() string { return r.JSON.raw } +func (r *BatchErrors) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r batchErrorsJSON) RawJSON() string { - return r.raw -} - type BatchError struct { // An error code identifying the error type. Code string `json:"code"` @@ -243,28 +219,25 @@ type BatchError struct { // A human-readable message providing more details about the error. Message string `json:"message"` // The name of the parameter that caused the error, if applicable. - Param string `json:"param,nullable"` - JSON batchErrorJSON `json:"-"` + Param string `json:"param,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Code resp.Field + Line resp.Field + Message resp.Field + Param resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// batchErrorJSON contains the JSON metadata for the struct [BatchError] -type batchErrorJSON struct { - Code apijson.Field - Line apijson.Field - Message apijson.Field - Param apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *BatchError) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r BatchError) RawJSON() string { return r.JSON.raw } +func (r *BatchError) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r batchErrorJSON) RawJSON() string { - return r.raw -} - // The request counts for different statuses within the batch. type BatchRequestCounts struct { // Number of requests that have been completed successfully. @@ -272,37 +245,38 @@ type BatchRequestCounts struct { // Number of requests that have failed. Failed int64 `json:"failed,required"` // Total number of requests in the batch. - Total int64 `json:"total,required"` - JSON batchRequestCountsJSON `json:"-"` -} - -// batchRequestCountsJSON contains the JSON metadata for the struct -// [BatchRequestCounts] -type batchRequestCountsJSON struct { - Completed apijson.Field - Failed apijson.Field - Total apijson.Field - raw string - ExtraFields map[string]apijson.Field + Total int64 `json:"total,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Completed resp.Field + Failed resp.Field + Total resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -func (r *BatchRequestCounts) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r BatchRequestCounts) RawJSON() string { return r.JSON.raw } +func (r *BatchRequestCounts) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r batchRequestCountsJSON) RawJSON() string { - return r.raw -} - type BatchNewParams struct { // The time frame within which the batch should be processed. Currently only `24h` // is supported. - CompletionWindow param.Field[BatchNewParamsCompletionWindow] `json:"completion_window,required"` + // + // Any of "24h". + CompletionWindow BatchNewParamsCompletionWindow `json:"completion_window,omitzero,required"` // The endpoint to be used for all requests in the batch. Currently // `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, and `/v1/completions` // are supported. Note that `/v1/embeddings` batches are also restricted to a // maximum of 50,000 embedding inputs across all requests in the batch. - Endpoint param.Field[BatchNewParamsEndpoint] `json:"endpoint,required"` + // + // Any of "/v1/responses", "/v1/chat/completions", "/v1/embeddings", + // "/v1/completions". + Endpoint BatchNewParamsEndpoint `json:"endpoint,omitzero,required"` // The ID of an uploaded file that contains requests for the new batch. // // See [upload file](https://platform.openai.com/docs/api-reference/files/create) @@ -312,18 +286,24 @@ type BatchNewParams struct { // [JSONL file](https://platform.openai.com/docs/api-reference/batch/request-input), // and must be uploaded with the purpose `batch`. The file can contain up to 50,000 // requests, and can be up to 200 MB in size. - InputFileID param.Field[string] `json:"input_file_id,required"` + InputFileID string `json:"input_file_id,required"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BatchNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BatchNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BatchNewParams + return param.MarshalObject(r, (*shadow)(&r)) } // The time frame within which the batch should be processed. Currently only `24h` @@ -334,14 +314,6 @@ const ( BatchNewParamsCompletionWindow24h BatchNewParamsCompletionWindow = "24h" ) -func (r BatchNewParamsCompletionWindow) IsKnown() bool { - switch r { - case BatchNewParamsCompletionWindow24h: - return true - } - return false -} - // The endpoint to be used for all requests in the batch. Currently // `/v1/responses`, `/v1/chat/completions`, `/v1/embeddings`, and `/v1/completions` // are supported. Note that `/v1/embeddings` batches are also restricted to a @@ -355,25 +327,22 @@ const ( BatchNewParamsEndpointV1Completions BatchNewParamsEndpoint = "/v1/completions" ) -func (r BatchNewParamsEndpoint) IsKnown() bool { - switch r { - case BatchNewParamsEndpointV1Responses, BatchNewParamsEndpointV1ChatCompletions, BatchNewParamsEndpointV1Embeddings, BatchNewParamsEndpointV1Completions: - return true - } - return false -} - type BatchListParams struct { // A cursor for use in pagination. `after` is an object ID that defines your place // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A limit on the number of objects to be returned. Limit can range between 1 and // 100, and the default is 20. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BatchListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BatchListParams]'s query parameters as `url.Values`. func (r BatchListParams) URLQuery() (v url.Values) { return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ diff --git a/batch_test.go b/batch_test.go index fcd5353b..e80cac96 100644 --- a/batch_test.go +++ b/batch_test.go @@ -27,12 +27,12 @@ func TestBatchNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Batches.New(context.TODO(), openai.BatchNewParams{ - CompletionWindow: openai.F(openai.BatchNewParamsCompletionWindow24h), - Endpoint: openai.F(openai.BatchNewParamsEndpointV1Responses), - InputFileID: openai.F("input_file_id"), - Metadata: openai.F(shared.MetadataParam{ + CompletionWindow: openai.BatchNewParamsCompletionWindow24h, + Endpoint: openai.BatchNewParamsEndpointV1Responses, + InputFileID: "input_file_id", + Metadata: shared.MetadataParam{ "foo": "string", - }), + }, }) if err != nil { var apierr *openai.Error @@ -78,8 +78,8 @@ func TestBatchListWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Batches.List(context.TODO(), openai.BatchListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), + After: openai.String("after"), + Limit: openai.Int(0), }) if err != nil { var apierr *openai.Error diff --git a/beta.go b/beta.go index f81002a2..c426f355 100644 --- a/beta.go +++ b/beta.go @@ -14,15 +14,15 @@ import ( // the [NewBetaService] method instead. type BetaService struct { Options []option.RequestOption - Assistants *BetaAssistantService - Threads *BetaThreadService + Assistants BetaAssistantService + Threads BetaThreadService } // NewBetaService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewBetaService(opts ...option.RequestOption) (r *BetaService) { - r = &BetaService{} +func NewBetaService(opts ...option.RequestOption) (r BetaService) { + r = BetaService{} r.Options = opts r.Assistants = NewBetaAssistantService(opts...) r.Threads = NewBetaThreadService(opts...) diff --git a/betaassistant.go b/betaassistant.go index 5c1e9a23..ae7b2f7b 100644 --- a/betaassistant.go +++ b/betaassistant.go @@ -4,6 +4,7 @@ package openai import ( "context" + "encoding/json" "errors" "fmt" "net/http" @@ -12,11 +13,13 @@ import ( "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" "github.com/tidwall/gjson" ) @@ -33,8 +36,8 @@ type BetaAssistantService struct { // NewBetaAssistantService generates a new service that applies the given options // to each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewBetaAssistantService(opts ...option.RequestOption) (r *BetaAssistantService) { - r = &BetaAssistantService{} +func NewBetaAssistantService(opts ...option.RequestOption) (r BetaAssistantService) { + r = BetaAssistantService{} r.Options = opts return } @@ -117,17 +120,17 @@ type Assistant struct { // The Unix timestamp (in seconds) for when the assistant was created. CreatedAt int64 `json:"created_at,required"` // The description of the assistant. The maximum length is 512 characters. - Description string `json:"description,required,nullable"` + Description string `json:"description,required"` // The system instructions that the assistant uses. The maximum length is 256,000 // characters. - Instructions string `json:"instructions,required,nullable"` + Instructions string `json:"instructions,required"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata shared.Metadata `json:"metadata,required,nullable"` + Metadata shared.Metadata `json:"metadata,required"` // ID of the model to use. You can use the // [List models](https://platform.openai.com/docs/api-reference/models/list) API to // see all of your available models, or see our @@ -135,13 +138,13 @@ type Assistant struct { // them. Model string `json:"model,required"` // The name of the assistant. The maximum length is 256 characters. - Name string `json:"name,required,nullable"` + Name string `json:"name,required"` // The object type, which is always `assistant`. - Object AssistantObject `json:"object,required"` + Object constant.Assistant `json:"object,required"` // A list of tool enabled on the assistant. There can be a maximum of 128 tools per // assistant. Tools can be of types `code_interpreter`, `file_search`, or // `function`. - Tools []AssistantTool `json:"tools,required"` + Tools []AssistantToolUnion `json:"tools,required"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -177,52 +180,34 @@ type Assistant struct { // means only the tokens comprising the top 10% probability mass are considered. // // We generally recommend altering this or temperature but not both. - TopP float64 `json:"top_p,nullable"` - JSON assistantJSON `json:"-"` -} - -// assistantJSON contains the JSON metadata for the struct [Assistant] -type assistantJSON struct { - ID apijson.Field - CreatedAt apijson.Field - Description apijson.Field - Instructions apijson.Field - Metadata apijson.Field - Model apijson.Field - Name apijson.Field - Object apijson.Field - Tools apijson.Field - ResponseFormat apijson.Field - Temperature apijson.Field - ToolResources apijson.Field - TopP apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Assistant) UnmarshalJSON(data []byte) (err error) { + TopP float64 `json:"top_p,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CreatedAt resp.Field + Description resp.Field + Instructions resp.Field + Metadata resp.Field + Model resp.Field + Name resp.Field + Object resp.Field + Tools resp.Field + ResponseFormat resp.Field + Temperature resp.Field + ToolResources resp.Field + TopP resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Assistant) RawJSON() string { return r.JSON.raw } +func (r *Assistant) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `assistant`. -type AssistantObject string - -const ( - AssistantObjectAssistant AssistantObject = "assistant" -) - -func (r AssistantObject) IsKnown() bool { - switch r { - case AssistantObjectAssistant: - return true - } - return false -} - // A set of resources that are used by the assistant's tools. The resources are // specific to the type of tool. For example, the `code_interpreter` tool requires // a list of file IDs, while the `file_search` tool requires a list of vector store @@ -230,173 +215,87 @@ func (r AssistantObject) IsKnown() bool { type AssistantToolResources struct { CodeInterpreter AssistantToolResourcesCodeInterpreter `json:"code_interpreter"` FileSearch AssistantToolResourcesFileSearch `json:"file_search"` - JSON assistantToolResourcesJSON `json:"-"` -} - -// assistantToolResourcesJSON contains the JSON metadata for the struct -// [AssistantToolResources] -type assistantToolResourcesJSON struct { - CodeInterpreter apijson.Field - FileSearch apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantToolResources) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + CodeInterpreter resp.Field + FileSearch resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantToolResources) RawJSON() string { return r.JSON.raw } +func (r *AssistantToolResources) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantToolResourcesJSON) RawJSON() string { - return r.raw -} - type AssistantToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter“ tool. There can be a maximum of 20 files // associated with the tool. - FileIDs []string `json:"file_ids"` - JSON assistantToolResourcesCodeInterpreterJSON `json:"-"` -} - -// assistantToolResourcesCodeInterpreterJSON contains the JSON metadata for the -// struct [AssistantToolResourcesCodeInterpreter] -type assistantToolResourcesCodeInterpreterJSON struct { - FileIDs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) (err error) { + FileIDs []string `json:"file_ids"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileIDs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantToolResourcesCodeInterpreter) RawJSON() string { return r.JSON.raw } +func (r *AssistantToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantToolResourcesCodeInterpreterJSON) RawJSON() string { - return r.raw -} - type AssistantToolResourcesFileSearch struct { // The ID of the // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this assistant. There can be a maximum of 1 vector store attached to // the assistant. - VectorStoreIDs []string `json:"vector_store_ids"` - JSON assistantToolResourcesFileSearchJSON `json:"-"` -} - -// assistantToolResourcesFileSearchJSON contains the JSON metadata for the struct -// [AssistantToolResourcesFileSearch] -type assistantToolResourcesFileSearchJSON struct { - VectorStoreIDs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantToolResourcesFileSearch) UnmarshalJSON(data []byte) (err error) { + VectorStoreIDs []string `json:"vector_store_ids"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + VectorStoreIDs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantToolResourcesFileSearch) RawJSON() string { return r.JSON.raw } +func (r *AssistantToolResourcesFileSearch) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantToolResourcesFileSearchJSON) RawJSON() string { - return r.raw -} - type AssistantDeleted struct { - ID string `json:"id,required"` - Deleted bool `json:"deleted,required"` - Object AssistantDeletedObject `json:"object,required"` - JSON assistantDeletedJSON `json:"-"` -} - -// assistantDeletedJSON contains the JSON metadata for the struct -// [AssistantDeleted] -type assistantDeletedJSON struct { - ID apijson.Field - Deleted apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantDeleted) UnmarshalJSON(data []byte) (err error) { + ID string `json:"id,required"` + Deleted bool `json:"deleted,required"` + Object constant.AssistantDeleted `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Deleted resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantDeleted) RawJSON() string { return r.JSON.raw } +func (r *AssistantDeleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantDeletedJSON) RawJSON() string { - return r.raw -} - -type AssistantDeletedObject string - -const ( - AssistantDeletedObjectAssistantDeleted AssistantDeletedObject = "assistant.deleted" -) - -func (r AssistantDeletedObject) IsKnown() bool { - switch r { - case AssistantDeletedObjectAssistantDeleted: - return true - } - return false -} - -// Represents an event emitted when streaming a Run. -// -// Each event in a server-sent events stream has an `event` and `data` property: -// -// ``` -// event: thread.created -// data: {"id": "thread_123", "object": "thread", ...} -// ``` -// -// We emit events whenever a new object is created, transitions to a new state, or -// is being streamed in parts (deltas). For example, we emit `thread.run.created` -// when a new run is created, `thread.run.completed` when a run completes, and so -// on. When an Assistant chooses to create a message during a run, we emit a -// `thread.message.created event`, a `thread.message.in_progress` event, many -// `thread.message.delta` events, and finally a `thread.message.completed` event. -// -// We may add additional events over time, so we recommend handling unknown events -// gracefully in your code. See the -// [Assistants API quickstart](https://platform.openai.com/docs/assistants/overview) -// to learn how to integrate the Assistants API with streaming. -type AssistantStreamEvent struct { - // This field can have the runtime type of [Thread], [Run], [RunStep], - // [RunStepDeltaEvent], [Message], [MessageDeltaEvent], [shared.ErrorObject]. - Data interface{} `json:"data,required"` - Event AssistantStreamEventEvent `json:"event,required"` - // Whether to enable input audio transcription. - Enabled bool `json:"enabled"` - JSON assistantStreamEventJSON `json:"-"` - union AssistantStreamEventUnion -} - -// assistantStreamEventJSON contains the JSON metadata for the struct -// [AssistantStreamEvent] -type assistantStreamEventJSON struct { - Data apijson.Field - Event apijson.Field - Enabled apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r assistantStreamEventJSON) RawJSON() string { - return r.raw -} - -func (r *AssistantStreamEvent) UnmarshalJSON(data []byte) (err error) { - *r = AssistantStreamEvent{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) -} - -// AsUnion returns a [AssistantStreamEventUnion] interface which you can cast to -// the specific types for more type safety. -// -// Possible runtime types of the union are [AssistantStreamEventThreadCreated], -// [AssistantStreamEventThreadRunCreated], [AssistantStreamEventThreadRunQueued], +// AssistantStreamEventUnion contains all possible properties and values from +// [AssistantStreamEventThreadCreated], [AssistantStreamEventThreadRunCreated], +// [AssistantStreamEventThreadRunQueued], // [AssistantStreamEventThreadRunInProgress], // [AssistantStreamEventThreadRunRequiresAction], // [AssistantStreamEventThreadRunCompleted], @@ -417,445 +316,595 @@ func (r *AssistantStreamEvent) UnmarshalJSON(data []byte) (err error) { // [AssistantStreamEventThreadMessageDelta], // [AssistantStreamEventThreadMessageCompleted], // [AssistantStreamEventThreadMessageIncomplete], [AssistantStreamEventErrorEvent]. -func (r AssistantStreamEvent) AsUnion() AssistantStreamEventUnion { - return r.union -} - -// Represents an event emitted when streaming a Run. // -// Each event in a server-sent events stream has an `event` and `data` property: +// Use the [AssistantStreamEventUnion.AsAny] method to switch on the variant. // -// ``` -// event: thread.created -// data: {"id": "thread_123", "object": "thread", ...} -// ``` +// Use the methods beginning with 'As' to cast the union to one of its variants. +type AssistantStreamEventUnion struct { + // This field is a union of [Thread], [Run], [RunStep], [RunStepDeltaEvent], + // [Message], [MessageDeltaEvent], [shared.ErrorObject] + Data AssistantStreamEventUnionData `json:"data"` + // Any of "thread.created", "thread.run.created", "thread.run.queued", + // "thread.run.in_progress", "thread.run.requires_action", "thread.run.completed", + // "thread.run.incomplete", "thread.run.failed", "thread.run.cancelling", + // "thread.run.cancelled", "thread.run.expired", "thread.run.step.created", + // "thread.run.step.in_progress", "thread.run.step.delta", + // "thread.run.step.completed", "thread.run.step.failed", + // "thread.run.step.cancelled", "thread.run.step.expired", + // "thread.message.created", "thread.message.in_progress", "thread.message.delta", + // "thread.message.completed", "thread.message.incomplete", "error". + Event string `json:"event"` + // This field is from variant [AssistantStreamEventThreadCreated]. + Enabled bool `json:"enabled"` + JSON struct { + Data resp.Field + Event resp.Field + Enabled resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant // -// We emit events whenever a new object is created, transitions to a new state, or -// is being streamed in parts (deltas). For example, we emit `thread.run.created` -// when a new run is created, `thread.run.completed` when a run completes, and so -// on. When an Assistant chooses to create a message during a run, we emit a -// `thread.message.created event`, a `thread.message.in_progress` event, many -// `thread.message.delta` events, and finally a `thread.message.completed` event. -// -// We may add additional events over time, so we recommend handling unknown events -// gracefully in your code. See the -// [Assistants API quickstart](https://platform.openai.com/docs/assistants/overview) -// to learn how to integrate the Assistants API with streaming. -// -// Union satisfied by [AssistantStreamEventThreadCreated], -// [AssistantStreamEventThreadRunCreated], [AssistantStreamEventThreadRunQueued], -// [AssistantStreamEventThreadRunInProgress], -// [AssistantStreamEventThreadRunRequiresAction], -// [AssistantStreamEventThreadRunCompleted], -// [AssistantStreamEventThreadRunIncomplete], -// [AssistantStreamEventThreadRunFailed], -// [AssistantStreamEventThreadRunCancelling], -// [AssistantStreamEventThreadRunCancelled], -// [AssistantStreamEventThreadRunExpired], -// [AssistantStreamEventThreadRunStepCreated], -// [AssistantStreamEventThreadRunStepInProgress], -// [AssistantStreamEventThreadRunStepDelta], -// [AssistantStreamEventThreadRunStepCompleted], -// [AssistantStreamEventThreadRunStepFailed], -// [AssistantStreamEventThreadRunStepCancelled], -// [AssistantStreamEventThreadRunStepExpired], -// [AssistantStreamEventThreadMessageCreated], -// [AssistantStreamEventThreadMessageInProgress], -// [AssistantStreamEventThreadMessageDelta], -// [AssistantStreamEventThreadMessageCompleted], -// [AssistantStreamEventThreadMessageIncomplete] or -// [AssistantStreamEventErrorEvent]. -type AssistantStreamEventUnion interface { - implementsAssistantStreamEvent() +// switch variant := AssistantStreamEventUnion.AsAny().(type) { +// case AssistantStreamEventThreadCreated: +// case AssistantStreamEventThreadRunCreated: +// case AssistantStreamEventThreadRunQueued: +// case AssistantStreamEventThreadRunInProgress: +// case AssistantStreamEventThreadRunRequiresAction: +// case AssistantStreamEventThreadRunCompleted: +// case AssistantStreamEventThreadRunIncomplete: +// case AssistantStreamEventThreadRunFailed: +// case AssistantStreamEventThreadRunCancelling: +// case AssistantStreamEventThreadRunCancelled: +// case AssistantStreamEventThreadRunExpired: +// case AssistantStreamEventThreadRunStepCreated: +// case AssistantStreamEventThreadRunStepInProgress: +// case AssistantStreamEventThreadRunStepDelta: +// case AssistantStreamEventThreadRunStepCompleted: +// case AssistantStreamEventThreadRunStepFailed: +// case AssistantStreamEventThreadRunStepCancelled: +// case AssistantStreamEventThreadRunStepExpired: +// case AssistantStreamEventThreadMessageCreated: +// case AssistantStreamEventThreadMessageInProgress: +// case AssistantStreamEventThreadMessageDelta: +// case AssistantStreamEventThreadMessageCompleted: +// case AssistantStreamEventThreadMessageIncomplete: +// case AssistantStreamEventErrorEvent: +// default: +// fmt.Errorf("no variant present") +// } +func (u AssistantStreamEventUnion) AsAny() any { + switch u.Event { + case "thread.created": + return u.AsThreadCreated() + case "thread.run.created": + return u.AsThreadRunCreated() + case "thread.run.queued": + return u.AsThreadRunQueued() + case "thread.run.in_progress": + return u.AsThreadRunInProgress() + case "thread.run.requires_action": + return u.AsThreadRunRequiresAction() + case "thread.run.completed": + return u.AsThreadRunCompleted() + case "thread.run.incomplete": + return u.AsThreadRunIncomplete() + case "thread.run.failed": + return u.AsThreadRunFailed() + case "thread.run.cancelling": + return u.AsThreadRunCancelling() + case "thread.run.cancelled": + return u.AsThreadRunCancelled() + case "thread.run.expired": + return u.AsThreadRunExpired() + case "thread.run.step.created": + return u.AsThreadRunStepCreated() + case "thread.run.step.in_progress": + return u.AsThreadRunStepInProgress() + case "thread.run.step.delta": + return u.AsThreadRunStepDelta() + case "thread.run.step.completed": + return u.AsThreadRunStepCompleted() + case "thread.run.step.failed": + return u.AsThreadRunStepFailed() + case "thread.run.step.cancelled": + return u.AsThreadRunStepCancelled() + case "thread.run.step.expired": + return u.AsThreadRunStepExpired() + case "thread.message.created": + return u.AsThreadMessageCreated() + case "thread.message.in_progress": + return u.AsThreadMessageInProgress() + case "thread.message.delta": + return u.AsThreadMessageDelta() + case "thread.message.completed": + return u.AsThreadMessageCompleted() + case "thread.message.incomplete": + return u.AsThreadMessageIncomplete() + case "error": + return u.AsErrorEvent() + } + return nil } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AssistantStreamEventUnion)(nil)).Elem(), - "event", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadCreated{}), - DiscriminatorValue: "thread.created", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunCreated{}), - DiscriminatorValue: "thread.run.created", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunQueued{}), - DiscriminatorValue: "thread.run.queued", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunInProgress{}), - DiscriminatorValue: "thread.run.in_progress", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunRequiresAction{}), - DiscriminatorValue: "thread.run.requires_action", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunCompleted{}), - DiscriminatorValue: "thread.run.completed", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunIncomplete{}), - DiscriminatorValue: "thread.run.incomplete", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunFailed{}), - DiscriminatorValue: "thread.run.failed", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunCancelling{}), - DiscriminatorValue: "thread.run.cancelling", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunCancelled{}), - DiscriminatorValue: "thread.run.cancelled", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunExpired{}), - DiscriminatorValue: "thread.run.expired", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepCreated{}), - DiscriminatorValue: "thread.run.step.created", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepInProgress{}), - DiscriminatorValue: "thread.run.step.in_progress", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepDelta{}), - DiscriminatorValue: "thread.run.step.delta", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepCompleted{}), - DiscriminatorValue: "thread.run.step.completed", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepFailed{}), - DiscriminatorValue: "thread.run.step.failed", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepCancelled{}), - DiscriminatorValue: "thread.run.step.cancelled", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadRunStepExpired{}), - DiscriminatorValue: "thread.run.step.expired", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadMessageCreated{}), - DiscriminatorValue: "thread.message.created", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadMessageInProgress{}), - DiscriminatorValue: "thread.message.in_progress", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadMessageDelta{}), - DiscriminatorValue: "thread.message.delta", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadMessageCompleted{}), - DiscriminatorValue: "thread.message.completed", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventThreadMessageIncomplete{}), - DiscriminatorValue: "thread.message.incomplete", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantStreamEventErrorEvent{}), - DiscriminatorValue: "error", - }, - ) +func (u AssistantStreamEventUnion) AsThreadCreated() (v AssistantStreamEventThreadCreated) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Occurs when a new -// [thread](https://platform.openai.com/docs/api-reference/threads/object) is -// created. -type AssistantStreamEventThreadCreated struct { - // Represents a thread that contains - // [messages](https://platform.openai.com/docs/api-reference/messages). - Data Thread `json:"data,required"` - Event AssistantStreamEventThreadCreatedEvent `json:"event,required"` - // Whether to enable input audio transcription. - Enabled bool `json:"enabled"` - JSON assistantStreamEventThreadCreatedJSON `json:"-"` +func (u AssistantStreamEventUnion) AsThreadRunCreated() (v AssistantStreamEventThreadRunCreated) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// assistantStreamEventThreadCreatedJSON contains the JSON metadata for the struct -// [AssistantStreamEventThreadCreated] -type assistantStreamEventThreadCreatedJSON struct { - Data apijson.Field - Event apijson.Field - Enabled apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u AssistantStreamEventUnion) AsThreadRunQueued() (v AssistantStreamEventThreadRunQueued) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *AssistantStreamEventThreadCreated) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (u AssistantStreamEventUnion) AsThreadRunInProgress() (v AssistantStreamEventThreadRunInProgress) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r assistantStreamEventThreadCreatedJSON) RawJSON() string { - return r.raw +func (u AssistantStreamEventUnion) AsThreadRunRequiresAction() (v AssistantStreamEventThreadRunRequiresAction) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantStreamEventThreadCreated) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadCreatedEvent string - -const ( - AssistantStreamEventThreadCreatedEventThreadCreated AssistantStreamEventThreadCreatedEvent = "thread.created" -) - -func (r AssistantStreamEventThreadCreatedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadCreatedEventThreadCreated: - return true - } - return false +func (u AssistantStreamEventUnion) AsThreadRunCompleted() (v AssistantStreamEventThreadRunCompleted) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Occurs when a new -// [run](https://platform.openai.com/docs/api-reference/runs/object) is created. -type AssistantStreamEventThreadRunCreated struct { - // Represents an execution run on a - // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunCreatedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunCreatedJSON `json:"-"` +func (u AssistantStreamEventUnion) AsThreadRunIncomplete() (v AssistantStreamEventThreadRunIncomplete) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// assistantStreamEventThreadRunCreatedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunCreated] -type assistantStreamEventThreadRunCreatedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u AssistantStreamEventUnion) AsThreadRunFailed() (v AssistantStreamEventThreadRunFailed) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *AssistantStreamEventThreadRunCreated) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (u AssistantStreamEventUnion) AsThreadRunCancelling() (v AssistantStreamEventThreadRunCancelling) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r assistantStreamEventThreadRunCreatedJSON) RawJSON() string { - return r.raw +func (u AssistantStreamEventUnion) AsThreadRunCancelled() (v AssistantStreamEventThreadRunCancelled) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantStreamEventThreadRunCreated) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunCreatedEvent string - -const ( - AssistantStreamEventThreadRunCreatedEventThreadRunCreated AssistantStreamEventThreadRunCreatedEvent = "thread.run.created" -) - -func (r AssistantStreamEventThreadRunCreatedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunCreatedEventThreadRunCreated: - return true - } - return false +func (u AssistantStreamEventUnion) AsThreadRunExpired() (v AssistantStreamEventThreadRunExpired) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) -// moves to a `queued` status. -type AssistantStreamEventThreadRunQueued struct { - // Represents an execution run on a - // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunQueuedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunQueuedJSON `json:"-"` +func (u AssistantStreamEventUnion) AsThreadRunStepCreated() (v AssistantStreamEventThreadRunStepCreated) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// assistantStreamEventThreadRunQueuedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunQueued] -type assistantStreamEventThreadRunQueuedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u AssistantStreamEventUnion) AsThreadRunStepInProgress() (v AssistantStreamEventThreadRunStepInProgress) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *AssistantStreamEventThreadRunQueued) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (u AssistantStreamEventUnion) AsThreadRunStepDelta() (v AssistantStreamEventThreadRunStepDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r assistantStreamEventThreadRunQueuedJSON) RawJSON() string { - return r.raw +func (u AssistantStreamEventUnion) AsThreadRunStepCompleted() (v AssistantStreamEventThreadRunStepCompleted) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantStreamEventThreadRunQueued) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunQueuedEvent string +func (u AssistantStreamEventUnion) AsThreadRunStepFailed() (v AssistantStreamEventThreadRunStepFailed) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - AssistantStreamEventThreadRunQueuedEventThreadRunQueued AssistantStreamEventThreadRunQueuedEvent = "thread.run.queued" -) +func (u AssistantStreamEventUnion) AsThreadRunStepCancelled() (v AssistantStreamEventThreadRunStepCancelled) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -func (r AssistantStreamEventThreadRunQueuedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunQueuedEventThreadRunQueued: - return true - } - return false +func (u AssistantStreamEventUnion) AsThreadRunStepExpired() (v AssistantStreamEventThreadRunStepExpired) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) -// moves to an `in_progress` status. -type AssistantStreamEventThreadRunInProgress struct { - // Represents an execution run on a - // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunInProgressEvent `json:"event,required"` - JSON assistantStreamEventThreadRunInProgressJSON `json:"-"` +func (u AssistantStreamEventUnion) AsThreadMessageCreated() (v AssistantStreamEventThreadMessageCreated) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// assistantStreamEventThreadRunInProgressJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunInProgress] -type assistantStreamEventThreadRunInProgressJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u AssistantStreamEventUnion) AsThreadMessageInProgress() (v AssistantStreamEventThreadMessageInProgress) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *AssistantStreamEventThreadRunInProgress) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (u AssistantStreamEventUnion) AsThreadMessageDelta() (v AssistantStreamEventThreadMessageDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r assistantStreamEventThreadRunInProgressJSON) RawJSON() string { - return r.raw +func (u AssistantStreamEventUnion) AsThreadMessageCompleted() (v AssistantStreamEventThreadMessageCompleted) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantStreamEventThreadRunInProgress) implementsAssistantStreamEvent() {} +func (u AssistantStreamEventUnion) AsThreadMessageIncomplete() (v AssistantStreamEventThreadMessageIncomplete) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -type AssistantStreamEventThreadRunInProgressEvent string +func (u AssistantStreamEventUnion) AsErrorEvent() (v AssistantStreamEventErrorEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - AssistantStreamEventThreadRunInProgressEventThreadRunInProgress AssistantStreamEventThreadRunInProgressEvent = "thread.run.in_progress" -) +// Returns the unmodified JSON received from the API +func (u AssistantStreamEventUnion) RawJSON() string { return u.JSON.raw } -func (r AssistantStreamEventThreadRunInProgressEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunInProgressEventThreadRunInProgress: - return true - } - return false +func (r *AssistantStreamEventUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) -// moves to a `requires_action` status. -type AssistantStreamEventThreadRunRequiresAction struct { - // Represents an execution run on a - // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunRequiresActionEvent `json:"event,required"` - JSON assistantStreamEventThreadRunRequiresActionJSON `json:"-"` +// AssistantStreamEventUnionData is an implicit subunion of +// [AssistantStreamEventUnion]. AssistantStreamEventUnionData provides convenient +// access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [AssistantStreamEventUnion]. +type AssistantStreamEventUnionData struct { + ID string `json:"id"` + CreatedAt int64 `json:"created_at"` + // This field is from variant [Thread]. + Metadata shared.Metadata `json:"metadata"` + Object string `json:"object"` + // This field is from variant [Thread]. + ToolResources ThreadToolResources `json:"tool_resources"` + AssistantID string `json:"assistant_id"` + CancelledAt int64 `json:"cancelled_at"` + CompletedAt int64 `json:"completed_at"` + // This field is from variant [Run]. + ExpiresAt int64 `json:"expires_at"` + FailedAt int64 `json:"failed_at"` + // This field is a union of [RunIncompleteDetails], [MessageIncompleteDetails] + IncompleteDetails AssistantStreamEventUnionDataIncompleteDetails `json:"incomplete_details"` + // This field is from variant [Run]. + Instructions string `json:"instructions"` + // This field is a union of [RunLastError], [RunStepLastError] + LastError AssistantStreamEventUnionDataLastError `json:"last_error"` + // This field is from variant [Run]. + MaxCompletionTokens int64 `json:"max_completion_tokens"` + // This field is from variant [Run]. + MaxPromptTokens int64 `json:"max_prompt_tokens"` + // This field is from variant [Run]. + Model string `json:"model"` + // This field is from variant [Run]. + ParallelToolCalls bool `json:"parallel_tool_calls"` + // This field is from variant [Run]. + RequiredAction RunRequiredAction `json:"required_action"` + // This field is from variant [Run]. + ResponseFormat AssistantResponseFormatOptionUnion `json:"response_format"` + // This field is from variant [Run]. + StartedAt int64 `json:"started_at"` + Status string `json:"status"` + ThreadID string `json:"thread_id"` + // This field is from variant [Run]. + ToolChoice AssistantToolChoiceOptionUnion `json:"tool_choice"` + // This field is from variant [Run]. + Tools []AssistantToolUnion `json:"tools"` + // This field is from variant [Run]. + TruncationStrategy RunTruncationStrategy `json:"truncation_strategy"` + // This field is a union of [RunUsage], [RunStepUsage] + Usage AssistantStreamEventUnionDataUsage `json:"usage"` + // This field is from variant [Run]. + Temperature float64 `json:"temperature"` + // This field is from variant [Run]. + TopP float64 `json:"top_p"` + // This field is from variant [RunStep]. + ExpiredAt int64 `json:"expired_at"` + RunID string `json:"run_id"` + // This field is from variant [RunStep]. + StepDetails RunStepStepDetailsUnion `json:"step_details"` + Type string `json:"type"` + // This field is a union of [RunStepDelta], [MessageDelta] + Delta AssistantStreamEventUnionDataDelta `json:"delta"` + // This field is from variant [Message]. + Attachments []MessageAttachment `json:"attachments"` + // This field is from variant [Message]. + Content []MessageContentUnion `json:"content"` + // This field is from variant [Message]. + IncompleteAt int64 `json:"incomplete_at"` + // This field is from variant [Message]. + Role MessageRole `json:"role"` + // This field is from variant [shared.ErrorObject]. + Code string `json:"code"` + // This field is from variant [shared.ErrorObject]. + Message string `json:"message"` + // This field is from variant [shared.ErrorObject]. + Param string `json:"param"` + JSON struct { + ID resp.Field + CreatedAt resp.Field + Metadata resp.Field + Object resp.Field + ToolResources resp.Field + AssistantID resp.Field + CancelledAt resp.Field + CompletedAt resp.Field + ExpiresAt resp.Field + FailedAt resp.Field + IncompleteDetails resp.Field + Instructions resp.Field + LastError resp.Field + MaxCompletionTokens resp.Field + MaxPromptTokens resp.Field + Model resp.Field + ParallelToolCalls resp.Field + RequiredAction resp.Field + ResponseFormat resp.Field + StartedAt resp.Field + Status resp.Field + ThreadID resp.Field + ToolChoice resp.Field + Tools resp.Field + TruncationStrategy resp.Field + Usage resp.Field + Temperature resp.Field + TopP resp.Field + ExpiredAt resp.Field + RunID resp.Field + StepDetails resp.Field + Type resp.Field + Delta resp.Field + Attachments resp.Field + Content resp.Field + IncompleteAt resp.Field + Role resp.Field + Code resp.Field + Message resp.Field + Param resp.Field + raw string + } `json:"-"` +} + +func (r *AssistantStreamEventUnionData) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// assistantStreamEventThreadRunRequiresActionJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadRunRequiresAction] -type assistantStreamEventThreadRunRequiresActionJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field +// AssistantStreamEventUnionDataIncompleteDetails is an implicit subunion of +// [AssistantStreamEventUnion]. AssistantStreamEventUnionDataIncompleteDetails +// provides convenient access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [AssistantStreamEventUnion]. +type AssistantStreamEventUnionDataIncompleteDetails struct { + Reason string `json:"reason"` + JSON struct { + Reason resp.Field + raw string + } `json:"-"` } -func (r *AssistantStreamEventThreadRunRequiresAction) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantStreamEventUnionDataIncompleteDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunRequiresActionJSON) RawJSON() string { - return r.raw +// AssistantStreamEventUnionDataLastError is an implicit subunion of +// [AssistantStreamEventUnion]. AssistantStreamEventUnionDataLastError provides +// convenient access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [AssistantStreamEventUnion]. +type AssistantStreamEventUnionDataLastError struct { + Code string `json:"code"` + Message string `json:"message"` + JSON struct { + Code resp.Field + Message resp.Field + raw string + } `json:"-"` +} + +func (r *AssistantStreamEventUnionDataLastError) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r AssistantStreamEventThreadRunRequiresAction) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunRequiresActionEvent string +// AssistantStreamEventUnionDataUsage is an implicit subunion of +// [AssistantStreamEventUnion]. AssistantStreamEventUnionDataUsage provides +// convenient access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [AssistantStreamEventUnion]. +type AssistantStreamEventUnionDataUsage struct { + CompletionTokens int64 `json:"completion_tokens"` + PromptTokens int64 `json:"prompt_tokens"` + TotalTokens int64 `json:"total_tokens"` + JSON struct { + CompletionTokens resp.Field + PromptTokens resp.Field + TotalTokens resp.Field + raw string + } `json:"-"` +} + +func (r *AssistantStreamEventUnionDataUsage) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} -const ( - AssistantStreamEventThreadRunRequiresActionEventThreadRunRequiresAction AssistantStreamEventThreadRunRequiresActionEvent = "thread.run.requires_action" -) +// AssistantStreamEventUnionDataDelta is an implicit subunion of +// [AssistantStreamEventUnion]. AssistantStreamEventUnionDataDelta provides +// convenient access to the sub-properties of the union. +// +// For type safety it is recommended to directly use a variant of the +// [AssistantStreamEventUnion]. +type AssistantStreamEventUnionDataDelta struct { + // This field is from variant [RunStepDelta]. + StepDetails RunStepDeltaStepDetailsUnion `json:"step_details"` + // This field is from variant [MessageDelta]. + Content []MessageContentDeltaUnion `json:"content"` + // This field is from variant [MessageDelta]. + Role MessageDeltaRole `json:"role"` + JSON struct { + StepDetails resp.Field + Content resp.Field + Role resp.Field + raw string + } `json:"-"` +} + +func (r *AssistantStreamEventUnionDataDelta) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} -func (r AssistantStreamEventThreadRunRequiresActionEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunRequiresActionEventThreadRunRequiresAction: - return true - } - return false +// Occurs when a new +// [thread](https://platform.openai.com/docs/api-reference/threads/object) is +// created. +type AssistantStreamEventThreadCreated struct { + // Represents a thread that contains + // [messages](https://platform.openai.com/docs/api-reference/messages). + Data Thread `json:"data,required"` + Event constant.ThreadCreated `json:"event,required"` + // Whether to enable input audio transcription. + Enabled bool `json:"enabled"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + Enabled resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadCreated) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadCreated) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) -// is completed. -type AssistantStreamEventThreadRunCompleted struct { +// Occurs when a new +// [run](https://platform.openai.com/docs/api-reference/runs/object) is created. +type AssistantStreamEventThreadRunCreated struct { // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunCompletedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunCompletedJSON `json:"-"` + Data Run `json:"data,required"` + Event constant.ThreadRunCreated `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunCreated) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunCreated) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// assistantStreamEventThreadRunCompletedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunCompleted] -type assistantStreamEventThreadRunCompletedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field +// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) +// moves to a `queued` status. +type AssistantStreamEventThreadRunQueued struct { + // Represents an execution run on a + // [thread](https://platform.openai.com/docs/api-reference/threads). + Data Run `json:"data,required"` + Event constant.ThreadRunQueued `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunQueued) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunQueued) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r *AssistantStreamEventThreadRunCompleted) UnmarshalJSON(data []byte) (err error) { +// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) +// moves to an `in_progress` status. +type AssistantStreamEventThreadRunInProgress struct { + // Represents an execution run on a + // [thread](https://platform.openai.com/docs/api-reference/threads). + Data Run `json:"data,required"` + Event constant.ThreadRunInProgress `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunInProgress) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunInProgress) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunCompletedJSON) RawJSON() string { - return r.raw +// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) +// moves to a `requires_action` status. +type AssistantStreamEventThreadRunRequiresAction struct { + // Represents an execution run on a + // [thread](https://platform.openai.com/docs/api-reference/threads). + Data Run `json:"data,required"` + Event constant.ThreadRunRequiresAction `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunRequiresAction) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunRequiresAction) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r AssistantStreamEventThreadRunCompleted) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunCompletedEvent string - -const ( - AssistantStreamEventThreadRunCompletedEventThreadRunCompleted AssistantStreamEventThreadRunCompletedEvent = "thread.run.completed" -) - -func (r AssistantStreamEventThreadRunCompletedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunCompletedEventThreadRunCompleted: - return true - } - return false +// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) +// is completed. +type AssistantStreamEventThreadRunCompleted struct { + // Represents an execution run on a + // [thread](https://platform.openai.com/docs/api-reference/threads). + Data Run `json:"data,required"` + Event constant.ThreadRunCompleted `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunCompleted) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunCompleted) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) @@ -863,214 +912,114 @@ func (r AssistantStreamEventThreadRunCompletedEvent) IsKnown() bool { type AssistantStreamEventThreadRunIncomplete struct { // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunIncompleteEvent `json:"event,required"` - JSON assistantStreamEventThreadRunIncompleteJSON `json:"-"` -} - -// assistantStreamEventThreadRunIncompleteJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunIncomplete] -type assistantStreamEventThreadRunIncompleteJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunIncomplete) UnmarshalJSON(data []byte) (err error) { + Data Run `json:"data,required"` + Event constant.ThreadRunIncomplete `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunIncomplete) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunIncomplete) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunIncompleteJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunIncomplete) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunIncompleteEvent string - -const ( - AssistantStreamEventThreadRunIncompleteEventThreadRunIncomplete AssistantStreamEventThreadRunIncompleteEvent = "thread.run.incomplete" -) - -func (r AssistantStreamEventThreadRunIncompleteEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunIncompleteEventThreadRunIncomplete: - return true - } - return false -} - // Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) // fails. type AssistantStreamEventThreadRunFailed struct { // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunFailedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunFailedJSON `json:"-"` -} - -// assistantStreamEventThreadRunFailedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunFailed] -type assistantStreamEventThreadRunFailedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunFailed) UnmarshalJSON(data []byte) (err error) { + Data Run `json:"data,required"` + Event constant.ThreadRunFailed `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunFailed) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunFailed) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunFailedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunFailed) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunFailedEvent string - -const ( - AssistantStreamEventThreadRunFailedEventThreadRunFailed AssistantStreamEventThreadRunFailedEvent = "thread.run.failed" -) - -func (r AssistantStreamEventThreadRunFailedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunFailedEventThreadRunFailed: - return true - } - return false -} - // Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) // moves to a `cancelling` status. type AssistantStreamEventThreadRunCancelling struct { // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunCancellingEvent `json:"event,required"` - JSON assistantStreamEventThreadRunCancellingJSON `json:"-"` -} - -// assistantStreamEventThreadRunCancellingJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunCancelling] -type assistantStreamEventThreadRunCancellingJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunCancelling) UnmarshalJSON(data []byte) (err error) { + Data Run `json:"data,required"` + Event constant.ThreadRunCancelling `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunCancelling) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunCancelling) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunCancellingJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunCancelling) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunCancellingEvent string - -const ( - AssistantStreamEventThreadRunCancellingEventThreadRunCancelling AssistantStreamEventThreadRunCancellingEvent = "thread.run.cancelling" -) - -func (r AssistantStreamEventThreadRunCancellingEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunCancellingEventThreadRunCancelling: - return true - } - return false -} - // Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) // is cancelled. type AssistantStreamEventThreadRunCancelled struct { // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunCancelledEvent `json:"event,required"` - JSON assistantStreamEventThreadRunCancelledJSON `json:"-"` -} - -// assistantStreamEventThreadRunCancelledJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunCancelled] -type assistantStreamEventThreadRunCancelledJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunCancelled) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r assistantStreamEventThreadRunCancelledJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunCancelled) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunCancelledEvent string - -const ( - AssistantStreamEventThreadRunCancelledEventThreadRunCancelled AssistantStreamEventThreadRunCancelledEvent = "thread.run.cancelled" -) - -func (r AssistantStreamEventThreadRunCancelledEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunCancelledEventThreadRunCancelled: - return true - } - return false -} - -// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) -// expires. -type AssistantStreamEventThreadRunExpired struct { - // Represents an execution run on a - // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Run `json:"data,required"` - Event AssistantStreamEventThreadRunExpiredEvent `json:"event,required"` - JSON assistantStreamEventThreadRunExpiredJSON `json:"-"` -} - -// assistantStreamEventThreadRunExpiredJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunExpired] -type assistantStreamEventThreadRunExpiredJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunExpired) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) -} - -func (r assistantStreamEventThreadRunExpiredJSON) RawJSON() string { - return r.raw + Data Run `json:"data,required"` + Event constant.ThreadRunCancelled `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunCancelled) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunCancelled) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r AssistantStreamEventThreadRunExpired) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunExpiredEvent string - -const ( - AssistantStreamEventThreadRunExpiredEventThreadRunExpired AssistantStreamEventThreadRunExpiredEvent = "thread.run.expired" -) - -func (r AssistantStreamEventThreadRunExpiredEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunExpiredEventThreadRunExpired: - return true - } - return false +// Occurs when a [run](https://platform.openai.com/docs/api-reference/runs/object) +// expires. +type AssistantStreamEventThreadRunExpired struct { + // Represents an execution run on a + // [thread](https://platform.openai.com/docs/api-reference/threads). + Data Run `json:"data,required"` + Event constant.ThreadRunExpired `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunExpired) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunExpired) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Occurs when a @@ -1078,809 +1027,533 @@ func (r AssistantStreamEventThreadRunExpiredEvent) IsKnown() bool { // is created. type AssistantStreamEventThreadRunStepCreated struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepCreatedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepCreatedJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepCreatedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunStepCreated] -type assistantStreamEventThreadRunStepCreatedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepCreated) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepCreated `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepCreated) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepCreated) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepCreatedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepCreated) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepCreatedEvent string - -const ( - AssistantStreamEventThreadRunStepCreatedEventThreadRunStepCreated AssistantStreamEventThreadRunStepCreatedEvent = "thread.run.step.created" -) - -func (r AssistantStreamEventThreadRunStepCreatedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepCreatedEventThreadRunStepCreated: - return true - } - return false -} - // Occurs when a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // moves to an `in_progress` state. type AssistantStreamEventThreadRunStepInProgress struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepInProgressEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepInProgressJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepInProgressJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadRunStepInProgress] -type assistantStreamEventThreadRunStepInProgressJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepInProgress) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepInProgress `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepInProgress) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepInProgress) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepInProgressJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepInProgress) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepInProgressEvent string - -const ( - AssistantStreamEventThreadRunStepInProgressEventThreadRunStepInProgress AssistantStreamEventThreadRunStepInProgressEvent = "thread.run.step.in_progress" -) - -func (r AssistantStreamEventThreadRunStepInProgressEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepInProgressEventThreadRunStepInProgress: - return true - } - return false -} - // Occurs when parts of a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // are being streamed. type AssistantStreamEventThreadRunStepDelta struct { // Represents a run step delta i.e. any changed fields on a run step during // streaming. - Data RunStepDeltaEvent `json:"data,required"` - Event AssistantStreamEventThreadRunStepDeltaEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepDeltaJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepDeltaJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunStepDelta] -type assistantStreamEventThreadRunStepDeltaJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepDelta) UnmarshalJSON(data []byte) (err error) { + Data RunStepDeltaEvent `json:"data,required"` + Event constant.ThreadRunStepDelta `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepDelta) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepDeltaJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepDelta) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepDeltaEvent string - -const ( - AssistantStreamEventThreadRunStepDeltaEventThreadRunStepDelta AssistantStreamEventThreadRunStepDeltaEvent = "thread.run.step.delta" -) - -func (r AssistantStreamEventThreadRunStepDeltaEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepDeltaEventThreadRunStepDelta: - return true - } - return false -} - // Occurs when a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // is completed. type AssistantStreamEventThreadRunStepCompleted struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepCompletedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepCompletedJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepCompletedJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadRunStepCompleted] -type assistantStreamEventThreadRunStepCompletedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepCompleted) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepCompleted `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepCompleted) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepCompleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepCompletedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepCompleted) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepCompletedEvent string - -const ( - AssistantStreamEventThreadRunStepCompletedEventThreadRunStepCompleted AssistantStreamEventThreadRunStepCompletedEvent = "thread.run.step.completed" -) - -func (r AssistantStreamEventThreadRunStepCompletedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepCompletedEventThreadRunStepCompleted: - return true - } - return false -} - // Occurs when a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // fails. type AssistantStreamEventThreadRunStepFailed struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepFailedEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepFailedJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepFailedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunStepFailed] -type assistantStreamEventThreadRunStepFailedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepFailed) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepFailed `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepFailed) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepFailed) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepFailedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepFailed) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepFailedEvent string - -const ( - AssistantStreamEventThreadRunStepFailedEventThreadRunStepFailed AssistantStreamEventThreadRunStepFailedEvent = "thread.run.step.failed" -) - -func (r AssistantStreamEventThreadRunStepFailedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepFailedEventThreadRunStepFailed: - return true - } - return false -} - // Occurs when a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // is cancelled. type AssistantStreamEventThreadRunStepCancelled struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepCancelledEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepCancelledJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepCancelledJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadRunStepCancelled] -type assistantStreamEventThreadRunStepCancelledJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepCancelled) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepCancelled `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepCancelled) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepCancelled) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepCancelledJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepCancelled) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepCancelledEvent string - -const ( - AssistantStreamEventThreadRunStepCancelledEventThreadRunStepCancelled AssistantStreamEventThreadRunStepCancelledEvent = "thread.run.step.cancelled" -) - -func (r AssistantStreamEventThreadRunStepCancelledEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepCancelledEventThreadRunStepCancelled: - return true - } - return false -} - // Occurs when a // [run step](https://platform.openai.com/docs/api-reference/run-steps/step-object) // expires. type AssistantStreamEventThreadRunStepExpired struct { // Represents a step in execution of a run. - Data RunStep `json:"data,required"` - Event AssistantStreamEventThreadRunStepExpiredEvent `json:"event,required"` - JSON assistantStreamEventThreadRunStepExpiredJSON `json:"-"` -} - -// assistantStreamEventThreadRunStepExpiredJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadRunStepExpired] -type assistantStreamEventThreadRunStepExpiredJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadRunStepExpired) UnmarshalJSON(data []byte) (err error) { + Data RunStep `json:"data,required"` + Event constant.ThreadRunStepExpired `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadRunStepExpired) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadRunStepExpired) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadRunStepExpiredJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadRunStepExpired) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadRunStepExpiredEvent string - -const ( - AssistantStreamEventThreadRunStepExpiredEventThreadRunStepExpired AssistantStreamEventThreadRunStepExpiredEvent = "thread.run.step.expired" -) - -func (r AssistantStreamEventThreadRunStepExpiredEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadRunStepExpiredEventThreadRunStepExpired: - return true - } - return false -} - // Occurs when a // [message](https://platform.openai.com/docs/api-reference/messages/object) is // created. type AssistantStreamEventThreadMessageCreated struct { // Represents a message within a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Message `json:"data,required"` - Event AssistantStreamEventThreadMessageCreatedEvent `json:"event,required"` - JSON assistantStreamEventThreadMessageCreatedJSON `json:"-"` -} - -// assistantStreamEventThreadMessageCreatedJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadMessageCreated] -type assistantStreamEventThreadMessageCreatedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadMessageCreated) UnmarshalJSON(data []byte) (err error) { + Data Message `json:"data,required"` + Event constant.ThreadMessageCreated `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadMessageCreated) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadMessageCreated) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadMessageCreatedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadMessageCreated) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadMessageCreatedEvent string - -const ( - AssistantStreamEventThreadMessageCreatedEventThreadMessageCreated AssistantStreamEventThreadMessageCreatedEvent = "thread.message.created" -) - -func (r AssistantStreamEventThreadMessageCreatedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadMessageCreatedEventThreadMessageCreated: - return true - } - return false -} - // Occurs when a // [message](https://platform.openai.com/docs/api-reference/messages/object) moves // to an `in_progress` state. type AssistantStreamEventThreadMessageInProgress struct { // Represents a message within a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Message `json:"data,required"` - Event AssistantStreamEventThreadMessageInProgressEvent `json:"event,required"` - JSON assistantStreamEventThreadMessageInProgressJSON `json:"-"` -} - -// assistantStreamEventThreadMessageInProgressJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadMessageInProgress] -type assistantStreamEventThreadMessageInProgressJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadMessageInProgress) UnmarshalJSON(data []byte) (err error) { + Data Message `json:"data,required"` + Event constant.ThreadMessageInProgress `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadMessageInProgress) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadMessageInProgress) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadMessageInProgressJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadMessageInProgress) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadMessageInProgressEvent string - -const ( - AssistantStreamEventThreadMessageInProgressEventThreadMessageInProgress AssistantStreamEventThreadMessageInProgressEvent = "thread.message.in_progress" -) - -func (r AssistantStreamEventThreadMessageInProgressEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadMessageInProgressEventThreadMessageInProgress: - return true - } - return false -} - // Occurs when parts of a // [Message](https://platform.openai.com/docs/api-reference/messages/object) are // being streamed. type AssistantStreamEventThreadMessageDelta struct { // Represents a message delta i.e. any changed fields on a message during // streaming. - Data MessageDeltaEvent `json:"data,required"` - Event AssistantStreamEventThreadMessageDeltaEvent `json:"event,required"` - JSON assistantStreamEventThreadMessageDeltaJSON `json:"-"` -} - -// assistantStreamEventThreadMessageDeltaJSON contains the JSON metadata for the -// struct [AssistantStreamEventThreadMessageDelta] -type assistantStreamEventThreadMessageDeltaJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadMessageDelta) UnmarshalJSON(data []byte) (err error) { + Data MessageDeltaEvent `json:"data,required"` + Event constant.ThreadMessageDelta `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadMessageDelta) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadMessageDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadMessageDeltaJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadMessageDelta) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadMessageDeltaEvent string - -const ( - AssistantStreamEventThreadMessageDeltaEventThreadMessageDelta AssistantStreamEventThreadMessageDeltaEvent = "thread.message.delta" -) - -func (r AssistantStreamEventThreadMessageDeltaEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadMessageDeltaEventThreadMessageDelta: - return true - } - return false -} - // Occurs when a // [message](https://platform.openai.com/docs/api-reference/messages/object) is // completed. type AssistantStreamEventThreadMessageCompleted struct { // Represents a message within a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Message `json:"data,required"` - Event AssistantStreamEventThreadMessageCompletedEvent `json:"event,required"` - JSON assistantStreamEventThreadMessageCompletedJSON `json:"-"` -} - -// assistantStreamEventThreadMessageCompletedJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadMessageCompleted] -type assistantStreamEventThreadMessageCompletedJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadMessageCompleted) UnmarshalJSON(data []byte) (err error) { + Data Message `json:"data,required"` + Event constant.ThreadMessageCompleted `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadMessageCompleted) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadMessageCompleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadMessageCompletedJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadMessageCompleted) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadMessageCompletedEvent string - -const ( - AssistantStreamEventThreadMessageCompletedEventThreadMessageCompleted AssistantStreamEventThreadMessageCompletedEvent = "thread.message.completed" -) - -func (r AssistantStreamEventThreadMessageCompletedEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadMessageCompletedEventThreadMessageCompleted: - return true - } - return false -} - // Occurs when a // [message](https://platform.openai.com/docs/api-reference/messages/object) ends // before it is completed. type AssistantStreamEventThreadMessageIncomplete struct { // Represents a message within a // [thread](https://platform.openai.com/docs/api-reference/threads). - Data Message `json:"data,required"` - Event AssistantStreamEventThreadMessageIncompleteEvent `json:"event,required"` - JSON assistantStreamEventThreadMessageIncompleteJSON `json:"-"` -} - -// assistantStreamEventThreadMessageIncompleteJSON contains the JSON metadata for -// the struct [AssistantStreamEventThreadMessageIncomplete] -type assistantStreamEventThreadMessageIncompleteJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventThreadMessageIncomplete) UnmarshalJSON(data []byte) (err error) { + Data Message `json:"data,required"` + Event constant.ThreadMessageIncomplete `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventThreadMessageIncomplete) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventThreadMessageIncomplete) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventThreadMessageIncompleteJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventThreadMessageIncomplete) implementsAssistantStreamEvent() {} - -type AssistantStreamEventThreadMessageIncompleteEvent string - -const ( - AssistantStreamEventThreadMessageIncompleteEventThreadMessageIncomplete AssistantStreamEventThreadMessageIncompleteEvent = "thread.message.incomplete" -) - -func (r AssistantStreamEventThreadMessageIncompleteEvent) IsKnown() bool { - switch r { - case AssistantStreamEventThreadMessageIncompleteEventThreadMessageIncomplete: - return true - } - return false -} - // Occurs when an // [error](https://platform.openai.com/docs/guides/error-codes#api-errors) occurs. // This can happen due to an internal server error or a timeout. type AssistantStreamEventErrorEvent struct { - Data shared.ErrorObject `json:"data,required"` - Event AssistantStreamEventErrorEventEvent `json:"event,required"` - JSON assistantStreamEventErrorEventJSON `json:"-"` -} - -// assistantStreamEventErrorEventJSON contains the JSON metadata for the struct -// [AssistantStreamEventErrorEvent] -type assistantStreamEventErrorEventJSON struct { - Data apijson.Field - Event apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantStreamEventErrorEvent) UnmarshalJSON(data []byte) (err error) { + Data shared.ErrorObject `json:"data,required"` + Event constant.Error `json:"event,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Event resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantStreamEventErrorEvent) RawJSON() string { return r.JSON.raw } +func (r *AssistantStreamEventErrorEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantStreamEventErrorEventJSON) RawJSON() string { - return r.raw -} - -func (r AssistantStreamEventErrorEvent) implementsAssistantStreamEvent() {} - -type AssistantStreamEventErrorEventEvent string - -const ( - AssistantStreamEventErrorEventEventError AssistantStreamEventErrorEventEvent = "error" -) - -func (r AssistantStreamEventErrorEventEvent) IsKnown() bool { - switch r { - case AssistantStreamEventErrorEventEventError: - return true - } - return false -} - -type AssistantStreamEventEvent string - -const ( - AssistantStreamEventEventThreadCreated AssistantStreamEventEvent = "thread.created" - AssistantStreamEventEventThreadRunCreated AssistantStreamEventEvent = "thread.run.created" - AssistantStreamEventEventThreadRunQueued AssistantStreamEventEvent = "thread.run.queued" - AssistantStreamEventEventThreadRunInProgress AssistantStreamEventEvent = "thread.run.in_progress" - AssistantStreamEventEventThreadRunRequiresAction AssistantStreamEventEvent = "thread.run.requires_action" - AssistantStreamEventEventThreadRunCompleted AssistantStreamEventEvent = "thread.run.completed" - AssistantStreamEventEventThreadRunIncomplete AssistantStreamEventEvent = "thread.run.incomplete" - AssistantStreamEventEventThreadRunFailed AssistantStreamEventEvent = "thread.run.failed" - AssistantStreamEventEventThreadRunCancelling AssistantStreamEventEvent = "thread.run.cancelling" - AssistantStreamEventEventThreadRunCancelled AssistantStreamEventEvent = "thread.run.cancelled" - AssistantStreamEventEventThreadRunExpired AssistantStreamEventEvent = "thread.run.expired" - AssistantStreamEventEventThreadRunStepCreated AssistantStreamEventEvent = "thread.run.step.created" - AssistantStreamEventEventThreadRunStepInProgress AssistantStreamEventEvent = "thread.run.step.in_progress" - AssistantStreamEventEventThreadRunStepDelta AssistantStreamEventEvent = "thread.run.step.delta" - AssistantStreamEventEventThreadRunStepCompleted AssistantStreamEventEvent = "thread.run.step.completed" - AssistantStreamEventEventThreadRunStepFailed AssistantStreamEventEvent = "thread.run.step.failed" - AssistantStreamEventEventThreadRunStepCancelled AssistantStreamEventEvent = "thread.run.step.cancelled" - AssistantStreamEventEventThreadRunStepExpired AssistantStreamEventEvent = "thread.run.step.expired" - AssistantStreamEventEventThreadMessageCreated AssistantStreamEventEvent = "thread.message.created" - AssistantStreamEventEventThreadMessageInProgress AssistantStreamEventEvent = "thread.message.in_progress" - AssistantStreamEventEventThreadMessageDelta AssistantStreamEventEvent = "thread.message.delta" - AssistantStreamEventEventThreadMessageCompleted AssistantStreamEventEvent = "thread.message.completed" - AssistantStreamEventEventThreadMessageIncomplete AssistantStreamEventEvent = "thread.message.incomplete" - AssistantStreamEventEventError AssistantStreamEventEvent = "error" -) - -func (r AssistantStreamEventEvent) IsKnown() bool { - switch r { - case AssistantStreamEventEventThreadCreated, AssistantStreamEventEventThreadRunCreated, AssistantStreamEventEventThreadRunQueued, AssistantStreamEventEventThreadRunInProgress, AssistantStreamEventEventThreadRunRequiresAction, AssistantStreamEventEventThreadRunCompleted, AssistantStreamEventEventThreadRunIncomplete, AssistantStreamEventEventThreadRunFailed, AssistantStreamEventEventThreadRunCancelling, AssistantStreamEventEventThreadRunCancelled, AssistantStreamEventEventThreadRunExpired, AssistantStreamEventEventThreadRunStepCreated, AssistantStreamEventEventThreadRunStepInProgress, AssistantStreamEventEventThreadRunStepDelta, AssistantStreamEventEventThreadRunStepCompleted, AssistantStreamEventEventThreadRunStepFailed, AssistantStreamEventEventThreadRunStepCancelled, AssistantStreamEventEventThreadRunStepExpired, AssistantStreamEventEventThreadMessageCreated, AssistantStreamEventEventThreadMessageInProgress, AssistantStreamEventEventThreadMessageDelta, AssistantStreamEventEventThreadMessageCompleted, AssistantStreamEventEventThreadMessageIncomplete, AssistantStreamEventEventError: - return true - } - return false -} - -type AssistantTool struct { - // The type of tool being defined: `code_interpreter` - Type AssistantToolType `json:"type,required"` - // This field can have the runtime type of [FileSearchToolFileSearch]. - FileSearch interface{} `json:"file_search"` - Function shared.FunctionDefinition `json:"function"` - JSON assistantToolJSON `json:"-"` - union AssistantToolUnion -} - -// assistantToolJSON contains the JSON metadata for the struct [AssistantTool] -type assistantToolJSON struct { - Type apijson.Field - FileSearch apijson.Field - Function apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r assistantToolJSON) RawJSON() string { - return r.raw -} - -func (r *AssistantTool) UnmarshalJSON(data []byte) (err error) { - *r = AssistantTool{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) -} - -// AsUnion returns a [AssistantToolUnion] interface which you can cast to the -// specific types for more type safety. +// AssistantToolUnion contains all possible properties and values from +// [CodeInterpreterTool], [FileSearchTool], [FunctionTool]. // -// Possible runtime types of the union are [CodeInterpreterTool], [FileSearchTool], -// [FunctionTool]. -func (r AssistantTool) AsUnion() AssistantToolUnion { - return r.union -} - -// Union satisfied by [CodeInterpreterTool], [FileSearchTool] or [FunctionTool]. -type AssistantToolUnion interface { - implementsAssistantTool() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AssistantToolUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterTool{}), - DiscriminatorValue: "code_interpreter", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FileSearchTool{}), - DiscriminatorValue: "file_search", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FunctionTool{}), - DiscriminatorValue: "function", - }, - ) +// Use the [AssistantToolUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type AssistantToolUnion struct { + // Any of "code_interpreter", "file_search", "function". + Type string `json:"type"` + // This field is from variant [FileSearchTool]. + FileSearch FileSearchToolFileSearch `json:"file_search"` + // This field is from variant [FunctionTool]. + Function shared.FunctionDefinition `json:"function"` + JSON struct { + Type resp.Field + FileSearch resp.Field + Function resp.Field + raw string + } `json:"-"` } -// The type of tool being defined: `code_interpreter` -type AssistantToolType string - -const ( - AssistantToolTypeCodeInterpreter AssistantToolType = "code_interpreter" - AssistantToolTypeFileSearch AssistantToolType = "file_search" - AssistantToolTypeFunction AssistantToolType = "function" -) - -func (r AssistantToolType) IsKnown() bool { - switch r { - case AssistantToolTypeCodeInterpreter, AssistantToolTypeFileSearch, AssistantToolTypeFunction: - return true +// Use the following switch statement to find the correct variant +// +// switch variant := AssistantToolUnion.AsAny().(type) { +// case CodeInterpreterTool: +// case FileSearchTool: +// case FunctionTool: +// default: +// fmt.Errorf("no variant present") +// } +func (u AssistantToolUnion) AsAny() any { + switch u.Type { + case "code_interpreter": + return u.AsCodeInterpreter() + case "file_search": + return u.AsFileSearch() + case "function": + return u.AsFunction() } - return false -} - -type AssistantToolParam struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[AssistantToolType] `json:"type,required"` - FileSearch param.Field[interface{}] `json:"file_search"` - Function param.Field[shared.FunctionDefinitionParam] `json:"function"` + return nil } -func (r AssistantToolParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +func (u AssistantToolUnion) AsCodeInterpreter() (v CodeInterpreterTool) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantToolParam) implementsAssistantToolUnionParam() {} - -// Satisfied by [CodeInterpreterToolParam], [FileSearchToolParam], -// [FunctionToolParam], [AssistantToolParam]. -type AssistantToolUnionParam interface { - implementsAssistantToolUnionParam() +func (u AssistantToolUnion) AsFileSearch() (v FileSearchTool) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type CodeInterpreterTool struct { - // The type of tool being defined: `code_interpreter` - Type CodeInterpreterToolType `json:"type,required"` - JSON codeInterpreterToolJSON `json:"-"` +func (u AssistantToolUnion) AsFunction() (v FunctionTool) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// codeInterpreterToolJSON contains the JSON metadata for the struct -// [CodeInterpreterTool] -type codeInterpreterToolJSON struct { - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} +// Returns the unmodified JSON received from the API +func (u AssistantToolUnion) RawJSON() string { return u.JSON.raw } -func (r *CodeInterpreterTool) UnmarshalJSON(data []byte) (err error) { +func (r *AssistantToolUnion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolJSON) RawJSON() string { - return r.raw +// ToParam converts this AssistantToolUnion to a AssistantToolUnionParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// AssistantToolUnionParam.IsOverridden() +func (r AssistantToolUnion) ToParam() AssistantToolUnionParam { + return param.OverrideObj[AssistantToolUnionParam](r.RawJSON()) } -func (r CodeInterpreterTool) implementsAssistantTool() {} - -func (r CodeInterpreterTool) implementsMessageAttachmentsTool() {} - -// The type of tool being defined: `code_interpreter` -type CodeInterpreterToolType string - -const ( - CodeInterpreterToolTypeCodeInterpreter CodeInterpreterToolType = "code_interpreter" -) +func AssistantToolParamOfFunction(function shared.FunctionDefinitionParam) AssistantToolUnionParam { + var variant FunctionToolParam + variant.Function = function + return AssistantToolUnionParam{OfFunction: &variant} +} -func (r CodeInterpreterToolType) IsKnown() bool { - switch r { - case CodeInterpreterToolTypeCodeInterpreter: - return true +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type AssistantToolUnionParam struct { + OfCodeInterpreter *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearch *FileSearchToolParam `json:",omitzero,inline"` + OfFunction *FunctionToolParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u AssistantToolUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u AssistantToolUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[AssistantToolUnionParam](u.OfCodeInterpreter, u.OfFileSearch, u.OfFunction) +} + +func (u *AssistantToolUnionParam) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreter) { + return u.OfCodeInterpreter + } else if !param.IsOmitted(u.OfFileSearch) { + return u.OfFileSearch + } else if !param.IsOmitted(u.OfFunction) { + return u.OfFunction } - return false + return nil } -type CodeInterpreterToolParam struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[CodeInterpreterToolType] `json:"type,required"` +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantToolUnionParam) GetFileSearch() *FileSearchToolFileSearchParam { + if vt := u.OfFileSearch; vt != nil { + return &vt.FileSearch + } + return nil } -func (r CodeInterpreterToolParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantToolUnionParam) GetFunction() *shared.FunctionDefinitionParam { + if vt := u.OfFunction; vt != nil { + return &vt.Function + } + return nil } -func (r CodeInterpreterToolParam) implementsAssistantToolUnionParam() {} +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantToolUnionParam) GetType() *string { + if vt := u.OfCodeInterpreter; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearch; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFunction; vt != nil { + return (*string)(&vt.Type) + } + return nil +} -func (r CodeInterpreterToolParam) implementsBetaThreadNewParamsMessagesAttachmentsToolUnion() {} +func init() { + apijson.RegisterUnion[AssistantToolUnionParam]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(CodeInterpreterToolParam{}), + DiscriminatorValue: "code_interpreter", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(FileSearchToolParam{}), + DiscriminatorValue: "file_search", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(FunctionToolParam{}), + DiscriminatorValue: "function", + }, + ) +} -func (r CodeInterpreterToolParam) implementsBetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion() { +type CodeInterpreterTool struct { + // The type of tool being defined: `code_interpreter` + Type constant.CodeInterpreter `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterTool) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterTool) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r CodeInterpreterToolParam) implementsBetaThreadNewAndRunParamsToolUnion() {} +// ToParam converts this CodeInterpreterTool to a CodeInterpreterToolParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// CodeInterpreterToolParam.IsOverridden() +func (r CodeInterpreterTool) ToParam() CodeInterpreterToolParam { + return param.OverrideObj[CodeInterpreterToolParam](r.RawJSON()) +} -func (r CodeInterpreterToolParam) implementsBetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion() { +// The property Type is required. +type CodeInterpreterToolParam struct { + // The type of tool being defined: `code_interpreter` + // + // This field can be elided, and will marshal its zero value as "code_interpreter". + Type constant.CodeInterpreter `json:"type,required"` + paramObj } -func (r CodeInterpreterToolParam) implementsBetaThreadMessageNewParamsAttachmentsToolUnion() {} +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f CodeInterpreterToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } +func (r CodeInterpreterToolParam) MarshalJSON() (data []byte, err error) { + type shadow CodeInterpreterToolParam + return param.MarshalObject(r, (*shadow)(&r)) +} type FileSearchTool struct { // The type of tool being defined: `file_search` - Type FileSearchToolType `json:"type,required"` + Type constant.FileSearch `json:"type,required"` // Overrides for the file search tool. FileSearch FileSearchToolFileSearch `json:"file_search"` - JSON fileSearchToolJSON `json:"-"` -} - -// fileSearchToolJSON contains the JSON metadata for the struct [FileSearchTool] -type fileSearchToolJSON struct { - Type apijson.Field - FileSearch apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchTool) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + FileSearch resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchTool) RawJSON() string { return r.JSON.raw } +func (r *FileSearchTool) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolJSON) RawJSON() string { - return r.raw -} - -func (r FileSearchTool) implementsAssistantTool() {} - -// The type of tool being defined: `file_search` -type FileSearchToolType string - -const ( - FileSearchToolTypeFileSearch FileSearchToolType = "file_search" -) - -func (r FileSearchToolType) IsKnown() bool { - switch r { - case FileSearchToolTypeFileSearch: - return true - } - return false +// ToParam converts this FileSearchTool to a FileSearchToolParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// FileSearchToolParam.IsOverridden() +func (r FileSearchTool) ToParam() FileSearchToolParam { + return param.OverrideObj[FileSearchToolParam](r.RawJSON()) } // Overrides for the file search tool. @@ -1901,26 +1574,22 @@ type FileSearchToolFileSearch struct { // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. RankingOptions FileSearchToolFileSearchRankingOptions `json:"ranking_options"` - JSON fileSearchToolFileSearchJSON `json:"-"` -} - -// fileSearchToolFileSearchJSON contains the JSON metadata for the struct -// [FileSearchToolFileSearch] -type fileSearchToolFileSearchJSON struct { - MaxNumResults apijson.Field - RankingOptions apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolFileSearch) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + MaxNumResults resp.Field + RankingOptions resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolFileSearch) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolFileSearch) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolFileSearchJSON) RawJSON() string { - return r.raw -} - // The ranking options for the file search. If not specified, the file search tool // will use the `auto` ranker and a score_threshold of 0. // @@ -1933,59 +1602,44 @@ type FileSearchToolFileSearchRankingOptions struct { ScoreThreshold float64 `json:"score_threshold,required"` // The ranker to use for the file search. If not specified will use the `auto` // ranker. - Ranker FileSearchToolFileSearchRankingOptionsRanker `json:"ranker"` - JSON fileSearchToolFileSearchRankingOptionsJSON `json:"-"` -} - -// fileSearchToolFileSearchRankingOptionsJSON contains the JSON metadata for the -// struct [FileSearchToolFileSearchRankingOptions] -type fileSearchToolFileSearchRankingOptionsJSON struct { - ScoreThreshold apijson.Field - Ranker apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolFileSearchRankingOptions) UnmarshalJSON(data []byte) (err error) { + // + // Any of "auto", "default_2024_08_21". + Ranker string `json:"ranker"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ScoreThreshold resp.Field + Ranker resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolFileSearchRankingOptions) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolFileSearchRankingOptions) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolFileSearchRankingOptionsJSON) RawJSON() string { - return r.raw -} - -// The ranker to use for the file search. If not specified will use the `auto` -// ranker. -type FileSearchToolFileSearchRankingOptionsRanker string - -const ( - FileSearchToolFileSearchRankingOptionsRankerAuto FileSearchToolFileSearchRankingOptionsRanker = "auto" - FileSearchToolFileSearchRankingOptionsRankerDefault2024_08_21 FileSearchToolFileSearchRankingOptionsRanker = "default_2024_08_21" -) - -func (r FileSearchToolFileSearchRankingOptionsRanker) IsKnown() bool { - switch r { - case FileSearchToolFileSearchRankingOptionsRankerAuto, FileSearchToolFileSearchRankingOptionsRankerDefault2024_08_21: - return true - } - return false -} - +// The property Type is required. type FileSearchToolParam struct { - // The type of tool being defined: `file_search` - Type param.Field[FileSearchToolType] `json:"type,required"` // Overrides for the file search tool. - FileSearch param.Field[FileSearchToolFileSearchParam] `json:"file_search"` + FileSearch FileSearchToolFileSearchParam `json:"file_search,omitzero"` + // The type of tool being defined: `file_search` + // + // This field can be elided, and will marshal its zero value as "file_search". + Type constant.FileSearch `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FileSearchToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r FileSearchToolParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FileSearchToolParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r FileSearchToolParam) implementsAssistantToolUnionParam() {} - -func (r FileSearchToolParam) implementsBetaThreadNewAndRunParamsToolUnion() {} - // Overrides for the file search tool. type FileSearchToolFileSearchParam struct { // The maximum number of results the file search tool should output. The default is @@ -1996,18 +1650,23 @@ type FileSearchToolFileSearchParam struct { // See the // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. - MaxNumResults param.Field[int64] `json:"max_num_results"` + MaxNumResults param.Opt[int64] `json:"max_num_results,omitzero"` // The ranking options for the file search. If not specified, the file search tool // will use the `auto` ranker and a score_threshold of 0. // // See the // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. - RankingOptions param.Field[FileSearchToolFileSearchRankingOptionsParam] `json:"ranking_options"` + RankingOptions FileSearchToolFileSearchRankingOptionsParam `json:"ranking_options,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FileSearchToolFileSearchParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r FileSearchToolFileSearchParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FileSearchToolFileSearchParam + return param.MarshalObject(r, (*shadow)(&r)) } // The ranking options for the file search. If not specified, the file search tool @@ -2016,101 +1675,128 @@ func (r FileSearchToolFileSearchParam) MarshalJSON() (data []byte, err error) { // See the // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. +// +// The property ScoreThreshold is required. type FileSearchToolFileSearchRankingOptionsParam struct { // The score threshold for the file search. All values must be a floating point // number between 0 and 1. - ScoreThreshold param.Field[float64] `json:"score_threshold,required"` + ScoreThreshold float64 `json:"score_threshold,required"` // The ranker to use for the file search. If not specified will use the `auto` // ranker. - Ranker param.Field[FileSearchToolFileSearchRankingOptionsRanker] `json:"ranker"` + // + // Any of "auto", "default_2024_08_21". + Ranker string `json:"ranker,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FileSearchToolFileSearchRankingOptionsParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r FileSearchToolFileSearchRankingOptionsParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FileSearchToolFileSearchRankingOptionsParam + return param.MarshalObject(r, (*shadow)(&r)) +} + +func init() { + apijson.RegisterFieldValidator[FileSearchToolFileSearchRankingOptionsParam]( + "Ranker", false, "auto", "default_2024_08_21", + ) } type FunctionTool struct { Function shared.FunctionDefinition `json:"function,required"` // The type of tool being defined: `function` - Type FunctionToolType `json:"type,required"` - JSON functionToolJSON `json:"-"` -} - -// functionToolJSON contains the JSON metadata for the struct [FunctionTool] -type functionToolJSON struct { - Function apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FunctionTool) UnmarshalJSON(data []byte) (err error) { + Type constant.Function `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Function resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FunctionTool) RawJSON() string { return r.JSON.raw } +func (r *FunctionTool) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r functionToolJSON) RawJSON() string { - return r.raw -} - -func (r FunctionTool) implementsAssistantTool() {} - -// The type of tool being defined: `function` -type FunctionToolType string - -const ( - FunctionToolTypeFunction FunctionToolType = "function" -) - -func (r FunctionToolType) IsKnown() bool { - switch r { - case FunctionToolTypeFunction: - return true - } - return false +// ToParam converts this FunctionTool to a FunctionToolParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// FunctionToolParam.IsOverridden() +func (r FunctionTool) ToParam() FunctionToolParam { + return param.OverrideObj[FunctionToolParam](r.RawJSON()) } +// The properties Function, Type are required. type FunctionToolParam struct { - Function param.Field[shared.FunctionDefinitionParam] `json:"function,required"` + Function shared.FunctionDefinitionParam `json:"function,omitzero,required"` // The type of tool being defined: `function` - Type param.Field[FunctionToolType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "function". + Type constant.Function `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FunctionToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r FunctionToolParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FunctionToolParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r FunctionToolParam) implementsAssistantToolUnionParam() {} - -func (r FunctionToolParam) implementsBetaThreadNewAndRunParamsToolUnion() {} - type BetaAssistantNewParams struct { // ID of the model to use. You can use the // [List models](https://platform.openai.com/docs/api-reference/models/list) API to // see all of your available models, or see our // [Model overview](https://platform.openai.com/docs/models) for descriptions of // them. - Model param.Field[shared.ChatModel] `json:"model,required"` + Model shared.ChatModel `json:"model,omitzero,required"` // The description of the assistant. The maximum length is 512 characters. - Description param.Field[string] `json:"description"` + Description param.Opt[string] `json:"description,omitzero"` // The system instructions that the assistant uses. The maximum length is 256,000 // characters. - Instructions param.Field[string] `json:"instructions"` + Instructions param.Opt[string] `json:"instructions,omitzero"` + // The name of the assistant. The maximum length is 256 characters. + Name param.Opt[string] `json:"name,omitzero"` + // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will + // make the output more random, while lower values like 0.2 will make it more + // focused and deterministic. + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // An alternative to sampling with temperature, called nucleus sampling, where the + // model considers the results of the tokens with top_p probability mass. So 0.1 + // means only the tokens comprising the top 10% probability mass are considered. + // + // We generally recommend altering this or temperature but not both. + TopP param.Opt[float64] `json:"top_p,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` - // The name of the assistant. The maximum length is 256 characters. - Name param.Field[string] `json:"name"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // **o-series models only** // // Constrains effort on reasoning for // [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently // supported values are `low`, `medium`, and `high`. Reducing reasoning effort can // result in faster responses and fewer tokens used on reasoning in a response. - ReasoningEffort param.Field[shared.ReasoningEffort] `json:"reasoning_effort"` + // + // Any of "low", "medium", "high". + ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"` + // A set of resources that are used by the assistant's tools. The resources are + // specific to the type of tool. For example, the `code_interpreter` tool requires + // a list of file IDs, while the `file_search` tool requires a list of vector store + // IDs. + ToolResources AssistantToolResourcesParam `json:"tool_resources,omitzero"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -2131,235 +1817,68 @@ type BetaAssistantNewParams struct { // the message content may be partially cut off if `finish_reason="length"`, which // indicates the generation exceeded `max_tokens` or the conversation exceeded the // max context length. - ResponseFormat param.Field[AssistantResponseFormatOptionUnionParam] `json:"response_format"` - // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - // make the output more random, while lower values like 0.2 will make it more - // focused and deterministic. - Temperature param.Field[float64] `json:"temperature"` - // A set of resources that are used by the assistant's tools. The resources are - // specific to the type of tool. For example, the `code_interpreter` tool requires - // a list of file IDs, while the `file_search` tool requires a list of vector store - // IDs. - ToolResources param.Field[BetaAssistantNewParamsToolResources] `json:"tool_resources"` + ResponseFormat AssistantResponseFormatOptionUnionParam `json:"response_format,omitzero"` // A list of tool enabled on the assistant. There can be a maximum of 128 tools per // assistant. Tools can be of types `code_interpreter`, `file_search`, or // `function`. - Tools param.Field[[]AssistantToolUnionParam] `json:"tools"` - // An alternative to sampling with temperature, called nucleus sampling, where the - // model considers the results of the tokens with top_p probability mass. So 0.1 - // means only the tokens comprising the top 10% probability mass are considered. - // - // We generally recommend altering this or temperature but not both. - TopP param.Field[float64] `json:"top_p"` -} - -func (r BetaAssistantNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// A set of resources that are used by the assistant's tools. The resources are -// specific to the type of tool. For example, the `code_interpreter` tool requires -// a list of file IDs, while the `file_search` tool requires a list of vector store -// IDs. -type BetaAssistantNewParamsToolResources struct { - CodeInterpreter param.Field[BetaAssistantNewParamsToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaAssistantNewParamsToolResourcesFileSearch] `json:"file_search"` -} - -func (r BetaAssistantNewParamsToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -type BetaAssistantNewParamsToolResourcesCodeInterpreter struct { - // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made - // available to the `code_interpreter` tool. There can be a maximum of 20 files - // associated with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` -} - -func (r BetaAssistantNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -type BetaAssistantNewParamsToolResourcesFileSearch struct { - // The - // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) - // attached to this assistant. There can be a maximum of 1 vector store attached to - // the assistant. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` - // A helper to create a - // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) - // with file_ids and attach it to this assistant. There can be a maximum of 1 - // vector store attached to the assistant. - VectorStores param.Field[[]BetaAssistantNewParamsToolResourcesFileSearchVectorStore] `json:"vector_stores"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -type BetaAssistantNewParamsToolResourcesFileSearchVectorStore struct { - // The chunking strategy used to chunk the file(s). If not set, will use the `auto` - // strategy. - ChunkingStrategy param.Field[BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion] `json:"chunking_strategy"` - // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to - // add to the vector store. There can be a maximum of 10000 files in a vector - // store. - FileIDs param.Field[[]string] `json:"file_ids"` - // Set of 16 key-value pairs that can be attached to an object. This can be useful - // for storing additional information about the object in a structured format, and - // querying for objects via API or the dashboard. - // - // Keys are strings with a maximum length of 64 characters. Values are strings with - // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy struct { - // Always `auto`. - Type param.Field[BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType] `json:"type,required"` - Static param.Field[interface{}] `json:"static"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy) implementsBetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -// -// Satisfied by -// [BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto], -// [BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic], -// [BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy]. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion interface { - implementsBetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() -} - -// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of -// `800` and `chunk_overlap_tokens` of `400`. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto struct { - // Always `auto`. - Type param.Field[BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType] `json:"type,required"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto) implementsBetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// Always `auto`. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType string - -const ( - BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType = "auto" -) - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType) IsKnown() bool { - switch r { - case BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto: - return true - } - return false -} - -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic struct { - Static param.Field[BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic] `json:"static,required"` - // Always `static`. - Type param.Field[BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType] `json:"type,required"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic) implementsBetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic struct { - // The number of tokens that overlap between chunks. The default value is `400`. - // - // Note that the overlap must not exceed half of `max_chunk_size_tokens`. - ChunkOverlapTokens param.Field[int64] `json:"chunk_overlap_tokens,required"` - // The maximum number of tokens in each chunk. The default value is `800`. The - // minimum value is `100` and the maximum value is `4096`. - MaxChunkSizeTokens param.Field[int64] `json:"max_chunk_size_tokens,required"` -} - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// Always `static`. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType string - -const ( - BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType = "static" -) - -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType) IsKnown() bool { - switch r { - case BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic: - return true - } - return false + Tools []AssistantToolUnionParam `json:"tools,omitzero"` + paramObj } -// Always `auto`. -type BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType string - -const ( - BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType = "auto" - BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType = "static" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } -func (r BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType) IsKnown() bool { - switch r { - case BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto, BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic: - return true - } - return false +func (r BetaAssistantNewParams) MarshalJSON() (data []byte, err error) { + type shadow BetaAssistantNewParams + return param.MarshalObject(r, (*shadow)(&r)) } type BetaAssistantUpdateParams struct { // The description of the assistant. The maximum length is 512 characters. - Description param.Field[string] `json:"description"` + Description param.Opt[string] `json:"description,omitzero"` // The system instructions that the assistant uses. The maximum length is 256,000 // characters. - Instructions param.Field[string] `json:"instructions"` + Instructions param.Opt[string] `json:"instructions,omitzero"` + // The name of the assistant. The maximum length is 256 characters. + Name param.Opt[string] `json:"name,omitzero"` + // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will + // make the output more random, while lower values like 0.2 will make it more + // focused and deterministic. + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // An alternative to sampling with temperature, called nucleus sampling, where the + // model considers the results of the tokens with top_p probability mass. So 0.1 + // means only the tokens comprising the top 10% probability mass are considered. + // + // We generally recommend altering this or temperature but not both. + TopP param.Opt[float64] `json:"top_p,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` - // ID of the model to use. You can use the - // [List models](https://platform.openai.com/docs/api-reference/models/list) API to - // see all of your available models, or see our - // [Model overview](https://platform.openai.com/docs/models) for descriptions of - // them. - Model param.Field[BetaAssistantUpdateParamsModel] `json:"model"` - // The name of the assistant. The maximum length is 256 characters. - Name param.Field[string] `json:"name"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // **o-series models only** // // Constrains effort on reasoning for // [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently // supported values are `low`, `medium`, and `high`. Reducing reasoning effort can // result in faster responses and fewer tokens used on reasoning in a response. - ReasoningEffort param.Field[shared.ReasoningEffort] `json:"reasoning_effort"` + // + // Any of "low", "medium", "high". + ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"` + // A set of resources that are used by the assistant's tools. The resources are + // specific to the type of tool. For example, the `code_interpreter` tool requires + // a list of file IDs, while the `file_search` tool requires a list of vector store + // IDs. + ToolResources BetaAssistantUpdateParamsToolResources `json:"tool_resources,omitzero"` + // ID of the model to use. You can use the + // [List models](https://platform.openai.com/docs/api-reference/models/list) API to + // see all of your available models, or see our + // [Model overview](https://platform.openai.com/docs/models) for descriptions of + // them. + Model string `json:"model,omitzero"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -2380,78 +1899,21 @@ type BetaAssistantUpdateParams struct { // the message content may be partially cut off if `finish_reason="length"`, which // indicates the generation exceeded `max_tokens` or the conversation exceeded the // max context length. - ResponseFormat param.Field[AssistantResponseFormatOptionUnionParam] `json:"response_format"` - // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - // make the output more random, while lower values like 0.2 will make it more - // focused and deterministic. - Temperature param.Field[float64] `json:"temperature"` - // A set of resources that are used by the assistant's tools. The resources are - // specific to the type of tool. For example, the `code_interpreter` tool requires - // a list of file IDs, while the `file_search` tool requires a list of vector store - // IDs. - ToolResources param.Field[BetaAssistantUpdateParamsToolResources] `json:"tool_resources"` + ResponseFormat AssistantResponseFormatOptionUnionParam `json:"response_format,omitzero"` // A list of tool enabled on the assistant. There can be a maximum of 128 tools per // assistant. Tools can be of types `code_interpreter`, `file_search`, or // `function`. - Tools param.Field[[]AssistantToolUnionParam] `json:"tools"` - // An alternative to sampling with temperature, called nucleus sampling, where the - // model considers the results of the tokens with top_p probability mass. So 0.1 - // means only the tokens comprising the top 10% probability mass are considered. - // - // We generally recommend altering this or temperature but not both. - TopP param.Field[float64] `json:"top_p"` + Tools []AssistantToolUnionParam `json:"tools,omitzero"` + paramObj } -func (r BetaAssistantUpdateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// ID of the model to use. You can use the -// [List models](https://platform.openai.com/docs/api-reference/models/list) API to -// see all of your available models, or see our -// [Model overview](https://platform.openai.com/docs/models) for descriptions of -// them. -type BetaAssistantUpdateParamsModel string - -const ( - BetaAssistantUpdateParamsModelO3Mini BetaAssistantUpdateParamsModel = "o3-mini" - BetaAssistantUpdateParamsModelO3Mini2025_01_31 BetaAssistantUpdateParamsModel = "o3-mini-2025-01-31" - BetaAssistantUpdateParamsModelO1 BetaAssistantUpdateParamsModel = "o1" - BetaAssistantUpdateParamsModelO1_2024_12_17 BetaAssistantUpdateParamsModel = "o1-2024-12-17" - BetaAssistantUpdateParamsModelGPT4o BetaAssistantUpdateParamsModel = "gpt-4o" - BetaAssistantUpdateParamsModelGPT4o2024_11_20 BetaAssistantUpdateParamsModel = "gpt-4o-2024-11-20" - BetaAssistantUpdateParamsModelGPT4o2024_08_06 BetaAssistantUpdateParamsModel = "gpt-4o-2024-08-06" - BetaAssistantUpdateParamsModelGPT4o2024_05_13 BetaAssistantUpdateParamsModel = "gpt-4o-2024-05-13" - BetaAssistantUpdateParamsModelGPT4oMini BetaAssistantUpdateParamsModel = "gpt-4o-mini" - BetaAssistantUpdateParamsModelGPT4oMini2024_07_18 BetaAssistantUpdateParamsModel = "gpt-4o-mini-2024-07-18" - BetaAssistantUpdateParamsModelGPT4_5Preview BetaAssistantUpdateParamsModel = "gpt-4.5-preview" - BetaAssistantUpdateParamsModelGPT4_5Preview2025_02_27 BetaAssistantUpdateParamsModel = "gpt-4.5-preview-2025-02-27" - BetaAssistantUpdateParamsModelGPT4Turbo BetaAssistantUpdateParamsModel = "gpt-4-turbo" - BetaAssistantUpdateParamsModelGPT4Turbo2024_04_09 BetaAssistantUpdateParamsModel = "gpt-4-turbo-2024-04-09" - BetaAssistantUpdateParamsModelGPT4_0125Preview BetaAssistantUpdateParamsModel = "gpt-4-0125-preview" - BetaAssistantUpdateParamsModelGPT4TurboPreview BetaAssistantUpdateParamsModel = "gpt-4-turbo-preview" - BetaAssistantUpdateParamsModelGPT4_1106Preview BetaAssistantUpdateParamsModel = "gpt-4-1106-preview" - BetaAssistantUpdateParamsModelGPT4VisionPreview BetaAssistantUpdateParamsModel = "gpt-4-vision-preview" - BetaAssistantUpdateParamsModelGPT4 BetaAssistantUpdateParamsModel = "gpt-4" - BetaAssistantUpdateParamsModelGPT4_0314 BetaAssistantUpdateParamsModel = "gpt-4-0314" - BetaAssistantUpdateParamsModelGPT4_0613 BetaAssistantUpdateParamsModel = "gpt-4-0613" - BetaAssistantUpdateParamsModelGPT4_32k BetaAssistantUpdateParamsModel = "gpt-4-32k" - BetaAssistantUpdateParamsModelGPT4_32k0314 BetaAssistantUpdateParamsModel = "gpt-4-32k-0314" - BetaAssistantUpdateParamsModelGPT4_32k0613 BetaAssistantUpdateParamsModel = "gpt-4-32k-0613" - BetaAssistantUpdateParamsModelGPT3_5Turbo BetaAssistantUpdateParamsModel = "gpt-3.5-turbo" - BetaAssistantUpdateParamsModelGPT3_5Turbo16k BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-16k" - BetaAssistantUpdateParamsModelGPT3_5Turbo0613 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-0613" - BetaAssistantUpdateParamsModelGPT3_5Turbo1106 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-1106" - BetaAssistantUpdateParamsModelGPT3_5Turbo0125 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-0125" - BetaAssistantUpdateParamsModelGPT3_5Turbo16k0613 BetaAssistantUpdateParamsModel = "gpt-3.5-turbo-16k-0613" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } -func (r BetaAssistantUpdateParamsModel) IsKnown() bool { - switch r { - case BetaAssistantUpdateParamsModelO3Mini, BetaAssistantUpdateParamsModelO3Mini2025_01_31, BetaAssistantUpdateParamsModelO1, BetaAssistantUpdateParamsModelO1_2024_12_17, BetaAssistantUpdateParamsModelGPT4o, BetaAssistantUpdateParamsModelGPT4o2024_11_20, BetaAssistantUpdateParamsModelGPT4o2024_08_06, BetaAssistantUpdateParamsModelGPT4o2024_05_13, BetaAssistantUpdateParamsModelGPT4oMini, BetaAssistantUpdateParamsModelGPT4oMini2024_07_18, BetaAssistantUpdateParamsModelGPT4_5Preview, BetaAssistantUpdateParamsModelGPT4_5Preview2025_02_27, BetaAssistantUpdateParamsModelGPT4Turbo, BetaAssistantUpdateParamsModelGPT4Turbo2024_04_09, BetaAssistantUpdateParamsModelGPT4_0125Preview, BetaAssistantUpdateParamsModelGPT4TurboPreview, BetaAssistantUpdateParamsModelGPT4_1106Preview, BetaAssistantUpdateParamsModelGPT4VisionPreview, BetaAssistantUpdateParamsModelGPT4, BetaAssistantUpdateParamsModelGPT4_0314, BetaAssistantUpdateParamsModelGPT4_0613, BetaAssistantUpdateParamsModelGPT4_32k, BetaAssistantUpdateParamsModelGPT4_32k0314, BetaAssistantUpdateParamsModelGPT4_32k0613, BetaAssistantUpdateParamsModelGPT3_5Turbo, BetaAssistantUpdateParamsModelGPT3_5Turbo16k, BetaAssistantUpdateParamsModelGPT3_5Turbo0613, BetaAssistantUpdateParamsModelGPT3_5Turbo1106, BetaAssistantUpdateParamsModelGPT3_5Turbo0125, BetaAssistantUpdateParamsModelGPT3_5Turbo16k0613: - return true - } - return false +func (r BetaAssistantUpdateParams) MarshalJSON() (data []byte, err error) { + type shadow BetaAssistantUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) } // A set of resources that are used by the assistant's tools. The resources are @@ -2459,12 +1921,19 @@ func (r BetaAssistantUpdateParamsModel) IsKnown() bool { // a list of file IDs, while the `file_search` tool requires a list of vector store // IDs. type BetaAssistantUpdateParamsToolResources struct { - CodeInterpreter param.Field[BetaAssistantUpdateParamsToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaAssistantUpdateParamsToolResourcesFileSearch] `json:"file_search"` + CodeInterpreter BetaAssistantUpdateParamsToolResourcesCodeInterpreter `json:"code_interpreter,omitzero"` + FileSearch BetaAssistantUpdateParamsToolResourcesFileSearch `json:"file_search,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantUpdateParamsToolResources) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaAssistantUpdateParamsToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaAssistantUpdateParamsToolResources + return param.MarshalObject(r, (*shadow)(&r)) } type BetaAssistantUpdateParamsToolResourcesCodeInterpreter struct { @@ -2472,11 +1941,18 @@ type BetaAssistantUpdateParamsToolResourcesCodeInterpreter struct { // [file](https://platform.openai.com/docs/api-reference/files) IDs made available // to the `code_interpreter` tool. There can be a maximum of 20 files associated // with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` + FileIDs []string `json:"file_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantUpdateParamsToolResourcesCodeInterpreter) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaAssistantUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaAssistantUpdateParamsToolResourcesCodeInterpreter + return param.MarshalObject(r, (*shadow)(&r)) } type BetaAssistantUpdateParamsToolResourcesFileSearch struct { @@ -2484,11 +1960,18 @@ type BetaAssistantUpdateParamsToolResourcesFileSearch struct { // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this assistant. There can be a maximum of 1 vector store attached to // the assistant. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantUpdateParamsToolResourcesFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaAssistantUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaAssistantUpdateParamsToolResourcesFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } type BetaAssistantListParams struct { @@ -2496,20 +1979,27 @@ type BetaAssistantListParams struct { // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A cursor for use in pagination. `before` is an object ID that defines your place // in the list. For instance, if you make a list request and receive 100 objects, // starting with obj_foo, your subsequent call can include before=obj_foo in order // to fetch the previous page of the list. - Before param.Field[string] `query:"before"` + Before param.Opt[string] `query:"before,omitzero" json:"-"` // A limit on the number of objects to be returned. Limit can range between 1 and // 100, and the default is 20. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` // Sort order by the `created_at` timestamp of the objects. `asc` for ascending // order and `desc` for descending order. - Order param.Field[BetaAssistantListParamsOrder] `query:"order"` + // + // Any of "asc", "desc". + Order BetaAssistantListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaAssistantListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BetaAssistantListParams]'s query parameters as // `url.Values`. func (r BetaAssistantListParams) URLQuery() (v url.Values) { @@ -2527,11 +2017,3 @@ const ( BetaAssistantListParamsOrderAsc BetaAssistantListParamsOrder = "asc" BetaAssistantListParamsOrderDesc BetaAssistantListParamsOrder = "desc" ) - -func (r BetaAssistantListParamsOrder) IsKnown() bool { - switch r { - case BetaAssistantListParamsOrderAsc, BetaAssistantListParamsOrderDesc: - return true - } - return false -} diff --git a/betaassistant_test.go b/betaassistant_test.go index f8e9f8b4..f3e9b187 100644 --- a/betaassistant_test.go +++ b/betaassistant_test.go @@ -12,6 +12,7 @@ import ( "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" ) func TestBetaAssistantNewWithOptionalParams(t *testing.T) { @@ -27,37 +28,39 @@ func TestBetaAssistantNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Beta.Assistants.New(context.TODO(), openai.BetaAssistantNewParams{ - Model: openai.F(shared.ChatModelO3Mini), - Description: openai.F("description"), - Instructions: openai.F("instructions"), - Metadata: openai.F(shared.MetadataParam{ + Model: shared.ChatModelO3Mini, + Description: openai.String("description"), + Instructions: openai.String("instructions"), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Name: openai.F("name"), - ReasoningEffort: openai.F(shared.ReasoningEffortLow), - ResponseFormat: openai.F[openai.AssistantResponseFormatOptionUnionParam](openai.AssistantResponseFormatOptionString(openai.AssistantResponseFormatOptionStringAuto)), - Temperature: openai.F(1.000000), - ToolResources: openai.F(openai.BetaAssistantNewParamsToolResources{ - CodeInterpreter: openai.F(openai.BetaAssistantNewParamsToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaAssistantNewParamsToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - VectorStores: openai.F([]openai.BetaAssistantNewParamsToolResourcesFileSearchVectorStore{{ - ChunkingStrategy: openai.F[openai.BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion](openai.BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto{ - Type: openai.F(openai.BetaAssistantNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto), - }), - FileIDs: openai.F([]string{"string"}), - Metadata: openai.F(shared.MetadataParam{ + }, + Name: openai.String("name"), + ReasoningEffort: shared.ReasoningEffortLow, + ResponseFormat: openai.AssistantResponseFormatOptionUnionParam{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + Temperature: openai.Float(1), + ToolResources: openai.AssistantToolResourcesParam{ + CodeInterpreter: openai.AssistantToolResourcesCodeInterpreterParam{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.AssistantToolResourcesFileSearchParam{ + VectorStoreIDs: []string{"string"}, + VectorStores: []openai.AssistantToolResourcesFileSearchVectorStoreParam{{ + ChunkingStrategy: openai.AssisstantVectorStoreChunkingStrategyUnionParam{ + OfAuto: &openai.AssisstantVectorStoreChunkingStrategyAutoParam{}, + }, + FileIDs: []string{"string"}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - }), - }), - Tools: openai.F([]openai.AssistantToolUnionParam{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - TopP: openai.F(1.000000), + }, + }}, + }, + }, + Tools: []openai.AssistantToolUnionParam{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + TopP: openai.Float(1), }) if err != nil { var apierr *openai.Error @@ -106,28 +109,30 @@ func TestBetaAssistantUpdateWithOptionalParams(t *testing.T) { context.TODO(), "assistant_id", openai.BetaAssistantUpdateParams{ - Description: openai.F("description"), - Instructions: openai.F("instructions"), - Metadata: openai.F(shared.MetadataParam{ + Description: openai.String("description"), + Instructions: openai.String("instructions"), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Model: openai.F(openai.BetaAssistantUpdateParamsModelO3Mini), - Name: openai.F("name"), - ReasoningEffort: openai.F(shared.ReasoningEffortLow), - ResponseFormat: openai.F[openai.AssistantResponseFormatOptionUnionParam](openai.AssistantResponseFormatOptionString(openai.AssistantResponseFormatOptionStringAuto)), - Temperature: openai.F(1.000000), - ToolResources: openai.F(openai.BetaAssistantUpdateParamsToolResources{ - CodeInterpreter: openai.F(openai.BetaAssistantUpdateParamsToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaAssistantUpdateParamsToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - }), - }), - Tools: openai.F([]openai.AssistantToolUnionParam{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - TopP: openai.F(1.000000), + }, + Model: "o3-mini", + Name: openai.String("name"), + ReasoningEffort: shared.ReasoningEffortLow, + ResponseFormat: openai.AssistantResponseFormatOptionUnionParam{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + Temperature: openai.Float(1), + ToolResources: openai.BetaAssistantUpdateParamsToolResources{ + CodeInterpreter: openai.BetaAssistantUpdateParamsToolResourcesCodeInterpreter{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.BetaAssistantUpdateParamsToolResourcesFileSearch{ + VectorStoreIDs: []string{"string"}, + }, + }, + Tools: []openai.AssistantToolUnionParam{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + TopP: openai.Float(1), }, ) if err != nil { @@ -152,10 +157,10 @@ func TestBetaAssistantListWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Beta.Assistants.List(context.TODO(), openai.BetaAssistantListParams{ - After: openai.F("after"), - Before: openai.F("before"), - Limit: openai.F(int64(0)), - Order: openai.F(openai.BetaAssistantListParamsOrderAsc), + After: openai.String("after"), + Before: openai.String("before"), + Limit: openai.Int(0), + Order: openai.BetaAssistantListParamsOrderAsc, }) if err != nil { var apierr *openai.Error diff --git a/betathread.go b/betathread.go index ac631bc6..0d76a4e2 100644 --- a/betathread.go +++ b/betathread.go @@ -4,17 +4,20 @@ package openai import ( "context" + "encoding/json" "errors" "fmt" "net/http" "reflect" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/packages/ssestream" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" "github.com/tidwall/gjson" ) @@ -26,15 +29,15 @@ import ( // the [NewBetaThreadService] method instead. type BetaThreadService struct { Options []option.RequestOption - Runs *BetaThreadRunService - Messages *BetaThreadMessageService + Runs BetaThreadRunService + Messages BetaThreadMessageService } // NewBetaThreadService generates a new service that applies the given options to // each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewBetaThreadService(opts ...option.RequestOption) (r *BetaThreadService) { - r = &BetaThreadService{} +func NewBetaThreadService(opts ...option.RequestOption) (r BetaThreadService) { + r = BetaThreadService{} r.Options = opts r.Runs = NewBetaThreadRunService(opts...) r.Messages = NewBetaThreadMessageService(opts...) @@ -50,6 +53,15 @@ func (r *BetaThreadService) New(ctx context.Context, body BetaThreadNewParams, o return } +// Create a thread and run it in one request. Poll the API until the run is complete. +func (r *BetaThreadService) NewAndRunPoll(ctx context.Context, body BetaThreadNewAndRunParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) { + run, err := r.NewAndRun(ctx, body, opts...) + if err != nil { + return nil, err + } + return r.Runs.PollStatus(ctx, run.ThreadID, run.ID, pollIntervalMs, opts...) +} + // Retrieves a thread. func (r *BetaThreadService) Get(ctx context.Context, threadID string, opts ...option.RequestOption) (res *Thread, err error) { opts = append(r.Options[:], opts...) @@ -98,17 +110,8 @@ func (r *BetaThreadService) NewAndRun(ctx context.Context, body BetaThreadNewAnd return } -// Create a thread and run it in one request. Poll the API until the run is complete. -func (r *BetaThreadService) NewAndRunPoll(ctx context.Context, body BetaThreadNewAndRunParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) { - run, err := r.NewAndRun(ctx, body, opts...) - if err != nil { - return nil, err - } - return r.Runs.PollStatus(ctx, run.ThreadID, run.ID, pollIntervalMs, opts...) -} - // Create a thread and run it in one request. -func (r *BetaThreadService) NewAndRunStreaming(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEvent]) { +func (r *BetaThreadService) NewAndRunStreaming(ctx context.Context, body BetaThreadNewAndRunParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) { var ( raw *http.Response err error @@ -117,184 +120,298 @@ func (r *BetaThreadService) NewAndRunStreaming(ctx context.Context, body BetaThr opts = append([]option.RequestOption{option.WithHeader("OpenAI-Beta", "assistants=v2"), option.WithJSONSet("stream", true)}, opts...) path := "threads/runs" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...) - return ssestream.NewStream[AssistantStreamEvent](ssestream.NewDecoder(raw), err) + return ssestream.NewStream[AssistantStreamEventUnion](ssestream.NewDecoder(raw), err) } -// Specifies the format that the model must output. Compatible with -// [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), -// [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), -// and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. -// -// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured -// Outputs which ensures the model will match your supplied JSON schema. Learn more -// in the -// [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). -// -// Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the -// message the model generates is valid JSON. -// -// **Important:** when using JSON mode, you **must** also instruct the model to -// produce JSON yourself via a system or user message. Without this, the model may -// generate an unending stream of whitespace until the generation reaches the token -// limit, resulting in a long-running and seemingly "stuck" request. Also note that -// the message content may be partially cut off if `finish_reason="length"`, which -// indicates the generation exceeded `max_tokens` or the conversation exceeded the -// max context length. +func AssisstantVectorStoreChunkingStrategyParamOfStatic(static AssisstantVectorStoreChunkingStrategyStaticStaticParam) AssisstantVectorStoreChunkingStrategyUnionParam { + var variant AssisstantVectorStoreChunkingStrategyStaticParam + variant.Static = static + return AssisstantVectorStoreChunkingStrategyUnionParam{OfStatic: &variant} +} + +// Only one field can be non-zero. // -// Union satisfied by [AssistantResponseFormatOptionString], -// [shared.ResponseFormatText], [shared.ResponseFormatJSONObject] or -// [shared.ResponseFormatJSONSchema]. -type AssistantResponseFormatOptionUnion interface { - ImplementsAssistantResponseFormatOptionUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type AssisstantVectorStoreChunkingStrategyUnionParam struct { + OfAuto *AssisstantVectorStoreChunkingStrategyAutoParam `json:",omitzero,inline"` + OfStatic *AssisstantVectorStoreChunkingStrategyStaticParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u AssisstantVectorStoreChunkingStrategyUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u AssisstantVectorStoreChunkingStrategyUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[AssisstantVectorStoreChunkingStrategyUnionParam](u.OfAuto, u.OfStatic) +} + +func (u *AssisstantVectorStoreChunkingStrategyUnionParam) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return u.OfAuto + } else if !param.IsOmitted(u.OfStatic) { + return u.OfStatic + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u AssisstantVectorStoreChunkingStrategyUnionParam) GetStatic() *AssisstantVectorStoreChunkingStrategyStaticStaticParam { + if vt := u.OfStatic; vt != nil { + return &vt.Static + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u AssisstantVectorStoreChunkingStrategyUnionParam) GetType() *string { + if vt := u.OfAuto; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfStatic; vt != nil { + return (*string)(&vt.Type) + } + return nil } func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AssistantResponseFormatOptionUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(AssistantResponseFormatOptionString("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(shared.ResponseFormatText{}), - }, + apijson.RegisterUnion[AssisstantVectorStoreChunkingStrategyUnionParam]( + "type", apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(shared.ResponseFormatJSONObject{}), + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(AssisstantVectorStoreChunkingStrategyAutoParam{}), + DiscriminatorValue: "auto", }, apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(shared.ResponseFormatJSONSchema{}), + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(AssisstantVectorStoreChunkingStrategyStaticParam{}), + DiscriminatorValue: "static", }, ) } -// `auto` is the default value -type AssistantResponseFormatOptionString string +// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of +// `800` and `chunk_overlap_tokens` of `400`. +// +// The property Type is required. +type AssisstantVectorStoreChunkingStrategyAutoParam struct { + // Always `auto`. + // + // This field can be elided, and will marshal its zero value as "auto". + Type constant.Auto `json:"type,required"` + paramObj +} -const ( - AssistantResponseFormatOptionStringAuto AssistantResponseFormatOptionString = "auto" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssisstantVectorStoreChunkingStrategyAutoParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssisstantVectorStoreChunkingStrategyAutoParam) MarshalJSON() (data []byte, err error) { + type shadow AssisstantVectorStoreChunkingStrategyAutoParam + return param.MarshalObject(r, (*shadow)(&r)) +} -func (r AssistantResponseFormatOptionString) IsKnown() bool { - switch r { - case AssistantResponseFormatOptionStringAuto: - return true - } - return false +// The properties Static, Type are required. +type AssisstantVectorStoreChunkingStrategyStaticParam struct { + Static AssisstantVectorStoreChunkingStrategyStaticStaticParam `json:"static,omitzero,required"` + // Always `static`. + // + // This field can be elided, and will marshal its zero value as "static". + Type constant.Static `json:"type,required"` + paramObj } -func (r AssistantResponseFormatOptionString) ImplementsAssistantResponseFormatOptionUnion() {} +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssisstantVectorStoreChunkingStrategyStaticParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssisstantVectorStoreChunkingStrategyStaticParam) MarshalJSON() (data []byte, err error) { + type shadow AssisstantVectorStoreChunkingStrategyStaticParam + return param.MarshalObject(r, (*shadow)(&r)) +} + +// The properties ChunkOverlapTokens, MaxChunkSizeTokens are required. +type AssisstantVectorStoreChunkingStrategyStaticStaticParam struct { + // The number of tokens that overlap between chunks. The default value is `400`. + // + // Note that the overlap must not exceed half of `max_chunk_size_tokens`. + ChunkOverlapTokens int64 `json:"chunk_overlap_tokens,required"` + // The maximum number of tokens in each chunk. The default value is `800`. The + // minimum value is `100` and the maximum value is `4096`. + MaxChunkSizeTokens int64 `json:"max_chunk_size_tokens,required"` + paramObj +} -func (r AssistantResponseFormatOptionString) ImplementsAssistantResponseFormatOptionUnionParam() {} +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssisstantVectorStoreChunkingStrategyStaticStaticParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssisstantVectorStoreChunkingStrategyStaticStaticParam) MarshalJSON() (data []byte, err error) { + type shadow AssisstantVectorStoreChunkingStrategyStaticStaticParam + return param.MarshalObject(r, (*shadow)(&r)) +} -// Specifies the format that the model must output. Compatible with -// [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), -// [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), -// and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. -// -// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured -// Outputs which ensures the model will match your supplied JSON schema. Learn more -// in the -// [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). +// AssistantResponseFormatOptionUnion contains all possible properties and values +// from [constant.Auto], [shared.ResponseFormatText], +// [shared.ResponseFormatJSONObject], [shared.ResponseFormatJSONSchema]. // -// Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the -// message the model generates is valid JSON. +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// **Important:** when using JSON mode, you **must** also instruct the model to -// produce JSON yourself via a system or user message. Without this, the model may -// generate an unending stream of whitespace until the generation reaches the token -// limit, resulting in a long-running and seemingly "stuck" request. Also note that -// the message content may be partially cut off if `finish_reason="length"`, which -// indicates the generation exceeded `max_tokens` or the conversation exceeded the -// max context length. -type AssistantResponseFormatOptionParam struct { - // The type of response format being defined. Always `text`. - Type param.Field[AssistantResponseFormatOptionType] `json:"type,required"` - JSONSchema param.Field[interface{}] `json:"json_schema"` +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto] +type AssistantResponseFormatOptionUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + Type string `json:"type"` + // This field is from variant [shared.ResponseFormatJSONSchema]. + JSONSchema shared.ResponseFormatJSONSchemaJSONSchema `json:"json_schema"` + JSON struct { + OfAuto resp.Field + Type resp.Field + JSONSchema resp.Field + raw string + } `json:"-"` +} + +func (u AssistantResponseFormatOptionUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantResponseFormatOptionParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +func (u AssistantResponseFormatOptionUnion) AsText() (v shared.ResponseFormatText) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r AssistantResponseFormatOptionParam) ImplementsAssistantResponseFormatOptionUnionParam() {} +func (u AssistantResponseFormatOptionUnion) AsJSONObject() (v shared.ResponseFormatJSONObject) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -// Specifies the format that the model must output. Compatible with -// [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), -// [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), -// and all GPT-3.5 Turbo models since `gpt-3.5-turbo-1106`. -// -// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured -// Outputs which ensures the model will match your supplied JSON schema. Learn more -// in the -// [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). -// -// Setting to `{ "type": "json_object" }` enables JSON mode, which ensures the -// message the model generates is valid JSON. -// -// **Important:** when using JSON mode, you **must** also instruct the model to -// produce JSON yourself via a system or user message. Without this, the model may -// generate an unending stream of whitespace until the generation reaches the token -// limit, resulting in a long-running and seemingly "stuck" request. Also note that -// the message content may be partially cut off if `finish_reason="length"`, which -// indicates the generation exceeded `max_tokens` or the conversation exceeded the -// max context length. +func (u AssistantResponseFormatOptionUnion) AsJSONSchema() (v shared.ResponseFormatJSONSchema) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u AssistantResponseFormatOptionUnion) RawJSON() string { return u.JSON.raw } + +func (r *AssistantResponseFormatOptionUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// ToParam converts this AssistantResponseFormatOptionUnion to a +// AssistantResponseFormatOptionUnionParam. // -// Satisfied by [AssistantResponseFormatOptionString], -// [shared.ResponseFormatTextParam], [shared.ResponseFormatJSONObjectParam], -// [shared.ResponseFormatJSONSchemaParam], [AssistantResponseFormatOptionParam]. -type AssistantResponseFormatOptionUnionParam interface { - ImplementsAssistantResponseFormatOptionUnionParam() +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// AssistantResponseFormatOptionUnionParam.IsOverridden() +func (r AssistantResponseFormatOptionUnion) ToParam() AssistantResponseFormatOptionUnionParam { + return param.OverrideObj[AssistantResponseFormatOptionUnionParam](r.RawJSON()) } -// The type of response format being defined. Always `text`. -type AssistantResponseFormatOptionType string +func AssistantResponseFormatOptionParamOfAuto() AssistantResponseFormatOptionUnionParam { + return AssistantResponseFormatOptionUnionParam{OfAuto: constant.ValueOf[constant.Auto]()} +} -const ( - AssistantResponseFormatOptionTypeText AssistantResponseFormatOptionType = "text" - AssistantResponseFormatOptionTypeJSONObject AssistantResponseFormatOptionType = "json_object" - AssistantResponseFormatOptionTypeJSONSchema AssistantResponseFormatOptionType = "json_schema" -) +func AssistantResponseFormatOptionParamOfJSONSchema(jsonSchema shared.ResponseFormatJSONSchemaJSONSchemaParam) AssistantResponseFormatOptionUnionParam { + var variant shared.ResponseFormatJSONSchemaParam + variant.JSONSchema = jsonSchema + return AssistantResponseFormatOptionUnionParam{OfJSONSchema: &variant} +} + +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type AssistantResponseFormatOptionUnionParam struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfText *shared.ResponseFormatTextParam `json:",omitzero,inline"` + OfJSONObject *shared.ResponseFormatJSONObjectParam `json:",omitzero,inline"` + OfJSONSchema *shared.ResponseFormatJSONSchemaParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u AssistantResponseFormatOptionUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u AssistantResponseFormatOptionUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[AssistantResponseFormatOptionUnionParam](u.OfAuto, u.OfText, u.OfJSONObject, u.OfJSONSchema) +} + +func (u *AssistantResponseFormatOptionUnionParam) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfText) { + return u.OfText + } else if !param.IsOmitted(u.OfJSONObject) { + return u.OfJSONObject + } else if !param.IsOmitted(u.OfJSONSchema) { + return u.OfJSONSchema + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantResponseFormatOptionUnionParam) GetJSONSchema() *shared.ResponseFormatJSONSchemaJSONSchemaParam { + if vt := u.OfJSONSchema; vt != nil { + return &vt.JSONSchema + } + return nil +} -func (r AssistantResponseFormatOptionType) IsKnown() bool { - switch r { - case AssistantResponseFormatOptionTypeText, AssistantResponseFormatOptionTypeJSONObject, AssistantResponseFormatOptionTypeJSONSchema: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantResponseFormatOptionUnionParam) GetType() *string { + if vt := u.OfText; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfJSONObject; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfJSONSchema; vt != nil { + return (*string)(&vt.Type) } - return false + return nil } // Specifies a tool the model should use. Use to force the model to call a specific // tool. type AssistantToolChoice struct { // The type of the tool. If type is `function`, the function name must be set + // + // Any of "function", "code_interpreter", "file_search". Type AssistantToolChoiceType `json:"type,required"` Function AssistantToolChoiceFunction `json:"function"` - JSON assistantToolChoiceJSON `json:"-"` -} - -// assistantToolChoiceJSON contains the JSON metadata for the struct -// [AssistantToolChoice] -type assistantToolChoiceJSON struct { - Type apijson.Field - Function apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantToolChoice) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + Function resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantToolChoice) RawJSON() string { return r.JSON.raw } +func (r *AssistantToolChoice) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantToolChoiceJSON) RawJSON() string { - return r.raw +// ToParam converts this AssistantToolChoice to a AssistantToolChoiceParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// AssistantToolChoiceParam.IsOverridden() +func (r AssistantToolChoice) ToParam() AssistantToolChoiceParam { + return param.OverrideObj[AssistantToolChoiceParam](r.RawJSON()) } -func (r AssistantToolChoice) implementsAssistantToolChoiceOptionUnion() {} - // The type of the tool. If type is `function`, the function name must be set type AssistantToolChoiceType string @@ -304,122 +421,255 @@ const ( AssistantToolChoiceTypeFileSearch AssistantToolChoiceType = "file_search" ) -func (r AssistantToolChoiceType) IsKnown() bool { - switch r { - case AssistantToolChoiceTypeFunction, AssistantToolChoiceTypeCodeInterpreter, AssistantToolChoiceTypeFileSearch: - return true - } - return false -} - // Specifies a tool the model should use. Use to force the model to call a specific // tool. +// +// The property Type is required. type AssistantToolChoiceParam struct { // The type of the tool. If type is `function`, the function name must be set - Type param.Field[AssistantToolChoiceType] `json:"type,required"` - Function param.Field[AssistantToolChoiceFunctionParam] `json:"function"` + // + // Any of "function", "code_interpreter", "file_search". + Type AssistantToolChoiceType `json:"type,omitzero,required"` + Function AssistantToolChoiceFunctionParam `json:"function,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolChoiceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r AssistantToolChoiceParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow AssistantToolChoiceParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r AssistantToolChoiceParam) implementsAssistantToolChoiceOptionUnionParam() {} - type AssistantToolChoiceFunction struct { // The name of the function to call. - Name string `json:"name,required"` - JSON assistantToolChoiceFunctionJSON `json:"-"` -} - -// assistantToolChoiceFunctionJSON contains the JSON metadata for the struct -// [AssistantToolChoiceFunction] -type assistantToolChoiceFunctionJSON struct { - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *AssistantToolChoiceFunction) UnmarshalJSON(data []byte) (err error) { + Name string `json:"name,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AssistantToolChoiceFunction) RawJSON() string { return r.JSON.raw } +func (r *AssistantToolChoiceFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r assistantToolChoiceFunctionJSON) RawJSON() string { - return r.raw +// ToParam converts this AssistantToolChoiceFunction to a +// AssistantToolChoiceFunctionParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// AssistantToolChoiceFunctionParam.IsOverridden() +func (r AssistantToolChoiceFunction) ToParam() AssistantToolChoiceFunctionParam { + return param.OverrideObj[AssistantToolChoiceFunctionParam](r.RawJSON()) } +// The property Name is required. type AssistantToolChoiceFunctionParam struct { // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolChoiceFunctionParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r AssistantToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow AssistantToolChoiceFunctionParam + return param.MarshalObject(r, (*shadow)(&r)) } -// Controls which (if any) tool is called by the model. `none` means the model will -// not call any tools and instead generates a message. `auto` is the default value -// and means the model can pick between generating a message or calling one or more -// tools. `required` means the model must call one or more tools before responding -// to the user. Specifying a particular tool like `{"type": "file_search"}` or -// `{"type": "function", "function": {"name": "my_function"}}` forces the model to -// call that tool. +// AssistantToolChoiceOptionUnion contains all possible properties and values from +// [string], [AssistantToolChoice]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [AssistantToolChoiceOptionAuto] or [AssistantToolChoice]. -type AssistantToolChoiceOptionUnion interface { - implementsAssistantToolChoiceOptionUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto] +type AssistantToolChoiceOptionUnion struct { + // This field will be present if the value is a [string] instead of an object. + OfAuto string `json:",inline"` + // This field is from variant [AssistantToolChoice]. + Type AssistantToolChoiceType `json:"type"` + // This field is from variant [AssistantToolChoice]. + Function AssistantToolChoiceFunction `json:"function"` + JSON struct { + OfAuto resp.Field + Type resp.Field + Function resp.Field + raw string + } `json:"-"` } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AssistantToolChoiceOptionUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(AssistantToolChoiceOptionAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(AssistantToolChoice{}), - }, - ) +func (u AssistantToolChoiceOptionUnion) AsAuto() (v string) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// `none` means the model will not call any tools and instead generates a message. -// `auto` means the model can pick between generating a message or calling one or -// more tools. `required` means the model must call one or more tools before -// responding to the user. -type AssistantToolChoiceOptionAuto string +func (u AssistantToolChoiceOptionUnion) AsAssistantToolChoice() (v AssistantToolChoice) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - AssistantToolChoiceOptionAutoNone AssistantToolChoiceOptionAuto = "none" - AssistantToolChoiceOptionAutoAuto AssistantToolChoiceOptionAuto = "auto" - AssistantToolChoiceOptionAutoRequired AssistantToolChoiceOptionAuto = "required" -) +// Returns the unmodified JSON received from the API +func (u AssistantToolChoiceOptionUnion) RawJSON() string { return u.JSON.raw } -func (r AssistantToolChoiceOptionAuto) IsKnown() bool { - switch r { - case AssistantToolChoiceOptionAutoNone, AssistantToolChoiceOptionAutoAuto, AssistantToolChoiceOptionAutoRequired: - return true - } - return false +func (r *AssistantToolChoiceOptionUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r AssistantToolChoiceOptionAuto) implementsAssistantToolChoiceOptionUnion() {} +// ToParam converts this AssistantToolChoiceOptionUnion to a +// AssistantToolChoiceOptionUnionParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// AssistantToolChoiceOptionUnionParam.IsOverridden() +func (r AssistantToolChoiceOptionUnion) ToParam() AssistantToolChoiceOptionUnionParam { + return param.OverrideObj[AssistantToolChoiceOptionUnionParam](r.RawJSON()) +} -func (r AssistantToolChoiceOptionAuto) implementsAssistantToolChoiceOptionUnionParam() {} +func AssistantToolChoiceOptionParamOfAssistantToolChoice(type_ AssistantToolChoiceType) AssistantToolChoiceOptionUnionParam { + var variant AssistantToolChoiceParam + variant.Type = type_ + return AssistantToolChoiceOptionUnionParam{OfAssistantToolChoice: &variant} +} -// Controls which (if any) tool is called by the model. `none` means the model will -// not call any tools and instead generates a message. `auto` is the default value -// and means the model can pick between generating a message or calling one or more -// tools. `required` means the model must call one or more tools before responding -// to the user. Specifying a particular tool like `{"type": "file_search"}` or -// `{"type": "function", "function": {"name": "my_function"}}` forces the model to -// call that tool. +// Only one field can be non-zero. // -// Satisfied by [AssistantToolChoiceOptionAuto], [AssistantToolChoiceParam]. -type AssistantToolChoiceOptionUnionParam interface { - implementsAssistantToolChoiceOptionUnionParam() +// Use [param.IsOmitted] to confirm if a field is set. +type AssistantToolChoiceOptionUnionParam struct { + // Check if union is this variant with !param.IsOmitted(union.OfAuto) + OfAuto param.Opt[string] `json:",omitzero,inline"` + OfAssistantToolChoice *AssistantToolChoiceParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u AssistantToolChoiceOptionUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u AssistantToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[AssistantToolChoiceOptionUnionParam](u.OfAuto, u.OfAssistantToolChoice) +} + +func (u *AssistantToolChoiceOptionUnionParam) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfAssistantToolChoice) { + return u.OfAssistantToolChoice + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantToolChoiceOptionUnionParam) GetType() *string { + if vt := u.OfAssistantToolChoice; vt != nil { + return (*string)(&vt.Type) + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u AssistantToolChoiceOptionUnionParam) GetFunction() *AssistantToolChoiceFunctionParam { + if vt := u.OfAssistantToolChoice; vt != nil { + return &vt.Function + } + return nil +} + +// A set of resources that are used by the assistant's tools. The resources are +// specific to the type of tool. For example, the `code_interpreter` tool requires +// a list of file IDs, while the `file_search` tool requires a list of vector store +// IDs. +type AssistantToolResourcesParam struct { + CodeInterpreter AssistantToolResourcesCodeInterpreterParam `json:"code_interpreter,omitzero"` + FileSearch AssistantToolResourcesFileSearchParam `json:"file_search,omitzero"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolResourcesParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } +func (r AssistantToolResourcesParam) MarshalJSON() (data []byte, err error) { + type shadow AssistantToolResourcesParam + return param.MarshalObject(r, (*shadow)(&r)) +} + +type AssistantToolResourcesCodeInterpreterParam struct { + // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made + // available to the `code_interpreter` tool. There can be a maximum of 20 files + // associated with the tool. + FileIDs []string `json:"file_ids,omitzero"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolResourcesCodeInterpreterParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssistantToolResourcesCodeInterpreterParam) MarshalJSON() (data []byte, err error) { + type shadow AssistantToolResourcesCodeInterpreterParam + return param.MarshalObject(r, (*shadow)(&r)) +} + +type AssistantToolResourcesFileSearchParam struct { + // The + // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + // attached to this assistant. There can be a maximum of 1 vector store attached to + // the assistant. + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` + // A helper to create a + // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) + // with file_ids and attach it to this assistant. There can be a maximum of 1 + // vector store attached to the assistant. + VectorStores []AssistantToolResourcesFileSearchVectorStoreParam `json:"vector_stores,omitzero"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolResourcesFileSearchParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssistantToolResourcesFileSearchParam) MarshalJSON() (data []byte, err error) { + type shadow AssistantToolResourcesFileSearchParam + return param.MarshalObject(r, (*shadow)(&r)) +} + +type AssistantToolResourcesFileSearchVectorStoreParam struct { + // Set of 16 key-value pairs that can be attached to an object. This can be useful + // for storing additional information about the object in a structured format, and + // querying for objects via API or the dashboard. + // + // Keys are strings with a maximum length of 64 characters. Values are strings with + // a maximum length of 512 characters. + Metadata shared.MetadataParam `json:"metadata,omitzero"` + // The chunking strategy used to chunk the file(s). If not set, will use the `auto` + // strategy. + ChunkingStrategy AssisstantVectorStoreChunkingStrategyUnionParam `json:"chunking_strategy,omitzero"` + // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + // add to the vector store. There can be a maximum of 10000 files in a vector + // store. + FileIDs []string `json:"file_ids,omitzero"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f AssistantToolResourcesFileSearchVectorStoreParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r AssistantToolResourcesFileSearchVectorStoreParam) MarshalJSON() (data []byte, err error) { + type shadow AssistantToolResourcesFileSearchVectorStoreParam + return param.MarshalObject(r, (*shadow)(&r)) } // Represents a thread that contains @@ -435,51 +685,33 @@ type Thread struct { // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata shared.Metadata `json:"metadata,required,nullable"` + Metadata shared.Metadata `json:"metadata,required"` // The object type, which is always `thread`. - Object ThreadObject `json:"object,required"` + Object constant.Thread `json:"object,required"` // A set of resources that are made available to the assistant's tools in this // thread. The resources are specific to the type of tool. For example, the // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. - ToolResources ThreadToolResources `json:"tool_resources,required,nullable"` - JSON threadJSON `json:"-"` -} - -// threadJSON contains the JSON metadata for the struct [Thread] -type threadJSON struct { - ID apijson.Field - CreatedAt apijson.Field - Metadata apijson.Field - Object apijson.Field - ToolResources apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Thread) UnmarshalJSON(data []byte) (err error) { + ToolResources ThreadToolResources `json:"tool_resources,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CreatedAt resp.Field + Metadata resp.Field + Object resp.Field + ToolResources resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Thread) RawJSON() string { return r.JSON.raw } +func (r *Thread) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r threadJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `thread`. -type ThreadObject string - -const ( - ThreadObjectThread ThreadObject = "thread" -) - -func (r ThreadObject) IsKnown() bool { - switch r { - case ThreadObjectThread: - return true - } - return false -} - // A set of resources that are made available to the assistant's tools in this // thread. The resources are specific to the type of tool. For example, the // `code_interpreter` tool requires a list of file IDs, while the `file_search` @@ -487,265 +719,266 @@ func (r ThreadObject) IsKnown() bool { type ThreadToolResources struct { CodeInterpreter ThreadToolResourcesCodeInterpreter `json:"code_interpreter"` FileSearch ThreadToolResourcesFileSearch `json:"file_search"` - JSON threadToolResourcesJSON `json:"-"` -} - -// threadToolResourcesJSON contains the JSON metadata for the struct -// [ThreadToolResources] -type threadToolResourcesJSON struct { - CodeInterpreter apijson.Field - FileSearch apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ThreadToolResources) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + CodeInterpreter resp.Field + FileSearch resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ThreadToolResources) RawJSON() string { return r.JSON.raw } +func (r *ThreadToolResources) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r threadToolResourcesJSON) RawJSON() string { - return r.raw -} - type ThreadToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter` tool. There can be a maximum of 20 files // associated with the tool. - FileIDs []string `json:"file_ids"` - JSON threadToolResourcesCodeInterpreterJSON `json:"-"` -} - -// threadToolResourcesCodeInterpreterJSON contains the JSON metadata for the struct -// [ThreadToolResourcesCodeInterpreter] -type threadToolResourcesCodeInterpreterJSON struct { - FileIDs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ThreadToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) (err error) { + FileIDs []string `json:"file_ids"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileIDs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ThreadToolResourcesCodeInterpreter) RawJSON() string { return r.JSON.raw } +func (r *ThreadToolResourcesCodeInterpreter) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r threadToolResourcesCodeInterpreterJSON) RawJSON() string { - return r.raw -} - type ThreadToolResourcesFileSearch struct { // The // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this thread. There can be a maximum of 1 vector store attached to // the thread. - VectorStoreIDs []string `json:"vector_store_ids"` - JSON threadToolResourcesFileSearchJSON `json:"-"` -} - -// threadToolResourcesFileSearchJSON contains the JSON metadata for the struct -// [ThreadToolResourcesFileSearch] -type threadToolResourcesFileSearchJSON struct { - VectorStoreIDs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ThreadToolResourcesFileSearch) UnmarshalJSON(data []byte) (err error) { + VectorStoreIDs []string `json:"vector_store_ids"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + VectorStoreIDs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ThreadToolResourcesFileSearch) RawJSON() string { return r.JSON.raw } +func (r *ThreadToolResourcesFileSearch) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r threadToolResourcesFileSearchJSON) RawJSON() string { - return r.raw -} - type ThreadDeleted struct { - ID string `json:"id,required"` - Deleted bool `json:"deleted,required"` - Object ThreadDeletedObject `json:"object,required"` - JSON threadDeletedJSON `json:"-"` -} - -// threadDeletedJSON contains the JSON metadata for the struct [ThreadDeleted] -type threadDeletedJSON struct { - ID apijson.Field - Deleted apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ThreadDeleted) UnmarshalJSON(data []byte) (err error) { + ID string `json:"id,required"` + Deleted bool `json:"deleted,required"` + Object constant.ThreadDeleted `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Deleted resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ThreadDeleted) RawJSON() string { return r.JSON.raw } +func (r *ThreadDeleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r threadDeletedJSON) RawJSON() string { - return r.raw -} - -type ThreadDeletedObject string - -const ( - ThreadDeletedObjectThreadDeleted ThreadDeletedObject = "thread.deleted" -) - -func (r ThreadDeletedObject) IsKnown() bool { - switch r { - case ThreadDeletedObjectThreadDeleted: - return true - } - return false -} - type BetaThreadNewParams struct { - // A list of [messages](https://platform.openai.com/docs/api-reference/messages) to - // start the thread with. - Messages param.Field[[]BetaThreadNewParamsMessage] `json:"messages"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // A set of resources that are made available to the assistant's tools in this // thread. The resources are specific to the type of tool. For example, the // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. - ToolResources param.Field[BetaThreadNewParamsToolResources] `json:"tool_resources"` + ToolResources BetaThreadNewParamsToolResources `json:"tool_resources,omitzero"` + // A list of [messages](https://platform.openai.com/docs/api-reference/messages) to + // start the thread with. + Messages []BetaThreadNewParamsMessage `json:"messages,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewParams + return param.MarshalObject(r, (*shadow)(&r)) } +// The properties Content, Role are required. type BetaThreadNewParamsMessage struct { // The text contents of the message. - Content param.Field[BetaThreadNewParamsMessagesContentUnion] `json:"content,required"` + Content BetaThreadNewParamsMessageContentUnion `json:"content,omitzero,required"` // The role of the entity that is creating the message. Allowed values include: // // - `user`: Indicates the message is sent by an actual user and should be used in // most cases to represent user-generated messages. // - `assistant`: Indicates the message is generated by the assistant. Use this // value to insert messages from the assistant into the conversation. - Role param.Field[BetaThreadNewParamsMessagesRole] `json:"role,required"` + // + // Any of "user", "assistant". + Role string `json:"role,omitzero,required"` // A list of files attached to the message, and the tools they should be added to. - Attachments param.Field[[]BetaThreadNewParamsMessagesAttachment] `json:"attachments"` + Attachments []BetaThreadNewParamsMessageAttachment `json:"attachments,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsMessage) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r BetaThreadNewParamsMessage) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// The text contents of the message. -// -// Satisfied by [shared.UnionString], -// [BetaThreadNewParamsMessagesContentArrayOfContentParts]. -type BetaThreadNewParamsMessagesContentUnion interface { - ImplementsBetaThreadNewParamsMessagesContentUnion() + type shadow BetaThreadNewParamsMessage + return param.MarshalObject(r, (*shadow)(&r)) } -type BetaThreadNewParamsMessagesContentArrayOfContentParts []MessageContentPartParamUnion - -func (r BetaThreadNewParamsMessagesContentArrayOfContentParts) ImplementsBetaThreadNewParamsMessagesContentUnion() { +func init() { + apijson.RegisterFieldValidator[BetaThreadNewParamsMessage]( + "Role", false, "user", "assistant", + ) } -// The role of the entity that is creating the message. Allowed values include: +// Only one field can be non-zero. // -// - `user`: Indicates the message is sent by an actual user and should be used in -// most cases to represent user-generated messages. -// - `assistant`: Indicates the message is generated by the assistant. Use this -// value to insert messages from the assistant into the conversation. -type BetaThreadNewParamsMessagesRole string +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadNewParamsMessageContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []MessageContentPartParamUnion `json:",omitzero,inline"` + paramUnion +} -const ( - BetaThreadNewParamsMessagesRoleUser BetaThreadNewParamsMessagesRole = "user" - BetaThreadNewParamsMessagesRoleAssistant BetaThreadNewParamsMessagesRole = "assistant" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadNewParamsMessageContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u BetaThreadNewParamsMessageContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadNewParamsMessageContentUnion](u.OfString, u.OfArrayOfContentParts) +} -func (r BetaThreadNewParamsMessagesRole) IsKnown() bool { - switch r { - case BetaThreadNewParamsMessagesRoleUser, BetaThreadNewParamsMessagesRoleAssistant: - return true +func (u *BetaThreadNewParamsMessageContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } -type BetaThreadNewParamsMessagesAttachment struct { +type BetaThreadNewParamsMessageAttachment struct { // The ID of the file to attach to the message. - FileID param.Field[string] `json:"file_id"` + FileID param.Opt[string] `json:"file_id,omitzero"` // The tools to add this file to. - Tools param.Field[[]BetaThreadNewParamsMessagesAttachmentsToolUnion] `json:"tools"` + Tools []BetaThreadNewParamsMessageAttachmentToolUnion `json:"tools,omitzero"` + paramObj } -func (r BetaThreadNewParamsMessagesAttachment) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsMessageAttachment) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -type BetaThreadNewParamsMessagesAttachmentsTool struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[BetaThreadNewParamsMessagesAttachmentsToolsType] `json:"type,required"` +func (r BetaThreadNewParamsMessageAttachment) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewParamsMessageAttachment + return param.MarshalObject(r, (*shadow)(&r)) } -func (r BetaThreadNewParamsMessagesAttachmentsTool) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadNewParamsMessageAttachmentToolUnion struct { + OfCodeInterpreter *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearch *BetaThreadNewParamsMessageAttachmentToolFileSearch `json:",omitzero,inline"` + paramUnion } -func (r BetaThreadNewParamsMessagesAttachmentsTool) implementsBetaThreadNewParamsMessagesAttachmentsToolUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadNewParamsMessageAttachmentToolUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() } - -// Satisfied by [CodeInterpreterToolParam], -// [BetaThreadNewParamsMessagesAttachmentsToolsFileSearch], -// [BetaThreadNewParamsMessagesAttachmentsTool]. -type BetaThreadNewParamsMessagesAttachmentsToolUnion interface { - implementsBetaThreadNewParamsMessagesAttachmentsToolUnion() +func (u BetaThreadNewParamsMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadNewParamsMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch) } -type BetaThreadNewParamsMessagesAttachmentsToolsFileSearch struct { - // The type of tool being defined: `file_search` - Type param.Field[BetaThreadNewParamsMessagesAttachmentsToolsFileSearchType] `json:"type,required"` +func (u *BetaThreadNewParamsMessageAttachmentToolUnion) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreter) { + return u.OfCodeInterpreter + } else if !param.IsOmitted(u.OfFileSearch) { + return u.OfFileSearch + } + return nil } -func (r BetaThreadNewParamsMessagesAttachmentsToolsFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadNewParamsMessageAttachmentToolUnion) GetType() *string { + if vt := u.OfCodeInterpreter; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearch; vt != nil { + return (*string)(&vt.Type) + } + return nil } -func (r BetaThreadNewParamsMessagesAttachmentsToolsFileSearch) implementsBetaThreadNewParamsMessagesAttachmentsToolUnion() { +func init() { + apijson.RegisterUnion[BetaThreadNewParamsMessageAttachmentToolUnion]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(CodeInterpreterToolParam{}), + DiscriminatorValue: "code_interpreter", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(BetaThreadNewParamsMessageAttachmentToolFileSearch{}), + DiscriminatorValue: "file_search", + }, + ) } -// The type of tool being defined: `file_search` -type BetaThreadNewParamsMessagesAttachmentsToolsFileSearchType string - -const ( - BetaThreadNewParamsMessagesAttachmentsToolsFileSearchTypeFileSearch BetaThreadNewParamsMessagesAttachmentsToolsFileSearchType = "file_search" -) - -func (r BetaThreadNewParamsMessagesAttachmentsToolsFileSearchType) IsKnown() bool { - switch r { - case BetaThreadNewParamsMessagesAttachmentsToolsFileSearchTypeFileSearch: - return true - } - return false +// The property Type is required. +type BetaThreadNewParamsMessageAttachmentToolFileSearch struct { + // The type of tool being defined: `file_search` + // + // This field can be elided, and will marshal its zero value as "file_search". + Type constant.FileSearch `json:"type,required"` + paramObj } -// The type of tool being defined: `code_interpreter` -type BetaThreadNewParamsMessagesAttachmentsToolsType string - -const ( - BetaThreadNewParamsMessagesAttachmentsToolsTypeCodeInterpreter BetaThreadNewParamsMessagesAttachmentsToolsType = "code_interpreter" - BetaThreadNewParamsMessagesAttachmentsToolsTypeFileSearch BetaThreadNewParamsMessagesAttachmentsToolsType = "file_search" -) - -func (r BetaThreadNewParamsMessagesAttachmentsToolsType) IsKnown() bool { - switch r { - case BetaThreadNewParamsMessagesAttachmentsToolsTypeCodeInterpreter, BetaThreadNewParamsMessagesAttachmentsToolsTypeFileSearch: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsMessageAttachmentToolFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r BetaThreadNewParamsMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewParamsMessageAttachmentToolFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } // A set of resources that are made available to the assistant's tools in this @@ -753,23 +986,35 @@ func (r BetaThreadNewParamsMessagesAttachmentsToolsType) IsKnown() bool { // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. type BetaThreadNewParamsToolResources struct { - CodeInterpreter param.Field[BetaThreadNewParamsToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaThreadNewParamsToolResourcesFileSearch] `json:"file_search"` + CodeInterpreter BetaThreadNewParamsToolResourcesCodeInterpreter `json:"code_interpreter,omitzero"` + FileSearch BetaThreadNewParamsToolResourcesFileSearch `json:"file_search,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsToolResources) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r BetaThreadNewParamsToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewParamsToolResources + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewParamsToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter` tool. There can be a maximum of 20 files // associated with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` + FileIDs []string `json:"file_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsToolResourcesCodeInterpreter) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewParamsToolResourcesCodeInterpreter + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewParamsToolResourcesFileSearch struct { @@ -777,150 +1022,51 @@ type BetaThreadNewParamsToolResourcesFileSearch struct { // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this thread. There can be a maximum of 1 vector store attached to // the thread. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` // A helper to create a // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // with file_ids and attach it to this thread. There can be a maximum of 1 vector // store attached to the thread. - VectorStores param.Field[[]BetaThreadNewParamsToolResourcesFileSearchVectorStore] `json:"vector_stores"` + VectorStores []BetaThreadNewParamsToolResourcesFileSearchVectorStore `json:"vector_stores,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsToolResourcesFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewParamsToolResourcesFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewParamsToolResourcesFileSearchVectorStore struct { - // The chunking strategy used to chunk the file(s). If not set, will use the `auto` - // strategy. - ChunkingStrategy param.Field[BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion] `json:"chunking_strategy"` - // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to - // add to the vector store. There can be a maximum of 10000 files in a vector - // store. - FileIDs param.Field[[]string] `json:"file_ids"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy struct { - // Always `auto`. - Type param.Field[BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType] `json:"type,required"` - Static param.Field[interface{}] `json:"static"` -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy) implementsBetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -// -// Satisfied by -// [BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto], -// [BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic], -// [BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategy]. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion interface { - implementsBetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() -} - -// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of -// `800` and `chunk_overlap_tokens` of `400`. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto struct { - // Always `auto`. - Type param.Field[BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType] `json:"type,required"` -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto) implementsBetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// Always `auto`. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType string - -const ( - BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType = "auto" -) - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoType) IsKnown() bool { - switch r { - case BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto: - return true - } - return false -} - -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic struct { - Static param.Field[BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic] `json:"static,required"` - // Always `static`. - Type param.Field[BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType] `json:"type,required"` -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStatic) implementsBetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic struct { - // The number of tokens that overlap between chunks. The default value is `400`. - // - // Note that the overlap must not exceed half of `max_chunk_size_tokens`. - ChunkOverlapTokens param.Field[int64] `json:"chunk_overlap_tokens,required"` - // The maximum number of tokens in each chunk. The default value is `800`. The - // minimum value is `100` and the maximum value is `4096`. - MaxChunkSizeTokens param.Field[int64] `json:"max_chunk_size_tokens,required"` -} - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + Metadata shared.MetadataParam `json:"metadata,omitzero"` + // The chunking strategy used to chunk the file(s). If not set, will use the `auto` + // strategy. + ChunkingStrategy AssisstantVectorStoreChunkingStrategyUnionParam `json:"chunking_strategy,omitzero"` + // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + // add to the vector store. There can be a maximum of 10000 files in a vector + // store. + FileIDs []string `json:"file_ids,omitzero"` + paramObj } -// Always `static`. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType string - -const ( - BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType = "static" -) - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticType) IsKnown() bool { - switch r { - case BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewParamsToolResourcesFileSearchVectorStore) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// Always `auto`. -type BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType string - -const ( - BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType = "auto" - BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType = "static" -) - -func (r BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyType) IsKnown() bool { - switch r { - case BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto, BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic: - return true - } - return false +func (r BetaThreadNewParamsToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewParamsToolResourcesFileSearchVectorStore + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadUpdateParams struct { @@ -930,16 +1076,22 @@ type BetaThreadUpdateParams struct { // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // A set of resources that are made available to the assistant's tools in this // thread. The resources are specific to the type of tool. For example, the // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. - ToolResources param.Field[BetaThreadUpdateParamsToolResources] `json:"tool_resources"` + ToolResources BetaThreadUpdateParamsToolResources `json:"tool_resources,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadUpdateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) } // A set of resources that are made available to the assistant's tools in this @@ -947,23 +1099,37 @@ func (r BetaThreadUpdateParams) MarshalJSON() (data []byte, err error) { // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. type BetaThreadUpdateParamsToolResources struct { - CodeInterpreter param.Field[BetaThreadUpdateParamsToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaThreadUpdateParamsToolResourcesFileSearch] `json:"file_search"` + CodeInterpreter BetaThreadUpdateParamsToolResourcesCodeInterpreter `json:"code_interpreter,omitzero"` + FileSearch BetaThreadUpdateParamsToolResourcesFileSearch `json:"file_search,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadUpdateParamsToolResources) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadUpdateParamsToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadUpdateParamsToolResources + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadUpdateParamsToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter` tool. There can be a maximum of 20 files // associated with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` + FileIDs []string `json:"file_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadUpdateParamsToolResourcesCodeInterpreter) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadUpdateParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadUpdateParamsToolResourcesCodeInterpreter + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadUpdateParamsToolResourcesFileSearch struct { @@ -971,49 +1137,77 @@ type BetaThreadUpdateParamsToolResourcesFileSearch struct { // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this thread. There can be a maximum of 1 vector store attached to // the thread. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadUpdateParamsToolResourcesFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadUpdateParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadUpdateParamsToolResourcesFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParams struct { // The ID of the // [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to // execute this run. - AssistantID param.Field[string] `json:"assistant_id,required"` + AssistantID string `json:"assistant_id,required"` // Override the default system message of the assistant. This is useful for // modifying the behavior on a per-run basis. - Instructions param.Field[string] `json:"instructions"` + Instructions param.Opt[string] `json:"instructions,omitzero"` // The maximum number of completion tokens that may be used over the course of the // run. The run will make a best effort to use only the number of completion tokens // specified, across multiple turns of the run. If the run exceeds the number of // completion tokens specified, the run will end with status `incomplete`. See // `incomplete_details` for more info. - MaxCompletionTokens param.Field[int64] `json:"max_completion_tokens"` + MaxCompletionTokens param.Opt[int64] `json:"max_completion_tokens,omitzero"` // The maximum number of prompt tokens that may be used over the course of the run. // The run will make a best effort to use only the number of prompt tokens // specified, across multiple turns of the run. If the run exceeds the number of // prompt tokens specified, the run will end with status `incomplete`. See // `incomplete_details` for more info. - MaxPromptTokens param.Field[int64] `json:"max_prompt_tokens"` + MaxPromptTokens param.Opt[int64] `json:"max_prompt_tokens,omitzero"` + // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will + // make the output more random, while lower values like 0.2 will make it more + // focused and deterministic. + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // An alternative to sampling with temperature, called nucleus sampling, where the + // model considers the results of the tokens with top_p probability mass. So 0.1 + // means only the tokens comprising the top 10% probability mass are considered. + // + // We generally recommend altering this or temperature but not both. + TopP param.Opt[float64] `json:"top_p,omitzero"` + // Whether to enable + // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + // during tool use. + ParallelToolCalls param.Opt[bool] `json:"parallel_tool_calls,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to // be used to execute this run. If a value is provided here, it will override the // model associated with the assistant. If not, the model associated with the // assistant will be used. - Model param.Field[shared.ChatModel] `json:"model"` - // Whether to enable - // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) - // during tool use. - ParallelToolCalls param.Field[bool] `json:"parallel_tool_calls"` + Model shared.ChatModel `json:"model,omitzero"` + // A set of resources that are used by the assistant's tools. The resources are + // specific to the type of tool. For example, the `code_interpreter` tool requires + // a list of file IDs, while the `file_search` tool requires a list of vector store + // IDs. + ToolResources BetaThreadNewAndRunParamsToolResources `json:"tool_resources,omitzero"` + // Override the tools the assistant can use for this run. This is useful for + // modifying the behavior on a per-run basis. + Tools []BetaThreadNewAndRunParamsToolUnion `json:"tools,omitzero"` + // Controls for how a thread will be truncated prior to the run. Use this to + // control the intial context window of the run. + TruncationStrategy BetaThreadNewAndRunParamsTruncationStrategy `json:"truncation_strategy,omitzero"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -1034,14 +1228,10 @@ type BetaThreadNewAndRunParams struct { // the message content may be partially cut off if `finish_reason="length"`, which // indicates the generation exceeded `max_tokens` or the conversation exceeded the // max context length. - ResponseFormat param.Field[AssistantResponseFormatOptionUnionParam] `json:"response_format"` - // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - // make the output more random, while lower values like 0.2 will make it more - // focused and deterministic. - Temperature param.Field[float64] `json:"temperature"` + ResponseFormat AssistantResponseFormatOptionUnionParam `json:"response_format,omitzero"` // Options to create a new thread. If no thread is provided when running a request, // an empty thread will be created. - Thread param.Field[BetaThreadNewAndRunParamsThread] `json:"thread"` + Thread BetaThreadNewAndRunParamsThread `json:"thread,omitzero"` // Controls which (if any) tool is called by the model. `none` means the model will // not call any tools and instead generates a message. `auto` is the default value // and means the model can pick between generating a message or calling one or more @@ -1049,184 +1239,204 @@ type BetaThreadNewAndRunParams struct { // to the user. Specifying a particular tool like `{"type": "file_search"}` or // `{"type": "function", "function": {"name": "my_function"}}` forces the model to // call that tool. - ToolChoice param.Field[AssistantToolChoiceOptionUnionParam] `json:"tool_choice"` - // A set of resources that are used by the assistant's tools. The resources are - // specific to the type of tool. For example, the `code_interpreter` tool requires - // a list of file IDs, while the `file_search` tool requires a list of vector store - // IDs. - ToolResources param.Field[BetaThreadNewAndRunParamsToolResources] `json:"tool_resources"` - // Override the tools the assistant can use for this run. This is useful for - // modifying the behavior on a per-run basis. - Tools param.Field[[]BetaThreadNewAndRunParamsToolUnion] `json:"tools"` - // An alternative to sampling with temperature, called nucleus sampling, where the - // model considers the results of the tokens with top_p probability mass. So 0.1 - // means only the tokens comprising the top 10% probability mass are considered. - // - // We generally recommend altering this or temperature but not both. - TopP param.Field[float64] `json:"top_p"` - // Controls for how a thread will be truncated prior to the run. Use this to - // control the intial context window of the run. - TruncationStrategy param.Field[BetaThreadNewAndRunParamsTruncationStrategy] `json:"truncation_strategy"` + ToolChoice AssistantToolChoiceOptionUnionParam `json:"tool_choice,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadNewAndRunParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParams + return param.MarshalObject(r, (*shadow)(&r)) } // Options to create a new thread. If no thread is provided when running a request, // an empty thread will be created. type BetaThreadNewAndRunParamsThread struct { - // A list of [messages](https://platform.openai.com/docs/api-reference/messages) to - // start the thread with. - Messages param.Field[[]BetaThreadNewAndRunParamsThreadMessage] `json:"messages"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // A set of resources that are made available to the assistant's tools in this // thread. The resources are specific to the type of tool. For example, the // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. - ToolResources param.Field[BetaThreadNewAndRunParamsThreadToolResources] `json:"tool_resources"` + ToolResources BetaThreadNewAndRunParamsThreadToolResources `json:"tool_resources,omitzero"` + // A list of [messages](https://platform.openai.com/docs/api-reference/messages) to + // start the thread with. + Messages []BetaThreadNewAndRunParamsThreadMessage `json:"messages,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThread) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r BetaThreadNewAndRunParamsThread) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsThread + return param.MarshalObject(r, (*shadow)(&r)) } +// The properties Content, Role are required. type BetaThreadNewAndRunParamsThreadMessage struct { // The text contents of the message. - Content param.Field[BetaThreadNewAndRunParamsThreadMessagesContentUnion] `json:"content,required"` + Content BetaThreadNewAndRunParamsThreadMessageContentUnion `json:"content,omitzero,required"` // The role of the entity that is creating the message. Allowed values include: // // - `user`: Indicates the message is sent by an actual user and should be used in // most cases to represent user-generated messages. // - `assistant`: Indicates the message is generated by the assistant. Use this // value to insert messages from the assistant into the conversation. - Role param.Field[BetaThreadNewAndRunParamsThreadMessagesRole] `json:"role,required"` + // + // Any of "user", "assistant". + Role string `json:"role,omitzero,required"` // A list of files attached to the message, and the tools they should be added to. - Attachments param.Field[[]BetaThreadNewAndRunParamsThreadMessagesAttachment] `json:"attachments"` + Attachments []BetaThreadNewAndRunParamsThreadMessageAttachment `json:"attachments,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } -func (r BetaThreadNewAndRunParamsThreadMessage) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadMessage) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The text contents of the message. -// -// Satisfied by [shared.UnionString], -// [BetaThreadNewAndRunParamsThreadMessagesContentArrayOfContentParts]. -type BetaThreadNewAndRunParamsThreadMessagesContentUnion interface { - ImplementsBetaThreadNewAndRunParamsThreadMessagesContentUnion() +func (r BetaThreadNewAndRunParamsThreadMessage) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewAndRunParamsThreadMessage + return param.MarshalObject(r, (*shadow)(&r)) } -type BetaThreadNewAndRunParamsThreadMessagesContentArrayOfContentParts []MessageContentPartParamUnion - -func (r BetaThreadNewAndRunParamsThreadMessagesContentArrayOfContentParts) ImplementsBetaThreadNewAndRunParamsThreadMessagesContentUnion() { +func init() { + apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsThreadMessage]( + "Role", false, "user", "assistant", + ) } -// The role of the entity that is creating the message. Allowed values include: +// Only one field can be non-zero. // -// - `user`: Indicates the message is sent by an actual user and should be used in -// most cases to represent user-generated messages. -// - `assistant`: Indicates the message is generated by the assistant. Use this -// value to insert messages from the assistant into the conversation. -type BetaThreadNewAndRunParamsThreadMessagesRole string +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadNewAndRunParamsThreadMessageContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []MessageContentPartParamUnion `json:",omitzero,inline"` + paramUnion +} -const ( - BetaThreadNewAndRunParamsThreadMessagesRoleUser BetaThreadNewAndRunParamsThreadMessagesRole = "user" - BetaThreadNewAndRunParamsThreadMessagesRoleAssistant BetaThreadNewAndRunParamsThreadMessagesRole = "assistant" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadNewAndRunParamsThreadMessageContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u BetaThreadNewAndRunParamsThreadMessageContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadNewAndRunParamsThreadMessageContentUnion](u.OfString, u.OfArrayOfContentParts) +} -func (r BetaThreadNewAndRunParamsThreadMessagesRole) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadMessagesRoleUser, BetaThreadNewAndRunParamsThreadMessagesRoleAssistant: - return true +func (u *BetaThreadNewAndRunParamsThreadMessageContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } -type BetaThreadNewAndRunParamsThreadMessagesAttachment struct { +type BetaThreadNewAndRunParamsThreadMessageAttachment struct { // The ID of the file to attach to the message. - FileID param.Field[string] `json:"file_id"` + FileID param.Opt[string] `json:"file_id,omitzero"` // The tools to add this file to. - Tools param.Field[[]BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion] `json:"tools"` + Tools []BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion `json:"tools,omitzero"` + paramObj } -func (r BetaThreadNewAndRunParamsThreadMessagesAttachment) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadMessageAttachment) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -type BetaThreadNewAndRunParamsThreadMessagesAttachmentsTool struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType] `json:"type,required"` +func (r BetaThreadNewAndRunParamsThreadMessageAttachment) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewAndRunParamsThreadMessageAttachment + return param.MarshalObject(r, (*shadow)(&r)) } -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsTool) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion struct { + OfCodeInterpreter *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearch *BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch `json:",omitzero,inline"` + paramUnion } -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsTool) implementsBetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() } - -// Satisfied by [CodeInterpreterToolParam], -// [BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearch], -// [BetaThreadNewAndRunParamsThreadMessagesAttachmentsTool]. -type BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion interface { - implementsBetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion() +func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch) } -type BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearch struct { - // The type of tool being defined: `file_search` - Type param.Field[BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchType] `json:"type,required"` +func (u *BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreter) { + return u.OfCodeInterpreter + } else if !param.IsOmitted(u.OfFileSearch) { + return u.OfFileSearch + } + return nil } -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion) GetType() *string { + if vt := u.OfCodeInterpreter; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearch; vt != nil { + return (*string)(&vt.Type) + } + return nil } -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearch) implementsBetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion() { +func init() { + apijson.RegisterUnion[BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(CodeInterpreterToolParam{}), + DiscriminatorValue: "code_interpreter", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch{}), + DiscriminatorValue: "file_search", + }, + ) } -// The type of tool being defined: `file_search` -type BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchType string - -const ( - BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchTypeFileSearch BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchType = "file_search" -) - -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsFileSearchTypeFileSearch: - return true - } - return false +// The property Type is required. +type BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch struct { + // The type of tool being defined: `file_search` + // + // This field can be elided, and will marshal its zero value as "file_search". + Type constant.FileSearch `json:"type,required"` + paramObj } -// The type of tool being defined: `code_interpreter` -type BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType string - -const ( - BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsTypeCodeInterpreter BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType = "code_interpreter" - BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsTypeFileSearch BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType = "file_search" -) - -func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsTypeCodeInterpreter, BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsTypeFileSearch: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewAndRunParamsThreadMessageAttachmentToolFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } // A set of resources that are made available to the assistant's tools in this @@ -1234,23 +1444,37 @@ func (r BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolsType) IsKnown() b // `code_interpreter` tool requires a list of file IDs, while the `file_search` // tool requires a list of vector store IDs. type BetaThreadNewAndRunParamsThreadToolResources struct { - CodeInterpreter param.Field[BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearch] `json:"file_search"` + CodeInterpreter BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter `json:"code_interpreter,omitzero"` + FileSearch BetaThreadNewAndRunParamsThreadToolResourcesFileSearch `json:"file_search,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadToolResources) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsThreadToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsThreadToolResources + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter` tool. There can be a maximum of 20 files // associated with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` + FileIDs []string `json:"file_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParamsThreadToolResourcesFileSearch struct { @@ -1258,150 +1482,51 @@ type BetaThreadNewAndRunParamsThreadToolResourcesFileSearch struct { // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this thread. There can be a maximum of 1 vector store attached to // the thread. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` // A helper to create a // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // with file_ids and attach it to this thread. There can be a maximum of 1 vector // store attached to the thread. - VectorStores param.Field[[]BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore] `json:"vector_stores"` + VectorStores []BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore `json:"vector_stores,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore struct { - // The chunking strategy used to chunk the file(s). If not set, will use the `auto` - // strategy. - ChunkingStrategy param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion] `json:"chunking_strategy"` - // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to - // add to the vector store. There can be a maximum of 10000 files in a vector - // store. - FileIDs param.Field[[]string] `json:"file_ids"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategy struct { - // Always `auto`. - Type param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyType] `json:"type,required"` - Static param.Field[interface{}] `json:"static"` -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategy) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategy) implementsBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// The chunking strategy used to chunk the file(s). If not set, will use the `auto` -// strategy. -// -// Satisfied by -// [BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAuto], -// [BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStatic], -// [BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategy]. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion interface { - implementsBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion() -} - -// The default strategy. This strategy currently uses a `max_chunk_size_tokens` of -// `800` and `chunk_overlap_tokens` of `400`. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAuto struct { - // Always `auto`. - Type param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoType] `json:"type,required"` -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAuto) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAuto) implementsBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -// Always `auto`. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoType string - -const ( - BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoType = "auto" -) - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto: - return true - } - return false -} - -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStatic struct { - Static param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic] `json:"static,required"` - // Always `static`. - Type param.Field[BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticType] `json:"type,required"` -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStatic) implementsBetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion() { -} - -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic struct { - // The number of tokens that overlap between chunks. The default value is `400`. - // - // Note that the overlap must not exceed half of `max_chunk_size_tokens`. - ChunkOverlapTokens param.Field[int64] `json:"chunk_overlap_tokens,required"` - // The maximum number of tokens in each chunk. The default value is `800`. The - // minimum value is `100` and the maximum value is `4096`. - MaxChunkSizeTokens param.Field[int64] `json:"max_chunk_size_tokens,required"` -} - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticStatic) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + Metadata shared.MetadataParam `json:"metadata,omitzero"` + // The chunking strategy used to chunk the file(s). If not set, will use the `auto` + // strategy. + ChunkingStrategy AssisstantVectorStoreChunkingStrategyUnionParam `json:"chunking_strategy,omitzero"` + // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs to + // add to the vector store. There can be a maximum of 10000 files in a vector + // store. + FileIDs []string `json:"file_ids,omitzero"` + paramObj } -// Always `static`. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticType string - -const ( - BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticType = "static" -) - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyStaticTypeStatic: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// Always `auto`. -type BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyType string - -const ( - BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyType = "auto" - BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyType = "static" -) - -func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyTypeAuto, BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyTypeStatic: - return true - } - return false +func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore + return param.MarshalObject(r, (*shadow)(&r)) } // A set of resources that are used by the assistant's tools. The resources are @@ -1409,23 +1534,37 @@ func (r BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunki // a list of file IDs, while the `file_search` tool requires a list of vector store // IDs. type BetaThreadNewAndRunParamsToolResources struct { - CodeInterpreter param.Field[BetaThreadNewAndRunParamsToolResourcesCodeInterpreter] `json:"code_interpreter"` - FileSearch param.Field[BetaThreadNewAndRunParamsToolResourcesFileSearch] `json:"file_search"` + CodeInterpreter BetaThreadNewAndRunParamsToolResourcesCodeInterpreter `json:"code_interpreter,omitzero"` + FileSearch BetaThreadNewAndRunParamsToolResourcesFileSearch `json:"file_search,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsToolResources) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsToolResources) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsToolResources + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParamsToolResourcesCodeInterpreter struct { // A list of [file](https://platform.openai.com/docs/api-reference/files) IDs made // available to the `code_interpreter` tool. There can be a maximum of 20 files // associated with the tool. - FileIDs param.Field[[]string] `json:"file_ids"` + FileIDs []string `json:"file_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsToolResourcesCodeInterpreter) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsToolResourcesCodeInterpreter + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadNewAndRunParamsToolResourcesFileSearch struct { @@ -1433,81 +1572,108 @@ type BetaThreadNewAndRunParamsToolResourcesFileSearch struct { // [vector store](https://platform.openai.com/docs/api-reference/vector-stores/object) // attached to this assistant. There can be a maximum of 1 vector store attached to // the assistant. - VectorStoreIDs param.Field[[]string] `json:"vector_store_ids"` + VectorStoreIDs []string `json:"vector_store_ids,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsToolResourcesFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsToolResourcesFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsToolResourcesFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } -type BetaThreadNewAndRunParamsTool struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[BetaThreadNewAndRunParamsToolsType] `json:"type,required"` - FileSearch param.Field[interface{}] `json:"file_search"` - Function param.Field[shared.FunctionDefinitionParam] `json:"function"` +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadNewAndRunParamsToolUnion struct { + OfCodeInterpreterTool *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearchTool *FileSearchToolParam `json:",omitzero,inline"` + OfFunctionTool *FunctionToolParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadNewAndRunParamsToolUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u BetaThreadNewAndRunParamsToolUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadNewAndRunParamsToolUnion](u.OfCodeInterpreterTool, u.OfFileSearchTool, u.OfFunctionTool) +} + +func (u *BetaThreadNewAndRunParamsToolUnion) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreterTool) { + return u.OfCodeInterpreterTool + } else if !param.IsOmitted(u.OfFileSearchTool) { + return u.OfFileSearchTool + } else if !param.IsOmitted(u.OfFunctionTool) { + return u.OfFunctionTool + } + return nil } -func (r BetaThreadNewAndRunParamsTool) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadNewAndRunParamsToolUnion) GetFileSearch() *FileSearchToolFileSearchParam { + if vt := u.OfFileSearchTool; vt != nil { + return &vt.FileSearch + } + return nil } -func (r BetaThreadNewAndRunParamsTool) implementsBetaThreadNewAndRunParamsToolUnion() {} - -// Satisfied by [CodeInterpreterToolParam], [FileSearchToolParam], -// [FunctionToolParam], [BetaThreadNewAndRunParamsTool]. -type BetaThreadNewAndRunParamsToolUnion interface { - implementsBetaThreadNewAndRunParamsToolUnion() +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadNewAndRunParamsToolUnion) GetFunction() *shared.FunctionDefinitionParam { + if vt := u.OfFunctionTool; vt != nil { + return &vt.Function + } + return nil } -// The type of tool being defined: `code_interpreter` -type BetaThreadNewAndRunParamsToolsType string - -const ( - BetaThreadNewAndRunParamsToolsTypeCodeInterpreter BetaThreadNewAndRunParamsToolsType = "code_interpreter" - BetaThreadNewAndRunParamsToolsTypeFileSearch BetaThreadNewAndRunParamsToolsType = "file_search" - BetaThreadNewAndRunParamsToolsTypeFunction BetaThreadNewAndRunParamsToolsType = "function" -) - -func (r BetaThreadNewAndRunParamsToolsType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsToolsTypeCodeInterpreter, BetaThreadNewAndRunParamsToolsTypeFileSearch, BetaThreadNewAndRunParamsToolsTypeFunction: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadNewAndRunParamsToolUnion) GetType() *string { + if vt := u.OfCodeInterpreterTool; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearchTool; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFunctionTool; vt != nil { + return (*string)(&vt.Type) } - return false + return nil } // Controls for how a thread will be truncated prior to the run. Use this to // control the intial context window of the run. +// +// The property Type is required. type BetaThreadNewAndRunParamsTruncationStrategy struct { // The truncation strategy to use for the thread. The default is `auto`. If set to // `last_messages`, the thread will be truncated to the n most recent messages in // the thread. When set to `auto`, messages in the middle of the thread will be // dropped to fit the context length of the model, `max_prompt_tokens`. - Type param.Field[BetaThreadNewAndRunParamsTruncationStrategyType] `json:"type,required"` + // + // Any of "auto", "last_messages". + Type string `json:"type,omitzero,required"` // The number of most recent messages from the thread when constructing the context // for the run. - LastMessages param.Field[int64] `json:"last_messages"` + LastMessages param.Opt[int64] `json:"last_messages,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadNewAndRunParamsTruncationStrategy) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadNewAndRunParamsTruncationStrategy) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadNewAndRunParamsTruncationStrategy + return param.MarshalObject(r, (*shadow)(&r)) } -// The truncation strategy to use for the thread. The default is `auto`. If set to -// `last_messages`, the thread will be truncated to the n most recent messages in -// the thread. When set to `auto`, messages in the middle of the thread will be -// dropped to fit the context length of the model, `max_prompt_tokens`. -type BetaThreadNewAndRunParamsTruncationStrategyType string - -const ( - BetaThreadNewAndRunParamsTruncationStrategyTypeAuto BetaThreadNewAndRunParamsTruncationStrategyType = "auto" - BetaThreadNewAndRunParamsTruncationStrategyTypeLastMessages BetaThreadNewAndRunParamsTruncationStrategyType = "last_messages" -) - -func (r BetaThreadNewAndRunParamsTruncationStrategyType) IsKnown() bool { - switch r { - case BetaThreadNewAndRunParamsTruncationStrategyTypeAuto, BetaThreadNewAndRunParamsTruncationStrategyTypeLastMessages: - return true - } - return false +func init() { + apijson.RegisterFieldValidator[BetaThreadNewAndRunParamsTruncationStrategy]( + "Type", false, "auto", "last_messages", + ) } diff --git a/betathread_test.go b/betathread_test.go index 6b706a4d..2e580260 100644 --- a/betathread_test.go +++ b/betathread_test.go @@ -12,6 +12,7 @@ import ( "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" ) func TestBetaThreadNewWithOptionalParams(t *testing.T) { @@ -27,39 +28,41 @@ func TestBetaThreadNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Beta.Threads.New(context.TODO(), openai.BetaThreadNewParams{ - Messages: openai.F([]openai.BetaThreadNewParamsMessage{{ - Content: openai.F[openai.BetaThreadNewParamsMessagesContentUnion](shared.UnionString("string")), - Role: openai.F(openai.BetaThreadNewParamsMessagesRoleUser), - Attachments: openai.F([]openai.BetaThreadNewParamsMessagesAttachment{{ - FileID: openai.F("file_id"), - Tools: openai.F([]openai.BetaThreadNewParamsMessagesAttachmentsToolUnion{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - }}), - Metadata: openai.F(shared.MetadataParam{ + Messages: []openai.BetaThreadNewParamsMessage{{ + Content: openai.BetaThreadNewParamsMessageContentUnion{ + OfString: openai.String("string"), + }, + Role: "user", + Attachments: []openai.BetaThreadNewParamsMessageAttachment{{ + FileID: openai.String("file_id"), + Tools: []openai.BetaThreadNewParamsMessageAttachmentToolUnion{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - Metadata: openai.F(shared.MetadataParam{ + }, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - ToolResources: openai.F(openai.BetaThreadNewParamsToolResources{ - CodeInterpreter: openai.F(openai.BetaThreadNewParamsToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaThreadNewParamsToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - VectorStores: openai.F([]openai.BetaThreadNewParamsToolResourcesFileSearchVectorStore{{ - ChunkingStrategy: openai.F[openai.BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyUnion](openai.BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAuto{ - Type: openai.F(openai.BetaThreadNewParamsToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto), - }), - FileIDs: openai.F([]string{"string"}), - Metadata: openai.F(shared.MetadataParam{ + }, + ToolResources: openai.BetaThreadNewParamsToolResources{ + CodeInterpreter: openai.BetaThreadNewParamsToolResourcesCodeInterpreter{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.BetaThreadNewParamsToolResourcesFileSearch{ + VectorStoreIDs: []string{"string"}, + VectorStores: []openai.BetaThreadNewParamsToolResourcesFileSearchVectorStore{{ + ChunkingStrategy: openai.AssisstantVectorStoreChunkingStrategyUnionParam{ + OfAuto: &openai.AssisstantVectorStoreChunkingStrategyAutoParam{}, + }, + FileIDs: []string{"string"}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - }), - }), + }, + }}, + }, + }, }) if err != nil { var apierr *openai.Error @@ -108,17 +111,17 @@ func TestBetaThreadUpdateWithOptionalParams(t *testing.T) { context.TODO(), "thread_id", openai.BetaThreadUpdateParams{ - Metadata: openai.F(shared.MetadataParam{ + Metadata: shared.MetadataParam{ "foo": "string", - }), - ToolResources: openai.F(openai.BetaThreadUpdateParamsToolResources{ - CodeInterpreter: openai.F(openai.BetaThreadUpdateParamsToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaThreadUpdateParamsToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - }), - }), + }, + ToolResources: openai.BetaThreadUpdateParamsToolResources{ + CodeInterpreter: openai.BetaThreadUpdateParamsToolResourcesCodeInterpreter{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.BetaThreadUpdateParamsToolResourcesFileSearch{ + VectorStoreIDs: []string{"string"}, + }, + }, }, ) if err != nil { @@ -165,69 +168,75 @@ func TestBetaThreadNewAndRunWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Beta.Threads.NewAndRun(context.TODO(), openai.BetaThreadNewAndRunParams{ - AssistantID: openai.F("assistant_id"), - Instructions: openai.F("instructions"), - MaxCompletionTokens: openai.F(int64(256)), - MaxPromptTokens: openai.F(int64(256)), - Metadata: openai.F(shared.MetadataParam{ + AssistantID: "assistant_id", + Instructions: openai.String("instructions"), + MaxCompletionTokens: openai.Int(256), + MaxPromptTokens: openai.Int(256), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Model: openai.F(shared.ChatModelO3Mini), - ParallelToolCalls: openai.F(true), - ResponseFormat: openai.F[openai.AssistantResponseFormatOptionUnionParam](openai.AssistantResponseFormatOptionString(openai.AssistantResponseFormatOptionStringAuto)), - Temperature: openai.F(1.000000), - Thread: openai.F(openai.BetaThreadNewAndRunParamsThread{ - Messages: openai.F([]openai.BetaThreadNewAndRunParamsThreadMessage{{ - Content: openai.F[openai.BetaThreadNewAndRunParamsThreadMessagesContentUnion](shared.UnionString("string")), - Role: openai.F(openai.BetaThreadNewAndRunParamsThreadMessagesRoleUser), - Attachments: openai.F([]openai.BetaThreadNewAndRunParamsThreadMessagesAttachment{{ - FileID: openai.F("file_id"), - Tools: openai.F([]openai.BetaThreadNewAndRunParamsThreadMessagesAttachmentsToolUnion{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - }}), - Metadata: openai.F(shared.MetadataParam{ + }, + Model: shared.ChatModelO3Mini, + ParallelToolCalls: openai.Bool(true), + ResponseFormat: openai.AssistantResponseFormatOptionUnionParam{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + Temperature: openai.Float(1), + Thread: openai.BetaThreadNewAndRunParamsThread{ + Messages: []openai.BetaThreadNewAndRunParamsThreadMessage{{ + Content: openai.BetaThreadNewAndRunParamsThreadMessageContentUnion{ + OfString: openai.String("string"), + }, + Role: "user", + Attachments: []openai.BetaThreadNewAndRunParamsThreadMessageAttachment{{ + FileID: openai.String("file_id"), + Tools: []openai.BetaThreadNewAndRunParamsThreadMessageAttachmentToolUnion{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - Metadata: openai.F(shared.MetadataParam{ + }, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - ToolResources: openai.F(openai.BetaThreadNewAndRunParamsThreadToolResources{ - CodeInterpreter: openai.F(openai.BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - VectorStores: openai.F([]openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore{{ - ChunkingStrategy: openai.F[openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyUnion](openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAuto{ - Type: openai.F(openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStoresChunkingStrategyAutoTypeAuto), - }), - FileIDs: openai.F([]string{"string"}), - Metadata: openai.F(shared.MetadataParam{ + }, + ToolResources: openai.BetaThreadNewAndRunParamsThreadToolResources{ + CodeInterpreter: openai.BetaThreadNewAndRunParamsThreadToolResourcesCodeInterpreter{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearch{ + VectorStoreIDs: []string{"string"}, + VectorStores: []openai.BetaThreadNewAndRunParamsThreadToolResourcesFileSearchVectorStore{{ + ChunkingStrategy: openai.AssisstantVectorStoreChunkingStrategyUnionParam{ + OfAuto: &openai.AssisstantVectorStoreChunkingStrategyAutoParam{}, + }, + FileIDs: []string{"string"}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - }), - }), - }), - ToolChoice: openai.F[openai.AssistantToolChoiceOptionUnionParam](openai.AssistantToolChoiceOptionAuto(openai.AssistantToolChoiceOptionAutoNone)), - ToolResources: openai.F(openai.BetaThreadNewAndRunParamsToolResources{ - CodeInterpreter: openai.F(openai.BetaThreadNewAndRunParamsToolResourcesCodeInterpreter{ - FileIDs: openai.F([]string{"string"}), - }), - FileSearch: openai.F(openai.BetaThreadNewAndRunParamsToolResourcesFileSearch{ - VectorStoreIDs: openai.F([]string{"string"}), - }), - }), - Tools: openai.F([]openai.BetaThreadNewAndRunParamsToolUnion{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - TopP: openai.F(1.000000), - TruncationStrategy: openai.F(openai.BetaThreadNewAndRunParamsTruncationStrategy{ - Type: openai.F(openai.BetaThreadNewAndRunParamsTruncationStrategyTypeAuto), - LastMessages: openai.F(int64(1)), - }), + }, + }}, + }, + }, + }, + ToolChoice: openai.AssistantToolChoiceOptionUnionParam{ + OfAuto: openai.String("none"), + }, + ToolResources: openai.BetaThreadNewAndRunParamsToolResources{ + CodeInterpreter: openai.BetaThreadNewAndRunParamsToolResourcesCodeInterpreter{ + FileIDs: []string{"string"}, + }, + FileSearch: openai.BetaThreadNewAndRunParamsToolResourcesFileSearch{ + VectorStoreIDs: []string{"string"}, + }, + }, + Tools: []openai.BetaThreadNewAndRunParamsToolUnion{{ + OfCodeInterpreterTool: &openai.CodeInterpreterToolParam{}, + }}, + TopP: openai.Float(1), + TruncationStrategy: openai.BetaThreadNewAndRunParamsTruncationStrategy{ + Type: "auto", + LastMessages: openai.Int(1), + }, }) if err != nil { var apierr *openai.Error diff --git a/betathreadmessage.go b/betathreadmessage.go index 57fdd410..bd9f34a2 100644 --- a/betathreadmessage.go +++ b/betathreadmessage.go @@ -4,6 +4,7 @@ package openai import ( "context" + "encoding/json" "errors" "fmt" "net/http" @@ -12,11 +13,13 @@ import ( "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" "github.com/tidwall/gjson" ) @@ -33,8 +36,8 @@ type BetaThreadMessageService struct { // NewBetaThreadMessageService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewBetaThreadMessageService(opts ...option.RequestOption) (r *BetaThreadMessageService) { - r = &BetaThreadMessageService{} +func NewBetaThreadMessageService(opts ...option.RequestOption) (r BetaThreadMessageService) { + r = BetaThreadMessageService{} r.Options = opts return } @@ -130,196 +133,130 @@ func (r *BetaThreadMessageService) Delete(ctx context.Context, threadID string, return } -// A citation within the message that points to a specific quote from a specific -// File associated with the assistant or the message. Generated when the assistant -// uses the "file_search" tool to search files. -type Annotation struct { - EndIndex int64 `json:"end_index,required"` - StartIndex int64 `json:"start_index,required"` - // The text in the message content that needs to be replaced. - Text string `json:"text,required"` - // Always `file_citation`. - Type AnnotationType `json:"type,required"` - // This field can have the runtime type of [FileCitationAnnotationFileCitation]. - FileCitation interface{} `json:"file_citation"` - // This field can have the runtime type of [FilePathAnnotationFilePath]. - FilePath interface{} `json:"file_path"` - JSON annotationJSON `json:"-"` - union AnnotationUnion -} - -// annotationJSON contains the JSON metadata for the struct [Annotation] -type annotationJSON struct { - EndIndex apijson.Field - StartIndex apijson.Field - Text apijson.Field - Type apijson.Field - FileCitation apijson.Field - FilePath apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r annotationJSON) RawJSON() string { - return r.raw -} - -func (r *Annotation) UnmarshalJSON(data []byte) (err error) { - *r = Annotation{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) -} - -// AsUnion returns a [AnnotationUnion] interface which you can cast to the specific -// types for more type safety. +// AnnotationUnion contains all possible properties and values from +// [FileCitationAnnotation], [FilePathAnnotation]. // -// Possible runtime types of the union are [FileCitationAnnotation], -// [FilePathAnnotation]. -func (r Annotation) AsUnion() AnnotationUnion { - return r.union -} - -// A citation within the message that points to a specific quote from a specific -// File associated with the assistant or the message. Generated when the assistant -// uses the "file_search" tool to search files. +// Use the [AnnotationUnion.AsAny] method to switch on the variant. // -// Union satisfied by [FileCitationAnnotation] or [FilePathAnnotation]. -type AnnotationUnion interface { - implementsAnnotation() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AnnotationUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FileCitationAnnotation{}), - DiscriminatorValue: "file_citation", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FilePathAnnotation{}), - DiscriminatorValue: "file_path", - }, - ) -} - -// Always `file_citation`. -type AnnotationType string - -const ( - AnnotationTypeFileCitation AnnotationType = "file_citation" - AnnotationTypeFilePath AnnotationType = "file_path" -) - -func (r AnnotationType) IsKnown() bool { - switch r { - case AnnotationTypeFileCitation, AnnotationTypeFilePath: - return true +// Use the methods beginning with 'As' to cast the union to one of its variants. +type AnnotationUnion struct { + EndIndex int64 `json:"end_index"` + // This field is from variant [FileCitationAnnotation]. + FileCitation FileCitationAnnotationFileCitation `json:"file_citation"` + StartIndex int64 `json:"start_index"` + Text string `json:"text"` + // Any of "file_citation", "file_path". + Type string `json:"type"` + // This field is from variant [FilePathAnnotation]. + FilePath FilePathAnnotationFilePath `json:"file_path"` + JSON struct { + EndIndex resp.Field + FileCitation resp.Field + StartIndex resp.Field + Text resp.Field + Type resp.Field + FilePath resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := AnnotationUnion.AsAny().(type) { +// case FileCitationAnnotation: +// case FilePathAnnotation: +// default: +// fmt.Errorf("no variant present") +// } +func (u AnnotationUnion) AsAny() any { + switch u.Type { + case "file_citation": + return u.AsFileCitation() + case "file_path": + return u.AsFilePath() } - return false + return nil } -// A citation within the message that points to a specific quote from a specific -// File associated with the assistant or the message. Generated when the assistant -// uses the "file_search" tool to search files. -type AnnotationDelta struct { - // The index of the annotation in the text content part. - Index int64 `json:"index,required"` - // Always `file_citation`. - Type AnnotationDeltaType `json:"type,required"` - EndIndex int64 `json:"end_index"` - // This field can have the runtime type of - // [FileCitationDeltaAnnotationFileCitation]. - FileCitation interface{} `json:"file_citation"` - // This field can have the runtime type of [FilePathDeltaAnnotationFilePath]. - FilePath interface{} `json:"file_path"` - StartIndex int64 `json:"start_index"` - // The text in the message content that needs to be replaced. - Text string `json:"text"` - JSON annotationDeltaJSON `json:"-"` - union AnnotationDeltaUnion +func (u AnnotationUnion) AsFileCitation() (v FileCitationAnnotation) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// annotationDeltaJSON contains the JSON metadata for the struct [AnnotationDelta] -type annotationDeltaJSON struct { - Index apijson.Field - Type apijson.Field - EndIndex apijson.Field - FileCitation apijson.Field - FilePath apijson.Field - StartIndex apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u AnnotationUnion) AsFilePath() (v FilePathAnnotation) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r annotationDeltaJSON) RawJSON() string { - return r.raw -} +// Returns the unmodified JSON received from the API +func (u AnnotationUnion) RawJSON() string { return u.JSON.raw } -func (r *AnnotationDelta) UnmarshalJSON(data []byte) (err error) { - *r = AnnotationDelta{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +func (r *AnnotationUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// AsUnion returns a [AnnotationDeltaUnion] interface which you can cast to the -// specific types for more type safety. +// AnnotationDeltaUnion contains all possible properties and values from +// [FileCitationDeltaAnnotation], [FilePathDeltaAnnotation]. // -// Possible runtime types of the union are [FileCitationDeltaAnnotation], -// [FilePathDeltaAnnotation]. -func (r AnnotationDelta) AsUnion() AnnotationDeltaUnion { - return r.union -} - -// A citation within the message that points to a specific quote from a specific -// File associated with the assistant or the message. Generated when the assistant -// uses the "file_search" tool to search files. +// Use the [AnnotationDeltaUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type AnnotationDeltaUnion struct { + Index int64 `json:"index"` + // Any of "file_citation", "file_path". + Type string `json:"type"` + EndIndex int64 `json:"end_index"` + // This field is from variant [FileCitationDeltaAnnotation]. + FileCitation FileCitationDeltaAnnotationFileCitation `json:"file_citation"` + StartIndex int64 `json:"start_index"` + Text string `json:"text"` + // This field is from variant [FilePathDeltaAnnotation]. + FilePath FilePathDeltaAnnotationFilePath `json:"file_path"` + JSON struct { + Index resp.Field + Type resp.Field + EndIndex resp.Field + FileCitation resp.Field + StartIndex resp.Field + Text resp.Field + FilePath resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant // -// Union satisfied by [FileCitationDeltaAnnotation] or [FilePathDeltaAnnotation]. -type AnnotationDeltaUnion interface { - implementsAnnotationDelta() +// switch variant := AnnotationDeltaUnion.AsAny().(type) { +// case FileCitationDeltaAnnotation: +// case FilePathDeltaAnnotation: +// default: +// fmt.Errorf("no variant present") +// } +func (u AnnotationDeltaUnion) AsAny() any { + switch u.Type { + case "file_citation": + return u.AsFileCitation() + case "file_path": + return u.AsFilePath() + } + return nil } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*AnnotationDeltaUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FileCitationDeltaAnnotation{}), - DiscriminatorValue: "file_citation", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FilePathDeltaAnnotation{}), - DiscriminatorValue: "file_path", - }, - ) +func (u AnnotationDeltaUnion) AsFileCitation() (v FileCitationDeltaAnnotation) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Always `file_citation`. -type AnnotationDeltaType string +func (u AnnotationDeltaUnion) AsFilePath() (v FilePathDeltaAnnotation) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - AnnotationDeltaTypeFileCitation AnnotationDeltaType = "file_citation" - AnnotationDeltaTypeFilePath AnnotationDeltaType = "file_path" -) +// Returns the unmodified JSON received from the API +func (u AnnotationDeltaUnion) RawJSON() string { return u.JSON.raw } -func (r AnnotationDeltaType) IsKnown() bool { - switch r { - case AnnotationDeltaTypeFileCitation, AnnotationDeltaTypeFilePath: - return true - } - return false +func (r *AnnotationDeltaUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // A citation within the message that points to a specific quote from a specific @@ -332,69 +269,44 @@ type FileCitationAnnotation struct { // The text in the message content that needs to be replaced. Text string `json:"text,required"` // Always `file_citation`. - Type FileCitationAnnotationType `json:"type,required"` - JSON fileCitationAnnotationJSON `json:"-"` -} - -// fileCitationAnnotationJSON contains the JSON metadata for the struct -// [FileCitationAnnotation] -type fileCitationAnnotationJSON struct { - EndIndex apijson.Field - FileCitation apijson.Field - StartIndex apijson.Field - Text apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileCitationAnnotation) UnmarshalJSON(data []byte) (err error) { + Type constant.FileCitation `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + EndIndex resp.Field + FileCitation resp.Field + StartIndex resp.Field + Text resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileCitationAnnotation) RawJSON() string { return r.JSON.raw } +func (r *FileCitationAnnotation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileCitationAnnotationJSON) RawJSON() string { - return r.raw -} - -func (r FileCitationAnnotation) implementsAnnotation() {} - type FileCitationAnnotationFileCitation struct { // The ID of the specific File the citation is from. - FileID string `json:"file_id,required"` - JSON fileCitationAnnotationFileCitationJSON `json:"-"` -} - -// fileCitationAnnotationFileCitationJSON contains the JSON metadata for the struct -// [FileCitationAnnotationFileCitation] -type fileCitationAnnotationFileCitationJSON struct { - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileCitationAnnotationFileCitation) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileCitationAnnotationFileCitation) RawJSON() string { return r.JSON.raw } +func (r *FileCitationAnnotationFileCitation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileCitationAnnotationFileCitationJSON) RawJSON() string { - return r.raw -} - -// Always `file_citation`. -type FileCitationAnnotationType string - -const ( - FileCitationAnnotationTypeFileCitation FileCitationAnnotationType = "file_citation" -) - -func (r FileCitationAnnotationType) IsKnown() bool { - switch r { - case FileCitationAnnotationTypeFileCitation: - return true - } - return false -} - // A citation within the message that points to a specific quote from a specific // File associated with the assistant or the message. Generated when the assistant // uses the "file_search" tool to search files. @@ -402,78 +314,53 @@ type FileCitationDeltaAnnotation struct { // The index of the annotation in the text content part. Index int64 `json:"index,required"` // Always `file_citation`. - Type FileCitationDeltaAnnotationType `json:"type,required"` + Type constant.FileCitation `json:"type,required"` EndIndex int64 `json:"end_index"` FileCitation FileCitationDeltaAnnotationFileCitation `json:"file_citation"` StartIndex int64 `json:"start_index"` // The text in the message content that needs to be replaced. - Text string `json:"text"` - JSON fileCitationDeltaAnnotationJSON `json:"-"` -} - -// fileCitationDeltaAnnotationJSON contains the JSON metadata for the struct -// [FileCitationDeltaAnnotation] -type fileCitationDeltaAnnotationJSON struct { - Index apijson.Field - Type apijson.Field - EndIndex apijson.Field - FileCitation apijson.Field - StartIndex apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileCitationDeltaAnnotation) UnmarshalJSON(data []byte) (err error) { + Text string `json:"text"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + EndIndex resp.Field + FileCitation resp.Field + StartIndex resp.Field + Text resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileCitationDeltaAnnotation) RawJSON() string { return r.JSON.raw } +func (r *FileCitationDeltaAnnotation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileCitationDeltaAnnotationJSON) RawJSON() string { - return r.raw -} - -func (r FileCitationDeltaAnnotation) implementsAnnotationDelta() {} - -// Always `file_citation`. -type FileCitationDeltaAnnotationType string - -const ( - FileCitationDeltaAnnotationTypeFileCitation FileCitationDeltaAnnotationType = "file_citation" -) - -func (r FileCitationDeltaAnnotationType) IsKnown() bool { - switch r { - case FileCitationDeltaAnnotationTypeFileCitation: - return true - } - return false -} - type FileCitationDeltaAnnotationFileCitation struct { // The ID of the specific File the citation is from. FileID string `json:"file_id"` // The specific quote in the file. - Quote string `json:"quote"` - JSON fileCitationDeltaAnnotationFileCitationJSON `json:"-"` -} - -// fileCitationDeltaAnnotationFileCitationJSON contains the JSON metadata for the -// struct [FileCitationDeltaAnnotationFileCitation] -type fileCitationDeltaAnnotationFileCitationJSON struct { - FileID apijson.Field - Quote apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileCitationDeltaAnnotationFileCitation) UnmarshalJSON(data []byte) (err error) { + Quote string `json:"quote"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + Quote resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileCitationDeltaAnnotationFileCitation) RawJSON() string { return r.JSON.raw } +func (r *FileCitationDeltaAnnotationFileCitation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileCitationDeltaAnnotationFileCitationJSON) RawJSON() string { - return r.raw -} - // A URL for the file that's generated when the assistant used the // `code_interpreter` tool to generate a file. type FilePathAnnotation struct { @@ -483,144 +370,94 @@ type FilePathAnnotation struct { // The text in the message content that needs to be replaced. Text string `json:"text,required"` // Always `file_path`. - Type FilePathAnnotationType `json:"type,required"` - JSON filePathAnnotationJSON `json:"-"` -} - -// filePathAnnotationJSON contains the JSON metadata for the struct -// [FilePathAnnotation] -type filePathAnnotationJSON struct { - EndIndex apijson.Field - FilePath apijson.Field - StartIndex apijson.Field - Text apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FilePathAnnotation) UnmarshalJSON(data []byte) (err error) { + Type constant.FilePath `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + EndIndex resp.Field + FilePath resp.Field + StartIndex resp.Field + Text resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FilePathAnnotation) RawJSON() string { return r.JSON.raw } +func (r *FilePathAnnotation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r filePathAnnotationJSON) RawJSON() string { - return r.raw -} - -func (r FilePathAnnotation) implementsAnnotation() {} - type FilePathAnnotationFilePath struct { // The ID of the file that was generated. - FileID string `json:"file_id,required"` - JSON filePathAnnotationFilePathJSON `json:"-"` -} - -// filePathAnnotationFilePathJSON contains the JSON metadata for the struct -// [FilePathAnnotationFilePath] -type filePathAnnotationFilePathJSON struct { - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FilePathAnnotationFilePath) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FilePathAnnotationFilePath) RawJSON() string { return r.JSON.raw } +func (r *FilePathAnnotationFilePath) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r filePathAnnotationFilePathJSON) RawJSON() string { - return r.raw -} - -// Always `file_path`. -type FilePathAnnotationType string - -const ( - FilePathAnnotationTypeFilePath FilePathAnnotationType = "file_path" -) - -func (r FilePathAnnotationType) IsKnown() bool { - switch r { - case FilePathAnnotationTypeFilePath: - return true - } - return false -} - // A URL for the file that's generated when the assistant used the // `code_interpreter` tool to generate a file. type FilePathDeltaAnnotation struct { // The index of the annotation in the text content part. Index int64 `json:"index,required"` // Always `file_path`. - Type FilePathDeltaAnnotationType `json:"type,required"` + Type constant.FilePath `json:"type,required"` EndIndex int64 `json:"end_index"` FilePath FilePathDeltaAnnotationFilePath `json:"file_path"` StartIndex int64 `json:"start_index"` // The text in the message content that needs to be replaced. - Text string `json:"text"` - JSON filePathDeltaAnnotationJSON `json:"-"` -} - -// filePathDeltaAnnotationJSON contains the JSON metadata for the struct -// [FilePathDeltaAnnotation] -type filePathDeltaAnnotationJSON struct { - Index apijson.Field - Type apijson.Field - EndIndex apijson.Field - FilePath apijson.Field - StartIndex apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FilePathDeltaAnnotation) UnmarshalJSON(data []byte) (err error) { + Text string `json:"text"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + EndIndex resp.Field + FilePath resp.Field + StartIndex resp.Field + Text resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FilePathDeltaAnnotation) RawJSON() string { return r.JSON.raw } +func (r *FilePathDeltaAnnotation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r filePathDeltaAnnotationJSON) RawJSON() string { - return r.raw -} - -func (r FilePathDeltaAnnotation) implementsAnnotationDelta() {} - -// Always `file_path`. -type FilePathDeltaAnnotationType string - -const ( - FilePathDeltaAnnotationTypeFilePath FilePathDeltaAnnotationType = "file_path" -) - -func (r FilePathDeltaAnnotationType) IsKnown() bool { - switch r { - case FilePathDeltaAnnotationTypeFilePath: - return true - } - return false -} - type FilePathDeltaAnnotationFilePath struct { // The ID of the file that was generated. - FileID string `json:"file_id"` - JSON filePathDeltaAnnotationFilePathJSON `json:"-"` -} - -// filePathDeltaAnnotationFilePathJSON contains the JSON metadata for the struct -// [FilePathDeltaAnnotationFilePath] -type filePathDeltaAnnotationFilePathJSON struct { - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FilePathDeltaAnnotationFilePath) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FilePathDeltaAnnotationFilePath) RawJSON() string { return r.JSON.raw } +func (r *FilePathDeltaAnnotationFilePath) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r filePathDeltaAnnotationFilePathJSON) RawJSON() string { - return r.raw -} - type ImageFile struct { // The [File](https://platform.openai.com/docs/api-reference/files) ID of the image // in the message content. Set `purpose="vision"` when uploading the File if you @@ -628,24 +465,32 @@ type ImageFile struct { FileID string `json:"file_id,required"` // Specifies the detail level of the image if specified by the user. `low` uses // fewer tokens, you can opt in to high resolution using `high`. + // + // Any of "auto", "low", "high". Detail ImageFileDetail `json:"detail"` - JSON imageFileJSON `json:"-"` -} - -// imageFileJSON contains the JSON metadata for the struct [ImageFile] -type imageFileJSON struct { - FileID apijson.Field - Detail apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageFile) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + Detail resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageFile) RawJSON() string { return r.JSON.raw } +func (r *ImageFile) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageFileJSON) RawJSON() string { - return r.raw +// ToParam converts this ImageFile to a ImageFileParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ImageFileParam.IsOverridden() +func (r ImageFile) ToParam() ImageFileParam { + return param.OverrideObj[ImageFileParam](r.RawJSON()) } // Specifies the detail level of the image if specified by the user. `low` uses @@ -658,26 +503,26 @@ const ( ImageFileDetailHigh ImageFileDetail = "high" ) -func (r ImageFileDetail) IsKnown() bool { - switch r { - case ImageFileDetailAuto, ImageFileDetailLow, ImageFileDetailHigh: - return true - } - return false -} - +// The property FileID is required. type ImageFileParam struct { // The [File](https://platform.openai.com/docs/api-reference/files) ID of the image // in the message content. Set `purpose="vision"` when uploading the File if you // need to later display the file content. - FileID param.Field[string] `json:"file_id,required"` + FileID string `json:"file_id,required"` // Specifies the detail level of the image if specified by the user. `low` uses // fewer tokens, you can opt in to high resolution using `high`. - Detail param.Field[ImageFileDetail] `json:"detail"` + // + // Any of "auto", "low", "high". + Detail ImageFileDetail `json:"detail,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageFileParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ImageFileParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ImageFileParam + return param.MarshalObject(r, (*shadow)(&r)) } // References an image [File](https://platform.openai.com/docs/api-reference/files) @@ -685,85 +530,79 @@ func (r ImageFileParam) MarshalJSON() (data []byte, err error) { type ImageFileContentBlock struct { ImageFile ImageFile `json:"image_file,required"` // Always `image_file`. - Type ImageFileContentBlockType `json:"type,required"` - JSON imageFileContentBlockJSON `json:"-"` -} - -// imageFileContentBlockJSON contains the JSON metadata for the struct -// [ImageFileContentBlock] -type imageFileContentBlockJSON struct { - ImageFile apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageFileContentBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.ImageFile `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ImageFile resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageFileContentBlock) RawJSON() string { return r.JSON.raw } +func (r *ImageFileContentBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageFileContentBlockJSON) RawJSON() string { - return r.raw -} - -func (r ImageFileContentBlock) implementsMessageContent() {} - -// Always `image_file`. -type ImageFileContentBlockType string - -const ( - ImageFileContentBlockTypeImageFile ImageFileContentBlockType = "image_file" -) - -func (r ImageFileContentBlockType) IsKnown() bool { - switch r { - case ImageFileContentBlockTypeImageFile: - return true - } - return false +// ToParam converts this ImageFileContentBlock to a ImageFileContentBlockParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ImageFileContentBlockParam.IsOverridden() +func (r ImageFileContentBlock) ToParam() ImageFileContentBlockParam { + return param.OverrideObj[ImageFileContentBlockParam](r.RawJSON()) } // References an image [File](https://platform.openai.com/docs/api-reference/files) // in the content of a message. +// +// The properties ImageFile, Type are required. type ImageFileContentBlockParam struct { - ImageFile param.Field[ImageFileParam] `json:"image_file,required"` + ImageFile ImageFileParam `json:"image_file,omitzero,required"` // Always `image_file`. - Type param.Field[ImageFileContentBlockType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "image_file". + Type constant.ImageFile `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageFileContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ImageFileContentBlockParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ImageFileContentBlockParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ImageFileContentBlockParam) implementsMessageContentPartParamUnion() {} - type ImageFileDelta struct { // Specifies the detail level of the image if specified by the user. `low` uses // fewer tokens, you can opt in to high resolution using `high`. + // + // Any of "auto", "low", "high". Detail ImageFileDeltaDetail `json:"detail"` // The [File](https://platform.openai.com/docs/api-reference/files) ID of the image // in the message content. Set `purpose="vision"` when uploading the File if you // need to later display the file content. - FileID string `json:"file_id"` - JSON imageFileDeltaJSON `json:"-"` -} - -// imageFileDeltaJSON contains the JSON metadata for the struct [ImageFileDelta] -type imageFileDeltaJSON struct { - Detail apijson.Field - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageFileDelta) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Detail resp.Field + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageFileDelta) RawJSON() string { return r.JSON.raw } +func (r *ImageFileDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageFileDeltaJSON) RawJSON() string { - return r.raw -} - // Specifies the detail level of the image if specified by the user. `low` uses // fewer tokens, you can opt in to high resolution using `high`. type ImageFileDeltaDetail string @@ -774,84 +613,63 @@ const ( ImageFileDeltaDetailHigh ImageFileDeltaDetail = "high" ) -func (r ImageFileDeltaDetail) IsKnown() bool { - switch r { - case ImageFileDeltaDetailAuto, ImageFileDeltaDetailLow, ImageFileDeltaDetailHigh: - return true - } - return false -} - // References an image [File](https://platform.openai.com/docs/api-reference/files) // in the content of a message. type ImageFileDeltaBlock struct { // The index of the content part in the message. Index int64 `json:"index,required"` // Always `image_file`. - Type ImageFileDeltaBlockType `json:"type,required"` - ImageFile ImageFileDelta `json:"image_file"` - JSON imageFileDeltaBlockJSON `json:"-"` -} - -// imageFileDeltaBlockJSON contains the JSON metadata for the struct -// [ImageFileDeltaBlock] -type imageFileDeltaBlockJSON struct { - Index apijson.Field - Type apijson.Field - ImageFile apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageFileDeltaBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.ImageFile `json:"type,required"` + ImageFile ImageFileDelta `json:"image_file"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + ImageFile resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageFileDeltaBlock) RawJSON() string { return r.JSON.raw } +func (r *ImageFileDeltaBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageFileDeltaBlockJSON) RawJSON() string { - return r.raw -} - -func (r ImageFileDeltaBlock) implementsMessageContentDelta() {} - -// Always `image_file`. -type ImageFileDeltaBlockType string - -const ( - ImageFileDeltaBlockTypeImageFile ImageFileDeltaBlockType = "image_file" -) - -func (r ImageFileDeltaBlockType) IsKnown() bool { - switch r { - case ImageFileDeltaBlockTypeImageFile: - return true - } - return false -} - type ImageURL struct { // The external URL of the image, must be a supported image types: jpeg, jpg, png, // gif, webp. URL string `json:"url,required" format:"uri"` // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in // to high resolution using `high`. Default value is `auto` + // + // Any of "auto", "low", "high". Detail ImageURLDetail `json:"detail"` - JSON imageURLJSON `json:"-"` -} - -// imageURLJSON contains the JSON metadata for the struct [ImageURL] -type imageURLJSON struct { - URL apijson.Field - Detail apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageURL) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + URL resp.Field + Detail resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageURL) RawJSON() string { return r.JSON.raw } +func (r *ImageURL) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageURLJSON) RawJSON() string { - return r.raw +// ToParam converts this ImageURL to a ImageURLParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ImageURLParam.IsOverridden() +func (r ImageURL) ToParam() ImageURLParam { + return param.OverrideObj[ImageURLParam](r.RawJSON()) } // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in @@ -864,108 +682,102 @@ const ( ImageURLDetailHigh ImageURLDetail = "high" ) -func (r ImageURLDetail) IsKnown() bool { - switch r { - case ImageURLDetailAuto, ImageURLDetailLow, ImageURLDetailHigh: - return true - } - return false -} - +// The property URL is required. type ImageURLParam struct { // The external URL of the image, must be a supported image types: jpeg, jpg, png, // gif, webp. - URL param.Field[string] `json:"url,required" format:"uri"` + URL string `json:"url,required" format:"uri"` // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in // to high resolution using `high`. Default value is `auto` - Detail param.Field[ImageURLDetail] `json:"detail"` + // + // Any of "auto", "low", "high". + Detail ImageURLDetail `json:"detail,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageURLParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ImageURLParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ImageURLParam + return param.MarshalObject(r, (*shadow)(&r)) } // References an image URL in the content of a message. type ImageURLContentBlock struct { ImageURL ImageURL `json:"image_url,required"` // The type of the content part. - Type ImageURLContentBlockType `json:"type,required"` - JSON imageURLContentBlockJSON `json:"-"` -} - -// imageURLContentBlockJSON contains the JSON metadata for the struct -// [ImageURLContentBlock] -type imageURLContentBlockJSON struct { - ImageURL apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageURLContentBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.ImageURL `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ImageURL resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageURLContentBlock) RawJSON() string { return r.JSON.raw } +func (r *ImageURLContentBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageURLContentBlockJSON) RawJSON() string { - return r.raw -} - -func (r ImageURLContentBlock) implementsMessageContent() {} - -// The type of the content part. -type ImageURLContentBlockType string - -const ( - ImageURLContentBlockTypeImageURL ImageURLContentBlockType = "image_url" -) - -func (r ImageURLContentBlockType) IsKnown() bool { - switch r { - case ImageURLContentBlockTypeImageURL: - return true - } - return false +// ToParam converts this ImageURLContentBlock to a ImageURLContentBlockParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ImageURLContentBlockParam.IsOverridden() +func (r ImageURLContentBlock) ToParam() ImageURLContentBlockParam { + return param.OverrideObj[ImageURLContentBlockParam](r.RawJSON()) } // References an image URL in the content of a message. +// +// The properties ImageURL, Type are required. type ImageURLContentBlockParam struct { - ImageURL param.Field[ImageURLParam] `json:"image_url,required"` + ImageURL ImageURLParam `json:"image_url,omitzero,required"` // The type of the content part. - Type param.Field[ImageURLContentBlockType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "image_url". + Type constant.ImageURL `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageURLContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ImageURLContentBlockParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ImageURLContentBlockParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ImageURLContentBlockParam) implementsMessageContentPartParamUnion() {} - type ImageURLDelta struct { // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in // to high resolution using `high`. + // + // Any of "auto", "low", "high". Detail ImageURLDeltaDetail `json:"detail"` // The URL of the image, must be a supported image types: jpeg, jpg, png, gif, // webp. - URL string `json:"url"` - JSON imageURLDeltaJSON `json:"-"` -} - -// imageURLDeltaJSON contains the JSON metadata for the struct [ImageURLDelta] -type imageURLDeltaJSON struct { - Detail apijson.Field - URL apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageURLDelta) UnmarshalJSON(data []byte) (err error) { + URL string `json:"url"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Detail resp.Field + URL resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageURLDelta) RawJSON() string { return r.JSON.raw } +func (r *ImageURLDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageURLDeltaJSON) RawJSON() string { - return r.raw -} - // Specifies the detail level of the image. `low` uses fewer tokens, you can opt in // to high resolution using `high`. type ImageURLDeltaDetail string @@ -976,59 +788,30 @@ const ( ImageURLDeltaDetailHigh ImageURLDeltaDetail = "high" ) -func (r ImageURLDeltaDetail) IsKnown() bool { - switch r { - case ImageURLDeltaDetailAuto, ImageURLDeltaDetailLow, ImageURLDeltaDetailHigh: - return true - } - return false -} - // References an image URL in the content of a message. type ImageURLDeltaBlock struct { // The index of the content part in the message. Index int64 `json:"index,required"` // Always `image_url`. - Type ImageURLDeltaBlockType `json:"type,required"` - ImageURL ImageURLDelta `json:"image_url"` - JSON imageURLDeltaBlockJSON `json:"-"` -} - -// imageURLDeltaBlockJSON contains the JSON metadata for the struct -// [ImageURLDeltaBlock] -type imageURLDeltaBlockJSON struct { - Index apijson.Field - Type apijson.Field - ImageURL apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ImageURLDeltaBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.ImageURL `json:"type,required"` + ImageURL ImageURLDelta `json:"image_url"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + ImageURL resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ImageURLDeltaBlock) RawJSON() string { return r.JSON.raw } +func (r *ImageURLDeltaBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageURLDeltaBlockJSON) RawJSON() string { - return r.raw -} - -func (r ImageURLDeltaBlock) implementsMessageContentDelta() {} - -// Always `image_url`. -type ImageURLDeltaBlockType string - -const ( - ImageURLDeltaBlockTypeImageURL ImageURLDeltaBlockType = "image_url" -) - -func (r ImageURLDeltaBlockType) IsKnown() bool { - switch r { - case ImageURLDeltaBlockTypeImageURL: - return true - } - return false -} - // Represents a message within a // [thread](https://platform.openai.com/docs/api-reference/threads). type Message struct { @@ -1037,611 +820,488 @@ type Message struct { // If applicable, the ID of the // [assistant](https://platform.openai.com/docs/api-reference/assistants) that // authored this message. - AssistantID string `json:"assistant_id,required,nullable"` + AssistantID string `json:"assistant_id,required"` // A list of files attached to the message, and the tools they were added to. - Attachments []MessageAttachment `json:"attachments,required,nullable"` + Attachments []MessageAttachment `json:"attachments,required"` // The Unix timestamp (in seconds) for when the message was completed. - CompletedAt int64 `json:"completed_at,required,nullable"` + CompletedAt int64 `json:"completed_at,required"` // The content of the message in array of text and/or images. - Content []MessageContent `json:"content,required"` + Content []MessageContentUnion `json:"content,required"` // The Unix timestamp (in seconds) for when the message was created. CreatedAt int64 `json:"created_at,required"` // The Unix timestamp (in seconds) for when the message was marked as incomplete. - IncompleteAt int64 `json:"incomplete_at,required,nullable"` + IncompleteAt int64 `json:"incomplete_at,required"` // On an incomplete message, details about why the message is incomplete. - IncompleteDetails MessageIncompleteDetails `json:"incomplete_details,required,nullable"` + IncompleteDetails MessageIncompleteDetails `json:"incomplete_details,required"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata shared.Metadata `json:"metadata,required,nullable"` + Metadata shared.Metadata `json:"metadata,required"` // The object type, which is always `thread.message`. - Object MessageObject `json:"object,required"` + Object constant.ThreadMessage `json:"object,required"` // The entity that produced the message. One of `user` or `assistant`. + // + // Any of "user", "assistant". Role MessageRole `json:"role,required"` // The ID of the [run](https://platform.openai.com/docs/api-reference/runs) // associated with the creation of this message. Value is `null` when messages are // created manually using the create message or create thread endpoints. - RunID string `json:"run_id,required,nullable"` + RunID string `json:"run_id,required"` // The status of the message, which can be either `in_progress`, `incomplete`, or // `completed`. + // + // Any of "in_progress", "incomplete", "completed". Status MessageStatus `json:"status,required"` // The [thread](https://platform.openai.com/docs/api-reference/threads) ID that // this message belongs to. - ThreadID string `json:"thread_id,required"` - JSON messageJSON `json:"-"` -} - -// messageJSON contains the JSON metadata for the struct [Message] -type messageJSON struct { - ID apijson.Field - AssistantID apijson.Field - Attachments apijson.Field - CompletedAt apijson.Field - Content apijson.Field - CreatedAt apijson.Field - IncompleteAt apijson.Field - IncompleteDetails apijson.Field - Metadata apijson.Field - Object apijson.Field - Role apijson.Field - RunID apijson.Field - Status apijson.Field - ThreadID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Message) UnmarshalJSON(data []byte) (err error) { + ThreadID string `json:"thread_id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + AssistantID resp.Field + Attachments resp.Field + CompletedAt resp.Field + Content resp.Field + CreatedAt resp.Field + IncompleteAt resp.Field + IncompleteDetails resp.Field + Metadata resp.Field + Object resp.Field + Role resp.Field + RunID resp.Field + Status resp.Field + ThreadID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Message) RawJSON() string { return r.JSON.raw } +func (r *Message) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageJSON) RawJSON() string { - return r.raw -} - type MessageAttachment struct { // The ID of the file to attach to the message. FileID string `json:"file_id"` // The tools to add this file to. - Tools []MessageAttachmentsTool `json:"tools"` - JSON messageAttachmentJSON `json:"-"` -} - -// messageAttachmentJSON contains the JSON metadata for the struct -// [MessageAttachment] -type messageAttachmentJSON struct { - FileID apijson.Field - Tools apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageAttachment) UnmarshalJSON(data []byte) (err error) { + Tools []MessageAttachmentToolUnion `json:"tools"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + Tools resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageAttachment) RawJSON() string { return r.JSON.raw } +func (r *MessageAttachment) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageAttachmentJSON) RawJSON() string { - return r.raw -} - -type MessageAttachmentsTool struct { - // The type of tool being defined: `code_interpreter` - Type MessageAttachmentsToolsType `json:"type,required"` - JSON messageAttachmentsToolJSON `json:"-"` - union MessageAttachmentsToolsUnion -} - -// messageAttachmentsToolJSON contains the JSON metadata for the struct -// [MessageAttachmentsTool] -type messageAttachmentsToolJSON struct { - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r messageAttachmentsToolJSON) RawJSON() string { - return r.raw -} - -func (r *MessageAttachmentsTool) UnmarshalJSON(data []byte) (err error) { - *r = MessageAttachmentsTool{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) -} - -// AsUnion returns a [MessageAttachmentsToolsUnion] interface which you can cast to -// the specific types for more type safety. +// MessageAttachmentToolUnion contains all possible properties and values from +// [CodeInterpreterTool], [MessageAttachmentToolAssistantToolsFileSearchTypeOnly]. // -// Possible runtime types of the union are [CodeInterpreterTool], -// [MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly]. -func (r MessageAttachmentsTool) AsUnion() MessageAttachmentsToolsUnion { - return r.union +// Use the methods beginning with 'As' to cast the union to one of its variants. +type MessageAttachmentToolUnion struct { + Type string `json:"type"` + JSON struct { + Type resp.Field + raw string + } `json:"-"` } -// Union satisfied by [CodeInterpreterTool] or -// [MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly]. -type MessageAttachmentsToolsUnion interface { - implementsMessageAttachmentsTool() +func (u MessageAttachmentToolUnion) AsCodeInterpreterTool() (v CodeInterpreterTool) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*MessageAttachmentsToolsUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterTool{}), - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly{}), - }, - ) +func (u MessageAttachmentToolUnion) AsFileSearchTool() (v MessageAttachmentToolAssistantToolsFileSearchTypeOnly) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly struct { - // The type of tool being defined: `file_search` - Type MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyType `json:"type,required"` - JSON messageAttachmentsToolsAssistantToolsFileSearchTypeOnlyJSON `json:"-"` -} +// Returns the unmodified JSON received from the API +func (u MessageAttachmentToolUnion) RawJSON() string { return u.JSON.raw } -// messageAttachmentsToolsAssistantToolsFileSearchTypeOnlyJSON contains the JSON -// metadata for the struct -// [MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly] -type messageAttachmentsToolsAssistantToolsFileSearchTypeOnlyJSON struct { - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (r *MessageAttachmentToolUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r *MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly) UnmarshalJSON(data []byte) (err error) { +type MessageAttachmentToolAssistantToolsFileSearchTypeOnly struct { + // The type of tool being defined: `file_search` + Type constant.FileSearch `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageAttachmentToolAssistantToolsFileSearchTypeOnly) RawJSON() string { return r.JSON.raw } +func (r *MessageAttachmentToolAssistantToolsFileSearchTypeOnly) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageAttachmentsToolsAssistantToolsFileSearchTypeOnlyJSON) RawJSON() string { - return r.raw +// On an incomplete message, details about why the message is incomplete. +type MessageIncompleteDetails struct { + // The reason the message is incomplete. + // + // Any of "content_filter", "max_tokens", "run_cancelled", "run_expired", + // "run_failed". + Reason string `json:"reason,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Reason resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageIncompleteDetails) RawJSON() string { return r.JSON.raw } +func (r *MessageIncompleteDetails) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -func (r MessageAttachmentsToolsAssistantToolsFileSearchTypeOnly) implementsMessageAttachmentsTool() {} - -// The type of tool being defined: `file_search` -type MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyType string +// The entity that produced the message. One of `user` or `assistant`. +type MessageRole string const ( - MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyTypeFileSearch MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyType = "file_search" + MessageRoleUser MessageRole = "user" + MessageRoleAssistant MessageRole = "assistant" ) -func (r MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyType) IsKnown() bool { - switch r { - case MessageAttachmentsToolsAssistantToolsFileSearchTypeOnlyTypeFileSearch: - return true - } - return false -} - -// The type of tool being defined: `code_interpreter` -type MessageAttachmentsToolsType string +// The status of the message, which can be either `in_progress`, `incomplete`, or +// `completed`. +type MessageStatus string const ( - MessageAttachmentsToolsTypeCodeInterpreter MessageAttachmentsToolsType = "code_interpreter" - MessageAttachmentsToolsTypeFileSearch MessageAttachmentsToolsType = "file_search" + MessageStatusInProgress MessageStatus = "in_progress" + MessageStatusIncomplete MessageStatus = "incomplete" + MessageStatusCompleted MessageStatus = "completed" ) -func (r MessageAttachmentsToolsType) IsKnown() bool { - switch r { - case MessageAttachmentsToolsTypeCodeInterpreter, MessageAttachmentsToolsTypeFileSearch: - return true +// MessageContentUnion contains all possible properties and values from +// [ImageFileContentBlock], [ImageURLContentBlock], [TextContentBlock], +// [RefusalContentBlock]. +// +// Use the [MessageContentUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type MessageContentUnion struct { + // This field is from variant [ImageFileContentBlock]. + ImageFile ImageFile `json:"image_file"` + // Any of "image_file", "image_url", "text", "refusal". + Type string `json:"type"` + // This field is from variant [ImageURLContentBlock]. + ImageURL ImageURL `json:"image_url"` + // This field is from variant [TextContentBlock]. + Text Text `json:"text"` + // This field is from variant [RefusalContentBlock]. + Refusal string `json:"refusal"` + JSON struct { + ImageFile resp.Field + Type resp.Field + ImageURL resp.Field + Text resp.Field + Refusal resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := MessageContentUnion.AsAny().(type) { +// case ImageFileContentBlock: +// case ImageURLContentBlock: +// case TextContentBlock: +// case RefusalContentBlock: +// default: +// fmt.Errorf("no variant present") +// } +func (u MessageContentUnion) AsAny() any { + switch u.Type { + case "image_file": + return u.AsImageFile() + case "image_url": + return u.AsImageURL() + case "text": + return u.AsText() + case "refusal": + return u.AsRefusal() } - return false + return nil } -// On an incomplete message, details about why the message is incomplete. -type MessageIncompleteDetails struct { - // The reason the message is incomplete. - Reason MessageIncompleteDetailsReason `json:"reason,required"` - JSON messageIncompleteDetailsJSON `json:"-"` +func (u MessageContentUnion) AsImageFile() (v ImageFileContentBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// messageIncompleteDetailsJSON contains the JSON metadata for the struct -// [MessageIncompleteDetails] -type messageIncompleteDetailsJSON struct { - Reason apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u MessageContentUnion) AsImageURL() (v ImageURLContentBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *MessageIncompleteDetails) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func (u MessageContentUnion) AsText() (v TextContentBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r messageIncompleteDetailsJSON) RawJSON() string { - return r.raw +func (u MessageContentUnion) AsRefusal() (v RefusalContentBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The reason the message is incomplete. -type MessageIncompleteDetailsReason string - -const ( - MessageIncompleteDetailsReasonContentFilter MessageIncompleteDetailsReason = "content_filter" - MessageIncompleteDetailsReasonMaxTokens MessageIncompleteDetailsReason = "max_tokens" - MessageIncompleteDetailsReasonRunCancelled MessageIncompleteDetailsReason = "run_cancelled" - MessageIncompleteDetailsReasonRunExpired MessageIncompleteDetailsReason = "run_expired" - MessageIncompleteDetailsReasonRunFailed MessageIncompleteDetailsReason = "run_failed" -) +// Returns the unmodified JSON received from the API +func (u MessageContentUnion) RawJSON() string { return u.JSON.raw } -func (r MessageIncompleteDetailsReason) IsKnown() bool { - switch r { - case MessageIncompleteDetailsReasonContentFilter, MessageIncompleteDetailsReasonMaxTokens, MessageIncompleteDetailsReasonRunCancelled, MessageIncompleteDetailsReasonRunExpired, MessageIncompleteDetailsReasonRunFailed: - return true - } - return false +func (r *MessageContentUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The object type, which is always `thread.message`. -type MessageObject string - -const ( - MessageObjectThreadMessage MessageObject = "thread.message" -) - -func (r MessageObject) IsKnown() bool { - switch r { - case MessageObjectThreadMessage: - return true +// MessageContentDeltaUnion contains all possible properties and values from +// [ImageFileDeltaBlock], [TextDeltaBlock], [RefusalDeltaBlock], +// [ImageURLDeltaBlock]. +// +// Use the [MessageContentDeltaUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type MessageContentDeltaUnion struct { + Index int64 `json:"index"` + // Any of "image_file", "text", "refusal", "image_url". + Type string `json:"type"` + // This field is from variant [ImageFileDeltaBlock]. + ImageFile ImageFileDelta `json:"image_file"` + // This field is from variant [TextDeltaBlock]. + Text TextDelta `json:"text"` + // This field is from variant [RefusalDeltaBlock]. + Refusal string `json:"refusal"` + // This field is from variant [ImageURLDeltaBlock]. + ImageURL ImageURLDelta `json:"image_url"` + JSON struct { + Index resp.Field + Type resp.Field + ImageFile resp.Field + Text resp.Field + Refusal resp.Field + ImageURL resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := MessageContentDeltaUnion.AsAny().(type) { +// case ImageFileDeltaBlock: +// case TextDeltaBlock: +// case RefusalDeltaBlock: +// case ImageURLDeltaBlock: +// default: +// fmt.Errorf("no variant present") +// } +func (u MessageContentDeltaUnion) AsAny() any { + switch u.Type { + case "image_file": + return u.AsImageFile() + case "text": + return u.AsText() + case "refusal": + return u.AsRefusal() + case "image_url": + return u.AsImageURL() } - return false + return nil } -// The entity that produced the message. One of `user` or `assistant`. -type MessageRole string - -const ( - MessageRoleUser MessageRole = "user" - MessageRoleAssistant MessageRole = "assistant" -) - -func (r MessageRole) IsKnown() bool { - switch r { - case MessageRoleUser, MessageRoleAssistant: - return true - } - return false +func (u MessageContentDeltaUnion) AsImageFile() (v ImageFileDeltaBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The status of the message, which can be either `in_progress`, `incomplete`, or -// `completed`. -type MessageStatus string - -const ( - MessageStatusInProgress MessageStatus = "in_progress" - MessageStatusIncomplete MessageStatus = "incomplete" - MessageStatusCompleted MessageStatus = "completed" -) - -func (r MessageStatus) IsKnown() bool { - switch r { - case MessageStatusInProgress, MessageStatusIncomplete, MessageStatusCompleted: - return true - } - return false +func (u MessageContentDeltaUnion) AsText() (v TextDeltaBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -type MessageContent struct { - // Always `image_file`. - Type MessageContentType `json:"type,required"` - ImageFile ImageFile `json:"image_file"` - ImageURL ImageURL `json:"image_url"` - Refusal string `json:"refusal"` - Text Text `json:"text"` - JSON messageContentJSON `json:"-"` - union MessageContentUnion +func (u MessageContentDeltaUnion) AsRefusal() (v RefusalDeltaBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// messageContentJSON contains the JSON metadata for the struct [MessageContent] -type messageContentJSON struct { - Type apijson.Field - ImageFile apijson.Field - ImageURL apijson.Field - Refusal apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u MessageContentDeltaUnion) AsImageURL() (v ImageURLDeltaBlock) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r messageContentJSON) RawJSON() string { - return r.raw -} +// Returns the unmodified JSON received from the API +func (u MessageContentDeltaUnion) RawJSON() string { return u.JSON.raw } -func (r *MessageContent) UnmarshalJSON(data []byte) (err error) { - *r = MessageContent{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +func (r *MessageContentDeltaUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// AsUnion returns a [MessageContentUnion] interface which you can cast to the -// specific types for more type safety. -// -// Possible runtime types of the union are [ImageFileContentBlock], -// [ImageURLContentBlock], [TextContentBlock], [RefusalContentBlock]. -func (r MessageContent) AsUnion() MessageContentUnion { - return r.union +func MessageContentPartParamOfImageFile(imageFile ImageFileParam) MessageContentPartParamUnion { + var variant ImageFileContentBlockParam + variant.ImageFile = imageFile + return MessageContentPartParamUnion{OfImageFile: &variant} } -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -// -// Union satisfied by [ImageFileContentBlock], [ImageURLContentBlock], -// [TextContentBlock] or [RefusalContentBlock]. -type MessageContentUnion interface { - implementsMessageContent() +func MessageContentPartParamOfImageURL(imageURL ImageURLParam) MessageContentPartParamUnion { + var variant ImageURLContentBlockParam + variant.ImageURL = imageURL + return MessageContentPartParamUnion{OfImageURL: &variant} } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*MessageContentUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ImageFileContentBlock{}), - DiscriminatorValue: "image_file", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ImageURLContentBlock{}), - DiscriminatorValue: "image_url", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(TextContentBlock{}), - DiscriminatorValue: "text", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(RefusalContentBlock{}), - DiscriminatorValue: "refusal", - }, - ) +func MessageContentPartParamOfText(text string) MessageContentPartParamUnion { + var variant TextContentBlockParam + variant.Text = text + return MessageContentPartParamUnion{OfText: &variant} } -// Always `image_file`. -type MessageContentType string - -const ( - MessageContentTypeImageFile MessageContentType = "image_file" - MessageContentTypeImageURL MessageContentType = "image_url" - MessageContentTypeText MessageContentType = "text" - MessageContentTypeRefusal MessageContentType = "refusal" -) +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type MessageContentPartParamUnion struct { + OfImageFile *ImageFileContentBlockParam `json:",omitzero,inline"` + OfImageURL *ImageURLContentBlockParam `json:",omitzero,inline"` + OfText *TextContentBlockParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u MessageContentPartParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u MessageContentPartParamUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[MessageContentPartParamUnion](u.OfImageFile, u.OfImageURL, u.OfText) +} + +func (u *MessageContentPartParamUnion) asAny() any { + if !param.IsOmitted(u.OfImageFile) { + return u.OfImageFile + } else if !param.IsOmitted(u.OfImageURL) { + return u.OfImageURL + } else if !param.IsOmitted(u.OfText) { + return u.OfText + } + return nil +} -func (r MessageContentType) IsKnown() bool { - switch r { - case MessageContentTypeImageFile, MessageContentTypeImageURL, MessageContentTypeText, MessageContentTypeRefusal: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u MessageContentPartParamUnion) GetImageFile() *ImageFileParam { + if vt := u.OfImageFile; vt != nil { + return &vt.ImageFile } - return false + return nil } -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -type MessageContentDelta struct { - // The index of the content part in the message. - Index int64 `json:"index,required"` - // Always `image_file`. - Type MessageContentDeltaType `json:"type,required"` - ImageFile ImageFileDelta `json:"image_file"` - ImageURL ImageURLDelta `json:"image_url"` - Refusal string `json:"refusal"` - Text TextDelta `json:"text"` - JSON messageContentDeltaJSON `json:"-"` - union MessageContentDeltaUnion -} - -// messageContentDeltaJSON contains the JSON metadata for the struct -// [MessageContentDelta] -type messageContentDeltaJSON struct { - Index apijson.Field - Type apijson.Field - ImageFile apijson.Field - ImageURL apijson.Field - Refusal apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r messageContentDeltaJSON) RawJSON() string { - return r.raw -} - -func (r *MessageContentDelta) UnmarshalJSON(data []byte) (err error) { - *r = MessageContentDelta{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err +// Returns a pointer to the underlying variant's property, if present. +func (u MessageContentPartParamUnion) GetImageURL() *ImageURLParam { + if vt := u.OfImageURL; vt != nil { + return &vt.ImageURL } - return apijson.Port(r.union, &r) + return nil } -// AsUnion returns a [MessageContentDeltaUnion] interface which you can cast to the -// specific types for more type safety. -// -// Possible runtime types of the union are [ImageFileDeltaBlock], [TextDeltaBlock], -// [RefusalDeltaBlock], [ImageURLDeltaBlock]. -func (r MessageContentDelta) AsUnion() MessageContentDeltaUnion { - return r.union +// Returns a pointer to the underlying variant's property, if present. +func (u MessageContentPartParamUnion) GetText() *string { + if vt := u.OfText; vt != nil { + return &vt.Text + } + return nil } -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -// -// Union satisfied by [ImageFileDeltaBlock], [TextDeltaBlock], [RefusalDeltaBlock] -// or [ImageURLDeltaBlock]. -type MessageContentDeltaUnion interface { - implementsMessageContentDelta() +// Returns a pointer to the underlying variant's property, if present. +func (u MessageContentPartParamUnion) GetType() *string { + if vt := u.OfImageFile; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfImageURL; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfText; vt != nil { + return (*string)(&vt.Type) + } + return nil } func init() { - apijson.RegisterUnion( - reflect.TypeOf((*MessageContentDeltaUnion)(nil)).Elem(), + apijson.RegisterUnion[MessageContentPartParamUnion]( "type", apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ImageFileDeltaBlock{}), + Type: reflect.TypeOf(ImageFileContentBlockParam{}), DiscriminatorValue: "image_file", }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(TextDeltaBlock{}), - DiscriminatorValue: "text", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(RefusalDeltaBlock{}), - DiscriminatorValue: "refusal", + Type: reflect.TypeOf(ImageURLContentBlockParam{}), + DiscriminatorValue: "image_url", }, apijson.UnionVariant{ TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ImageURLDeltaBlock{}), - DiscriminatorValue: "image_url", + Type: reflect.TypeOf(TextContentBlockParam{}), + DiscriminatorValue: "text", }, ) } -// Always `image_file`. -type MessageContentDeltaType string - -const ( - MessageContentDeltaTypeImageFile MessageContentDeltaType = "image_file" - MessageContentDeltaTypeText MessageContentDeltaType = "text" - MessageContentDeltaTypeRefusal MessageContentDeltaType = "refusal" - MessageContentDeltaTypeImageURL MessageContentDeltaType = "image_url" -) - -func (r MessageContentDeltaType) IsKnown() bool { - switch r { - case MessageContentDeltaTypeImageFile, MessageContentDeltaTypeText, MessageContentDeltaTypeRefusal, MessageContentDeltaTypeImageURL: - return true - } - return false -} - -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -type MessageContentPartParam struct { - // Always `image_file`. - Type param.Field[MessageContentPartParamType] `json:"type,required"` - ImageFile param.Field[ImageFileParam] `json:"image_file"` - ImageURL param.Field[ImageURLParam] `json:"image_url"` - // Text content to be sent to the model - Text param.Field[string] `json:"text"` -} - -func (r MessageContentPartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r MessageContentPartParam) implementsMessageContentPartParamUnion() {} - -// References an image [File](https://platform.openai.com/docs/api-reference/files) -// in the content of a message. -// -// Satisfied by [ImageFileContentBlockParam], [ImageURLContentBlockParam], -// [TextContentBlockParam], [MessageContentPartParam]. -type MessageContentPartParamUnion interface { - implementsMessageContentPartParamUnion() -} - -// Always `image_file`. -type MessageContentPartParamType string - -const ( - MessageContentPartParamTypeImageFile MessageContentPartParamType = "image_file" - MessageContentPartParamTypeImageURL MessageContentPartParamType = "image_url" - MessageContentPartParamTypeText MessageContentPartParamType = "text" -) - -func (r MessageContentPartParamType) IsKnown() bool { - switch r { - case MessageContentPartParamTypeImageFile, MessageContentPartParamTypeImageURL, MessageContentPartParamTypeText: - return true - } - return false -} - type MessageDeleted struct { - ID string `json:"id,required"` - Deleted bool `json:"deleted,required"` - Object MessageDeletedObject `json:"object,required"` - JSON messageDeletedJSON `json:"-"` -} - -// messageDeletedJSON contains the JSON metadata for the struct [MessageDeleted] -type messageDeletedJSON struct { - ID apijson.Field - Deleted apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageDeleted) UnmarshalJSON(data []byte) (err error) { + ID string `json:"id,required"` + Deleted bool `json:"deleted,required"` + Object constant.ThreadMessageDeleted `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Deleted resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageDeleted) RawJSON() string { return r.JSON.raw } +func (r *MessageDeleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageDeletedJSON) RawJSON() string { - return r.raw -} - -type MessageDeletedObject string - -const ( - MessageDeletedObjectThreadMessageDeleted MessageDeletedObject = "thread.message.deleted" -) - -func (r MessageDeletedObject) IsKnown() bool { - switch r { - case MessageDeletedObjectThreadMessageDeleted: - return true - } - return false -} - // The delta containing the fields that have changed on the Message. type MessageDelta struct { // The content of the message in array of text and/or images. - Content []MessageContentDelta `json:"content"` + Content []MessageContentDeltaUnion `json:"content"` // The entity that produced the message. One of `user` or `assistant`. + // + // Any of "user", "assistant". Role MessageDeltaRole `json:"role"` - JSON messageDeltaJSON `json:"-"` -} - -// messageDeltaJSON contains the JSON metadata for the struct [MessageDelta] -type messageDeltaJSON struct { - Content apijson.Field - Role apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageDelta) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Content resp.Field + Role resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageDelta) RawJSON() string { return r.JSON.raw } +func (r *MessageDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageDeltaJSON) RawJSON() string { - return r.raw -} - // The entity that produced the message. One of `user` or `assistant`. type MessageDeltaRole string @@ -1650,14 +1310,6 @@ const ( MessageDeltaRoleAssistant MessageDeltaRole = "assistant" ) -func (r MessageDeltaRole) IsKnown() bool { - switch r { - case MessageDeltaRoleUser, MessageDeltaRoleAssistant: - return true - } - return false -} - // Represents a message delta i.e. any changed fields on a message during // streaming. type MessageDeltaEvent struct { @@ -1666,327 +1318,233 @@ type MessageDeltaEvent struct { // The delta containing the fields that have changed on the Message. Delta MessageDelta `json:"delta,required"` // The object type, which is always `thread.message.delta`. - Object MessageDeltaEventObject `json:"object,required"` - JSON messageDeltaEventJSON `json:"-"` -} - -// messageDeltaEventJSON contains the JSON metadata for the struct -// [MessageDeltaEvent] -type messageDeltaEventJSON struct { - ID apijson.Field - Delta apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageDeltaEvent) UnmarshalJSON(data []byte) (err error) { + Object constant.ThreadMessageDelta `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Delta resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageDeltaEvent) RawJSON() string { return r.JSON.raw } +func (r *MessageDeltaEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageDeltaEventJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `thread.message.delta`. -type MessageDeltaEventObject string - -const ( - MessageDeltaEventObjectThreadMessageDelta MessageDeltaEventObject = "thread.message.delta" -) - -func (r MessageDeltaEventObject) IsKnown() bool { - switch r { - case MessageDeltaEventObjectThreadMessageDelta: - return true - } - return false -} - // The refusal content generated by the assistant. type RefusalContentBlock struct { Refusal string `json:"refusal,required"` // Always `refusal`. - Type RefusalContentBlockType `json:"type,required"` - JSON refusalContentBlockJSON `json:"-"` -} - -// refusalContentBlockJSON contains the JSON metadata for the struct -// [RefusalContentBlock] -type refusalContentBlockJSON struct { - Refusal apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RefusalContentBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.Refusal `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Refusal resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RefusalContentBlock) RawJSON() string { return r.JSON.raw } +func (r *RefusalContentBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r refusalContentBlockJSON) RawJSON() string { - return r.raw -} - -func (r RefusalContentBlock) implementsMessageContent() {} - -// Always `refusal`. -type RefusalContentBlockType string - -const ( - RefusalContentBlockTypeRefusal RefusalContentBlockType = "refusal" -) - -func (r RefusalContentBlockType) IsKnown() bool { - switch r { - case RefusalContentBlockTypeRefusal: - return true - } - return false -} - // The refusal content that is part of a message. type RefusalDeltaBlock struct { // The index of the refusal part in the message. Index int64 `json:"index,required"` // Always `refusal`. - Type RefusalDeltaBlockType `json:"type,required"` - Refusal string `json:"refusal"` - JSON refusalDeltaBlockJSON `json:"-"` -} - -// refusalDeltaBlockJSON contains the JSON metadata for the struct -// [RefusalDeltaBlock] -type refusalDeltaBlockJSON struct { - Index apijson.Field - Type apijson.Field - Refusal apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RefusalDeltaBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.Refusal `json:"type,required"` + Refusal string `json:"refusal"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + Refusal resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RefusalDeltaBlock) RawJSON() string { return r.JSON.raw } +func (r *RefusalDeltaBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r refusalDeltaBlockJSON) RawJSON() string { - return r.raw -} - -func (r RefusalDeltaBlock) implementsMessageContentDelta() {} - -// Always `refusal`. -type RefusalDeltaBlockType string - -const ( - RefusalDeltaBlockTypeRefusal RefusalDeltaBlockType = "refusal" -) - -func (r RefusalDeltaBlockType) IsKnown() bool { - switch r { - case RefusalDeltaBlockTypeRefusal: - return true - } - return false -} - type Text struct { - Annotations []Annotation `json:"annotations,required"` + Annotations []AnnotationUnion `json:"annotations,required"` // The data that makes up the text. - Value string `json:"value,required"` - JSON textJSON `json:"-"` -} - -// textJSON contains the JSON metadata for the struct [Text] -type textJSON struct { - Annotations apijson.Field - Value apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Text) UnmarshalJSON(data []byte) (err error) { + Value string `json:"value,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Annotations resp.Field + Value resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Text) RawJSON() string { return r.JSON.raw } +func (r *Text) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r textJSON) RawJSON() string { - return r.raw -} - // The text content that is part of a message. type TextContentBlock struct { Text Text `json:"text,required"` // Always `text`. - Type TextContentBlockType `json:"type,required"` - JSON textContentBlockJSON `json:"-"` -} - -// textContentBlockJSON contains the JSON metadata for the struct -// [TextContentBlock] -type textContentBlockJSON struct { - Text apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *TextContentBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.Text `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Text resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TextContentBlock) RawJSON() string { return r.JSON.raw } +func (r *TextContentBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r textContentBlockJSON) RawJSON() string { - return r.raw -} - -func (r TextContentBlock) implementsMessageContent() {} - -// Always `text`. -type TextContentBlockType string - -const ( - TextContentBlockTypeText TextContentBlockType = "text" -) - -func (r TextContentBlockType) IsKnown() bool { - switch r { - case TextContentBlockTypeText: - return true - } - return false -} - // The text content that is part of a message. +// +// The properties Text, Type are required. type TextContentBlockParam struct { // Text content to be sent to the model - Text param.Field[string] `json:"text,required"` + Text string `json:"text,required"` // Always `text`. - Type param.Field[TextContentBlockParamType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "text". + Type constant.Text `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f TextContentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r TextContentBlockParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r TextContentBlockParam) implementsMessageContentPartParamUnion() {} - -// Always `text`. -type TextContentBlockParamType string - -const ( - TextContentBlockParamTypeText TextContentBlockParamType = "text" -) - -func (r TextContentBlockParamType) IsKnown() bool { - switch r { - case TextContentBlockParamTypeText: - return true - } - return false + type shadow TextContentBlockParam + return param.MarshalObject(r, (*shadow)(&r)) } type TextDelta struct { - Annotations []AnnotationDelta `json:"annotations"` + Annotations []AnnotationDeltaUnion `json:"annotations"` // The data that makes up the text. - Value string `json:"value"` - JSON textDeltaJSON `json:"-"` -} - -// textDeltaJSON contains the JSON metadata for the struct [TextDelta] -type textDeltaJSON struct { - Annotations apijson.Field - Value apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *TextDelta) UnmarshalJSON(data []byte) (err error) { + Value string `json:"value"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Annotations resp.Field + Value resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TextDelta) RawJSON() string { return r.JSON.raw } +func (r *TextDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r textDeltaJSON) RawJSON() string { - return r.raw -} - // The text content that is part of a message. type TextDeltaBlock struct { // The index of the content part in the message. Index int64 `json:"index,required"` // Always `text`. - Type TextDeltaBlockType `json:"type,required"` - Text TextDelta `json:"text"` - JSON textDeltaBlockJSON `json:"-"` -} - -// textDeltaBlockJSON contains the JSON metadata for the struct [TextDeltaBlock] -type textDeltaBlockJSON struct { - Index apijson.Field - Type apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *TextDeltaBlock) UnmarshalJSON(data []byte) (err error) { + Type constant.Text `json:"type,required"` + Text TextDelta `json:"text"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + Text resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r TextDeltaBlock) RawJSON() string { return r.JSON.raw } +func (r *TextDeltaBlock) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r textDeltaBlockJSON) RawJSON() string { - return r.raw -} - -func (r TextDeltaBlock) implementsMessageContentDelta() {} - -// Always `text`. -type TextDeltaBlockType string - -const ( - TextDeltaBlockTypeText TextDeltaBlockType = "text" -) - -func (r TextDeltaBlockType) IsKnown() bool { - switch r { - case TextDeltaBlockTypeText: - return true - } - return false -} - type BetaThreadMessageNewParams struct { // The text contents of the message. - Content param.Field[BetaThreadMessageNewParamsContentUnion] `json:"content,required"` + Content BetaThreadMessageNewParamsContentUnion `json:"content,omitzero,required"` // The role of the entity that is creating the message. Allowed values include: // // - `user`: Indicates the message is sent by an actual user and should be used in // most cases to represent user-generated messages. // - `assistant`: Indicates the message is generated by the assistant. Use this // value to insert messages from the assistant into the conversation. - Role param.Field[BetaThreadMessageNewParamsRole] `json:"role,required"` + // + // Any of "user", "assistant". + Role BetaThreadMessageNewParamsRole `json:"role,omitzero,required"` // A list of files attached to the message, and the tools they should be added to. - Attachments param.Field[[]BetaThreadMessageNewParamsAttachment] `json:"attachments"` + Attachments []BetaThreadMessageNewParamsAttachment `json:"attachments,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadMessageNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadMessageNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadMessageNewParams + return param.MarshalObject(r, (*shadow)(&r)) } -// The text contents of the message. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [BetaThreadMessageNewParamsContentArrayOfContentParts]. -type BetaThreadMessageNewParamsContentUnion interface { - ImplementsBetaThreadMessageNewParamsContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadMessageNewParamsContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []MessageContentPartParamUnion `json:",omitzero,inline"` + paramUnion } -type BetaThreadMessageNewParamsContentArrayOfContentParts []MessageContentPartParamUnion +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadMessageNewParamsContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u BetaThreadMessageNewParamsContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadMessageNewParamsContentUnion](u.OfString, u.OfArrayOfContentParts) +} -func (r BetaThreadMessageNewParamsContentArrayOfContentParts) ImplementsBetaThreadMessageNewParamsContentUnion() { +func (u *BetaThreadMessageNewParamsContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts + } + return nil } // The role of the entity that is creating the message. Allowed values include: @@ -2002,85 +1560,94 @@ const ( BetaThreadMessageNewParamsRoleAssistant BetaThreadMessageNewParamsRole = "assistant" ) -func (r BetaThreadMessageNewParamsRole) IsKnown() bool { - switch r { - case BetaThreadMessageNewParamsRoleUser, BetaThreadMessageNewParamsRoleAssistant: - return true - } - return false -} - type BetaThreadMessageNewParamsAttachment struct { // The ID of the file to attach to the message. - FileID param.Field[string] `json:"file_id"` + FileID param.Opt[string] `json:"file_id,omitzero"` // The tools to add this file to. - Tools param.Field[[]BetaThreadMessageNewParamsAttachmentsToolUnion] `json:"tools"` + Tools []BetaThreadMessageNewParamsAttachmentToolUnion `json:"tools,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadMessageNewParamsAttachment) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadMessageNewParamsAttachment) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadMessageNewParamsAttachment + return param.MarshalObject(r, (*shadow)(&r)) } -type BetaThreadMessageNewParamsAttachmentsTool struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[BetaThreadMessageNewParamsAttachmentsToolsType] `json:"type,required"` +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadMessageNewParamsAttachmentToolUnion struct { + OfCodeInterpreter *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearch *BetaThreadMessageNewParamsAttachmentToolFileSearch `json:",omitzero,inline"` + paramUnion } -func (r BetaThreadMessageNewParamsAttachmentsTool) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadMessageNewParamsAttachmentToolUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() } - -func (r BetaThreadMessageNewParamsAttachmentsTool) implementsBetaThreadMessageNewParamsAttachmentsToolUnion() { +func (u BetaThreadMessageNewParamsAttachmentToolUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadMessageNewParamsAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch) } -// Satisfied by [CodeInterpreterToolParam], -// [BetaThreadMessageNewParamsAttachmentsToolsFileSearch], -// [BetaThreadMessageNewParamsAttachmentsTool]. -type BetaThreadMessageNewParamsAttachmentsToolUnion interface { - implementsBetaThreadMessageNewParamsAttachmentsToolUnion() +func (u *BetaThreadMessageNewParamsAttachmentToolUnion) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreter) { + return u.OfCodeInterpreter + } else if !param.IsOmitted(u.OfFileSearch) { + return u.OfFileSearch + } + return nil } -type BetaThreadMessageNewParamsAttachmentsToolsFileSearch struct { - // The type of tool being defined: `file_search` - Type param.Field[BetaThreadMessageNewParamsAttachmentsToolsFileSearchType] `json:"type,required"` +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadMessageNewParamsAttachmentToolUnion) GetType() *string { + if vt := u.OfCodeInterpreter; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearch; vt != nil { + return (*string)(&vt.Type) + } + return nil } -func (r BetaThreadMessageNewParamsAttachmentsToolsFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +func init() { + apijson.RegisterUnion[BetaThreadMessageNewParamsAttachmentToolUnion]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(CodeInterpreterToolParam{}), + DiscriminatorValue: "code_interpreter", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(BetaThreadMessageNewParamsAttachmentToolFileSearch{}), + DiscriminatorValue: "file_search", + }, + ) } -func (r BetaThreadMessageNewParamsAttachmentsToolsFileSearch) implementsBetaThreadMessageNewParamsAttachmentsToolUnion() { +// The property Type is required. +type BetaThreadMessageNewParamsAttachmentToolFileSearch struct { + // The type of tool being defined: `file_search` + // + // This field can be elided, and will marshal its zero value as "file_search". + Type constant.FileSearch `json:"type,required"` + paramObj } -// The type of tool being defined: `file_search` -type BetaThreadMessageNewParamsAttachmentsToolsFileSearchType string - -const ( - BetaThreadMessageNewParamsAttachmentsToolsFileSearchTypeFileSearch BetaThreadMessageNewParamsAttachmentsToolsFileSearchType = "file_search" -) - -func (r BetaThreadMessageNewParamsAttachmentsToolsFileSearchType) IsKnown() bool { - switch r { - case BetaThreadMessageNewParamsAttachmentsToolsFileSearchTypeFileSearch: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadMessageNewParamsAttachmentToolFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of tool being defined: `code_interpreter` -type BetaThreadMessageNewParamsAttachmentsToolsType string - -const ( - BetaThreadMessageNewParamsAttachmentsToolsTypeCodeInterpreter BetaThreadMessageNewParamsAttachmentsToolsType = "code_interpreter" - BetaThreadMessageNewParamsAttachmentsToolsTypeFileSearch BetaThreadMessageNewParamsAttachmentsToolsType = "file_search" -) - -func (r BetaThreadMessageNewParamsAttachmentsToolsType) IsKnown() bool { - switch r { - case BetaThreadMessageNewParamsAttachmentsToolsTypeCodeInterpreter, BetaThreadMessageNewParamsAttachmentsToolsTypeFileSearch: - return true - } - return false +func (r BetaThreadMessageNewParamsAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadMessageNewParamsAttachmentToolFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadMessageUpdateParams struct { @@ -2090,11 +1657,17 @@ type BetaThreadMessageUpdateParams struct { // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadMessageUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadMessageUpdateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadMessageUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadMessageListParams struct { @@ -2102,22 +1675,29 @@ type BetaThreadMessageListParams struct { // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A cursor for use in pagination. `before` is an object ID that defines your place // in the list. For instance, if you make a list request and receive 100 objects, // starting with obj_foo, your subsequent call can include before=obj_foo in order // to fetch the previous page of the list. - Before param.Field[string] `query:"before"` + Before param.Opt[string] `query:"before,omitzero" json:"-"` // A limit on the number of objects to be returned. Limit can range between 1 and // 100, and the default is 20. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // Filter messages by the run ID that generated them. + RunID param.Opt[string] `query:"run_id,omitzero" json:"-"` // Sort order by the `created_at` timestamp of the objects. `asc` for ascending // order and `desc` for descending order. - Order param.Field[BetaThreadMessageListParamsOrder] `query:"order"` - // Filter messages by the run ID that generated them. - RunID param.Field[string] `query:"run_id"` + // + // Any of "asc", "desc". + Order BetaThreadMessageListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadMessageListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BetaThreadMessageListParams]'s query parameters as // `url.Values`. func (r BetaThreadMessageListParams) URLQuery() (v url.Values) { @@ -2135,11 +1715,3 @@ const ( BetaThreadMessageListParamsOrderAsc BetaThreadMessageListParamsOrder = "asc" BetaThreadMessageListParamsOrderDesc BetaThreadMessageListParamsOrder = "desc" ) - -func (r BetaThreadMessageListParamsOrder) IsKnown() bool { - switch r { - case BetaThreadMessageListParamsOrderAsc, BetaThreadMessageListParamsOrderDesc: - return true - } - return false -} diff --git a/betathreadmessage_test.go b/betathreadmessage_test.go index a151eb9d..e6b3f616 100644 --- a/betathreadmessage_test.go +++ b/betathreadmessage_test.go @@ -30,17 +30,19 @@ func TestBetaThreadMessageNewWithOptionalParams(t *testing.T) { context.TODO(), "thread_id", openai.BetaThreadMessageNewParams{ - Content: openai.F[openai.BetaThreadMessageNewParamsContentUnion](shared.UnionString("string")), - Role: openai.F(openai.BetaThreadMessageNewParamsRoleUser), - Attachments: openai.F([]openai.BetaThreadMessageNewParamsAttachment{{ - FileID: openai.F("file_id"), - Tools: openai.F([]openai.BetaThreadMessageNewParamsAttachmentsToolUnion{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - }}), - Metadata: openai.F(shared.MetadataParam{ + Content: openai.BetaThreadMessageNewParamsContentUnion{ + OfString: openai.String("string"), + }, + Role: openai.BetaThreadMessageNewParamsRoleUser, + Attachments: []openai.BetaThreadMessageNewParamsAttachment{{ + FileID: openai.String("file_id"), + Tools: []openai.BetaThreadMessageNewParamsAttachmentToolUnion{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), + }, }, ) if err != nil { @@ -95,9 +97,9 @@ func TestBetaThreadMessageUpdateWithOptionalParams(t *testing.T) { "thread_id", "message_id", openai.BetaThreadMessageUpdateParams{ - Metadata: openai.F(shared.MetadataParam{ + Metadata: shared.MetadataParam{ "foo": "string", - }), + }, }, ) if err != nil { @@ -125,11 +127,11 @@ func TestBetaThreadMessageListWithOptionalParams(t *testing.T) { context.TODO(), "thread_id", openai.BetaThreadMessageListParams{ - After: openai.F("after"), - Before: openai.F("before"), - Limit: openai.F(int64(0)), - Order: openai.F(openai.BetaThreadMessageListParamsOrderAsc), - RunID: openai.F("run_id"), + After: openai.String("after"), + Before: openai.String("before"), + Limit: openai.Int(0), + Order: openai.BetaThreadMessageListParamsOrderAsc, + RunID: openai.String("run_id"), }, ) if err != nil { diff --git a/betathreadrun.go b/betathreadrun.go index 3c4edcee..5d85cb65 100644 --- a/betathreadrun.go +++ b/betathreadrun.go @@ -8,15 +8,19 @@ import ( "fmt" "net/http" "net/url" + "reflect" "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/packages/ssestream" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" + "github.com/tidwall/gjson" ) // BetaThreadRunService contains methods and other services that help with @@ -27,14 +31,14 @@ import ( // the [NewBetaThreadRunService] method instead. type BetaThreadRunService struct { Options []option.RequestOption - Steps *BetaThreadRunStepService + Steps BetaThreadRunStepService } // NewBetaThreadRunService generates a new service that applies the given options // to each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewBetaThreadRunService(opts ...option.RequestOption) (r *BetaThreadRunService) { - r = &BetaThreadRunService{} +func NewBetaThreadRunService(opts ...option.RequestOption) (r BetaThreadRunService) { + r = BetaThreadRunService{} r.Options = opts r.Steps = NewBetaThreadRunStepService(opts...) return @@ -53,8 +57,18 @@ func (r *BetaThreadRunService) New(ctx context.Context, threadID string, params return } +// Create a run and poll until task is completed. +// Pass 0 to pollIntervalMs to use the default polling interval. +func (r *BetaThreadRunService) NewAndPoll(ctx context.Context, threadID string, params BetaThreadRunNewParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) { + run, err := r.New(ctx, threadID, params, opts...) + if err != nil { + return nil, err + } + return r.PollStatus(ctx, threadID, run.ID, pollIntervalMs, opts...) +} + // Create a run. -func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEvent]) { +func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string, params BetaThreadRunNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) { var ( raw *http.Response err error @@ -67,17 +81,7 @@ func (r *BetaThreadRunService) NewStreaming(ctx context.Context, threadID string } path := fmt.Sprintf("threads/%s/runs", threadID) err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &raw, opts...) - return ssestream.NewStream[AssistantStreamEvent](ssestream.NewDecoder(raw), err) -} - -// Create a run and poll until task is completed. -// Pass 0 to pollIntervalMs to use the default polling interval. -func (r *BetaThreadRunService) NewAndPoll(ctx context.Context, threadID string, params BetaThreadRunNewParams, pollIntervalMs int, opts ...option.RequestOption) (res *Run, err error) { - run, err := r.New(ctx, threadID, params, opts...) - if err != nil { - return nil, err - } - return r.PollStatus(ctx, threadID, run.ID, pollIntervalMs, opts...) + return ssestream.NewStream[AssistantStreamEventUnion](ssestream.NewDecoder(raw), err) } // Retrieves a run. @@ -194,7 +198,7 @@ func (r *BetaThreadRunService) SubmitToolOutputsAndPoll(ctx context.Context, thr // `submit_tool_outputs`, this endpoint can be used to submit the outputs from the // tool calls once they're all completed. All outputs must be submitted in a single // request. -func (r *BetaThreadRunService) SubmitToolOutputsStreaming(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEvent]) { +func (r *BetaThreadRunService) SubmitToolOutputsStreaming(ctx context.Context, threadID string, runID string, body BetaThreadRunSubmitToolOutputsParams, opts ...option.RequestOption) (stream *ssestream.Stream[AssistantStreamEventUnion]) { var ( raw *http.Response err error @@ -211,7 +215,7 @@ func (r *BetaThreadRunService) SubmitToolOutputsStreaming(ctx context.Context, t } path := fmt.Sprintf("threads/%s/runs/%s/submit_tool_outputs", threadID, runID) err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...) - return ssestream.NewStream[AssistantStreamEvent](ssestream.NewDecoder(raw), err) + return ssestream.NewStream[AssistantStreamEventUnion](ssestream.NewDecoder(raw), err) } // Tool call objects @@ -225,70 +229,46 @@ type RequiredActionFunctionToolCall struct { Function RequiredActionFunctionToolCallFunction `json:"function,required"` // The type of tool call the output is required for. For now, this is always // `function`. - Type RequiredActionFunctionToolCallType `json:"type,required"` - JSON requiredActionFunctionToolCallJSON `json:"-"` -} - -// requiredActionFunctionToolCallJSON contains the JSON metadata for the struct -// [RequiredActionFunctionToolCall] -type requiredActionFunctionToolCallJSON struct { - ID apijson.Field - Function apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RequiredActionFunctionToolCall) UnmarshalJSON(data []byte) (err error) { + Type constant.Function `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Function resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RequiredActionFunctionToolCall) RawJSON() string { return r.JSON.raw } +func (r *RequiredActionFunctionToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r requiredActionFunctionToolCallJSON) RawJSON() string { - return r.raw -} - // The function definition. type RequiredActionFunctionToolCallFunction struct { // The arguments that the model expects you to pass to the function. Arguments string `json:"arguments,required"` // The name of the function. - Name string `json:"name,required"` - JSON requiredActionFunctionToolCallFunctionJSON `json:"-"` -} - -// requiredActionFunctionToolCallFunctionJSON contains the JSON metadata for the -// struct [RequiredActionFunctionToolCallFunction] -type requiredActionFunctionToolCallFunctionJSON struct { - Arguments apijson.Field - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RequiredActionFunctionToolCallFunction) UnmarshalJSON(data []byte) (err error) { + Name string `json:"name,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RequiredActionFunctionToolCallFunction) RawJSON() string { return r.JSON.raw } +func (r *RequiredActionFunctionToolCallFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r requiredActionFunctionToolCallFunctionJSON) RawJSON() string { - return r.raw -} - -// The type of tool call the output is required for. For now, this is always -// `function`. -type RequiredActionFunctionToolCallType string - -const ( - RequiredActionFunctionToolCallTypeFunction RequiredActionFunctionToolCallType = "function" -) - -func (r RequiredActionFunctionToolCallType) IsKnown() bool { - switch r { - case RequiredActionFunctionToolCallTypeFunction: - return true - } - return false -} - // Represents an execution run on a // [thread](https://platform.openai.com/docs/api-reference/threads). type Run struct { @@ -299,50 +279,50 @@ type Run struct { // execution of this run. AssistantID string `json:"assistant_id,required"` // The Unix timestamp (in seconds) for when the run was cancelled. - CancelledAt int64 `json:"cancelled_at,required,nullable"` + CancelledAt int64 `json:"cancelled_at,required"` // The Unix timestamp (in seconds) for when the run was completed. - CompletedAt int64 `json:"completed_at,required,nullable"` + CompletedAt int64 `json:"completed_at,required"` // The Unix timestamp (in seconds) for when the run was created. CreatedAt int64 `json:"created_at,required"` // The Unix timestamp (in seconds) for when the run will expire. - ExpiresAt int64 `json:"expires_at,required,nullable"` + ExpiresAt int64 `json:"expires_at,required"` // The Unix timestamp (in seconds) for when the run failed. - FailedAt int64 `json:"failed_at,required,nullable"` + FailedAt int64 `json:"failed_at,required"` // Details on why the run is incomplete. Will be `null` if the run is not // incomplete. - IncompleteDetails RunIncompleteDetails `json:"incomplete_details,required,nullable"` + IncompleteDetails RunIncompleteDetails `json:"incomplete_details,required"` // The instructions that the // [assistant](https://platform.openai.com/docs/api-reference/assistants) used for // this run. Instructions string `json:"instructions,required"` // The last error associated with this run. Will be `null` if there are no errors. - LastError RunLastError `json:"last_error,required,nullable"` + LastError RunLastError `json:"last_error,required"` // The maximum number of completion tokens specified to have been used over the // course of the run. - MaxCompletionTokens int64 `json:"max_completion_tokens,required,nullable"` + MaxCompletionTokens int64 `json:"max_completion_tokens,required"` // The maximum number of prompt tokens specified to have been used over the course // of the run. - MaxPromptTokens int64 `json:"max_prompt_tokens,required,nullable"` + MaxPromptTokens int64 `json:"max_prompt_tokens,required"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata shared.Metadata `json:"metadata,required,nullable"` + Metadata shared.Metadata `json:"metadata,required"` // The model that the // [assistant](https://platform.openai.com/docs/api-reference/assistants) used for // this run. Model string `json:"model,required"` // The object type, which is always `thread.run`. - Object RunObject `json:"object,required"` + Object constant.ThreadRun `json:"object,required"` // Whether to enable // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) // during tool use. ParallelToolCalls bool `json:"parallel_tool_calls,required"` // Details on the action required to continue the run. Will be `null` if no action // is required. - RequiredAction RunRequiredAction `json:"required_action,required,nullable"` + RequiredAction RunRequiredAction `json:"required_action,required"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -363,12 +343,15 @@ type Run struct { // the message content may be partially cut off if `finish_reason="length"`, which // indicates the generation exceeded `max_tokens` or the conversation exceeded the // max context length. - ResponseFormat AssistantResponseFormatOptionUnion `json:"response_format,required,nullable"` + ResponseFormat AssistantResponseFormatOptionUnion `json:"response_format,required"` // The Unix timestamp (in seconds) for when the run was started. - StartedAt int64 `json:"started_at,required,nullable"` + StartedAt int64 `json:"started_at,required"` // The status of the run, which can be either `queued`, `in_progress`, // `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, // `incomplete`, or `expired`. + // + // Any of "queued", "in_progress", "requires_action", "cancelling", "cancelled", + // "failed", "completed", "incomplete", "expired". Status RunStatus `json:"status,required"` // The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) // that was executed on as a part of this run. @@ -380,229 +363,151 @@ type Run struct { // to the user. Specifying a particular tool like `{"type": "file_search"}` or // `{"type": "function", "function": {"name": "my_function"}}` forces the model to // call that tool. - ToolChoice AssistantToolChoiceOptionUnion `json:"tool_choice,required,nullable"` + ToolChoice AssistantToolChoiceOptionUnion `json:"tool_choice,required"` // The list of tools that the // [assistant](https://platform.openai.com/docs/api-reference/assistants) used for // this run. - Tools []AssistantTool `json:"tools,required"` + Tools []AssistantToolUnion `json:"tools,required"` // Controls for how a thread will be truncated prior to the run. Use this to // control the intial context window of the run. - TruncationStrategy RunTruncationStrategy `json:"truncation_strategy,required,nullable"` + TruncationStrategy RunTruncationStrategy `json:"truncation_strategy,required"` // Usage statistics related to the run. This value will be `null` if the run is not // in a terminal state (i.e. `in_progress`, `queued`, etc.). - Usage RunUsage `json:"usage,required,nullable"` + Usage RunUsage `json:"usage,required"` // The sampling temperature used for this run. If not set, defaults to 1. Temperature float64 `json:"temperature,nullable"` // The nucleus sampling value used for this run. If not set, defaults to 1. TopP float64 `json:"top_p,nullable"` - JSON runJSON `json:"-"` -} - -// runJSON contains the JSON metadata for the struct [Run] -type runJSON struct { - ID apijson.Field - AssistantID apijson.Field - CancelledAt apijson.Field - CompletedAt apijson.Field - CreatedAt apijson.Field - ExpiresAt apijson.Field - FailedAt apijson.Field - IncompleteDetails apijson.Field - Instructions apijson.Field - LastError apijson.Field - MaxCompletionTokens apijson.Field - MaxPromptTokens apijson.Field - Metadata apijson.Field - Model apijson.Field - Object apijson.Field - ParallelToolCalls apijson.Field - RequiredAction apijson.Field - ResponseFormat apijson.Field - StartedAt apijson.Field - Status apijson.Field - ThreadID apijson.Field - ToolChoice apijson.Field - Tools apijson.Field - TruncationStrategy apijson.Field - Usage apijson.Field - Temperature apijson.Field - TopP apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Run) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + AssistantID resp.Field + CancelledAt resp.Field + CompletedAt resp.Field + CreatedAt resp.Field + ExpiresAt resp.Field + FailedAt resp.Field + IncompleteDetails resp.Field + Instructions resp.Field + LastError resp.Field + MaxCompletionTokens resp.Field + MaxPromptTokens resp.Field + Metadata resp.Field + Model resp.Field + Object resp.Field + ParallelToolCalls resp.Field + RequiredAction resp.Field + ResponseFormat resp.Field + StartedAt resp.Field + Status resp.Field + ThreadID resp.Field + ToolChoice resp.Field + Tools resp.Field + TruncationStrategy resp.Field + Usage resp.Field + Temperature resp.Field + TopP resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Run) RawJSON() string { return r.JSON.raw } +func (r *Run) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runJSON) RawJSON() string { - return r.raw -} - // Details on why the run is incomplete. Will be `null` if the run is not // incomplete. type RunIncompleteDetails struct { // The reason why the run is incomplete. This will point to which specific token // limit was reached over the course of the run. - Reason RunIncompleteDetailsReason `json:"reason"` - JSON runIncompleteDetailsJSON `json:"-"` -} - -// runIncompleteDetailsJSON contains the JSON metadata for the struct -// [RunIncompleteDetails] -type runIncompleteDetailsJSON struct { - Reason apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunIncompleteDetails) UnmarshalJSON(data []byte) (err error) { + // + // Any of "max_completion_tokens", "max_prompt_tokens". + Reason string `json:"reason"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Reason resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunIncompleteDetails) RawJSON() string { return r.JSON.raw } +func (r *RunIncompleteDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runIncompleteDetailsJSON) RawJSON() string { - return r.raw -} - -// The reason why the run is incomplete. This will point to which specific token -// limit was reached over the course of the run. -type RunIncompleteDetailsReason string - -const ( - RunIncompleteDetailsReasonMaxCompletionTokens RunIncompleteDetailsReason = "max_completion_tokens" - RunIncompleteDetailsReasonMaxPromptTokens RunIncompleteDetailsReason = "max_prompt_tokens" -) - -func (r RunIncompleteDetailsReason) IsKnown() bool { - switch r { - case RunIncompleteDetailsReasonMaxCompletionTokens, RunIncompleteDetailsReasonMaxPromptTokens: - return true - } - return false -} - // The last error associated with this run. Will be `null` if there are no errors. type RunLastError struct { // One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`. - Code RunLastErrorCode `json:"code,required"` + // + // Any of "server_error", "rate_limit_exceeded", "invalid_prompt". + Code string `json:"code,required"` // A human-readable description of the error. - Message string `json:"message,required"` - JSON runLastErrorJSON `json:"-"` -} - -// runLastErrorJSON contains the JSON metadata for the struct [RunLastError] -type runLastErrorJSON struct { - Code apijson.Field - Message apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunLastError) UnmarshalJSON(data []byte) (err error) { + Message string `json:"message,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Code resp.Field + Message resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunLastError) RawJSON() string { return r.JSON.raw } +func (r *RunLastError) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runLastErrorJSON) RawJSON() string { - return r.raw -} - -// One of `server_error`, `rate_limit_exceeded`, or `invalid_prompt`. -type RunLastErrorCode string - -const ( - RunLastErrorCodeServerError RunLastErrorCode = "server_error" - RunLastErrorCodeRateLimitExceeded RunLastErrorCode = "rate_limit_exceeded" - RunLastErrorCodeInvalidPrompt RunLastErrorCode = "invalid_prompt" -) - -func (r RunLastErrorCode) IsKnown() bool { - switch r { - case RunLastErrorCodeServerError, RunLastErrorCodeRateLimitExceeded, RunLastErrorCodeInvalidPrompt: - return true - } - return false -} - -// The object type, which is always `thread.run`. -type RunObject string - -const ( - RunObjectThreadRun RunObject = "thread.run" -) - -func (r RunObject) IsKnown() bool { - switch r { - case RunObjectThreadRun: - return true - } - return false -} - // Details on the action required to continue the run. Will be `null` if no action // is required. type RunRequiredAction struct { // Details on the tool outputs needed for this run to continue. SubmitToolOutputs RunRequiredActionSubmitToolOutputs `json:"submit_tool_outputs,required"` // For now, this is always `submit_tool_outputs`. - Type RunRequiredActionType `json:"type,required"` - JSON runRequiredActionJSON `json:"-"` -} - -// runRequiredActionJSON contains the JSON metadata for the struct -// [RunRequiredAction] -type runRequiredActionJSON struct { - SubmitToolOutputs apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunRequiredAction) UnmarshalJSON(data []byte) (err error) { + Type constant.SubmitToolOutputs `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + SubmitToolOutputs resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunRequiredAction) RawJSON() string { return r.JSON.raw } +func (r *RunRequiredAction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runRequiredActionJSON) RawJSON() string { - return r.raw -} - // Details on the tool outputs needed for this run to continue. type RunRequiredActionSubmitToolOutputs struct { // A list of the relevant tool calls. - ToolCalls []RequiredActionFunctionToolCall `json:"tool_calls,required"` - JSON runRequiredActionSubmitToolOutputsJSON `json:"-"` -} - -// runRequiredActionSubmitToolOutputsJSON contains the JSON metadata for the struct -// [RunRequiredActionSubmitToolOutputs] -type runRequiredActionSubmitToolOutputsJSON struct { - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunRequiredActionSubmitToolOutputs) UnmarshalJSON(data []byte) (err error) { + ToolCalls []RequiredActionFunctionToolCall `json:"tool_calls,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ToolCalls resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunRequiredActionSubmitToolOutputs) RawJSON() string { return r.JSON.raw } +func (r *RunRequiredActionSubmitToolOutputs) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runRequiredActionSubmitToolOutputsJSON) RawJSON() string { - return r.raw -} - -// For now, this is always `submit_tool_outputs`. -type RunRequiredActionType string - -const ( - RunRequiredActionTypeSubmitToolOutputs RunRequiredActionType = "submit_tool_outputs" -) - -func (r RunRequiredActionType) IsKnown() bool { - switch r { - case RunRequiredActionTypeSubmitToolOutputs: - return true - } - return false -} - // Controls for how a thread will be truncated prior to the run. Use this to // control the intial context window of the run. type RunTruncationStrategy struct { @@ -610,49 +515,28 @@ type RunTruncationStrategy struct { // `last_messages`, the thread will be truncated to the n most recent messages in // the thread. When set to `auto`, messages in the middle of the thread will be // dropped to fit the context length of the model, `max_prompt_tokens`. - Type RunTruncationStrategyType `json:"type,required"` + // + // Any of "auto", "last_messages". + Type string `json:"type,required"` // The number of most recent messages from the thread when constructing the context // for the run. - LastMessages int64 `json:"last_messages,nullable"` - JSON runTruncationStrategyJSON `json:"-"` -} - -// runTruncationStrategyJSON contains the JSON metadata for the struct -// [RunTruncationStrategy] -type runTruncationStrategyJSON struct { - Type apijson.Field - LastMessages apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunTruncationStrategy) UnmarshalJSON(data []byte) (err error) { + LastMessages int64 `json:"last_messages,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + LastMessages resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunTruncationStrategy) RawJSON() string { return r.JSON.raw } +func (r *RunTruncationStrategy) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runTruncationStrategyJSON) RawJSON() string { - return r.raw -} - -// The truncation strategy to use for the thread. The default is `auto`. If set to -// `last_messages`, the thread will be truncated to the n most recent messages in -// the thread. When set to `auto`, messages in the middle of the thread will be -// dropped to fit the context length of the model, `max_prompt_tokens`. -type RunTruncationStrategyType string - -const ( - RunTruncationStrategyTypeAuto RunTruncationStrategyType = "auto" - RunTruncationStrategyTypeLastMessages RunTruncationStrategyType = "last_messages" -) - -func (r RunTruncationStrategyType) IsKnown() bool { - switch r { - case RunTruncationStrategyTypeAuto, RunTruncationStrategyTypeLastMessages: - return true - } - return false -} - // Usage statistics related to the run. This value will be `null` if the run is not // in a terminal state (i.e. `in_progress`, `queued`, etc.). type RunUsage struct { @@ -661,27 +545,24 @@ type RunUsage struct { // Number of prompt tokens used over the course of the run. PromptTokens int64 `json:"prompt_tokens,required"` // Total number of tokens used (prompt + completion). - TotalTokens int64 `json:"total_tokens,required"` - JSON runUsageJSON `json:"-"` -} - -// runUsageJSON contains the JSON metadata for the struct [RunUsage] -type runUsageJSON struct { - CompletionTokens apijson.Field - PromptTokens apijson.Field - TotalTokens apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunUsage) UnmarshalJSON(data []byte) (err error) { + TotalTokens int64 `json:"total_tokens,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + CompletionTokens resp.Field + PromptTokens resp.Field + TotalTokens resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunUsage) RawJSON() string { return r.JSON.raw } +func (r *RunUsage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runUsageJSON) RawJSON() string { - return r.raw -} - // The status of the run, which can be either `queued`, `in_progress`, // `requires_action`, `cancelling`, `cancelled`, `failed`, `completed`, // `incomplete`, or `expired`. @@ -699,72 +580,82 @@ const ( RunStatusExpired RunStatus = "expired" ) -func (r RunStatus) IsKnown() bool { - switch r { - case RunStatusQueued, RunStatusInProgress, RunStatusRequiresAction, RunStatusCancelling, RunStatusCancelled, RunStatusFailed, RunStatusCompleted, RunStatusIncomplete, RunStatusExpired: - return true - } - return false -} - type BetaThreadRunNewParams struct { // The ID of the // [assistant](https://platform.openai.com/docs/api-reference/assistants) to use to // execute this run. - AssistantID param.Field[string] `json:"assistant_id,required"` - // A list of additional fields to include in the response. Currently the only - // supported value is `step_details.tool_calls[*].file_search.results[*].content` - // to fetch the file search result content. - // - // See the - // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) - // for more information. - Include param.Field[[]RunStepInclude] `query:"include"` + AssistantID string `json:"assistant_id,required"` // Appends additional instructions at the end of the instructions for the run. This // is useful for modifying the behavior on a per-run basis without overriding other // instructions. - AdditionalInstructions param.Field[string] `json:"additional_instructions"` - // Adds additional messages to the thread before creating the run. - AdditionalMessages param.Field[[]BetaThreadRunNewParamsAdditionalMessage] `json:"additional_messages"` + AdditionalInstructions param.Opt[string] `json:"additional_instructions,omitzero"` // Overrides the // [instructions](https://platform.openai.com/docs/api-reference/assistants/createAssistant) // of the assistant. This is useful for modifying the behavior on a per-run basis. - Instructions param.Field[string] `json:"instructions"` + Instructions param.Opt[string] `json:"instructions,omitzero"` // The maximum number of completion tokens that may be used over the course of the // run. The run will make a best effort to use only the number of completion tokens // specified, across multiple turns of the run. If the run exceeds the number of // completion tokens specified, the run will end with status `incomplete`. See // `incomplete_details` for more info. - MaxCompletionTokens param.Field[int64] `json:"max_completion_tokens"` + MaxCompletionTokens param.Opt[int64] `json:"max_completion_tokens,omitzero"` // The maximum number of prompt tokens that may be used over the course of the run. // The run will make a best effort to use only the number of prompt tokens // specified, across multiple turns of the run. If the run exceeds the number of // prompt tokens specified, the run will end with status `incomplete`. See // `incomplete_details` for more info. - MaxPromptTokens param.Field[int64] `json:"max_prompt_tokens"` + MaxPromptTokens param.Opt[int64] `json:"max_prompt_tokens,omitzero"` + // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will + // make the output more random, while lower values like 0.2 will make it more + // focused and deterministic. + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // An alternative to sampling with temperature, called nucleus sampling, where the + // model considers the results of the tokens with top_p probability mass. So 0.1 + // means only the tokens comprising the top 10% probability mass are considered. + // + // We generally recommend altering this or temperature but not both. + TopP param.Opt[float64] `json:"top_p,omitzero"` + // Whether to enable + // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + // during tool use. + ParallelToolCalls param.Opt[bool] `json:"parallel_tool_calls,omitzero"` + // Adds additional messages to the thread before creating the run. + AdditionalMessages []BetaThreadRunNewParamsAdditionalMessage `json:"additional_messages,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // The ID of the [Model](https://platform.openai.com/docs/api-reference/models) to // be used to execute this run. If a value is provided here, it will override the // model associated with the assistant. If not, the model associated with the // assistant will be used. - Model param.Field[shared.ChatModel] `json:"model"` - // Whether to enable - // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) - // during tool use. - ParallelToolCalls param.Field[bool] `json:"parallel_tool_calls"` + Model shared.ChatModel `json:"model,omitzero"` // **o-series models only** // // Constrains effort on reasoning for // [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently // supported values are `low`, `medium`, and `high`. Reducing reasoning effort can // result in faster responses and fewer tokens used on reasoning in a response. - ReasoningEffort param.Field[shared.ReasoningEffort] `json:"reasoning_effort"` + // + // Any of "low", "medium", "high". + ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"` + // Override the tools the assistant can use for this run. This is useful for + // modifying the behavior on a per-run basis. + Tools []AssistantToolUnionParam `json:"tools,omitzero"` + // Controls for how a thread will be truncated prior to the run. Use this to + // control the intial context window of the run. + TruncationStrategy BetaThreadRunNewParamsTruncationStrategy `json:"truncation_strategy,omitzero"` + // A list of additional fields to include in the response. Currently the only + // supported value is `step_details.tool_calls[*].file_search.results[*].content` + // to fetch the file search result content. + // + // See the + // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) + // for more information. + Include []RunStepInclude `query:"include,omitzero" json:"-"` // Specifies the format that the model must output. Compatible with // [GPT-4o](https://platform.openai.com/docs/models#gpt-4o), // [GPT-4 Turbo](https://platform.openai.com/docs/models#gpt-4-turbo-and-gpt-4), @@ -785,11 +676,7 @@ type BetaThreadRunNewParams struct { // the message content may be partially cut off if `finish_reason="length"`, which // indicates the generation exceeded `max_tokens` or the conversation exceeded the // max context length. - ResponseFormat param.Field[AssistantResponseFormatOptionUnionParam] `json:"response_format"` - // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - // make the output more random, while lower values like 0.2 will make it more - // focused and deterministic. - Temperature param.Field[float64] `json:"temperature"` + ResponseFormat AssistantResponseFormatOptionUnionParam `json:"response_format,omitzero"` // Controls which (if any) tool is called by the model. `none` means the model will // not call any tools and instead generates a message. `auto` is the default value // and means the model can pick between generating a message or calling one or more @@ -797,23 +684,17 @@ type BetaThreadRunNewParams struct { // to the user. Specifying a particular tool like `{"type": "file_search"}` or // `{"type": "function", "function": {"name": "my_function"}}` forces the model to // call that tool. - ToolChoice param.Field[AssistantToolChoiceOptionUnionParam] `json:"tool_choice"` - // Override the tools the assistant can use for this run. This is useful for - // modifying the behavior on a per-run basis. - Tools param.Field[[]AssistantToolUnionParam] `json:"tools"` - // An alternative to sampling with temperature, called nucleus sampling, where the - // model considers the results of the tokens with top_p probability mass. So 0.1 - // means only the tokens comprising the top 10% probability mass are considered. - // - // We generally recommend altering this or temperature but not both. - TopP param.Field[float64] `json:"top_p"` - // Controls for how a thread will be truncated prior to the run. Use this to - // control the intial context window of the run. - TruncationStrategy param.Field[BetaThreadRunNewParamsTruncationStrategy] `json:"truncation_strategy"` + ToolChoice AssistantToolChoiceOptionUnionParam `json:"tool_choice,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadRunNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadRunNewParams + return param.MarshalObject(r, (*shadow)(&r)) } // URLQuery serializes [BetaThreadRunNewParams]'s query parameters as `url.Values`. @@ -824,172 +705,196 @@ func (r BetaThreadRunNewParams) URLQuery() (v url.Values) { }) } +// The properties Content, Role are required. type BetaThreadRunNewParamsAdditionalMessage struct { // The text contents of the message. - Content param.Field[BetaThreadRunNewParamsAdditionalMessagesContentUnion] `json:"content,required"` + Content BetaThreadRunNewParamsAdditionalMessageContentUnion `json:"content,omitzero,required"` // The role of the entity that is creating the message. Allowed values include: // // - `user`: Indicates the message is sent by an actual user and should be used in // most cases to represent user-generated messages. // - `assistant`: Indicates the message is generated by the assistant. Use this // value to insert messages from the assistant into the conversation. - Role param.Field[BetaThreadRunNewParamsAdditionalMessagesRole] `json:"role,required"` + // + // Any of "user", "assistant". + Role string `json:"role,omitzero,required"` // A list of files attached to the message, and the tools they should be added to. - Attachments param.Field[[]BetaThreadRunNewParamsAdditionalMessagesAttachment] `json:"attachments"` + Attachments []BetaThreadRunNewParamsAdditionalMessageAttachment `json:"attachments,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } -func (r BetaThreadRunNewParamsAdditionalMessage) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunNewParamsAdditionalMessage) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The text contents of the message. -// -// Satisfied by [shared.UnionString], -// [BetaThreadRunNewParamsAdditionalMessagesContentArrayOfContentParts]. -type BetaThreadRunNewParamsAdditionalMessagesContentUnion interface { - ImplementsBetaThreadRunNewParamsAdditionalMessagesContentUnion() +func (r BetaThreadRunNewParamsAdditionalMessage) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadRunNewParamsAdditionalMessage + return param.MarshalObject(r, (*shadow)(&r)) } -type BetaThreadRunNewParamsAdditionalMessagesContentArrayOfContentParts []MessageContentPartParamUnion - -func (r BetaThreadRunNewParamsAdditionalMessagesContentArrayOfContentParts) ImplementsBetaThreadRunNewParamsAdditionalMessagesContentUnion() { +func init() { + apijson.RegisterFieldValidator[BetaThreadRunNewParamsAdditionalMessage]( + "Role", false, "user", "assistant", + ) } -// The role of the entity that is creating the message. Allowed values include: +// Only one field can be non-zero. // -// - `user`: Indicates the message is sent by an actual user and should be used in -// most cases to represent user-generated messages. -// - `assistant`: Indicates the message is generated by the assistant. Use this -// value to insert messages from the assistant into the conversation. -type BetaThreadRunNewParamsAdditionalMessagesRole string +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadRunNewParamsAdditionalMessageContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []MessageContentPartParamUnion `json:",omitzero,inline"` + paramUnion +} -const ( - BetaThreadRunNewParamsAdditionalMessagesRoleUser BetaThreadRunNewParamsAdditionalMessagesRole = "user" - BetaThreadRunNewParamsAdditionalMessagesRoleAssistant BetaThreadRunNewParamsAdditionalMessagesRole = "assistant" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadRunNewParamsAdditionalMessageContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u BetaThreadRunNewParamsAdditionalMessageContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadRunNewParamsAdditionalMessageContentUnion](u.OfString, u.OfArrayOfContentParts) +} -func (r BetaThreadRunNewParamsAdditionalMessagesRole) IsKnown() bool { - switch r { - case BetaThreadRunNewParamsAdditionalMessagesRoleUser, BetaThreadRunNewParamsAdditionalMessagesRoleAssistant: - return true +func (u *BetaThreadRunNewParamsAdditionalMessageContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } -type BetaThreadRunNewParamsAdditionalMessagesAttachment struct { +type BetaThreadRunNewParamsAdditionalMessageAttachment struct { // The ID of the file to attach to the message. - FileID param.Field[string] `json:"file_id"` + FileID param.Opt[string] `json:"file_id,omitzero"` // The tools to add this file to. - Tools param.Field[[]BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion] `json:"tools"` + Tools []BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion `json:"tools,omitzero"` + paramObj } -func (r BetaThreadRunNewParamsAdditionalMessagesAttachment) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunNewParamsAdditionalMessageAttachment) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -type BetaThreadRunNewParamsAdditionalMessagesAttachmentsTool struct { - // The type of tool being defined: `code_interpreter` - Type param.Field[BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsType] `json:"type,required"` +func (r BetaThreadRunNewParamsAdditionalMessageAttachment) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadRunNewParamsAdditionalMessageAttachment + return param.MarshalObject(r, (*shadow)(&r)) } -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsTool) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion struct { + OfCodeInterpreter *CodeInterpreterToolParam `json:",omitzero,inline"` + OfFileSearch *BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch `json:",omitzero,inline"` + paramUnion } -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsTool) implementsBetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() } - -// Satisfied by [CodeInterpreterToolParam], -// [BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearch], -// [BetaThreadRunNewParamsAdditionalMessagesAttachmentsTool]. -type BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion interface { - implementsBetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion() +func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion](u.OfCodeInterpreter, u.OfFileSearch) } -type BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearch struct { - // The type of tool being defined: `file_search` - Type param.Field[BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchType] `json:"type,required"` +func (u *BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) asAny() any { + if !param.IsOmitted(u.OfCodeInterpreter) { + return u.OfCodeInterpreter + } else if !param.IsOmitted(u.OfFileSearch) { + return u.OfFileSearch + } + return nil } -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearch) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion) GetType() *string { + if vt := u.OfCodeInterpreter; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFileSearch; vt != nil { + return (*string)(&vt.Type) + } + return nil +} + +func init() { + apijson.RegisterUnion[BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(CodeInterpreterToolParam{}), + DiscriminatorValue: "code_interpreter", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch{}), + DiscriminatorValue: "file_search", + }, + ) } -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearch) implementsBetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion() { +// The property Type is required. +type BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch struct { + // The type of tool being defined: `file_search` + // + // This field can be elided, and will marshal its zero value as "file_search". + Type constant.FileSearch `json:"type,required"` + paramObj } -// The type of tool being defined: `file_search` -type BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchType string - -const ( - BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchTypeFileSearch BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchType = "file_search" -) - -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchType) IsKnown() bool { - switch r { - case BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsFileSearchTypeFileSearch: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of tool being defined: `code_interpreter` -type BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsType string - -const ( - BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsTypeCodeInterpreter BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsType = "code_interpreter" - BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsTypeFileSearch BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsType = "file_search" -) - -func (r BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsType) IsKnown() bool { - switch r { - case BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsTypeCodeInterpreter, BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolsTypeFileSearch: - return true - } - return false +func (r BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch) MarshalJSON() (data []byte, err error) { + type shadow BetaThreadRunNewParamsAdditionalMessageAttachmentToolFileSearch + return param.MarshalObject(r, (*shadow)(&r)) } // Controls for how a thread will be truncated prior to the run. Use this to // control the intial context window of the run. +// +// The property Type is required. type BetaThreadRunNewParamsTruncationStrategy struct { // The truncation strategy to use for the thread. The default is `auto`. If set to // `last_messages`, the thread will be truncated to the n most recent messages in // the thread. When set to `auto`, messages in the middle of the thread will be // dropped to fit the context length of the model, `max_prompt_tokens`. - Type param.Field[BetaThreadRunNewParamsTruncationStrategyType] `json:"type,required"` + // + // Any of "auto", "last_messages". + Type string `json:"type,omitzero,required"` // The number of most recent messages from the thread when constructing the context // for the run. - LastMessages param.Field[int64] `json:"last_messages"` + LastMessages param.Opt[int64] `json:"last_messages,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunNewParamsTruncationStrategy) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadRunNewParamsTruncationStrategy) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadRunNewParamsTruncationStrategy + return param.MarshalObject(r, (*shadow)(&r)) } -// The truncation strategy to use for the thread. The default is `auto`. If set to -// `last_messages`, the thread will be truncated to the n most recent messages in -// the thread. When set to `auto`, messages in the middle of the thread will be -// dropped to fit the context length of the model, `max_prompt_tokens`. -type BetaThreadRunNewParamsTruncationStrategyType string - -const ( - BetaThreadRunNewParamsTruncationStrategyTypeAuto BetaThreadRunNewParamsTruncationStrategyType = "auto" - BetaThreadRunNewParamsTruncationStrategyTypeLastMessages BetaThreadRunNewParamsTruncationStrategyType = "last_messages" -) - -func (r BetaThreadRunNewParamsTruncationStrategyType) IsKnown() bool { - switch r { - case BetaThreadRunNewParamsTruncationStrategyTypeAuto, BetaThreadRunNewParamsTruncationStrategyTypeLastMessages: - return true - } - return false +func init() { + apijson.RegisterFieldValidator[BetaThreadRunNewParamsTruncationStrategy]( + "Type", false, "auto", "last_messages", + ) } type BetaThreadRunUpdateParams struct { @@ -999,11 +904,17 @@ type BetaThreadRunUpdateParams struct { // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r BetaThreadRunUpdateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadRunUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadRunListParams struct { @@ -1011,20 +922,27 @@ type BetaThreadRunListParams struct { // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A cursor for use in pagination. `before` is an object ID that defines your place // in the list. For instance, if you make a list request and receive 100 objects, // starting with obj_foo, your subsequent call can include before=obj_foo in order // to fetch the previous page of the list. - Before param.Field[string] `query:"before"` + Before param.Opt[string] `query:"before,omitzero" json:"-"` // A limit on the number of objects to be returned. Limit can range between 1 and // 100, and the default is 20. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` // Sort order by the `created_at` timestamp of the objects. `asc` for ascending // order and `desc` for descending order. - Order param.Field[BetaThreadRunListParamsOrder] `query:"order"` + // + // Any of "asc", "desc". + Order BetaThreadRunListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BetaThreadRunListParams]'s query parameters as // `url.Values`. func (r BetaThreadRunListParams) URLQuery() (v url.Values) { @@ -1043,31 +961,38 @@ const ( BetaThreadRunListParamsOrderDesc BetaThreadRunListParamsOrder = "desc" ) -func (r BetaThreadRunListParamsOrder) IsKnown() bool { - switch r { - case BetaThreadRunListParamsOrderAsc, BetaThreadRunListParamsOrderDesc: - return true - } - return false -} - type BetaThreadRunSubmitToolOutputsParams struct { // A list of tools for which the outputs are being submitted. - ToolOutputs param.Field[[]BetaThreadRunSubmitToolOutputsParamsToolOutput] `json:"tool_outputs,required"` + ToolOutputs []BetaThreadRunSubmitToolOutputsParamsToolOutput `json:"tool_outputs,omitzero,required"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunSubmitToolOutputsParams) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } func (r BetaThreadRunSubmitToolOutputsParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadRunSubmitToolOutputsParams + return param.MarshalObject(r, (*shadow)(&r)) } type BetaThreadRunSubmitToolOutputsParamsToolOutput struct { // The output of the tool call to be submitted to continue the run. - Output param.Field[string] `json:"output"` + Output param.Opt[string] `json:"output,omitzero"` // The ID of the tool call in the `required_action` object within the run object // the output is being submitted for. - ToolCallID param.Field[string] `json:"tool_call_id"` + ToolCallID param.Opt[string] `json:"tool_call_id,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunSubmitToolOutputsParamsToolOutput) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r BetaThreadRunSubmitToolOutputsParamsToolOutput) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow BetaThreadRunSubmitToolOutputsParamsToolOutput + return param.MarshalObject(r, (*shadow)(&r)) } diff --git a/betathreadrun_test.go b/betathreadrun_test.go index cb2d9325..a8771f6d 100644 --- a/betathreadrun_test.go +++ b/betathreadrun_test.go @@ -12,6 +12,7 @@ import ( "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" ) func TestBetaThreadRunNewWithOptionalParams(t *testing.T) { @@ -30,42 +31,48 @@ func TestBetaThreadRunNewWithOptionalParams(t *testing.T) { context.TODO(), "thread_id", openai.BetaThreadRunNewParams{ - AssistantID: openai.F("assistant_id"), - Include: openai.F([]openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}), - AdditionalInstructions: openai.F("additional_instructions"), - AdditionalMessages: openai.F([]openai.BetaThreadRunNewParamsAdditionalMessage{{ - Content: openai.F[openai.BetaThreadRunNewParamsAdditionalMessagesContentUnion](shared.UnionString("string")), - Role: openai.F(openai.BetaThreadRunNewParamsAdditionalMessagesRoleUser), - Attachments: openai.F([]openai.BetaThreadRunNewParamsAdditionalMessagesAttachment{{ - FileID: openai.F("file_id"), - Tools: openai.F([]openai.BetaThreadRunNewParamsAdditionalMessagesAttachmentsToolUnion{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - }}), - Metadata: openai.F(shared.MetadataParam{ + AssistantID: "assistant_id", + Include: []openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}, + AdditionalInstructions: openai.String("additional_instructions"), + AdditionalMessages: []openai.BetaThreadRunNewParamsAdditionalMessage{{ + Content: openai.BetaThreadRunNewParamsAdditionalMessageContentUnion{ + OfString: openai.String("string"), + }, + Role: "user", + Attachments: []openai.BetaThreadRunNewParamsAdditionalMessageAttachment{{ + FileID: openai.String("file_id"), + Tools: []openai.BetaThreadRunNewParamsAdditionalMessageAttachmentToolUnion{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - }}), - Instructions: openai.F("instructions"), - MaxCompletionTokens: openai.F(int64(256)), - MaxPromptTokens: openai.F(int64(256)), - Metadata: openai.F(shared.MetadataParam{ + }, + }}, + Instructions: openai.String("instructions"), + MaxCompletionTokens: openai.Int(256), + MaxPromptTokens: openai.Int(256), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Model: openai.F(shared.ChatModelO3Mini), - ParallelToolCalls: openai.F(true), - ReasoningEffort: openai.F(shared.ReasoningEffortLow), - ResponseFormat: openai.F[openai.AssistantResponseFormatOptionUnionParam](openai.AssistantResponseFormatOptionString(openai.AssistantResponseFormatOptionStringAuto)), - Temperature: openai.F(1.000000), - ToolChoice: openai.F[openai.AssistantToolChoiceOptionUnionParam](openai.AssistantToolChoiceOptionAuto(openai.AssistantToolChoiceOptionAutoNone)), - Tools: openai.F([]openai.AssistantToolUnionParam{openai.CodeInterpreterToolParam{ - Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter), - }}), - TopP: openai.F(1.000000), - TruncationStrategy: openai.F(openai.BetaThreadRunNewParamsTruncationStrategy{ - Type: openai.F(openai.BetaThreadRunNewParamsTruncationStrategyTypeAuto), - LastMessages: openai.F(int64(1)), - }), + }, + Model: shared.ChatModelO3Mini, + ParallelToolCalls: openai.Bool(true), + ReasoningEffort: shared.ReasoningEffortLow, + ResponseFormat: openai.AssistantResponseFormatOptionUnionParam{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + Temperature: openai.Float(1), + ToolChoice: openai.AssistantToolChoiceOptionUnionParam{ + OfAuto: openai.String("none"), + }, + Tools: []openai.AssistantToolUnionParam{{ + OfCodeInterpreter: &openai.CodeInterpreterToolParam{}, + }}, + TopP: openai.Float(1), + TruncationStrategy: openai.BetaThreadRunNewParamsTruncationStrategy{ + Type: "auto", + LastMessages: openai.Int(1), + }, }, ) if err != nil { @@ -120,9 +127,9 @@ func TestBetaThreadRunUpdateWithOptionalParams(t *testing.T) { "thread_id", "run_id", openai.BetaThreadRunUpdateParams{ - Metadata: openai.F(shared.MetadataParam{ + Metadata: shared.MetadataParam{ "foo": "string", - }), + }, }, ) if err != nil { @@ -150,10 +157,10 @@ func TestBetaThreadRunListWithOptionalParams(t *testing.T) { context.TODO(), "thread_id", openai.BetaThreadRunListParams{ - After: openai.F("after"), - Before: openai.F("before"), - Limit: openai.F(int64(0)), - Order: openai.F(openai.BetaThreadRunListParamsOrderAsc), + After: openai.String("after"), + Before: openai.String("before"), + Limit: openai.Int(0), + Order: openai.BetaThreadRunListParamsOrderAsc, }, ) if err != nil { @@ -208,10 +215,10 @@ func TestBetaThreadRunSubmitToolOutputsWithOptionalParams(t *testing.T) { "thread_id", "run_id", openai.BetaThreadRunSubmitToolOutputsParams{ - ToolOutputs: openai.F([]openai.BetaThreadRunSubmitToolOutputsParamsToolOutput{{ - Output: openai.F("output"), - ToolCallID: openai.F("tool_call_id"), - }}), + ToolOutputs: []openai.BetaThreadRunSubmitToolOutputsParamsToolOutput{{ + Output: openai.String("output"), + ToolCallID: openai.String("tool_call_id"), + }}, }, ) if err != nil { diff --git a/betathreadrunstep.go b/betathreadrunstep.go index eec646bb..1786bf19 100644 --- a/betathreadrunstep.go +++ b/betathreadrunstep.go @@ -4,20 +4,21 @@ package openai import ( "context" + "encoding/json" "errors" "fmt" "net/http" "net/url" - "reflect" "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" - "github.com/tidwall/gjson" + "github.com/openai/openai-go/shared/constant" ) // BetaThreadRunStepService contains methods and other services that help with @@ -33,8 +34,8 @@ type BetaThreadRunStepService struct { // NewBetaThreadRunStepService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewBetaThreadRunStepService(opts ...option.RequestOption) (r *BetaThreadRunStepService) { - r = &BetaThreadRunStepService{} +func NewBetaThreadRunStepService(opts ...option.RequestOption) (r BetaThreadRunStepService) { + r = BetaThreadRunStepService{} r.Options = opts return } @@ -96,114 +97,68 @@ type CodeInterpreterLogs struct { // The index of the output in the outputs array. Index int64 `json:"index,required"` // Always `logs`. - Type CodeInterpreterLogsType `json:"type,required"` + Type constant.Logs `json:"type,required"` // The text output from the Code Interpreter tool call. - Logs string `json:"logs"` - JSON codeInterpreterLogsJSON `json:"-"` -} - -// codeInterpreterLogsJSON contains the JSON metadata for the struct -// [CodeInterpreterLogs] -type codeInterpreterLogsJSON struct { - Index apijson.Field - Type apijson.Field - Logs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterLogs) UnmarshalJSON(data []byte) (err error) { + Logs string `json:"logs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + Logs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterLogs) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterLogs) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterLogsJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterLogs) implementsCodeInterpreterToolCallDeltaCodeInterpreterOutput() {} - -// Always `logs`. -type CodeInterpreterLogsType string - -const ( - CodeInterpreterLogsTypeLogs CodeInterpreterLogsType = "logs" -) - -func (r CodeInterpreterLogsType) IsKnown() bool { - switch r { - case CodeInterpreterLogsTypeLogs: - return true - } - return false -} - type CodeInterpreterOutputImage struct { // The index of the output in the outputs array. Index int64 `json:"index,required"` // Always `image`. - Type CodeInterpreterOutputImageType `json:"type,required"` + Type constant.Image `json:"type,required"` Image CodeInterpreterOutputImageImage `json:"image"` - JSON codeInterpreterOutputImageJSON `json:"-"` -} - -// codeInterpreterOutputImageJSON contains the JSON metadata for the struct -// [CodeInterpreterOutputImage] -type codeInterpreterOutputImageJSON struct { - Index apijson.Field - Type apijson.Field - Image apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterOutputImage) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + Image resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterOutputImage) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterOutputImage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterOutputImageJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterOutputImage) implementsCodeInterpreterToolCallDeltaCodeInterpreterOutput() {} - -// Always `image`. -type CodeInterpreterOutputImageType string - -const ( - CodeInterpreterOutputImageTypeImage CodeInterpreterOutputImageType = "image" -) - -func (r CodeInterpreterOutputImageType) IsKnown() bool { - switch r { - case CodeInterpreterOutputImageTypeImage: - return true - } - return false -} - type CodeInterpreterOutputImageImage struct { // The [file](https://platform.openai.com/docs/api-reference/files) ID of the // image. - FileID string `json:"file_id"` - JSON codeInterpreterOutputImageImageJSON `json:"-"` -} - -// codeInterpreterOutputImageImageJSON contains the JSON metadata for the struct -// [CodeInterpreterOutputImageImage] -type codeInterpreterOutputImageImageJSON struct { - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterOutputImageImage) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterOutputImageImage) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterOutputImageImage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterOutputImageImageJSON) RawJSON() string { - return r.raw -} - // Details of the Code Interpreter tool call the run step was involved in. type CodeInterpreterToolCall struct { // The ID of the tool call. @@ -212,30 +167,24 @@ type CodeInterpreterToolCall struct { CodeInterpreter CodeInterpreterToolCallCodeInterpreter `json:"code_interpreter,required"` // The type of tool call. This is always going to be `code_interpreter` for this // type of tool call. - Type CodeInterpreterToolCallType `json:"type,required"` - JSON codeInterpreterToolCallJSON `json:"-"` -} - -// codeInterpreterToolCallJSON contains the JSON metadata for the struct -// [CodeInterpreterToolCall] -type codeInterpreterToolCallJSON struct { - ID apijson.Field - CodeInterpreter apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCall) UnmarshalJSON(data []byte) (err error) { + Type constant.CodeInterpreter `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CodeInterpreter resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCall) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterToolCall) implementsToolCall() {} - // The Code Interpreter tool call definition. type CodeInterpreterToolCallCodeInterpreter struct { // The input to the Code Interpreter tool call. @@ -243,291 +192,171 @@ type CodeInterpreterToolCallCodeInterpreter struct { // The outputs from the Code Interpreter tool call. Code Interpreter can output one // or more items, including text (`logs`) or images (`image`). Each of these are // represented by a different object type. - Outputs []CodeInterpreterToolCallCodeInterpreterOutput `json:"outputs,required"` - JSON codeInterpreterToolCallCodeInterpreterJSON `json:"-"` -} - -// codeInterpreterToolCallCodeInterpreterJSON contains the JSON metadata for the -// struct [CodeInterpreterToolCallCodeInterpreter] -type codeInterpreterToolCallCodeInterpreterJSON struct { - Input apijson.Field - Outputs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallCodeInterpreter) UnmarshalJSON(data []byte) (err error) { + Outputs []CodeInterpreterToolCallCodeInterpreterOutputUnion `json:"outputs,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Input resp.Field + Outputs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallCodeInterpreter) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallCodeInterpreter) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallCodeInterpreterJSON) RawJSON() string { - return r.raw -} - -// Text output from the Code Interpreter tool call as part of a run step. -type CodeInterpreterToolCallCodeInterpreterOutput struct { - // Always `logs`. - Type CodeInterpreterToolCallCodeInterpreterOutputsType `json:"type,required"` - // This field can have the runtime type of - // [CodeInterpreterToolCallCodeInterpreterOutputsImageImage]. - Image interface{} `json:"image"` - // The text output from the Code Interpreter tool call. - Logs string `json:"logs"` - JSON codeInterpreterToolCallCodeInterpreterOutputJSON `json:"-"` - union CodeInterpreterToolCallCodeInterpreterOutputsUnion -} - -// codeInterpreterToolCallCodeInterpreterOutputJSON contains the JSON metadata for -// the struct [CodeInterpreterToolCallCodeInterpreterOutput] -type codeInterpreterToolCallCodeInterpreterOutputJSON struct { - Type apijson.Field - Image apijson.Field - Logs apijson.Field - raw string - ExtraFields map[string]apijson.Field +// CodeInterpreterToolCallCodeInterpreterOutputUnion contains all possible +// properties and values from [CodeInterpreterToolCallCodeInterpreterOutputLogs], +// [CodeInterpreterToolCallCodeInterpreterOutputImage]. +// +// Use the [CodeInterpreterToolCallCodeInterpreterOutputUnion.AsAny] method to +// switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type CodeInterpreterToolCallCodeInterpreterOutputUnion struct { + // This field is from variant [CodeInterpreterToolCallCodeInterpreterOutputLogs]. + Logs string `json:"logs"` + // Any of "logs", "image". + Type string `json:"type"` + // This field is from variant [CodeInterpreterToolCallCodeInterpreterOutputImage]. + Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image"` + JSON struct { + Logs resp.Field + Type resp.Field + Image resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := CodeInterpreterToolCallCodeInterpreterOutputUnion.AsAny().(type) { +// case CodeInterpreterToolCallCodeInterpreterOutputLogs: +// case CodeInterpreterToolCallCodeInterpreterOutputImage: +// default: +// fmt.Errorf("no variant present") +// } +func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) AsAny() any { + switch u.Type { + case "logs": + return u.AsLogs() + case "image": + return u.AsImage() + } + return nil } -func (r codeInterpreterToolCallCodeInterpreterOutputJSON) RawJSON() string { - return r.raw +func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) AsLogs() (v CodeInterpreterToolCallCodeInterpreterOutputLogs) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *CodeInterpreterToolCallCodeInterpreterOutput) UnmarshalJSON(data []byte) (err error) { - *r = CodeInterpreterToolCallCodeInterpreterOutput{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) AsImage() (v CodeInterpreterToolCallCodeInterpreterOutputImage) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// AsUnion returns a [CodeInterpreterToolCallCodeInterpreterOutputsUnion] interface -// which you can cast to the specific types for more type safety. -// -// Possible runtime types of the union are -// [CodeInterpreterToolCallCodeInterpreterOutputsLogs], -// [CodeInterpreterToolCallCodeInterpreterOutputsImage]. -func (r CodeInterpreterToolCallCodeInterpreterOutput) AsUnion() CodeInterpreterToolCallCodeInterpreterOutputsUnion { - return r.union -} +// Returns the unmodified JSON received from the API +func (u CodeInterpreterToolCallCodeInterpreterOutputUnion) RawJSON() string { return u.JSON.raw } -// Text output from the Code Interpreter tool call as part of a run step. -// -// Union satisfied by [CodeInterpreterToolCallCodeInterpreterOutputsLogs] or -// [CodeInterpreterToolCallCodeInterpreterOutputsImage]. -type CodeInterpreterToolCallCodeInterpreterOutputsUnion interface { - implementsCodeInterpreterToolCallCodeInterpreterOutput() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*CodeInterpreterToolCallCodeInterpreterOutputsUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterToolCallCodeInterpreterOutputsLogs{}), - DiscriminatorValue: "logs", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterToolCallCodeInterpreterOutputsImage{}), - DiscriminatorValue: "image", - }, - ) +func (r *CodeInterpreterToolCallCodeInterpreterOutputUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Text output from the Code Interpreter tool call as part of a run step. -type CodeInterpreterToolCallCodeInterpreterOutputsLogs struct { +type CodeInterpreterToolCallCodeInterpreterOutputLogs struct { // The text output from the Code Interpreter tool call. Logs string `json:"logs,required"` // Always `logs`. - Type CodeInterpreterToolCallCodeInterpreterOutputsLogsType `json:"type,required"` - JSON codeInterpreterToolCallCodeInterpreterOutputsLogsJSON `json:"-"` -} - -// codeInterpreterToolCallCodeInterpreterOutputsLogsJSON contains the JSON metadata -// for the struct [CodeInterpreterToolCallCodeInterpreterOutputsLogs] -type codeInterpreterToolCallCodeInterpreterOutputsLogsJSON struct { - Logs apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallCodeInterpreterOutputsLogs) UnmarshalJSON(data []byte) (err error) { + Type constant.Logs `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Logs resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallCodeInterpreterOutputLogs) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallCodeInterpreterOutputLogs) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallCodeInterpreterOutputsLogsJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterToolCallCodeInterpreterOutputsLogs) implementsCodeInterpreterToolCallCodeInterpreterOutput() { -} - -// Always `logs`. -type CodeInterpreterToolCallCodeInterpreterOutputsLogsType string - -const ( - CodeInterpreterToolCallCodeInterpreterOutputsLogsTypeLogs CodeInterpreterToolCallCodeInterpreterOutputsLogsType = "logs" -) - -func (r CodeInterpreterToolCallCodeInterpreterOutputsLogsType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallCodeInterpreterOutputsLogsTypeLogs: - return true - } - return false -} - -type CodeInterpreterToolCallCodeInterpreterOutputsImage struct { - Image CodeInterpreterToolCallCodeInterpreterOutputsImageImage `json:"image,required"` +type CodeInterpreterToolCallCodeInterpreterOutputImage struct { + Image CodeInterpreterToolCallCodeInterpreterOutputImageImage `json:"image,required"` // Always `image`. - Type CodeInterpreterToolCallCodeInterpreterOutputsImageType `json:"type,required"` - JSON codeInterpreterToolCallCodeInterpreterOutputsImageJSON `json:"-"` -} - -// codeInterpreterToolCallCodeInterpreterOutputsImageJSON contains the JSON -// metadata for the struct [CodeInterpreterToolCallCodeInterpreterOutputsImage] -type codeInterpreterToolCallCodeInterpreterOutputsImageJSON struct { - Image apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallCodeInterpreterOutputsImage) UnmarshalJSON(data []byte) (err error) { + Type constant.Image `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Image resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallCodeInterpreterOutputImage) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallCodeInterpreterOutputImage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallCodeInterpreterOutputsImageJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterToolCallCodeInterpreterOutputsImage) implementsCodeInterpreterToolCallCodeInterpreterOutput() { -} - -type CodeInterpreterToolCallCodeInterpreterOutputsImageImage struct { +type CodeInterpreterToolCallCodeInterpreterOutputImageImage struct { // The [file](https://platform.openai.com/docs/api-reference/files) ID of the // image. - FileID string `json:"file_id,required"` - JSON codeInterpreterToolCallCodeInterpreterOutputsImageImageJSON `json:"-"` -} - -// codeInterpreterToolCallCodeInterpreterOutputsImageImageJSON contains the JSON -// metadata for the struct -// [CodeInterpreterToolCallCodeInterpreterOutputsImageImage] -type codeInterpreterToolCallCodeInterpreterOutputsImageImageJSON struct { - FileID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallCodeInterpreterOutputsImageImage) UnmarshalJSON(data []byte) (err error) { + FileID string `json:"file_id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallCodeInterpreterOutputImageImage) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallCodeInterpreterOutputImageImage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallCodeInterpreterOutputsImageImageJSON) RawJSON() string { - return r.raw -} - -// Always `image`. -type CodeInterpreterToolCallCodeInterpreterOutputsImageType string - -const ( - CodeInterpreterToolCallCodeInterpreterOutputsImageTypeImage CodeInterpreterToolCallCodeInterpreterOutputsImageType = "image" -) - -func (r CodeInterpreterToolCallCodeInterpreterOutputsImageType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallCodeInterpreterOutputsImageTypeImage: - return true - } - return false -} - -// Always `logs`. -type CodeInterpreterToolCallCodeInterpreterOutputsType string - -const ( - CodeInterpreterToolCallCodeInterpreterOutputsTypeLogs CodeInterpreterToolCallCodeInterpreterOutputsType = "logs" - CodeInterpreterToolCallCodeInterpreterOutputsTypeImage CodeInterpreterToolCallCodeInterpreterOutputsType = "image" -) - -func (r CodeInterpreterToolCallCodeInterpreterOutputsType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallCodeInterpreterOutputsTypeLogs, CodeInterpreterToolCallCodeInterpreterOutputsTypeImage: - return true - } - return false -} - -// The type of tool call. This is always going to be `code_interpreter` for this -// type of tool call. -type CodeInterpreterToolCallType string - -const ( - CodeInterpreterToolCallTypeCodeInterpreter CodeInterpreterToolCallType = "code_interpreter" -) - -func (r CodeInterpreterToolCallType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallTypeCodeInterpreter: - return true - } - return false -} - // Details of the Code Interpreter tool call the run step was involved in. type CodeInterpreterToolCallDelta struct { // The index of the tool call in the tool calls array. Index int64 `json:"index,required"` // The type of tool call. This is always going to be `code_interpreter` for this // type of tool call. - Type CodeInterpreterToolCallDeltaType `json:"type,required"` + Type constant.CodeInterpreter `json:"type,required"` // The ID of the tool call. ID string `json:"id"` // The Code Interpreter tool call definition. CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"` - JSON codeInterpreterToolCallDeltaJSON `json:"-"` -} - -// codeInterpreterToolCallDeltaJSON contains the JSON metadata for the struct -// [CodeInterpreterToolCallDelta] -type codeInterpreterToolCallDeltaJSON struct { - Index apijson.Field - Type apijson.Field - ID apijson.Field - CodeInterpreter apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallDelta) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + ID resp.Field + CodeInterpreter resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallDelta) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallDeltaJSON) RawJSON() string { - return r.raw -} - -func (r CodeInterpreterToolCallDelta) implementsToolCallDelta() {} - -// The type of tool call. This is always going to be `code_interpreter` for this -// type of tool call. -type CodeInterpreterToolCallDeltaType string - -const ( - CodeInterpreterToolCallDeltaTypeCodeInterpreter CodeInterpreterToolCallDeltaType = "code_interpreter" -) - -func (r CodeInterpreterToolCallDeltaType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallDeltaTypeCodeInterpreter: - return true - } - return false -} - // The Code Interpreter tool call definition. type CodeInterpreterToolCallDeltaCodeInterpreter struct { // The input to the Code Interpreter tool call. @@ -535,112 +364,80 @@ type CodeInterpreterToolCallDeltaCodeInterpreter struct { // The outputs from the Code Interpreter tool call. Code Interpreter can output one // or more items, including text (`logs`) or images (`image`). Each of these are // represented by a different object type. - Outputs []CodeInterpreterToolCallDeltaCodeInterpreterOutput `json:"outputs"` - JSON codeInterpreterToolCallDeltaCodeInterpreterJSON `json:"-"` -} - -// codeInterpreterToolCallDeltaCodeInterpreterJSON contains the JSON metadata for -// the struct [CodeInterpreterToolCallDeltaCodeInterpreter] -type codeInterpreterToolCallDeltaCodeInterpreterJSON struct { - Input apijson.Field - Outputs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CodeInterpreterToolCallDeltaCodeInterpreter) UnmarshalJSON(data []byte) (err error) { + Outputs []CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion `json:"outputs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Input resp.Field + Outputs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CodeInterpreterToolCallDeltaCodeInterpreter) RawJSON() string { return r.JSON.raw } +func (r *CodeInterpreterToolCallDeltaCodeInterpreter) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r codeInterpreterToolCallDeltaCodeInterpreterJSON) RawJSON() string { - return r.raw -} - -// Text output from the Code Interpreter tool call as part of a run step. -type CodeInterpreterToolCallDeltaCodeInterpreterOutput struct { - // The index of the output in the outputs array. - Index int64 `json:"index,required"` - // Always `logs`. - Type CodeInterpreterToolCallDeltaCodeInterpreterOutputsType `json:"type,required"` - // This field can have the runtime type of [CodeInterpreterOutputImageImage]. - Image interface{} `json:"image"` - // The text output from the Code Interpreter tool call. - Logs string `json:"logs"` - JSON codeInterpreterToolCallDeltaCodeInterpreterOutputJSON `json:"-"` - union CodeInterpreterToolCallDeltaCodeInterpreterOutputsUnion -} - -// codeInterpreterToolCallDeltaCodeInterpreterOutputJSON contains the JSON metadata -// for the struct [CodeInterpreterToolCallDeltaCodeInterpreterOutput] -type codeInterpreterToolCallDeltaCodeInterpreterOutputJSON struct { - Index apijson.Field - Type apijson.Field - Image apijson.Field - Logs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r codeInterpreterToolCallDeltaCodeInterpreterOutputJSON) RawJSON() string { - return r.raw +// CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion contains all possible +// properties and values from [CodeInterpreterLogs], [CodeInterpreterOutputImage]. +// +// Use the [CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion.AsAny] method to +// switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion struct { + Index int64 `json:"index"` + // Any of "logs", "image". + Type string `json:"type"` + // This field is from variant [CodeInterpreterLogs]. + Logs string `json:"logs"` + // This field is from variant [CodeInterpreterOutputImage]. + Image CodeInterpreterOutputImageImage `json:"image"` + JSON struct { + Index resp.Field + Type resp.Field + Logs resp.Field + Image resp.Field + raw string + } `json:"-"` } -func (r *CodeInterpreterToolCallDeltaCodeInterpreterOutput) UnmarshalJSON(data []byte) (err error) { - *r = CodeInterpreterToolCallDeltaCodeInterpreterOutput{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err +// Use the following switch statement to find the correct variant +// +// switch variant := CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion.AsAny().(type) { +// case CodeInterpreterLogs: +// case CodeInterpreterOutputImage: +// default: +// fmt.Errorf("no variant present") +// } +func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) AsAny() any { + switch u.Type { + case "logs": + return u.AsLogs() + case "image": + return u.AsImage() } - return apijson.Port(r.union, &r) + return nil } -// AsUnion returns a [CodeInterpreterToolCallDeltaCodeInterpreterOutputsUnion] -// interface which you can cast to the specific types for more type safety. -// -// Possible runtime types of the union are [CodeInterpreterLogs], -// [CodeInterpreterOutputImage]. -func (r CodeInterpreterToolCallDeltaCodeInterpreterOutput) AsUnion() CodeInterpreterToolCallDeltaCodeInterpreterOutputsUnion { - return r.union +func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) AsLogs() (v CodeInterpreterLogs) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// Text output from the Code Interpreter tool call as part of a run step. -// -// Union satisfied by [CodeInterpreterLogs] or [CodeInterpreterOutputImage]. -type CodeInterpreterToolCallDeltaCodeInterpreterOutputsUnion interface { - implementsCodeInterpreterToolCallDeltaCodeInterpreterOutput() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*CodeInterpreterToolCallDeltaCodeInterpreterOutputsUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterLogs{}), - DiscriminatorValue: "logs", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterOutputImage{}), - DiscriminatorValue: "image", - }, - ) -} - -// Always `logs`. -type CodeInterpreterToolCallDeltaCodeInterpreterOutputsType string +func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) AsImage() (v CodeInterpreterOutputImage) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - CodeInterpreterToolCallDeltaCodeInterpreterOutputsTypeLogs CodeInterpreterToolCallDeltaCodeInterpreterOutputsType = "logs" - CodeInterpreterToolCallDeltaCodeInterpreterOutputsTypeImage CodeInterpreterToolCallDeltaCodeInterpreterOutputsType = "image" -) +// Returns the unmodified JSON received from the API +func (u CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) RawJSON() string { return u.JSON.raw } -func (r CodeInterpreterToolCallDeltaCodeInterpreterOutputsType) IsKnown() bool { - switch r { - case CodeInterpreterToolCallDeltaCodeInterpreterOutputsTypeLogs, CodeInterpreterToolCallDeltaCodeInterpreterOutputsTypeImage: - return true - } - return false +func (r *CodeInterpreterToolCallDeltaCodeInterpreterOutputUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } type FileSearchToolCall struct { @@ -650,101 +447,72 @@ type FileSearchToolCall struct { FileSearch FileSearchToolCallFileSearch `json:"file_search,required"` // The type of tool call. This is always going to be `file_search` for this type of // tool call. - Type FileSearchToolCallType `json:"type,required"` - JSON fileSearchToolCallJSON `json:"-"` -} - -// fileSearchToolCallJSON contains the JSON metadata for the struct -// [FileSearchToolCall] -type fileSearchToolCallJSON struct { - ID apijson.Field - FileSearch apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCall) UnmarshalJSON(data []byte) (err error) { + Type constant.FileSearch `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + FileSearch resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCall) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallJSON) RawJSON() string { - return r.raw -} - -func (r FileSearchToolCall) implementsToolCall() {} - // For now, this is always going to be an empty object. type FileSearchToolCallFileSearch struct { // The ranking options for the file search. RankingOptions FileSearchToolCallFileSearchRankingOptions `json:"ranking_options"` // The results of the file search. Results []FileSearchToolCallFileSearchResult `json:"results"` - JSON fileSearchToolCallFileSearchJSON `json:"-"` -} - -// fileSearchToolCallFileSearchJSON contains the JSON metadata for the struct -// [FileSearchToolCallFileSearch] -type fileSearchToolCallFileSearchJSON struct { - RankingOptions apijson.Field - Results apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCallFileSearch) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + RankingOptions resp.Field + Results resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCallFileSearch) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCallFileSearch) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallFileSearchJSON) RawJSON() string { - return r.raw -} - // The ranking options for the file search. type FileSearchToolCallFileSearchRankingOptions struct { // The ranker to use for the file search. If not specified will use the `auto` // ranker. - Ranker FileSearchToolCallFileSearchRankingOptionsRanker `json:"ranker,required"` + // + // Any of "auto", "default_2024_08_21". + Ranker string `json:"ranker,required"` // The score threshold for the file search. All values must be a floating point // number between 0 and 1. - ScoreThreshold float64 `json:"score_threshold,required"` - JSON fileSearchToolCallFileSearchRankingOptionsJSON `json:"-"` -} - -// fileSearchToolCallFileSearchRankingOptionsJSON contains the JSON metadata for -// the struct [FileSearchToolCallFileSearchRankingOptions] -type fileSearchToolCallFileSearchRankingOptionsJSON struct { - Ranker apijson.Field - ScoreThreshold apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCallFileSearchRankingOptions) UnmarshalJSON(data []byte) (err error) { + ScoreThreshold float64 `json:"score_threshold,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Ranker resp.Field + ScoreThreshold resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCallFileSearchRankingOptions) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCallFileSearchRankingOptions) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallFileSearchRankingOptionsJSON) RawJSON() string { - return r.raw -} - -// The ranker to use for the file search. If not specified will use the `auto` -// ranker. -type FileSearchToolCallFileSearchRankingOptionsRanker string - -const ( - FileSearchToolCallFileSearchRankingOptionsRankerAuto FileSearchToolCallFileSearchRankingOptionsRanker = "auto" - FileSearchToolCallFileSearchRankingOptionsRankerDefault2024_08_21 FileSearchToolCallFileSearchRankingOptionsRanker = "default_2024_08_21" -) - -func (r FileSearchToolCallFileSearchRankingOptionsRanker) IsKnown() bool { - switch r { - case FileSearchToolCallFileSearchRankingOptionsRankerAuto, FileSearchToolCallFileSearchRankingOptionsRankerDefault2024_08_21: - return true - } - return false -} - // A result instance of the file search. type FileSearchToolCallFileSearchResult struct { // The ID of the file that result was found in. @@ -756,85 +524,48 @@ type FileSearchToolCallFileSearchResult struct { Score float64 `json:"score,required"` // The content of the result that was found. The content is only included if // requested via the include query parameter. - Content []FileSearchToolCallFileSearchResultsContent `json:"content"` - JSON fileSearchToolCallFileSearchResultJSON `json:"-"` -} - -// fileSearchToolCallFileSearchResultJSON contains the JSON metadata for the struct -// [FileSearchToolCallFileSearchResult] -type fileSearchToolCallFileSearchResultJSON struct { - FileID apijson.Field - FileName apijson.Field - Score apijson.Field - Content apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCallFileSearchResult) UnmarshalJSON(data []byte) (err error) { + Content []FileSearchToolCallFileSearchResultContent `json:"content"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileID resp.Field + FileName resp.Field + Score resp.Field + Content resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCallFileSearchResult) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCallFileSearchResult) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallFileSearchResultJSON) RawJSON() string { - return r.raw -} - -type FileSearchToolCallFileSearchResultsContent struct { +type FileSearchToolCallFileSearchResultContent struct { // The text content of the file. Text string `json:"text"` // The type of the content. - Type FileSearchToolCallFileSearchResultsContentType `json:"type"` - JSON fileSearchToolCallFileSearchResultsContentJSON `json:"-"` -} - -// fileSearchToolCallFileSearchResultsContentJSON contains the JSON metadata for -// the struct [FileSearchToolCallFileSearchResultsContent] -type fileSearchToolCallFileSearchResultsContentJSON struct { - Text apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCallFileSearchResultsContent) UnmarshalJSON(data []byte) (err error) { + // + // Any of "text". + Type string `json:"type"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Text resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCallFileSearchResultContent) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCallFileSearchResultContent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallFileSearchResultsContentJSON) RawJSON() string { - return r.raw -} - -// The type of the content. -type FileSearchToolCallFileSearchResultsContentType string - -const ( - FileSearchToolCallFileSearchResultsContentTypeText FileSearchToolCallFileSearchResultsContentType = "text" -) - -func (r FileSearchToolCallFileSearchResultsContentType) IsKnown() bool { - switch r { - case FileSearchToolCallFileSearchResultsContentTypeText: - return true - } - return false -} - -// The type of tool call. This is always going to be `file_search` for this type of -// tool call. -type FileSearchToolCallType string - -const ( - FileSearchToolCallTypeFileSearch FileSearchToolCallType = "file_search" -) - -func (r FileSearchToolCallType) IsKnown() bool { - switch r { - case FileSearchToolCallTypeFileSearch: - return true - } - return false -} - type FileSearchToolCallDelta struct { // For now, this is always going to be an empty object. FileSearch interface{} `json:"file_search,required"` @@ -842,49 +573,27 @@ type FileSearchToolCallDelta struct { Index int64 `json:"index,required"` // The type of tool call. This is always going to be `file_search` for this type of // tool call. - Type FileSearchToolCallDeltaType `json:"type,required"` + Type constant.FileSearch `json:"type,required"` // The ID of the tool call object. - ID string `json:"id"` - JSON fileSearchToolCallDeltaJSON `json:"-"` -} - -// fileSearchToolCallDeltaJSON contains the JSON metadata for the struct -// [FileSearchToolCallDelta] -type fileSearchToolCallDeltaJSON struct { - FileSearch apijson.Field - Index apijson.Field - Type apijson.Field - ID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileSearchToolCallDelta) UnmarshalJSON(data []byte) (err error) { + ID string `json:"id"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FileSearch resp.Field + Index resp.Field + Type resp.Field + ID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FileSearchToolCallDelta) RawJSON() string { return r.JSON.raw } +func (r *FileSearchToolCallDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileSearchToolCallDeltaJSON) RawJSON() string { - return r.raw -} - -func (r FileSearchToolCallDelta) implementsToolCallDelta() {} - -// The type of tool call. This is always going to be `file_search` for this type of -// tool call. -type FileSearchToolCallDeltaType string - -const ( - FileSearchToolCallDeltaTypeFileSearch FileSearchToolCallDeltaType = "file_search" -) - -func (r FileSearchToolCallDeltaType) IsKnown() bool { - switch r { - case FileSearchToolCallDeltaTypeFileSearch: - return true - } - return false -} - type FunctionToolCall struct { // The ID of the tool call object. ID string `json:"id,required"` @@ -892,30 +601,24 @@ type FunctionToolCall struct { Function FunctionToolCallFunction `json:"function,required"` // The type of tool call. This is always going to be `function` for this type of // tool call. - Type FunctionToolCallType `json:"type,required"` - JSON functionToolCallJSON `json:"-"` -} - -// functionToolCallJSON contains the JSON metadata for the struct -// [FunctionToolCall] -type functionToolCallJSON struct { - ID apijson.Field - Function apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FunctionToolCall) UnmarshalJSON(data []byte) (err error) { + Type constant.Function `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Function resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FunctionToolCall) RawJSON() string { return r.JSON.raw } +func (r *FunctionToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r functionToolCallJSON) RawJSON() string { - return r.raw -} - -func (r FunctionToolCall) implementsToolCall() {} - // The definition of the function that was called. type FunctionToolCallFunction struct { // The arguments passed to the function. @@ -925,94 +628,52 @@ type FunctionToolCallFunction struct { // The output of the function. This will be `null` if the outputs have not been // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs) // yet. - Output string `json:"output,required,nullable"` - JSON functionToolCallFunctionJSON `json:"-"` -} - -// functionToolCallFunctionJSON contains the JSON metadata for the struct -// [FunctionToolCallFunction] -type functionToolCallFunctionJSON struct { - Arguments apijson.Field - Name apijson.Field - Output apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FunctionToolCallFunction) UnmarshalJSON(data []byte) (err error) { + Output string `json:"output,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + Output resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FunctionToolCallFunction) RawJSON() string { return r.JSON.raw } +func (r *FunctionToolCallFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r functionToolCallFunctionJSON) RawJSON() string { - return r.raw -} - -// The type of tool call. This is always going to be `function` for this type of -// tool call. -type FunctionToolCallType string - -const ( - FunctionToolCallTypeFunction FunctionToolCallType = "function" -) - -func (r FunctionToolCallType) IsKnown() bool { - switch r { - case FunctionToolCallTypeFunction: - return true - } - return false -} - type FunctionToolCallDelta struct { // The index of the tool call in the tool calls array. Index int64 `json:"index,required"` // The type of tool call. This is always going to be `function` for this type of // tool call. - Type FunctionToolCallDeltaType `json:"type,required"` + Type constant.Function `json:"type,required"` // The ID of the tool call object. ID string `json:"id"` // The definition of the function that was called. Function FunctionToolCallDeltaFunction `json:"function"` - JSON functionToolCallDeltaJSON `json:"-"` -} - -// functionToolCallDeltaJSON contains the JSON metadata for the struct -// [FunctionToolCallDelta] -type functionToolCallDeltaJSON struct { - Index apijson.Field - Type apijson.Field - ID apijson.Field - Function apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FunctionToolCallDelta) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + Type resp.Field + ID resp.Field + Function resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FunctionToolCallDelta) RawJSON() string { return r.JSON.raw } +func (r *FunctionToolCallDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r functionToolCallDeltaJSON) RawJSON() string { - return r.raw -} - -func (r FunctionToolCallDelta) implementsToolCallDelta() {} - -// The type of tool call. This is always going to be `function` for this type of -// tool call. -type FunctionToolCallDeltaType string - -const ( - FunctionToolCallDeltaTypeFunction FunctionToolCallDeltaType = "function" -) - -func (r FunctionToolCallDeltaType) IsKnown() bool { - switch r { - case FunctionToolCallDeltaTypeFunction: - return true - } - return false -} - // The definition of the function that was called. type FunctionToolCallDeltaFunction struct { // The arguments passed to the function. @@ -1022,92 +683,63 @@ type FunctionToolCallDeltaFunction struct { // The output of the function. This will be `null` if the outputs have not been // [submitted](https://platform.openai.com/docs/api-reference/runs/submitToolOutputs) // yet. - Output string `json:"output,nullable"` - JSON functionToolCallDeltaFunctionJSON `json:"-"` -} - -// functionToolCallDeltaFunctionJSON contains the JSON metadata for the struct -// [FunctionToolCallDeltaFunction] -type functionToolCallDeltaFunctionJSON struct { - Arguments apijson.Field - Name apijson.Field - Output apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FunctionToolCallDeltaFunction) UnmarshalJSON(data []byte) (err error) { + Output string `json:"output,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + Output resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FunctionToolCallDeltaFunction) RawJSON() string { return r.JSON.raw } +func (r *FunctionToolCallDeltaFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r functionToolCallDeltaFunctionJSON) RawJSON() string { - return r.raw -} - // Details of the message creation by the run step. type MessageCreationStepDetails struct { MessageCreation MessageCreationStepDetailsMessageCreation `json:"message_creation,required"` // Always `message_creation`. - Type MessageCreationStepDetailsType `json:"type,required"` - JSON messageCreationStepDetailsJSON `json:"-"` -} - -// messageCreationStepDetailsJSON contains the JSON metadata for the struct -// [MessageCreationStepDetails] -type messageCreationStepDetailsJSON struct { - MessageCreation apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageCreationStepDetails) UnmarshalJSON(data []byte) (err error) { + Type constant.MessageCreation `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + MessageCreation resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageCreationStepDetails) RawJSON() string { return r.JSON.raw } +func (r *MessageCreationStepDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageCreationStepDetailsJSON) RawJSON() string { - return r.raw -} - -func (r MessageCreationStepDetails) implementsRunStepStepDetails() {} - type MessageCreationStepDetailsMessageCreation struct { // The ID of the message that was created by this run step. - MessageID string `json:"message_id,required"` - JSON messageCreationStepDetailsMessageCreationJSON `json:"-"` -} - -// messageCreationStepDetailsMessageCreationJSON contains the JSON metadata for the -// struct [MessageCreationStepDetailsMessageCreation] -type messageCreationStepDetailsMessageCreationJSON struct { - MessageID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *MessageCreationStepDetailsMessageCreation) UnmarshalJSON(data []byte) (err error) { + MessageID string `json:"message_id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + MessageID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r MessageCreationStepDetailsMessageCreation) RawJSON() string { return r.JSON.raw } +func (r *MessageCreationStepDetailsMessageCreation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r messageCreationStepDetailsMessageCreationJSON) RawJSON() string { - return r.raw -} - -// Always `message_creation`. -type MessageCreationStepDetailsType string - -const ( - MessageCreationStepDetailsTypeMessageCreation MessageCreationStepDetailsType = "message_creation" -) - -func (r MessageCreationStepDetailsType) IsKnown() bool { - switch r { - case MessageCreationStepDetailsTypeMessageCreation: - return true - } - return false -} - // Represents a step in execution of a run. type RunStep struct { // The identifier of the run step, which can be referenced in API endpoints. @@ -1117,135 +749,103 @@ type RunStep struct { // associated with the run step. AssistantID string `json:"assistant_id,required"` // The Unix timestamp (in seconds) for when the run step was cancelled. - CancelledAt int64 `json:"cancelled_at,required,nullable"` + CancelledAt int64 `json:"cancelled_at,required"` // The Unix timestamp (in seconds) for when the run step completed. - CompletedAt int64 `json:"completed_at,required,nullable"` + CompletedAt int64 `json:"completed_at,required"` // The Unix timestamp (in seconds) for when the run step was created. CreatedAt int64 `json:"created_at,required"` // The Unix timestamp (in seconds) for when the run step expired. A step is // considered expired if the parent run is expired. - ExpiredAt int64 `json:"expired_at,required,nullable"` + ExpiredAt int64 `json:"expired_at,required"` // The Unix timestamp (in seconds) for when the run step failed. - FailedAt int64 `json:"failed_at,required,nullable"` + FailedAt int64 `json:"failed_at,required"` // The last error associated with this run step. Will be `null` if there are no // errors. - LastError RunStepLastError `json:"last_error,required,nullable"` + LastError RunStepLastError `json:"last_error,required"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata shared.Metadata `json:"metadata,required,nullable"` + Metadata shared.Metadata `json:"metadata,required"` // The object type, which is always `thread.run.step`. - Object RunStepObject `json:"object,required"` + Object constant.ThreadRunStep `json:"object,required"` // The ID of the [run](https://platform.openai.com/docs/api-reference/runs) that // this run step is a part of. RunID string `json:"run_id,required"` // The status of the run step, which can be either `in_progress`, `cancelled`, // `failed`, `completed`, or `expired`. + // + // Any of "in_progress", "cancelled", "failed", "completed", "expired". Status RunStepStatus `json:"status,required"` // The details of the run step. - StepDetails RunStepStepDetails `json:"step_details,required"` + StepDetails RunStepStepDetailsUnion `json:"step_details,required"` // The ID of the [thread](https://platform.openai.com/docs/api-reference/threads) // that was run. ThreadID string `json:"thread_id,required"` // The type of run step, which can be either `message_creation` or `tool_calls`. + // + // Any of "message_creation", "tool_calls". Type RunStepType `json:"type,required"` // Usage statistics related to the run step. This value will be `null` while the // run step's status is `in_progress`. - Usage RunStepUsage `json:"usage,required,nullable"` - JSON runStepJSON `json:"-"` -} - -// runStepJSON contains the JSON metadata for the struct [RunStep] -type runStepJSON struct { - ID apijson.Field - AssistantID apijson.Field - CancelledAt apijson.Field - CompletedAt apijson.Field - CreatedAt apijson.Field - ExpiredAt apijson.Field - FailedAt apijson.Field - LastError apijson.Field - Metadata apijson.Field - Object apijson.Field - RunID apijson.Field - Status apijson.Field - StepDetails apijson.Field - ThreadID apijson.Field - Type apijson.Field - Usage apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStep) UnmarshalJSON(data []byte) (err error) { + Usage RunStepUsage `json:"usage,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + AssistantID resp.Field + CancelledAt resp.Field + CompletedAt resp.Field + CreatedAt resp.Field + ExpiredAt resp.Field + FailedAt resp.Field + LastError resp.Field + Metadata resp.Field + Object resp.Field + RunID resp.Field + Status resp.Field + StepDetails resp.Field + ThreadID resp.Field + Type resp.Field + Usage resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStep) RawJSON() string { return r.JSON.raw } +func (r *RunStep) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepJSON) RawJSON() string { - return r.raw -} - // The last error associated with this run step. Will be `null` if there are no // errors. type RunStepLastError struct { // One of `server_error` or `rate_limit_exceeded`. - Code RunStepLastErrorCode `json:"code,required"` + // + // Any of "server_error", "rate_limit_exceeded". + Code string `json:"code,required"` // A human-readable description of the error. - Message string `json:"message,required"` - JSON runStepLastErrorJSON `json:"-"` -} - -// runStepLastErrorJSON contains the JSON metadata for the struct -// [RunStepLastError] -type runStepLastErrorJSON struct { - Code apijson.Field - Message apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepLastError) UnmarshalJSON(data []byte) (err error) { + Message string `json:"message,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Code resp.Field + Message resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepLastError) RawJSON() string { return r.JSON.raw } +func (r *RunStepLastError) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepLastErrorJSON) RawJSON() string { - return r.raw -} - -// One of `server_error` or `rate_limit_exceeded`. -type RunStepLastErrorCode string - -const ( - RunStepLastErrorCodeServerError RunStepLastErrorCode = "server_error" - RunStepLastErrorCodeRateLimitExceeded RunStepLastErrorCode = "rate_limit_exceeded" -) - -func (r RunStepLastErrorCode) IsKnown() bool { - switch r { - case RunStepLastErrorCodeServerError, RunStepLastErrorCodeRateLimitExceeded: - return true - } - return false -} - -// The object type, which is always `thread.run.step`. -type RunStepObject string - -const ( - RunStepObjectThreadRunStep RunStepObject = "thread.run.step" -) - -func (r RunStepObject) IsKnown() bool { - switch r { - case RunStepObjectThreadRunStep: - return true - } - return false -} - // The status of the run step, which can be either `in_progress`, `cancelled`, // `failed`, `completed`, or `expired`. type RunStepStatus string @@ -1258,97 +858,60 @@ const ( RunStepStatusExpired RunStepStatus = "expired" ) -func (r RunStepStatus) IsKnown() bool { - switch r { - case RunStepStatusInProgress, RunStepStatusCancelled, RunStepStatusFailed, RunStepStatusCompleted, RunStepStatusExpired: - return true +// RunStepStepDetailsUnion contains all possible properties and values from +// [MessageCreationStepDetails], [ToolCallsStepDetails]. +// +// Use the [RunStepStepDetailsUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type RunStepStepDetailsUnion struct { + // This field is from variant [MessageCreationStepDetails]. + MessageCreation MessageCreationStepDetailsMessageCreation `json:"message_creation"` + // Any of "message_creation", "tool_calls". + Type string `json:"type"` + // This field is from variant [ToolCallsStepDetails]. + ToolCalls []ToolCallUnion `json:"tool_calls"` + JSON struct { + MessageCreation resp.Field + Type resp.Field + ToolCalls resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := RunStepStepDetailsUnion.AsAny().(type) { +// case MessageCreationStepDetails: +// case ToolCallsStepDetails: +// default: +// fmt.Errorf("no variant present") +// } +func (u RunStepStepDetailsUnion) AsAny() any { + switch u.Type { + case "message_creation": + return u.AsMessageCreation() + case "tool_calls": + return u.AsToolCalls() } - return false -} - -// The details of the run step. -type RunStepStepDetails struct { - // Always `message_creation`. - Type RunStepStepDetailsType `json:"type,required"` - // This field can have the runtime type of - // [MessageCreationStepDetailsMessageCreation]. - MessageCreation interface{} `json:"message_creation"` - // This field can have the runtime type of [[]ToolCall]. - ToolCalls interface{} `json:"tool_calls"` - JSON runStepStepDetailsJSON `json:"-"` - union RunStepStepDetailsUnion -} - -// runStepStepDetailsJSON contains the JSON metadata for the struct -// [RunStepStepDetails] -type runStepStepDetailsJSON struct { - Type apijson.Field - MessageCreation apijson.Field - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field + return nil } -func (r runStepStepDetailsJSON) RawJSON() string { - return r.raw -} - -func (r *RunStepStepDetails) UnmarshalJSON(data []byte) (err error) { - *r = RunStepStepDetails{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +func (u RunStepStepDetailsUnion) AsMessageCreation() (v MessageCreationStepDetails) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// AsUnion returns a [RunStepStepDetailsUnion] interface which you can cast to the -// specific types for more type safety. -// -// Possible runtime types of the union are [MessageCreationStepDetails], -// [ToolCallsStepDetails]. -func (r RunStepStepDetails) AsUnion() RunStepStepDetailsUnion { - return r.union +func (u RunStepStepDetailsUnion) AsToolCalls() (v ToolCallsStepDetails) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The details of the run step. -// -// Union satisfied by [MessageCreationStepDetails] or [ToolCallsStepDetails]. -type RunStepStepDetailsUnion interface { - implementsRunStepStepDetails() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*RunStepStepDetailsUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(MessageCreationStepDetails{}), - DiscriminatorValue: "message_creation", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolCallsStepDetails{}), - DiscriminatorValue: "tool_calls", - }, - ) -} - -// Always `message_creation`. -type RunStepStepDetailsType string - -const ( - RunStepStepDetailsTypeMessageCreation RunStepStepDetailsType = "message_creation" - RunStepStepDetailsTypeToolCalls RunStepStepDetailsType = "tool_calls" -) +// Returns the unmodified JSON received from the API +func (u RunStepStepDetailsUnion) RawJSON() string { return u.JSON.raw } -func (r RunStepStepDetailsType) IsKnown() bool { - switch r { - case RunStepStepDetailsTypeMessageCreation, RunStepStepDetailsTypeToolCalls: - return true - } - return false +func (r *RunStepStepDetailsUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // The type of run step, which can be either `message_creation` or `tool_calls`. @@ -1359,14 +922,6 @@ const ( RunStepTypeToolCalls RunStepType = "tool_calls" ) -func (r RunStepType) IsKnown() bool { - switch r { - case RunStepTypeMessageCreation, RunStepTypeToolCalls: - return true - } - return false -} - // Usage statistics related to the run step. This value will be `null` while the // run step's status is `in_progress`. type RunStepUsage struct { @@ -1375,132 +930,97 @@ type RunStepUsage struct { // Number of prompt tokens used over the course of the run step. PromptTokens int64 `json:"prompt_tokens,required"` // Total number of tokens used (prompt + completion). - TotalTokens int64 `json:"total_tokens,required"` - JSON runStepUsageJSON `json:"-"` -} - -// runStepUsageJSON contains the JSON metadata for the struct [RunStepUsage] -type runStepUsageJSON struct { - CompletionTokens apijson.Field - PromptTokens apijson.Field - TotalTokens apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepUsage) UnmarshalJSON(data []byte) (err error) { + TotalTokens int64 `json:"total_tokens,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + CompletionTokens resp.Field + PromptTokens resp.Field + TotalTokens resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepUsage) RawJSON() string { return r.JSON.raw } +func (r *RunStepUsage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepUsageJSON) RawJSON() string { - return r.raw -} - // The delta containing the fields that have changed on the run step. type RunStepDelta struct { // The details of the run step. - StepDetails RunStepDeltaStepDetails `json:"step_details"` - JSON runStepDeltaJSON `json:"-"` -} - -// runStepDeltaJSON contains the JSON metadata for the struct [RunStepDelta] -type runStepDeltaJSON struct { - StepDetails apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepDelta) UnmarshalJSON(data []byte) (err error) { + StepDetails RunStepDeltaStepDetailsUnion `json:"step_details"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + StepDetails resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepDelta) RawJSON() string { return r.JSON.raw } +func (r *RunStepDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepDeltaJSON) RawJSON() string { - return r.raw -} - -// The details of the run step. -type RunStepDeltaStepDetails struct { - // Always `message_creation`. - Type RunStepDeltaStepDetailsType `json:"type,required"` - // This field can have the runtime type of - // [RunStepDeltaMessageDeltaMessageCreation]. - MessageCreation interface{} `json:"message_creation"` - // This field can have the runtime type of [[]ToolCallDelta]. - ToolCalls interface{} `json:"tool_calls"` - JSON runStepDeltaStepDetailsJSON `json:"-"` - union RunStepDeltaStepDetailsUnion -} - -// runStepDeltaStepDetailsJSON contains the JSON metadata for the struct -// [RunStepDeltaStepDetails] -type runStepDeltaStepDetailsJSON struct { - Type apijson.Field - MessageCreation apijson.Field - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r runStepDeltaStepDetailsJSON) RawJSON() string { - return r.raw +// RunStepDeltaStepDetailsUnion contains all possible properties and values from +// [RunStepDeltaMessageDelta], [ToolCallDeltaObject]. +// +// Use the [RunStepDeltaStepDetailsUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type RunStepDeltaStepDetailsUnion struct { + // Any of "message_creation", "tool_calls". + Type string `json:"type"` + // This field is from variant [RunStepDeltaMessageDelta]. + MessageCreation RunStepDeltaMessageDeltaMessageCreation `json:"message_creation"` + // This field is from variant [ToolCallDeltaObject]. + ToolCalls []ToolCallDeltaUnion `json:"tool_calls"` + JSON struct { + Type resp.Field + MessageCreation resp.Field + ToolCalls resp.Field + raw string + } `json:"-"` } -func (r *RunStepDeltaStepDetails) UnmarshalJSON(data []byte) (err error) { - *r = RunStepDeltaStepDetails{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err +// Use the following switch statement to find the correct variant +// +// switch variant := RunStepDeltaStepDetailsUnion.AsAny().(type) { +// case RunStepDeltaMessageDelta: +// case ToolCallDeltaObject: +// default: +// fmt.Errorf("no variant present") +// } +func (u RunStepDeltaStepDetailsUnion) AsAny() any { + switch u.Type { + case "message_creation": + return u.AsMessageCreation() + case "tool_calls": + return u.AsToolCalls() } - return apijson.Port(r.union, &r) + return nil } -// AsUnion returns a [RunStepDeltaStepDetailsUnion] interface which you can cast to -// the specific types for more type safety. -// -// Possible runtime types of the union are [RunStepDeltaMessageDelta], -// [ToolCallDeltaObject]. -func (r RunStepDeltaStepDetails) AsUnion() RunStepDeltaStepDetailsUnion { - return r.union +func (u RunStepDeltaStepDetailsUnion) AsMessageCreation() (v RunStepDeltaMessageDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The details of the run step. -// -// Union satisfied by [RunStepDeltaMessageDelta] or [ToolCallDeltaObject]. -type RunStepDeltaStepDetailsUnion interface { - implementsRunStepDeltaStepDetails() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*RunStepDeltaStepDetailsUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(RunStepDeltaMessageDelta{}), - DiscriminatorValue: "message_creation", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(ToolCallDeltaObject{}), - DiscriminatorValue: "tool_calls", - }, - ) -} - -// Always `message_creation`. -type RunStepDeltaStepDetailsType string +func (u RunStepDeltaStepDetailsUnion) AsToolCalls() (v ToolCallDeltaObject) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} -const ( - RunStepDeltaStepDetailsTypeMessageCreation RunStepDeltaStepDetailsType = "message_creation" - RunStepDeltaStepDetailsTypeToolCalls RunStepDeltaStepDetailsType = "tool_calls" -) +// Returns the unmodified JSON received from the API +func (u RunStepDeltaStepDetailsUnion) RawJSON() string { return u.JSON.raw } -func (r RunStepDeltaStepDetailsType) IsKnown() bool { - switch r { - case RunStepDeltaStepDetailsTypeMessageCreation, RunStepDeltaStepDetailsTypeToolCalls: - return true - } - return false +func (r *RunStepDeltaStepDetailsUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Represents a run step delta i.e. any changed fields on a run step during @@ -1511,412 +1031,258 @@ type RunStepDeltaEvent struct { // The delta containing the fields that have changed on the run step. Delta RunStepDelta `json:"delta,required"` // The object type, which is always `thread.run.step.delta`. - Object RunStepDeltaEventObject `json:"object,required"` - JSON runStepDeltaEventJSON `json:"-"` -} - -// runStepDeltaEventJSON contains the JSON metadata for the struct -// [RunStepDeltaEvent] -type runStepDeltaEventJSON struct { - ID apijson.Field - Delta apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepDeltaEvent) UnmarshalJSON(data []byte) (err error) { + Object constant.ThreadRunStepDelta `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Delta resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepDeltaEvent) RawJSON() string { return r.JSON.raw } +func (r *RunStepDeltaEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepDeltaEventJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `thread.run.step.delta`. -type RunStepDeltaEventObject string - -const ( - RunStepDeltaEventObjectThreadRunStepDelta RunStepDeltaEventObject = "thread.run.step.delta" -) - -func (r RunStepDeltaEventObject) IsKnown() bool { - switch r { - case RunStepDeltaEventObjectThreadRunStepDelta: - return true - } - return false -} - // Details of the message creation by the run step. type RunStepDeltaMessageDelta struct { // Always `message_creation`. - Type RunStepDeltaMessageDeltaType `json:"type,required"` + Type constant.MessageCreation `json:"type,required"` MessageCreation RunStepDeltaMessageDeltaMessageCreation `json:"message_creation"` - JSON runStepDeltaMessageDeltaJSON `json:"-"` -} - -// runStepDeltaMessageDeltaJSON contains the JSON metadata for the struct -// [RunStepDeltaMessageDelta] -type runStepDeltaMessageDeltaJSON struct { - Type apijson.Field - MessageCreation apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepDeltaMessageDelta) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + MessageCreation resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepDeltaMessageDelta) RawJSON() string { return r.JSON.raw } +func (r *RunStepDeltaMessageDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepDeltaMessageDeltaJSON) RawJSON() string { - return r.raw -} - -func (r RunStepDeltaMessageDelta) implementsRunStepDeltaStepDetails() {} - -// Always `message_creation`. -type RunStepDeltaMessageDeltaType string - -const ( - RunStepDeltaMessageDeltaTypeMessageCreation RunStepDeltaMessageDeltaType = "message_creation" -) - -func (r RunStepDeltaMessageDeltaType) IsKnown() bool { - switch r { - case RunStepDeltaMessageDeltaTypeMessageCreation: - return true - } - return false -} - type RunStepDeltaMessageDeltaMessageCreation struct { // The ID of the message that was created by this run step. - MessageID string `json:"message_id"` - JSON runStepDeltaMessageDeltaMessageCreationJSON `json:"-"` -} - -// runStepDeltaMessageDeltaMessageCreationJSON contains the JSON metadata for the -// struct [RunStepDeltaMessageDeltaMessageCreation] -type runStepDeltaMessageDeltaMessageCreationJSON struct { - MessageID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *RunStepDeltaMessageDeltaMessageCreation) UnmarshalJSON(data []byte) (err error) { + MessageID string `json:"message_id"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + MessageID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r RunStepDeltaMessageDeltaMessageCreation) RawJSON() string { return r.JSON.raw } +func (r *RunStepDeltaMessageDeltaMessageCreation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r runStepDeltaMessageDeltaMessageCreationJSON) RawJSON() string { - return r.raw -} - type RunStepInclude string const ( RunStepIncludeStepDetailsToolCallsFileSearchResultsContent RunStepInclude = "step_details.tool_calls[*].file_search.results[*].content" ) -func (r RunStepInclude) IsKnown() bool { - switch r { - case RunStepIncludeStepDetailsToolCallsFileSearchResultsContent: - return true +// ToolCallUnion contains all possible properties and values from +// [CodeInterpreterToolCall], [FileSearchToolCall], [FunctionToolCall]. +// +// Use the [ToolCallUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type ToolCallUnion struct { + ID string `json:"id"` + // This field is from variant [CodeInterpreterToolCall]. + CodeInterpreter CodeInterpreterToolCallCodeInterpreter `json:"code_interpreter"` + // Any of "code_interpreter", "file_search", "function". + Type string `json:"type"` + // This field is from variant [FileSearchToolCall]. + FileSearch FileSearchToolCallFileSearch `json:"file_search"` + // This field is from variant [FunctionToolCall]. + Function FunctionToolCallFunction `json:"function"` + JSON struct { + ID resp.Field + CodeInterpreter resp.Field + Type resp.Field + FileSearch resp.Field + Function resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := ToolCallUnion.AsAny().(type) { +// case CodeInterpreterToolCall: +// case FileSearchToolCall: +// case FunctionToolCall: +// default: +// fmt.Errorf("no variant present") +// } +func (u ToolCallUnion) AsAny() any { + switch u.Type { + case "code_interpreter": + return u.AsCodeInterpreter() + case "file_search": + return u.AsFileSearch() + case "function": + return u.AsFunction() } - return false + return nil } -// Details of the Code Interpreter tool call the run step was involved in. -type ToolCall struct { - // The ID of the tool call. - ID string `json:"id,required"` - // The type of tool call. This is always going to be `code_interpreter` for this - // type of tool call. - Type ToolCallType `json:"type,required"` - // This field can have the runtime type of - // [CodeInterpreterToolCallCodeInterpreter]. - CodeInterpreter interface{} `json:"code_interpreter"` - // This field can have the runtime type of [FileSearchToolCallFileSearch]. - FileSearch interface{} `json:"file_search"` - // This field can have the runtime type of [FunctionToolCallFunction]. - Function interface{} `json:"function"` - JSON toolCallJSON `json:"-"` - union ToolCallUnion +func (u ToolCallUnion) AsCodeInterpreter() (v CodeInterpreterToolCall) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// toolCallJSON contains the JSON metadata for the struct [ToolCall] -type toolCallJSON struct { - ID apijson.Field - Type apijson.Field - CodeInterpreter apijson.Field - FileSearch apijson.Field - Function apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u ToolCallUnion) AsFileSearch() (v FileSearchToolCall) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r toolCallJSON) RawJSON() string { - return r.raw +func (u ToolCallUnion) AsFunction() (v FunctionToolCall) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *ToolCall) UnmarshalJSON(data []byte) (err error) { - *r = ToolCall{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) -} +// Returns the unmodified JSON received from the API +func (u ToolCallUnion) RawJSON() string { return u.JSON.raw } -// AsUnion returns a [ToolCallUnion] interface which you can cast to the specific -// types for more type safety. -// -// Possible runtime types of the union are [CodeInterpreterToolCall], -// [FileSearchToolCall], [FunctionToolCall]. -func (r ToolCall) AsUnion() ToolCallUnion { - return r.union +func (r *ToolCallUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Details of the Code Interpreter tool call the run step was involved in. +// ToolCallDeltaUnion contains all possible properties and values from +// [CodeInterpreterToolCallDelta], [FileSearchToolCallDelta], +// [FunctionToolCallDelta]. // -// Union satisfied by [CodeInterpreterToolCall], [FileSearchToolCall] or -// [FunctionToolCall]. -type ToolCallUnion interface { - implementsToolCall() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*ToolCallUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterToolCall{}), - DiscriminatorValue: "code_interpreter", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FileSearchToolCall{}), - DiscriminatorValue: "file_search", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FunctionToolCall{}), - DiscriminatorValue: "function", - }, - ) -} - -// The type of tool call. This is always going to be `code_interpreter` for this -// type of tool call. -type ToolCallType string - -const ( - ToolCallTypeCodeInterpreter ToolCallType = "code_interpreter" - ToolCallTypeFileSearch ToolCallType = "file_search" - ToolCallTypeFunction ToolCallType = "function" -) - -func (r ToolCallType) IsKnown() bool { - switch r { - case ToolCallTypeCodeInterpreter, ToolCallTypeFileSearch, ToolCallTypeFunction: - return true - } - return false -} - -// Details of the Code Interpreter tool call the run step was involved in. -type ToolCallDelta struct { - // The index of the tool call in the tool calls array. - Index int64 `json:"index,required"` - // The type of tool call. This is always going to be `code_interpreter` for this - // type of tool call. - Type ToolCallDeltaType `json:"type,required"` - // The ID of the tool call. - ID string `json:"id"` - // This field can have the runtime type of - // [CodeInterpreterToolCallDeltaCodeInterpreter]. - CodeInterpreter interface{} `json:"code_interpreter"` - // This field can have the runtime type of [interface{}]. +// Use the [ToolCallDeltaUnion.AsAny] method to switch on the variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type ToolCallDeltaUnion struct { + Index int64 `json:"index"` + // Any of "code_interpreter", "file_search", "function". + Type string `json:"type"` + ID string `json:"id"` + // This field is from variant [CodeInterpreterToolCallDelta]. + CodeInterpreter CodeInterpreterToolCallDeltaCodeInterpreter `json:"code_interpreter"` + // This field is from variant [FileSearchToolCallDelta]. FileSearch interface{} `json:"file_search"` - // This field can have the runtime type of [FunctionToolCallDeltaFunction]. - Function interface{} `json:"function"` - JSON toolCallDeltaJSON `json:"-"` - union ToolCallDeltaUnion + // This field is from variant [FunctionToolCallDelta]. + Function FunctionToolCallDeltaFunction `json:"function"` + JSON struct { + Index resp.Field + Type resp.Field + ID resp.Field + CodeInterpreter resp.Field + FileSearch resp.Field + Function resp.Field + raw string + } `json:"-"` +} + +// Use the following switch statement to find the correct variant +// +// switch variant := ToolCallDeltaUnion.AsAny().(type) { +// case CodeInterpreterToolCallDelta: +// case FileSearchToolCallDelta: +// case FunctionToolCallDelta: +// default: +// fmt.Errorf("no variant present") +// } +func (u ToolCallDeltaUnion) AsAny() any { + switch u.Type { + case "code_interpreter": + return u.AsCodeInterpreter() + case "file_search": + return u.AsFileSearch() + case "function": + return u.AsFunction() + } + return nil } -// toolCallDeltaJSON contains the JSON metadata for the struct [ToolCallDelta] -type toolCallDeltaJSON struct { - Index apijson.Field - Type apijson.Field - ID apijson.Field - CodeInterpreter apijson.Field - FileSearch apijson.Field - Function apijson.Field - raw string - ExtraFields map[string]apijson.Field +func (u ToolCallDeltaUnion) AsCodeInterpreter() (v CodeInterpreterToolCallDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r toolCallDeltaJSON) RawJSON() string { - return r.raw +func (u ToolCallDeltaUnion) AsFileSearch() (v FileSearchToolCallDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r *ToolCallDelta) UnmarshalJSON(data []byte) (err error) { - *r = ToolCallDelta{} - err = apijson.UnmarshalRoot(data, &r.union) - if err != nil { - return err - } - return apijson.Port(r.union, &r) +func (u ToolCallDeltaUnion) AsFunction() (v FunctionToolCallDelta) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// AsUnion returns a [ToolCallDeltaUnion] interface which you can cast to the -// specific types for more type safety. -// -// Possible runtime types of the union are [CodeInterpreterToolCallDelta], -// [FileSearchToolCallDelta], [FunctionToolCallDelta]. -func (r ToolCallDelta) AsUnion() ToolCallDeltaUnion { - return r.union -} +// Returns the unmodified JSON received from the API +func (u ToolCallDeltaUnion) RawJSON() string { return u.JSON.raw } -// Details of the Code Interpreter tool call the run step was involved in. -// -// Union satisfied by [CodeInterpreterToolCallDelta], [FileSearchToolCallDelta] or -// [FunctionToolCallDelta]. -type ToolCallDeltaUnion interface { - implementsToolCallDelta() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*ToolCallDeltaUnion)(nil)).Elem(), - "type", - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(CodeInterpreterToolCallDelta{}), - DiscriminatorValue: "code_interpreter", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FileSearchToolCallDelta{}), - DiscriminatorValue: "file_search", - }, - apijson.UnionVariant{ - TypeFilter: gjson.JSON, - Type: reflect.TypeOf(FunctionToolCallDelta{}), - DiscriminatorValue: "function", - }, - ) -} - -// The type of tool call. This is always going to be `code_interpreter` for this -// type of tool call. -type ToolCallDeltaType string - -const ( - ToolCallDeltaTypeCodeInterpreter ToolCallDeltaType = "code_interpreter" - ToolCallDeltaTypeFileSearch ToolCallDeltaType = "file_search" - ToolCallDeltaTypeFunction ToolCallDeltaType = "function" -) - -func (r ToolCallDeltaType) IsKnown() bool { - switch r { - case ToolCallDeltaTypeCodeInterpreter, ToolCallDeltaTypeFileSearch, ToolCallDeltaTypeFunction: - return true - } - return false +func (r *ToolCallDeltaUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Details of the tool call. type ToolCallDeltaObject struct { // Always `tool_calls`. - Type ToolCallDeltaObjectType `json:"type,required"` + Type constant.ToolCalls `json:"type,required"` // An array of tool calls the run step was involved in. These can be associated // with one of three types of tools: `code_interpreter`, `file_search`, or // `function`. - ToolCalls []ToolCallDelta `json:"tool_calls"` - JSON toolCallDeltaObjectJSON `json:"-"` -} - -// toolCallDeltaObjectJSON contains the JSON metadata for the struct -// [ToolCallDeltaObject] -type toolCallDeltaObjectJSON struct { - Type apijson.Field - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ToolCallDeltaObject) UnmarshalJSON(data []byte) (err error) { + ToolCalls []ToolCallDeltaUnion `json:"tool_calls"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + ToolCalls resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ToolCallDeltaObject) RawJSON() string { return r.JSON.raw } +func (r *ToolCallDeltaObject) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r toolCallDeltaObjectJSON) RawJSON() string { - return r.raw -} - -func (r ToolCallDeltaObject) implementsRunStepDeltaStepDetails() {} - -// Always `tool_calls`. -type ToolCallDeltaObjectType string - -const ( - ToolCallDeltaObjectTypeToolCalls ToolCallDeltaObjectType = "tool_calls" -) - -func (r ToolCallDeltaObjectType) IsKnown() bool { - switch r { - case ToolCallDeltaObjectTypeToolCalls: - return true - } - return false -} - // Details of the tool call. type ToolCallsStepDetails struct { // An array of tool calls the run step was involved in. These can be associated // with one of three types of tools: `code_interpreter`, `file_search`, or // `function`. - ToolCalls []ToolCall `json:"tool_calls,required"` + ToolCalls []ToolCallUnion `json:"tool_calls,required"` // Always `tool_calls`. - Type ToolCallsStepDetailsType `json:"type,required"` - JSON toolCallsStepDetailsJSON `json:"-"` -} - -// toolCallsStepDetailsJSON contains the JSON metadata for the struct -// [ToolCallsStepDetails] -type toolCallsStepDetailsJSON struct { - ToolCalls apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ToolCallsStepDetails) UnmarshalJSON(data []byte) (err error) { + Type constant.ToolCalls `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ToolCalls resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ToolCallsStepDetails) RawJSON() string { return r.JSON.raw } +func (r *ToolCallsStepDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r toolCallsStepDetailsJSON) RawJSON() string { - return r.raw -} - -func (r ToolCallsStepDetails) implementsRunStepStepDetails() {} - -// Always `tool_calls`. -type ToolCallsStepDetailsType string - -const ( - ToolCallsStepDetailsTypeToolCalls ToolCallsStepDetailsType = "tool_calls" -) - -func (r ToolCallsStepDetailsType) IsKnown() bool { - switch r { - case ToolCallsStepDetailsTypeToolCalls: - return true - } - return false -} - type BetaThreadRunStepGetParams struct { // A list of additional fields to include in the response. Currently the only // supported value is `step_details.tool_calls[*].file_search.results[*].content` @@ -1925,9 +1291,14 @@ type BetaThreadRunStepGetParams struct { // See the // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. - Include param.Field[[]RunStepInclude] `query:"include"` + Include []RunStepInclude `query:"include,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunStepGetParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BetaThreadRunStepGetParams]'s query parameters as // `url.Values`. func (r BetaThreadRunStepGetParams) URLQuery() (v url.Values) { @@ -1942,12 +1313,15 @@ type BetaThreadRunStepListParams struct { // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A cursor for use in pagination. `before` is an object ID that defines your place // in the list. For instance, if you make a list request and receive 100 objects, // starting with obj_foo, your subsequent call can include before=obj_foo in order // to fetch the previous page of the list. - Before param.Field[string] `query:"before"` + Before param.Opt[string] `query:"before,omitzero" json:"-"` + // A limit on the number of objects to be returned. Limit can range between 1 and + // 100, and the default is 20. + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` // A list of additional fields to include in the response. Currently the only // supported value is `step_details.tool_calls[*].file_search.results[*].content` // to fetch the file search result content. @@ -1955,15 +1329,19 @@ type BetaThreadRunStepListParams struct { // See the // [file search tool documentation](https://platform.openai.com/docs/assistants/tools/file-search#customizing-file-search-settings) // for more information. - Include param.Field[[]RunStepInclude] `query:"include"` - // A limit on the number of objects to be returned. Limit can range between 1 and - // 100, and the default is 20. - Limit param.Field[int64] `query:"limit"` + Include []RunStepInclude `query:"include,omitzero" json:"-"` // Sort order by the `created_at` timestamp of the objects. `asc` for ascending // order and `desc` for descending order. - Order param.Field[BetaThreadRunStepListParamsOrder] `query:"order"` + // + // Any of "asc", "desc". + Order BetaThreadRunStepListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f BetaThreadRunStepListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [BetaThreadRunStepListParams]'s query parameters as // `url.Values`. func (r BetaThreadRunStepListParams) URLQuery() (v url.Values) { @@ -1981,11 +1359,3 @@ const ( BetaThreadRunStepListParamsOrderAsc BetaThreadRunStepListParamsOrder = "asc" BetaThreadRunStepListParamsOrderDesc BetaThreadRunStepListParamsOrder = "desc" ) - -func (r BetaThreadRunStepListParamsOrder) IsKnown() bool { - switch r { - case BetaThreadRunStepListParamsOrderAsc, BetaThreadRunStepListParamsOrderDesc: - return true - } - return false -} diff --git a/betathreadrunstep_test.go b/betathreadrunstep_test.go index cbae8446..7da3a8e8 100644 --- a/betathreadrunstep_test.go +++ b/betathreadrunstep_test.go @@ -31,7 +31,7 @@ func TestBetaThreadRunStepGetWithOptionalParams(t *testing.T) { "run_id", "step_id", openai.BetaThreadRunStepGetParams{ - Include: openai.F([]openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}), + Include: []openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}, }, ) if err != nil { @@ -60,11 +60,11 @@ func TestBetaThreadRunStepListWithOptionalParams(t *testing.T) { "thread_id", "run_id", openai.BetaThreadRunStepListParams{ - After: openai.F("after"), - Before: openai.F("before"), - Include: openai.F([]openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}), - Limit: openai.F(int64(0)), - Order: openai.F(openai.BetaThreadRunStepListParamsOrderAsc), + After: openai.String("after"), + Before: openai.String("before"), + Include: []openai.RunStepInclude{openai.RunStepIncludeStepDetailsToolCallsFileSearchResultsContent}, + Limit: openai.Int(0), + Order: openai.BetaThreadRunStepListParamsOrderAsc, }, ) if err != nil { diff --git a/chat.go b/chat.go index fb7af6e6..f579dc3c 100644 --- a/chat.go +++ b/chat.go @@ -14,14 +14,14 @@ import ( // the [NewChatService] method instead. type ChatService struct { Options []option.RequestOption - Completions *ChatCompletionService + Completions ChatCompletionService } // NewChatService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewChatService(opts ...option.RequestOption) (r *ChatService) { - r = &ChatService{} +func NewChatService(opts ...option.RequestOption) (r ChatService) { + r = ChatService{} r.Options = opts r.Completions = NewChatCompletionService(opts...) return diff --git a/chatcompletion.go b/chatcompletion.go index 53e05234..af0a6f0d 100644 --- a/chatcompletion.go +++ b/chatcompletion.go @@ -8,88 +8,21 @@ import ( "fmt" "net/http" "net/url" + "reflect" "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/packages/ssestream" "github.com/openai/openai-go/shared" - "github.com/tidwall/sjson" + "github.com/openai/openai-go/shared/constant" + "github.com/tidwall/gjson" ) -func UserMessage(content string) ChatCompletionMessageParamUnion { - return UserMessageParts(TextPart(content)) -} - -func UserMessageParts(parts ...ChatCompletionContentPartUnionParam) ChatCompletionUserMessageParam { - return ChatCompletionUserMessageParam{ - Role: F(ChatCompletionUserMessageParamRoleUser), - Content: F(parts), - } -} - -func TextPart(content string) ChatCompletionContentPartTextParam { - return ChatCompletionContentPartTextParam{ - Type: F(ChatCompletionContentPartTextTypeText), - Text: F(content), - } -} - -func RefusalPart(refusal string) ChatCompletionContentPartRefusalParam { - return ChatCompletionContentPartRefusalParam{ - Type: F(ChatCompletionContentPartRefusalTypeRefusal), - Refusal: F(refusal), - } -} - -func ImagePart(url string) ChatCompletionContentPartImageParam { - return ChatCompletionContentPartImageParam{ - Type: F(ChatCompletionContentPartImageTypeImageURL), - ImageURL: F(ChatCompletionContentPartImageImageURLParam{ - URL: F(url), - }), - } -} - -func AssistantMessage(content string) ChatCompletionAssistantMessageParam { - return ChatCompletionAssistantMessageParam{ - Role: F(ChatCompletionAssistantMessageParamRoleAssistant), - Content: F([]ChatCompletionAssistantMessageParamContentUnion{ - TextPart(content), - }), - } -} - -func ToolMessage(toolCallID, content string) ChatCompletionToolMessageParam { - return ChatCompletionToolMessageParam{ - Role: F(ChatCompletionToolMessageParamRoleTool), - ToolCallID: F(toolCallID), - Content: F([]ChatCompletionContentPartTextParam{ - TextPart(content), - }), - } -} - -func SystemMessage(content string) ChatCompletionMessageParamUnion { - return ChatCompletionSystemMessageParam{ - Role: F(ChatCompletionSystemMessageParamRoleSystem), - Content: F([]ChatCompletionContentPartTextParam{ - TextPart(content), - }), - } -} - -func FunctionMessage(name, content string) ChatCompletionMessageParamUnion { - return ChatCompletionFunctionMessageParam{ - Role: F(ChatCompletionFunctionMessageParamRoleFunction), - Name: F(name), - Content: F(content), - } -} - // ChatCompletionService contains methods and other services that help with // interacting with the openai API. // @@ -98,14 +31,14 @@ func FunctionMessage(name, content string) ChatCompletionMessageParamUnion { // the [NewChatCompletionService] method instead. type ChatCompletionService struct { Options []option.RequestOption - Messages *ChatCompletionMessageService + Messages ChatCompletionMessageService } // NewChatCompletionService generates a new service that applies the given options // to each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewChatCompletionService(opts ...option.RequestOption) (r *ChatCompletionService) { - r = &ChatCompletionService{} +func NewChatCompletionService(opts ...option.RequestOption) (r ChatCompletionService) { + r = ChatCompletionService{} r.Options = opts r.Messages = NewChatCompletionMessageService(opts...) return @@ -242,8 +175,10 @@ type ChatCompletion struct { // The model used for the chat completion. Model string `json:"model,required"` // The object type, which is always `chat.completion`. - Object ChatCompletionObject `json:"object,required"` + Object constant.ChatCompletion `json:"object,required"` // The service tier used for processing the request. + // + // Any of "scale", "default". ServiceTier ChatCompletionServiceTier `json:"service_tier,nullable"` // This fingerprint represents the backend configuration that the model runs with. // @@ -251,32 +186,29 @@ type ChatCompletion struct { // backend changes have been made that might impact determinism. SystemFingerprint string `json:"system_fingerprint"` // Usage statistics for the completion request. - Usage CompletionUsage `json:"usage"` - JSON chatCompletionJSON `json:"-"` -} - -// chatCompletionJSON contains the JSON metadata for the struct [ChatCompletion] -type chatCompletionJSON struct { - ID apijson.Field - Choices apijson.Field - Created apijson.Field - Model apijson.Field - Object apijson.Field - ServiceTier apijson.Field - SystemFingerprint apijson.Field - Usage apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletion) UnmarshalJSON(data []byte) (err error) { + Usage CompletionUsage `json:"usage"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Choices resp.Field + Created resp.Field + Model resp.Field + Object resp.Field + ServiceTier resp.Field + SystemFingerprint resp.Field + Usage resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletion) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionJSON) RawJSON() string { - return r.raw -} - type ChatCompletionChoice struct { // The reason the model stopped generating tokens. This will be `stop` if the model // hit a natural stop point or a provided stop sequence, `length` if the maximum @@ -284,100 +216,55 @@ type ChatCompletionChoice struct { // content was omitted due to a flag from our content filters, `tool_calls` if the // model called a tool, or `function_call` (deprecated) if the model called a // function. - FinishReason ChatCompletionChoicesFinishReason `json:"finish_reason,required"` + // + // Any of "stop", "length", "tool_calls", "content_filter", "function_call". + FinishReason string `json:"finish_reason,required"` // The index of the choice in the list of choices. Index int64 `json:"index,required"` // Log probability information for the choice. - Logprobs ChatCompletionChoicesLogprobs `json:"logprobs,required,nullable"` + Logprobs ChatCompletionChoiceLogprobs `json:"logprobs,required"` // A chat completion message generated by the model. - Message ChatCompletionMessage `json:"message,required"` - JSON chatCompletionChoiceJSON `json:"-"` -} - -// chatCompletionChoiceJSON contains the JSON metadata for the struct -// [ChatCompletionChoice] -type chatCompletionChoiceJSON struct { - FinishReason apijson.Field - Index apijson.Field - Logprobs apijson.Field - Message apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChoice) UnmarshalJSON(data []byte) (err error) { + Message ChatCompletionMessage `json:"message,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FinishReason resp.Field + Index resp.Field + Logprobs resp.Field + Message resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChoice) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChoice) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChoiceJSON) RawJSON() string { - return r.raw -} - -// The reason the model stopped generating tokens. This will be `stop` if the model -// hit a natural stop point or a provided stop sequence, `length` if the maximum -// number of tokens specified in the request was reached, `content_filter` if -// content was omitted due to a flag from our content filters, `tool_calls` if the -// model called a tool, or `function_call` (deprecated) if the model called a -// function. -type ChatCompletionChoicesFinishReason string - -const ( - ChatCompletionChoicesFinishReasonStop ChatCompletionChoicesFinishReason = "stop" - ChatCompletionChoicesFinishReasonLength ChatCompletionChoicesFinishReason = "length" - ChatCompletionChoicesFinishReasonToolCalls ChatCompletionChoicesFinishReason = "tool_calls" - ChatCompletionChoicesFinishReasonContentFilter ChatCompletionChoicesFinishReason = "content_filter" - ChatCompletionChoicesFinishReasonFunctionCall ChatCompletionChoicesFinishReason = "function_call" -) - -func (r ChatCompletionChoicesFinishReason) IsKnown() bool { - switch r { - case ChatCompletionChoicesFinishReasonStop, ChatCompletionChoicesFinishReasonLength, ChatCompletionChoicesFinishReasonToolCalls, ChatCompletionChoicesFinishReasonContentFilter, ChatCompletionChoicesFinishReasonFunctionCall: - return true - } - return false -} - // Log probability information for the choice. -type ChatCompletionChoicesLogprobs struct { +type ChatCompletionChoiceLogprobs struct { // A list of message content tokens with log probability information. - Content []ChatCompletionTokenLogprob `json:"content,required,nullable"` + Content []ChatCompletionTokenLogprob `json:"content,required"` // A list of message refusal tokens with log probability information. - Refusal []ChatCompletionTokenLogprob `json:"refusal,required,nullable"` - JSON chatCompletionChoicesLogprobsJSON `json:"-"` -} - -// chatCompletionChoicesLogprobsJSON contains the JSON metadata for the struct -// [ChatCompletionChoicesLogprobs] -type chatCompletionChoicesLogprobsJSON struct { - Content apijson.Field - Refusal apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChoicesLogprobs) UnmarshalJSON(data []byte) (err error) { + Refusal []ChatCompletionTokenLogprob `json:"refusal,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Content resp.Field + Refusal resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChoiceLogprobs) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChoiceLogprobs) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChoicesLogprobsJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `chat.completion`. -type ChatCompletionObject string - -const ( - ChatCompletionObjectChatCompletion ChatCompletionObject = "chat.completion" -) - -func (r ChatCompletionObject) IsKnown() bool { - switch r { - case ChatCompletionObjectChatCompletion: - return true - } - return false -} - // The service tier used for processing the request. type ChatCompletionServiceTier string @@ -386,144 +273,186 @@ const ( ChatCompletionServiceTierDefault ChatCompletionServiceTier = "default" ) -func (r ChatCompletionServiceTier) IsKnown() bool { - switch r { - case ChatCompletionServiceTierScale, ChatCompletionServiceTierDefault: - return true - } - return false -} - // Messages sent by the model in response to user messages. +// +// The property Role is required. type ChatCompletionAssistantMessageParam struct { - // The role of the messages author, in this case `assistant`. - Role param.Field[ChatCompletionAssistantMessageParamRole] `json:"role,required"` + // The refusal message by the assistant. + Refusal param.Opt[string] `json:"refusal,omitzero"` + // An optional name for the participant. Provides the model information to + // differentiate between participants of the same role. + Name param.Opt[string] `json:"name,omitzero"` // Data about a previous audio response from the model. // [Learn more](https://platform.openai.com/docs/guides/audio). - Audio param.Field[ChatCompletionAssistantMessageParamAudio] `json:"audio"` + Audio ChatCompletionAssistantMessageParamAudio `json:"audio,omitzero"` // The contents of the assistant message. Required unless `tool_calls` or // `function_call` is specified. - Content param.Field[ChatCompletionAssistantMessageParamContentUnion] `json:"content"` + Content ChatCompletionAssistantMessageParamContentUnion `json:"content,omitzero"` // Deprecated and replaced by `tool_calls`. The name and arguments of a function // that should be called, as generated by the model. // // Deprecated: deprecated - FunctionCall param.Field[ChatCompletionAssistantMessageParamFunctionCall] `json:"function_call"` - // An optional name for the participant. Provides the model information to - // differentiate between participants of the same role. - Name param.Field[string] `json:"name"` - // The refusal message by the assistant. - Refusal param.Field[string] `json:"refusal"` + FunctionCall ChatCompletionAssistantMessageParamFunctionCall `json:"function_call,omitzero"` // The tool calls generated by the model, such as function calls. - ToolCalls param.Field[[]ChatCompletionMessageToolCallParam] `json:"tool_calls"` + ToolCalls []ChatCompletionMessageToolCallParam `json:"tool_calls,omitzero"` + // The role of the messages author, in this case `assistant`. + // + // This field can be elided, and will marshal its zero value as "assistant". + Role constant.Assistant `json:"role,required"` + paramObj } -func (r ChatCompletionAssistantMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionAssistantMessageParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -func (r ChatCompletionAssistantMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The role of the messages author, in this case `assistant`. -type ChatCompletionAssistantMessageParamRole string - -const ( - ChatCompletionAssistantMessageParamRoleAssistant ChatCompletionAssistantMessageParamRole = "assistant" -) - -func (r ChatCompletionAssistantMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionAssistantMessageParamRoleAssistant: - return true - } - return false +func (r ChatCompletionAssistantMessageParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionAssistantMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } // Data about a previous audio response from the model. // [Learn more](https://platform.openai.com/docs/guides/audio). +// +// The property ID is required. type ChatCompletionAssistantMessageParamAudio struct { // Unique identifier for a previous audio response from the model. - ID param.Field[string] `json:"id,required"` + ID string `json:"id,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionAssistantMessageParamAudio) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionAssistantMessageParamAudio) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionAssistantMessageParamAudio + return param.MarshalObject(r, (*shadow)(&r)) } -// The contents of the assistant message. Required unless `tool_calls` or -// `function_call` is specified. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionAssistantMessageParamContentArrayOfContentParts]. -type ChatCompletionAssistantMessageParamContentUnion interface { - ImplementsChatCompletionAssistantMessageParamContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionAssistantMessageParamContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion `json:",omitzero,inline"` + paramUnion } -type ChatCompletionAssistantMessageParamContentArrayOfContentParts []ChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem - -func (r ChatCompletionAssistantMessageParamContentArrayOfContentParts) ImplementsChatCompletionAssistantMessageParamContentUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionAssistantMessageParamContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionAssistantMessageParamContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionAssistantMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts) } -// Learn about -// [text inputs](https://platform.openai.com/docs/guides/text-generation). -type ChatCompletionAssistantMessageParamContentArrayOfContentPart struct { - // The type of the content part. - Type param.Field[ChatCompletionAssistantMessageParamContentArrayOfContentPartsType] `json:"type,required"` - // The refusal message generated by the model. - Refusal param.Field[string] `json:"refusal"` - // The text content. - Text param.Field[string] `json:"text"` +func (u *ChatCompletionAssistantMessageParamContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts + } + return nil } -func (r ChatCompletionAssistantMessageParamContentArrayOfContentPart) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion struct { + OfText *ChatCompletionContentPartTextParam `json:",omitzero,inline"` + OfRefusal *ChatCompletionContentPartRefusalParam `json:",omitzero,inline"` + paramUnion } -func (r ChatCompletionAssistantMessageParamContentArrayOfContentPart) implementsChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion](u.OfText, u.OfRefusal) } -// Learn about -// [text inputs](https://platform.openai.com/docs/guides/text-generation). -// -// Satisfied by [ChatCompletionContentPartTextParam], -// [ChatCompletionContentPartRefusalParam], -// [ChatCompletionAssistantMessageParamContentArrayOfContentPart]. -type ChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem interface { - implementsChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem() +func (u *ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) asAny() any { + if !param.IsOmitted(u.OfText) { + return u.OfText + } else if !param.IsOmitted(u.OfRefusal) { + return u.OfRefusal + } + return nil } -// The type of the content part. -type ChatCompletionAssistantMessageParamContentArrayOfContentPartsType string +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) GetText() *string { + if vt := u.OfText; vt != nil { + return &vt.Text + } + return nil +} -const ( - ChatCompletionAssistantMessageParamContentArrayOfContentPartsTypeText ChatCompletionAssistantMessageParamContentArrayOfContentPartsType = "text" - ChatCompletionAssistantMessageParamContentArrayOfContentPartsTypeRefusal ChatCompletionAssistantMessageParamContentArrayOfContentPartsType = "refusal" -) +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) GetRefusal() *string { + if vt := u.OfRefusal; vt != nil { + return &vt.Refusal + } + return nil +} -func (r ChatCompletionAssistantMessageParamContentArrayOfContentPartsType) IsKnown() bool { - switch r { - case ChatCompletionAssistantMessageParamContentArrayOfContentPartsTypeText, ChatCompletionAssistantMessageParamContentArrayOfContentPartsTypeRefusal: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion) GetType() *string { + if vt := u.OfText; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfRefusal; vt != nil { + return (*string)(&vt.Type) } - return false + return nil +} + +func init() { + apijson.RegisterUnion[ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartTextParam{}), + DiscriminatorValue: "text", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartRefusalParam{}), + DiscriminatorValue: "refusal", + }, + ) } // Deprecated and replaced by `tool_calls`. The name and arguments of a function // that should be called, as generated by the model. // // Deprecated: deprecated +// +// The properties Arguments, Name are required. type ChatCompletionAssistantMessageParamFunctionCall struct { // The arguments to call the function with, as generated by the model in JSON // format. Note that the model does not always generate valid JSON, and may // hallucinate parameters not defined by your function schema. Validate the // arguments in your code before calling your function. - Arguments param.Field[string] `json:"arguments,required"` + Arguments string `json:"arguments,required"` // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionAssistantMessageParamFunctionCall) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionAssistantMessageParamFunctionCall) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionAssistantMessageParamFunctionCall + return param.MarshalObject(r, (*shadow)(&r)) } // If the audio output modality is requested, this object contains data about the @@ -539,43 +468,50 @@ type ChatCompletionAudio struct { // accessible on the server for use in multi-turn conversations. ExpiresAt int64 `json:"expires_at,required"` // Transcript of the audio generated by the model. - Transcript string `json:"transcript,required"` - JSON chatCompletionAudioJSON `json:"-"` -} - -// chatCompletionAudioJSON contains the JSON metadata for the struct -// [ChatCompletionAudio] -type chatCompletionAudioJSON struct { - ID apijson.Field - Data apijson.Field - ExpiresAt apijson.Field - Transcript apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionAudio) UnmarshalJSON(data []byte) (err error) { + Transcript string `json:"transcript,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Data resp.Field + ExpiresAt resp.Field + Transcript resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionAudio) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionAudio) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionAudioJSON) RawJSON() string { - return r.raw -} - // Parameters for audio output. Required when audio output is requested with // `modalities: ["audio"]`. // [Learn more](https://platform.openai.com/docs/guides/audio). +// +// The properties Format, Voice are required. type ChatCompletionAudioParam struct { // Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`, // or `pcm16`. - Format param.Field[ChatCompletionAudioParamFormat] `json:"format,required"` + // + // Any of "wav", "mp3", "flac", "opus", "pcm16". + Format ChatCompletionAudioParamFormat `json:"format,omitzero,required"` // The voice the model uses to respond. Supported voices are `alloy`, `ash`, // `ballad`, `coral`, `echo`, `sage`, and `shimmer`. - Voice param.Field[ChatCompletionAudioParamVoice] `json:"voice,required"` + // + // Any of "alloy", "ash", "ballad", "coral", "echo", "sage", "shimmer", "verse". + Voice ChatCompletionAudioParamVoice `json:"voice,omitzero,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionAudioParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionAudioParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionAudioParam + return param.MarshalObject(r, (*shadow)(&r)) } // Specifies the output audio format. Must be one of `wav`, `mp3`, `flac`, `opus`, @@ -590,14 +526,6 @@ const ( ChatCompletionAudioParamFormatPcm16 ChatCompletionAudioParamFormat = "pcm16" ) -func (r ChatCompletionAudioParamFormat) IsKnown() bool { - switch r { - case ChatCompletionAudioParamFormatWAV, ChatCompletionAudioParamFormatMP3, ChatCompletionAudioParamFormatFLAC, ChatCompletionAudioParamFormatOpus, ChatCompletionAudioParamFormatPcm16: - return true - } - return false -} - // The voice the model uses to respond. Supported voices are `alloy`, `ash`, // `ballad`, `coral`, `echo`, `sage`, and `shimmer`. type ChatCompletionAudioParamVoice string @@ -613,14 +541,6 @@ const ( ChatCompletionAudioParamVoiceVerse ChatCompletionAudioParamVoice = "verse" ) -func (r ChatCompletionAudioParamVoice) IsKnown() bool { - switch r { - case ChatCompletionAudioParamVoiceAlloy, ChatCompletionAudioParamVoiceAsh, ChatCompletionAudioParamVoiceBallad, ChatCompletionAudioParamVoiceCoral, ChatCompletionAudioParamVoiceEcho, ChatCompletionAudioParamVoiceSage, ChatCompletionAudioParamVoiceShimmer, ChatCompletionAudioParamVoiceVerse: - return true - } - return false -} - // Represents a streamed chunk of a chat completion response returned by the model, // based on the provided input. // [Learn more](https://platform.openai.com/docs/guides/streaming-responses). @@ -637,8 +557,10 @@ type ChatCompletionChunk struct { // The model to generate the completion. Model string `json:"model,required"` // The object type, which is always `chat.completion.chunk`. - Object ChatCompletionChunkObject `json:"object,required"` + Object constant.ChatCompletionChunk `json:"object,required"` // The service tier used for processing the request. + // + // Any of "scale", "default". ServiceTier ChatCompletionChunkServiceTier `json:"service_tier,nullable"` // This fingerprint represents the backend configuration that the model runs with. // Can be used in conjunction with the `seed` request parameter to understand when @@ -651,573 +573,522 @@ type ChatCompletionChunk struct { // // **NOTE:** If the stream is interrupted or cancelled, you may not receive the // final usage chunk which contains the total token usage for the request. - Usage CompletionUsage `json:"usage"` - JSON chatCompletionChunkJSON `json:"-"` -} - -// chatCompletionChunkJSON contains the JSON metadata for the struct -// [ChatCompletionChunk] -type chatCompletionChunkJSON struct { - ID apijson.Field - Choices apijson.Field - Created apijson.Field - Model apijson.Field - Object apijson.Field - ServiceTier apijson.Field - SystemFingerprint apijson.Field - Usage apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunk) UnmarshalJSON(data []byte) (err error) { + Usage CompletionUsage `json:"usage,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Choices resp.Field + Created resp.Field + Model resp.Field + Object resp.Field + ServiceTier resp.Field + SystemFingerprint resp.Field + Usage resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunk) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunk) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkJSON) RawJSON() string { - return r.raw -} - type ChatCompletionChunkChoice struct { // A chat completion delta generated by streamed model responses. - Delta ChatCompletionChunkChoicesDelta `json:"delta,required"` + Delta ChatCompletionChunkChoiceDelta `json:"delta,required"` // The reason the model stopped generating tokens. This will be `stop` if the model // hit a natural stop point or a provided stop sequence, `length` if the maximum // number of tokens specified in the request was reached, `content_filter` if // content was omitted due to a flag from our content filters, `tool_calls` if the // model called a tool, or `function_call` (deprecated) if the model called a // function. - FinishReason ChatCompletionChunkChoicesFinishReason `json:"finish_reason,required,nullable"` + // + // Any of "stop", "length", "tool_calls", "content_filter", "function_call". + FinishReason string `json:"finish_reason,required"` // The index of the choice in the list of choices. Index int64 `json:"index,required"` // Log probability information for the choice. - Logprobs ChatCompletionChunkChoicesLogprobs `json:"logprobs,nullable"` - JSON chatCompletionChunkChoiceJSON `json:"-"` -} - -// chatCompletionChunkChoiceJSON contains the JSON metadata for the struct -// [ChatCompletionChunkChoice] -type chatCompletionChunkChoiceJSON struct { - Delta apijson.Field - FinishReason apijson.Field - Index apijson.Field - Logprobs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunkChoice) UnmarshalJSON(data []byte) (err error) { + Logprobs ChatCompletionChunkChoiceLogprobs `json:"logprobs,nullable"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Delta resp.Field + FinishReason resp.Field + Index resp.Field + Logprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoice) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoice) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkChoiceJSON) RawJSON() string { - return r.raw -} - // A chat completion delta generated by streamed model responses. -type ChatCompletionChunkChoicesDelta struct { +type ChatCompletionChunkChoiceDelta struct { // The contents of the chunk message. Content string `json:"content,nullable"` // Deprecated and replaced by `tool_calls`. The name and arguments of a function // that should be called, as generated by the model. // // Deprecated: deprecated - FunctionCall ChatCompletionChunkChoicesDeltaFunctionCall `json:"function_call"` + FunctionCall ChatCompletionChunkChoiceDeltaFunctionCall `json:"function_call"` // The refusal message generated by the model. Refusal string `json:"refusal,nullable"` // The role of the author of this message. - Role ChatCompletionChunkChoicesDeltaRole `json:"role"` - ToolCalls []ChatCompletionChunkChoicesDeltaToolCall `json:"tool_calls"` - JSON chatCompletionChunkChoicesDeltaJSON `json:"-"` -} - -// chatCompletionChunkChoicesDeltaJSON contains the JSON metadata for the struct -// [ChatCompletionChunkChoicesDelta] -type chatCompletionChunkChoicesDeltaJSON struct { - Content apijson.Field - FunctionCall apijson.Field - Refusal apijson.Field - Role apijson.Field - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunkChoicesDelta) UnmarshalJSON(data []byte) (err error) { + // + // Any of "developer", "system", "user", "assistant", "tool". + Role string `json:"role"` + ToolCalls []ChatCompletionChunkChoiceDeltaToolCall `json:"tool_calls"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Content resp.Field + FunctionCall resp.Field + Refusal resp.Field + Role resp.Field + ToolCalls resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoiceDelta) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoiceDelta) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkChoicesDeltaJSON) RawJSON() string { - return r.raw -} - // Deprecated and replaced by `tool_calls`. The name and arguments of a function // that should be called, as generated by the model. // // Deprecated: deprecated -type ChatCompletionChunkChoicesDeltaFunctionCall struct { +type ChatCompletionChunkChoiceDeltaFunctionCall struct { // The arguments to call the function with, as generated by the model in JSON // format. Note that the model does not always generate valid JSON, and may // hallucinate parameters not defined by your function schema. Validate the // arguments in your code before calling your function. Arguments string `json:"arguments"` // The name of the function to call. - Name string `json:"name"` - JSON chatCompletionChunkChoicesDeltaFunctionCallJSON `json:"-"` -} - -// chatCompletionChunkChoicesDeltaFunctionCallJSON contains the JSON metadata for -// the struct [ChatCompletionChunkChoicesDeltaFunctionCall] -type chatCompletionChunkChoicesDeltaFunctionCallJSON struct { - Arguments apijson.Field - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunkChoicesDeltaFunctionCall) UnmarshalJSON(data []byte) (err error) { + Name string `json:"name"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoiceDeltaFunctionCall) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoiceDeltaFunctionCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkChoicesDeltaFunctionCallJSON) RawJSON() string { - return r.raw -} - -// The role of the author of this message. -type ChatCompletionChunkChoicesDeltaRole string - -const ( - ChatCompletionChunkChoicesDeltaRoleDeveloper ChatCompletionChunkChoicesDeltaRole = "developer" - ChatCompletionChunkChoicesDeltaRoleSystem ChatCompletionChunkChoicesDeltaRole = "system" - ChatCompletionChunkChoicesDeltaRoleUser ChatCompletionChunkChoicesDeltaRole = "user" - ChatCompletionChunkChoicesDeltaRoleAssistant ChatCompletionChunkChoicesDeltaRole = "assistant" - ChatCompletionChunkChoicesDeltaRoleTool ChatCompletionChunkChoicesDeltaRole = "tool" -) - -func (r ChatCompletionChunkChoicesDeltaRole) IsKnown() bool { - switch r { - case ChatCompletionChunkChoicesDeltaRoleDeveloper, ChatCompletionChunkChoicesDeltaRoleSystem, ChatCompletionChunkChoicesDeltaRoleUser, ChatCompletionChunkChoicesDeltaRoleAssistant, ChatCompletionChunkChoicesDeltaRoleTool: - return true - } - return false -} - -type ChatCompletionChunkChoicesDeltaToolCall struct { +type ChatCompletionChunkChoiceDeltaToolCall struct { Index int64 `json:"index,required"` // The ID of the tool call. - ID string `json:"id"` - Function ChatCompletionChunkChoicesDeltaToolCallsFunction `json:"function"` + ID string `json:"id"` + Function ChatCompletionChunkChoiceDeltaToolCallFunction `json:"function"` // The type of the tool. Currently, only `function` is supported. - Type ChatCompletionChunkChoicesDeltaToolCallsType `json:"type"` - JSON chatCompletionChunkChoicesDeltaToolCallJSON `json:"-"` -} - -// chatCompletionChunkChoicesDeltaToolCallJSON contains the JSON metadata for the -// struct [ChatCompletionChunkChoicesDeltaToolCall] -type chatCompletionChunkChoicesDeltaToolCallJSON struct { - Index apijson.Field - ID apijson.Field - Function apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunkChoicesDeltaToolCall) UnmarshalJSON(data []byte) (err error) { + // + // Any of "function". + Type string `json:"type"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Index resp.Field + ID resp.Field + Function resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoiceDeltaToolCall) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoiceDeltaToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkChoicesDeltaToolCallJSON) RawJSON() string { - return r.raw -} - -type ChatCompletionChunkChoicesDeltaToolCallsFunction struct { +type ChatCompletionChunkChoiceDeltaToolCallFunction struct { // The arguments to call the function with, as generated by the model in JSON // format. Note that the model does not always generate valid JSON, and may // hallucinate parameters not defined by your function schema. Validate the // arguments in your code before calling your function. Arguments string `json:"arguments"` // The name of the function to call. - Name string `json:"name"` - JSON chatCompletionChunkChoicesDeltaToolCallsFunctionJSON `json:"-"` -} - -// chatCompletionChunkChoicesDeltaToolCallsFunctionJSON contains the JSON metadata -// for the struct [ChatCompletionChunkChoicesDeltaToolCallsFunction] -type chatCompletionChunkChoicesDeltaToolCallsFunctionJSON struct { - Arguments apijson.Field - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionChunkChoicesDeltaToolCallsFunction) UnmarshalJSON(data []byte) (err error) { + Name string `json:"name"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoiceDeltaToolCallFunction) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoiceDeltaToolCallFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionChunkChoicesDeltaToolCallsFunctionJSON) RawJSON() string { - return r.raw -} - -// The type of the tool. Currently, only `function` is supported. -type ChatCompletionChunkChoicesDeltaToolCallsType string - -const ( - ChatCompletionChunkChoicesDeltaToolCallsTypeFunction ChatCompletionChunkChoicesDeltaToolCallsType = "function" -) - -func (r ChatCompletionChunkChoicesDeltaToolCallsType) IsKnown() bool { - switch r { - case ChatCompletionChunkChoicesDeltaToolCallsTypeFunction: - return true - } - return false +// Log probability information for the choice. +type ChatCompletionChunkChoiceLogprobs struct { + // A list of message content tokens with log probability information. + Content []ChatCompletionTokenLogprob `json:"content,required"` + // A list of message refusal tokens with log probability information. + Refusal []ChatCompletionTokenLogprob `json:"refusal,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Content resp.Field + Refusal resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionChunkChoiceLogprobs) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionChunkChoiceLogprobs) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The reason the model stopped generating tokens. This will be `stop` if the model -// hit a natural stop point or a provided stop sequence, `length` if the maximum -// number of tokens specified in the request was reached, `content_filter` if -// content was omitted due to a flag from our content filters, `tool_calls` if the -// model called a tool, or `function_call` (deprecated) if the model called a -// function. -type ChatCompletionChunkChoicesFinishReason string +// The service tier used for processing the request. +type ChatCompletionChunkServiceTier string const ( - ChatCompletionChunkChoicesFinishReasonStop ChatCompletionChunkChoicesFinishReason = "stop" - ChatCompletionChunkChoicesFinishReasonLength ChatCompletionChunkChoicesFinishReason = "length" - ChatCompletionChunkChoicesFinishReasonToolCalls ChatCompletionChunkChoicesFinishReason = "tool_calls" - ChatCompletionChunkChoicesFinishReasonContentFilter ChatCompletionChunkChoicesFinishReason = "content_filter" - ChatCompletionChunkChoicesFinishReasonFunctionCall ChatCompletionChunkChoicesFinishReason = "function_call" + ChatCompletionChunkServiceTierScale ChatCompletionChunkServiceTier = "scale" + ChatCompletionChunkServiceTierDefault ChatCompletionChunkServiceTier = "default" ) -func (r ChatCompletionChunkChoicesFinishReason) IsKnown() bool { - switch r { - case ChatCompletionChunkChoicesFinishReasonStop, ChatCompletionChunkChoicesFinishReasonLength, ChatCompletionChunkChoicesFinishReasonToolCalls, ChatCompletionChunkChoicesFinishReasonContentFilter, ChatCompletionChunkChoicesFinishReasonFunctionCall: - return true - } - return false -} - -// Log probability information for the choice. -type ChatCompletionChunkChoicesLogprobs struct { - // A list of message content tokens with log probability information. - Content []ChatCompletionTokenLogprob `json:"content,required,nullable"` - // A list of message refusal tokens with log probability information. - Refusal []ChatCompletionTokenLogprob `json:"refusal,required,nullable"` - JSON chatCompletionChunkChoicesLogprobsJSON `json:"-"` +func TextContentPart(text string) ChatCompletionContentPartUnionParam { + var variant ChatCompletionContentPartTextParam + variant.Text = text + return ChatCompletionContentPartUnionParam{OfText: &variant} } -// chatCompletionChunkChoicesLogprobsJSON contains the JSON metadata for the struct -// [ChatCompletionChunkChoicesLogprobs] -type chatCompletionChunkChoicesLogprobsJSON struct { - Content apijson.Field - Refusal apijson.Field - raw string - ExtraFields map[string]apijson.Field +func ImageContentPart(imageURL ChatCompletionContentPartImageImageURLParam) ChatCompletionContentPartUnionParam { + var variant ChatCompletionContentPartImageParam + variant.ImageURL = imageURL + return ChatCompletionContentPartUnionParam{OfImageURL: &variant} } -func (r *ChatCompletionChunkChoicesLogprobs) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func InputAudioContentPart(inputAudio ChatCompletionContentPartInputAudioInputAudioParam) ChatCompletionContentPartUnionParam { + var variant ChatCompletionContentPartInputAudioParam + variant.InputAudio = inputAudio + return ChatCompletionContentPartUnionParam{OfInputAudio: &variant} } -func (r chatCompletionChunkChoicesLogprobsJSON) RawJSON() string { - return r.raw +func FileContentPart(file ChatCompletionContentPartFileFileParam) ChatCompletionContentPartUnionParam { + var variant ChatCompletionContentPartFileParam + variant.File = file + return ChatCompletionContentPartUnionParam{OfFile: &variant} } -// The object type, which is always `chat.completion.chunk`. -type ChatCompletionChunkObject string - -const ( - ChatCompletionChunkObjectChatCompletionChunk ChatCompletionChunkObject = "chat.completion.chunk" -) - -func (r ChatCompletionChunkObject) IsKnown() bool { - switch r { - case ChatCompletionChunkObjectChatCompletionChunk: - return true +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionContentPartUnionParam struct { + OfText *ChatCompletionContentPartTextParam `json:",omitzero,inline"` + OfImageURL *ChatCompletionContentPartImageParam `json:",omitzero,inline"` + OfInputAudio *ChatCompletionContentPartInputAudioParam `json:",omitzero,inline"` + OfFile *ChatCompletionContentPartFileParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionContentPartUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionContentPartUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionContentPartUnionParam](u.OfText, u.OfImageURL, u.OfInputAudio, u.OfFile) +} + +func (u *ChatCompletionContentPartUnionParam) asAny() any { + if !param.IsOmitted(u.OfText) { + return u.OfText + } else if !param.IsOmitted(u.OfImageURL) { + return u.OfImageURL + } else if !param.IsOmitted(u.OfInputAudio) { + return u.OfInputAudio + } else if !param.IsOmitted(u.OfFile) { + return u.OfFile } - return false + return nil } -// The service tier used for processing the request. -type ChatCompletionChunkServiceTier string - -const ( - ChatCompletionChunkServiceTierScale ChatCompletionChunkServiceTier = "scale" - ChatCompletionChunkServiceTierDefault ChatCompletionChunkServiceTier = "default" -) - -func (r ChatCompletionChunkServiceTier) IsKnown() bool { - switch r { - case ChatCompletionChunkServiceTierScale, ChatCompletionChunkServiceTierDefault: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionContentPartUnionParam) GetText() *string { + if vt := u.OfText; vt != nil { + return &vt.Text } - return false + return nil } -// Learn about -// [text inputs](https://platform.openai.com/docs/guides/text-generation). -type ChatCompletionContentPartParam struct { - // The type of the content part. - Type param.Field[ChatCompletionContentPartType] `json:"type,required"` - File param.Field[interface{}] `json:"file"` - ImageURL param.Field[interface{}] `json:"image_url"` - InputAudio param.Field[interface{}] `json:"input_audio"` - // The text content. - Text param.Field[string] `json:"text"` +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionContentPartUnionParam) GetImageURL() *ChatCompletionContentPartImageImageURLParam { + if vt := u.OfImageURL; vt != nil { + return &vt.ImageURL + } + return nil } -func (r ChatCompletionContentPartParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionContentPartUnionParam) GetInputAudio() *ChatCompletionContentPartInputAudioInputAudioParam { + if vt := u.OfInputAudio; vt != nil { + return &vt.InputAudio + } + return nil } -func (r ChatCompletionContentPartParam) implementsChatCompletionContentPartUnionParam() {} - -// Learn about -// [text inputs](https://platform.openai.com/docs/guides/text-generation). -// -// Satisfied by [ChatCompletionContentPartTextParam], -// [ChatCompletionContentPartImageParam], -// [ChatCompletionContentPartInputAudioParam], -// [ChatCompletionContentPartFileParam], [ChatCompletionContentPartParam]. -type ChatCompletionContentPartUnionParam interface { - implementsChatCompletionContentPartUnionParam() +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionContentPartUnionParam) GetFile() *ChatCompletionContentPartFileFileParam { + if vt := u.OfFile; vt != nil { + return &vt.File + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionContentPartUnionParam) GetType() *string { + if vt := u.OfText; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfImageURL; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfInputAudio; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfFile; vt != nil { + return (*string)(&vt.Type) + } + return nil +} + +func init() { + apijson.RegisterUnion[ChatCompletionContentPartUnionParam]( + "type", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartTextParam{}), + DiscriminatorValue: "text", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartImageParam{}), + DiscriminatorValue: "image_url", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartInputAudioParam{}), + DiscriminatorValue: "input_audio", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionContentPartFileParam{}), + DiscriminatorValue: "file", + }, + ) } // Learn about [file inputs](https://platform.openai.com/docs/guides/text) for text // generation. +// +// The properties File, Type are required. type ChatCompletionContentPartFileParam struct { - File param.Field[ChatCompletionContentPartFileFileParam] `json:"file,required"` + File ChatCompletionContentPartFileFileParam `json:"file,omitzero,required"` // The type of the content part. Always `file`. - Type param.Field[ChatCompletionContentPartFileType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "file". + Type constant.File `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartFileParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionContentPartFileParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionContentPartFileParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionContentPartFileParam) implementsChatCompletionContentPartUnionParam() {} - type ChatCompletionContentPartFileFileParam struct { // The base64 encoded file data, used when passing the file to the model as a // string. - FileData param.Field[string] `json:"file_data"` + FileData param.Opt[string] `json:"file_data,omitzero"` // The ID of an uploaded file to use as input. - FileID param.Field[string] `json:"file_id"` + FileID param.Opt[string] `json:"file_id,omitzero"` // The name of the file, used when passing the file to the model as a string. - Filename param.Field[string] `json:"filename"` -} - -func (r ChatCompletionContentPartFileFileParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + Filename param.Opt[string] `json:"filename,omitzero"` + paramObj } -// The type of the content part. Always `file`. -type ChatCompletionContentPartFileType string - -const ( - ChatCompletionContentPartFileTypeFile ChatCompletionContentPartFileType = "file" -) - -func (r ChatCompletionContentPartFileType) IsKnown() bool { - switch r { - case ChatCompletionContentPartFileTypeFile: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartFileFileParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of the content part. -type ChatCompletionContentPartType string - -const ( - ChatCompletionContentPartTypeText ChatCompletionContentPartType = "text" - ChatCompletionContentPartTypeImageURL ChatCompletionContentPartType = "image_url" - ChatCompletionContentPartTypeInputAudio ChatCompletionContentPartType = "input_audio" - ChatCompletionContentPartTypeFile ChatCompletionContentPartType = "file" -) - -func (r ChatCompletionContentPartType) IsKnown() bool { - switch r { - case ChatCompletionContentPartTypeText, ChatCompletionContentPartTypeImageURL, ChatCompletionContentPartTypeInputAudio, ChatCompletionContentPartTypeFile: - return true - } - return false +func (r ChatCompletionContentPartFileFileParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionContentPartFileFileParam + return param.MarshalObject(r, (*shadow)(&r)) } // Learn about [image inputs](https://platform.openai.com/docs/guides/vision). +// +// The properties ImageURL, Type are required. type ChatCompletionContentPartImageParam struct { - ImageURL param.Field[ChatCompletionContentPartImageImageURLParam] `json:"image_url,required"` + ImageURL ChatCompletionContentPartImageImageURLParam `json:"image_url,omitzero,required"` // The type of the content part. - Type param.Field[ChatCompletionContentPartImageType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "image_url". + Type constant.ImageURL `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartImageParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionContentPartImageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionContentPartImageParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionContentPartImageParam) implementsChatCompletionContentPartUnionParam() {} - +// The property URL is required. type ChatCompletionContentPartImageImageURLParam struct { // Either a URL of the image or the base64 encoded image data. - URL param.Field[string] `json:"url,required" format:"uri"` + URL string `json:"url,required" format:"uri"` // Specifies the detail level of the image. Learn more in the // [Vision guide](https://platform.openai.com/docs/guides/vision#low-or-high-fidelity-image-understanding). - Detail param.Field[ChatCompletionContentPartImageImageURLDetail] `json:"detail"` + // + // Any of "auto", "low", "high". + Detail string `json:"detail,omitzero"` + paramObj } -func (r ChatCompletionContentPartImageImageURLParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartImageImageURLParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// Specifies the detail level of the image. Learn more in the -// [Vision guide](https://platform.openai.com/docs/guides/vision#low-or-high-fidelity-image-understanding). -type ChatCompletionContentPartImageImageURLDetail string - -const ( - ChatCompletionContentPartImageImageURLDetailAuto ChatCompletionContentPartImageImageURLDetail = "auto" - ChatCompletionContentPartImageImageURLDetailLow ChatCompletionContentPartImageImageURLDetail = "low" - ChatCompletionContentPartImageImageURLDetailHigh ChatCompletionContentPartImageImageURLDetail = "high" -) - -func (r ChatCompletionContentPartImageImageURLDetail) IsKnown() bool { - switch r { - case ChatCompletionContentPartImageImageURLDetailAuto, ChatCompletionContentPartImageImageURLDetailLow, ChatCompletionContentPartImageImageURLDetailHigh: - return true - } - return false +func (r ChatCompletionContentPartImageImageURLParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionContentPartImageImageURLParam + return param.MarshalObject(r, (*shadow)(&r)) } -// The type of the content part. -type ChatCompletionContentPartImageType string - -const ( - ChatCompletionContentPartImageTypeImageURL ChatCompletionContentPartImageType = "image_url" -) - -func (r ChatCompletionContentPartImageType) IsKnown() bool { - switch r { - case ChatCompletionContentPartImageTypeImageURL: - return true - } - return false +func init() { + apijson.RegisterFieldValidator[ChatCompletionContentPartImageImageURLParam]( + "Detail", false, "auto", "low", "high", + ) } // Learn about [audio inputs](https://platform.openai.com/docs/guides/audio). +// +// The properties InputAudio, Type are required. type ChatCompletionContentPartInputAudioParam struct { - InputAudio param.Field[ChatCompletionContentPartInputAudioInputAudioParam] `json:"input_audio,required"` + InputAudio ChatCompletionContentPartInputAudioInputAudioParam `json:"input_audio,omitzero,required"` // The type of the content part. Always `input_audio`. - Type param.Field[ChatCompletionContentPartInputAudioType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "input_audio". + Type constant.InputAudio `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartInputAudioParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionContentPartInputAudioParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionContentPartInputAudioParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionContentPartInputAudioParam) implementsChatCompletionContentPartUnionParam() {} - +// The properties Data, Format are required. type ChatCompletionContentPartInputAudioInputAudioParam struct { // Base64 encoded audio data. - Data param.Field[string] `json:"data,required"` + Data string `json:"data,required"` // The format of the encoded audio data. Currently supports "wav" and "mp3". - Format param.Field[ChatCompletionContentPartInputAudioInputAudioFormat] `json:"format,required"` + // + // Any of "wav", "mp3". + Format string `json:"format,omitzero,required"` + paramObj } -func (r ChatCompletionContentPartInputAudioInputAudioParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartInputAudioInputAudioParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The format of the encoded audio data. Currently supports "wav" and "mp3". -type ChatCompletionContentPartInputAudioInputAudioFormat string - -const ( - ChatCompletionContentPartInputAudioInputAudioFormatWAV ChatCompletionContentPartInputAudioInputAudioFormat = "wav" - ChatCompletionContentPartInputAudioInputAudioFormatMP3 ChatCompletionContentPartInputAudioInputAudioFormat = "mp3" -) - -func (r ChatCompletionContentPartInputAudioInputAudioFormat) IsKnown() bool { - switch r { - case ChatCompletionContentPartInputAudioInputAudioFormatWAV, ChatCompletionContentPartInputAudioInputAudioFormatMP3: - return true - } - return false +func (r ChatCompletionContentPartInputAudioInputAudioParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionContentPartInputAudioInputAudioParam + return param.MarshalObject(r, (*shadow)(&r)) } -// The type of the content part. Always `input_audio`. -type ChatCompletionContentPartInputAudioType string - -const ( - ChatCompletionContentPartInputAudioTypeInputAudio ChatCompletionContentPartInputAudioType = "input_audio" -) - -func (r ChatCompletionContentPartInputAudioType) IsKnown() bool { - switch r { - case ChatCompletionContentPartInputAudioTypeInputAudio: - return true - } - return false +func init() { + apijson.RegisterFieldValidator[ChatCompletionContentPartInputAudioInputAudioParam]( + "Format", false, "wav", "mp3", + ) } +// The properties Refusal, Type are required. type ChatCompletionContentPartRefusalParam struct { // The refusal message generated by the model. - Refusal param.Field[string] `json:"refusal,required"` + Refusal string `json:"refusal,required"` // The type of the content part. - Type param.Field[ChatCompletionContentPartRefusalType] `json:"type,required"` -} - -func (r ChatCompletionContentPartRefusalParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + // + // This field can be elided, and will marshal its zero value as "refusal". + Type constant.Refusal `json:"type,required"` + paramObj } -func (r ChatCompletionContentPartRefusalParam) implementsChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartRefusalParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of the content part. -type ChatCompletionContentPartRefusalType string - -const ( - ChatCompletionContentPartRefusalTypeRefusal ChatCompletionContentPartRefusalType = "refusal" -) - -func (r ChatCompletionContentPartRefusalType) IsKnown() bool { - switch r { - case ChatCompletionContentPartRefusalTypeRefusal: - return true - } - return false +func (r ChatCompletionContentPartRefusalParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionContentPartRefusalParam + return param.MarshalObject(r, (*shadow)(&r)) } // Learn about // [text inputs](https://platform.openai.com/docs/guides/text-generation). +// +// The properties Text, Type are required. type ChatCompletionContentPartTextParam struct { // The text content. - Text param.Field[string] `json:"text,required"` + Text string `json:"text,required"` // The type of the content part. - Type param.Field[ChatCompletionContentPartTextType] `json:"type,required"` -} - -func (r ChatCompletionContentPartTextParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + // + // This field can be elided, and will marshal its zero value as "text". + Type constant.Text `json:"type,required"` + paramObj } -func (r ChatCompletionContentPartTextParam) implementsChatCompletionAssistantMessageParamContentArrayOfContentPartsUnionItem() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionContentPartTextParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -func (r ChatCompletionContentPartTextParam) implementsChatCompletionContentPartUnionParam() {} - -// The type of the content part. -type ChatCompletionContentPartTextType string - -const ( - ChatCompletionContentPartTextTypeText ChatCompletionContentPartTextType = "text" -) - -func (r ChatCompletionContentPartTextType) IsKnown() bool { - switch r { - case ChatCompletionContentPartTextTypeText: - return true - } - return false +func (r ChatCompletionContentPartTextParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionContentPartTextParam + return param.MarshalObject(r, (*shadow)(&r)) } type ChatCompletionDeleted struct { @@ -1226,142 +1097,132 @@ type ChatCompletionDeleted struct { // Whether the chat completion was deleted. Deleted bool `json:"deleted,required"` // The type of object being deleted. - Object ChatCompletionDeletedObject `json:"object,required"` - JSON chatCompletionDeletedJSON `json:"-"` -} - -// chatCompletionDeletedJSON contains the JSON metadata for the struct -// [ChatCompletionDeleted] -type chatCompletionDeletedJSON struct { - ID apijson.Field - Deleted apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionDeleted) UnmarshalJSON(data []byte) (err error) { + Object constant.ChatCompletionDeleted `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Deleted resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionDeleted) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionDeleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionDeletedJSON) RawJSON() string { - return r.raw -} - -// The type of object being deleted. -type ChatCompletionDeletedObject string - -const ( - ChatCompletionDeletedObjectChatCompletionDeleted ChatCompletionDeletedObject = "chat.completion.deleted" -) - -func (r ChatCompletionDeletedObject) IsKnown() bool { - switch r { - case ChatCompletionDeletedObjectChatCompletionDeleted: - return true - } - return false -} - // Developer-provided instructions that the model should follow, regardless of // messages sent by the user. With o1 models and newer, `developer` messages // replace the previous `system` messages. +// +// The properties Content, Role are required. type ChatCompletionDeveloperMessageParam struct { // The contents of the developer message. - Content param.Field[ChatCompletionDeveloperMessageParamContentUnion] `json:"content,required"` - // The role of the messages author, in this case `developer`. - Role param.Field[ChatCompletionDeveloperMessageParamRole] `json:"role,required"` + Content ChatCompletionDeveloperMessageParamContentUnion `json:"content,omitzero,required"` // An optional name for the participant. Provides the model information to // differentiate between participants of the same role. - Name param.Field[string] `json:"name"` + Name param.Opt[string] `json:"name,omitzero"` + // The role of the messages author, in this case `developer`. + // + // This field can be elided, and will marshal its zero value as "developer". + Role constant.Developer `json:"role,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionDeveloperMessageParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionDeveloperMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionDeveloperMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionDeveloperMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The contents of the developer message. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionDeveloperMessageParamContentArrayOfContentParts]. -type ChatCompletionDeveloperMessageParamContentUnion interface { - ImplementsChatCompletionDeveloperMessageParamContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionDeveloperMessageParamContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionContentPartTextParam `json:",omitzero,inline"` + paramUnion } -type ChatCompletionDeveloperMessageParamContentArrayOfContentParts []ChatCompletionContentPartTextParam - -func (r ChatCompletionDeveloperMessageParamContentArrayOfContentParts) ImplementsChatCompletionDeveloperMessageParamContentUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionDeveloperMessageParamContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionDeveloperMessageParamContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionDeveloperMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts) } -// The role of the messages author, in this case `developer`. -type ChatCompletionDeveloperMessageParamRole string - -const ( - ChatCompletionDeveloperMessageParamRoleDeveloper ChatCompletionDeveloperMessageParamRole = "developer" -) - -func (r ChatCompletionDeveloperMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionDeveloperMessageParamRoleDeveloper: - return true +func (u *ChatCompletionDeveloperMessageParamContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } // Specifying a particular function via `{"name": "my_function"}` forces the model // to call that function. +// +// The property Name is required. type ChatCompletionFunctionCallOptionParam struct { // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionFunctionCallOptionParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionFunctionCallOptionParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionFunctionCallOptionParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionFunctionCallOptionParam) implementsChatCompletionNewParamsFunctionCallUnion() {} - // Deprecated: deprecated +// +// The properties Content, Name, Role are required. type ChatCompletionFunctionMessageParam struct { // The contents of the function message. - Content param.Field[string] `json:"content,required"` + Content param.Opt[string] `json:"content,omitzero,required"` // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` // The role of the messages author, in this case `function`. - Role param.Field[ChatCompletionFunctionMessageParamRole] `json:"role,required"` + // + // This field can be elided, and will marshal its zero value as "function". + Role constant.Function `json:"role,required"` + paramObj } -func (r ChatCompletionFunctionMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionFunctionMessageParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -func (r ChatCompletionFunctionMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The role of the messages author, in this case `function`. -type ChatCompletionFunctionMessageParamRole string - -const ( - ChatCompletionFunctionMessageParamRoleFunction ChatCompletionFunctionMessageParamRole = "function" -) - -func (r ChatCompletionFunctionMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionFunctionMessageParamRoleFunction: - return true - } - return false +func (r ChatCompletionFunctionMessageParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionFunctionMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } // A chat completion message generated by the model. type ChatCompletionMessage struct { // The contents of the message. - Content string `json:"content,required,nullable"` + Content string `json:"content,required"` // The refusal message generated by the model. - Refusal string `json:"refusal,required,nullable"` + Refusal string `json:"refusal,required"` // The role of the author of this message. - Role ChatCompletionMessageRole `json:"role,required"` + Role constant.Assistant `json:"role,required"` // Annotations for the message, when applicable, as when using the // [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). Annotations []ChatCompletionMessageAnnotation `json:"annotations"` @@ -1376,114 +1237,73 @@ type ChatCompletionMessage struct { FunctionCall ChatCompletionMessageFunctionCall `json:"function_call"` // The tool calls generated by the model, such as function calls. ToolCalls []ChatCompletionMessageToolCall `json:"tool_calls"` - JSON chatCompletionMessageJSON `json:"-"` -} - -// chatCompletionMessageJSON contains the JSON metadata for the struct -// [ChatCompletionMessage] -type chatCompletionMessageJSON struct { - Content apijson.Field - Refusal apijson.Field - Role apijson.Field - Annotations apijson.Field - Audio apijson.Field - FunctionCall apijson.Field - ToolCalls apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionMessage) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Content resp.Field + Refusal resp.Field + Role resp.Field + Annotations resp.Field + Audio resp.Field + FunctionCall resp.Field + ToolCalls resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessage) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r ChatCompletionMessage) MarshalJSON() (data []byte, err error) { - s := "" - s, _ = sjson.Set(s, "role", r.Role) - - if r.FunctionCall.Name != "" { - b, err := apijson.Marshal(r.FunctionCall) - if err != nil { - return nil, err - } - s, _ = sjson.SetRaw(s, "function_call", string(b)) - } else if len(r.ToolCalls) > 0 { - b, err := apijson.Marshal(r.ToolCalls) - if err != nil { - return nil, err - } - s, _ = sjson.SetRaw(s, "tool_calls", string(b)) - } else { - s, _ = sjson.Set(s, "content", r.Content) +func (r ChatCompletionMessage) ToParam() ChatCompletionMessageParamUnion { + asst := r.ToAssistantMessageParam() + return ChatCompletionMessageParamUnion{OfAssistant: &asst} +} + +func (r ChatCompletionMessage) ToAssistantMessageParam() ChatCompletionAssistantMessageParam { + var p ChatCompletionAssistantMessageParam + p.Content.OfString = toParam(r.Content, r.JSON.Content) + p.Refusal = toParam(r.Refusal, r.JSON.Refusal) + p.Audio.ID = r.Audio.ID + p.Role = r.Role + p.FunctionCall.Arguments = r.FunctionCall.Arguments + p.FunctionCall.Name = r.FunctionCall.Name + p.ToolCalls = make([]ChatCompletionMessageToolCallParam, len(r.ToolCalls)) + for i, v := range r.ToolCalls { + p.ToolCalls[i].ID = v.ID + p.ToolCalls[i].Function.Arguments = v.Function.Arguments + p.ToolCalls[i].Function.Name = v.Function.Name } - - return []byte(s), nil -} - -func (r chatCompletionMessageJSON) RawJSON() string { - return r.raw -} - -func (r ChatCompletionMessage) implementsChatCompletionMessageParamUnion() {} - -// The role of the author of this message. -type ChatCompletionMessageRole string - -const ( - ChatCompletionMessageRoleAssistant ChatCompletionMessageRole = "assistant" -) - -func (r ChatCompletionMessageRole) IsKnown() bool { - switch r { - case ChatCompletionMessageRoleAssistant: - return true - } - return false + return p } // A URL citation when using web search. type ChatCompletionMessageAnnotation struct { // The type of the URL citation. Always `url_citation`. - Type ChatCompletionMessageAnnotationsType `json:"type,required"` + Type constant.URLCitation `json:"type,required"` // A URL citation when using web search. - URLCitation ChatCompletionMessageAnnotationsURLCitation `json:"url_citation,required"` - JSON chatCompletionMessageAnnotationJSON `json:"-"` -} - -// chatCompletionMessageAnnotationJSON contains the JSON metadata for the struct -// [ChatCompletionMessageAnnotation] -type chatCompletionMessageAnnotationJSON struct { - Type apijson.Field - URLCitation apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionMessageAnnotation) UnmarshalJSON(data []byte) (err error) { + URLCitation ChatCompletionMessageAnnotationURLCitation `json:"url_citation,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + URLCitation resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessageAnnotation) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessageAnnotation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionMessageAnnotationJSON) RawJSON() string { - return r.raw -} - -// The type of the URL citation. Always `url_citation`. -type ChatCompletionMessageAnnotationsType string - -const ( - ChatCompletionMessageAnnotationsTypeURLCitation ChatCompletionMessageAnnotationsType = "url_citation" -) - -func (r ChatCompletionMessageAnnotationsType) IsKnown() bool { - switch r { - case ChatCompletionMessageAnnotationsTypeURLCitation: - return true - } - return false -} - // A URL citation when using web search. -type ChatCompletionMessageAnnotationsURLCitation struct { +type ChatCompletionMessageAnnotationURLCitation struct { // The index of the last character of the URL citation in the message. EndIndex int64 `json:"end_index,required"` // The index of the first character of the URL citation in the message. @@ -1491,29 +1311,25 @@ type ChatCompletionMessageAnnotationsURLCitation struct { // The title of the web resource. Title string `json:"title,required"` // The URL of the web resource. - URL string `json:"url,required"` - JSON chatCompletionMessageAnnotationsURLCitationJSON `json:"-"` -} - -// chatCompletionMessageAnnotationsURLCitationJSON contains the JSON metadata for -// the struct [ChatCompletionMessageAnnotationsURLCitation] -type chatCompletionMessageAnnotationsURLCitationJSON struct { - EndIndex apijson.Field - StartIndex apijson.Field - Title apijson.Field - URL apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionMessageAnnotationsURLCitation) UnmarshalJSON(data []byte) (err error) { + URL string `json:"url,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + EndIndex resp.Field + StartIndex resp.Field + Title resp.Field + URL resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessageAnnotationURLCitation) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessageAnnotationURLCitation) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionMessageAnnotationsURLCitationJSON) RawJSON() string { - return r.raw -} - // Deprecated and replaced by `tool_calls`. The name and arguments of a function // that should be called, as generated by the model. // @@ -1525,84 +1341,295 @@ type ChatCompletionMessageFunctionCall struct { // arguments in your code before calling your function. Arguments string `json:"arguments,required"` // The name of the function to call. - Name string `json:"name,required"` - JSON chatCompletionMessageFunctionCallJSON `json:"-"` + Name string `json:"name,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessageFunctionCall) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessageFunctionCall) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// chatCompletionMessageFunctionCallJSON contains the JSON metadata for the struct -// [ChatCompletionMessageFunctionCall] -type chatCompletionMessageFunctionCallJSON struct { - Arguments apijson.Field - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field +func AssistantMessage[T string | []ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion](content T) ChatCompletionMessageParamUnion { + var assistant ChatCompletionAssistantMessageParam + switch v := any(content).(type) { + case string: + assistant.Content.OfString = param.NewOpt(v) + case []ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion: + assistant.Content.OfArrayOfContentParts = v + } + return ChatCompletionMessageParamUnion{OfAssistant: &assistant} } -func (r *ChatCompletionMessageFunctionCall) UnmarshalJSON(data []byte) (err error) { - return apijson.UnmarshalRoot(data, r) +func DeveloperMessage[T string | []ChatCompletionContentPartTextParam](content T) ChatCompletionMessageParamUnion { + var developer ChatCompletionDeveloperMessageParam + switch v := any(content).(type) { + case string: + developer.Content.OfString = param.NewOpt(v) + case []ChatCompletionContentPartTextParam: + developer.Content.OfArrayOfContentParts = v + } + return ChatCompletionMessageParamUnion{OfDeveloper: &developer} } -func (r chatCompletionMessageFunctionCallJSON) RawJSON() string { - return r.raw +func SystemMessage[T string | []ChatCompletionContentPartTextParam](content T) ChatCompletionMessageParamUnion { + var system ChatCompletionSystemMessageParam + switch v := any(content).(type) { + case string: + system.Content.OfString = param.NewOpt(v) + case []ChatCompletionContentPartTextParam: + system.Content.OfArrayOfContentParts = v + } + return ChatCompletionMessageParamUnion{OfSystem: &system} } -// Developer-provided instructions that the model should follow, regardless of -// messages sent by the user. With o1 models and newer, `developer` messages -// replace the previous `system` messages. -type ChatCompletionMessageParam struct { - // The role of the messages author, in this case `developer`. - Role param.Field[ChatCompletionMessageParamRole] `json:"role,required"` - Audio param.Field[interface{}] `json:"audio"` - Content param.Field[interface{}] `json:"content"` - FunctionCall param.Field[interface{}] `json:"function_call"` - // An optional name for the participant. Provides the model information to - // differentiate between participants of the same role. - Name param.Field[string] `json:"name"` - // The refusal message by the assistant. - Refusal param.Field[string] `json:"refusal"` - // Tool call that this message is responding to. - ToolCallID param.Field[string] `json:"tool_call_id"` - ToolCalls param.Field[interface{}] `json:"tool_calls"` +func UserMessage[T string | []ChatCompletionContentPartUnionParam](content T) ChatCompletionMessageParamUnion { + var user ChatCompletionUserMessageParam + switch v := any(content).(type) { + case string: + user.Content.OfString = param.NewOpt(v) + case []ChatCompletionContentPartUnionParam: + user.Content.OfArrayOfContentParts = v + } + return ChatCompletionMessageParamUnion{OfUser: &user} } -func (r ChatCompletionMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +func ToolMessage[T string | []ChatCompletionContentPartTextParam](content T, toolCallID string) ChatCompletionMessageParamUnion { + var tool ChatCompletionToolMessageParam + switch v := any(content).(type) { + case string: + tool.Content.OfString = param.NewOpt(v) + case []ChatCompletionContentPartTextParam: + tool.Content.OfArrayOfContentParts = v + } + tool.ToolCallID = toolCallID + return ChatCompletionMessageParamUnion{OfTool: &tool} } -func (r ChatCompletionMessageParam) implementsChatCompletionMessageParamUnion() {} +func ChatCompletionMessageParamOfFunction(content string, name string) ChatCompletionMessageParamUnion { + var function ChatCompletionFunctionMessageParam + function.Content = param.NewOpt(content) + function.Name = name + return ChatCompletionMessageParamUnion{OfFunction: &function} +} -// Developer-provided instructions that the model should follow, regardless of -// messages sent by the user. With o1 models and newer, `developer` messages -// replace the previous `system` messages. +// Only one field can be non-zero. // -// Satisfied by [ChatCompletionDeveloperMessageParam], -// [ChatCompletionSystemMessageParam], [ChatCompletionUserMessageParam], -// [ChatCompletionAssistantMessageParam], [ChatCompletionToolMessageParam], -// [ChatCompletionFunctionMessageParam], [ChatCompletionMessageParam]. -// -// This union is additionally satisfied by the return types [ChatCompletionMessage] -type ChatCompletionMessageParamUnion interface { - implementsChatCompletionMessageParamUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionMessageParamUnion struct { + OfDeveloper *ChatCompletionDeveloperMessageParam `json:",omitzero,inline"` + OfSystem *ChatCompletionSystemMessageParam `json:",omitzero,inline"` + OfUser *ChatCompletionUserMessageParam `json:",omitzero,inline"` + OfAssistant *ChatCompletionAssistantMessageParam `json:",omitzero,inline"` + OfTool *ChatCompletionToolMessageParam `json:",omitzero,inline"` + OfFunction *ChatCompletionFunctionMessageParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionMessageParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u ChatCompletionMessageParamUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionMessageParamUnion](u.OfDeveloper, + u.OfSystem, + u.OfUser, + u.OfAssistant, + u.OfTool, + u.OfFunction) +} + +func (u *ChatCompletionMessageParamUnion) asAny() any { + if !param.IsOmitted(u.OfDeveloper) { + return u.OfDeveloper + } else if !param.IsOmitted(u.OfSystem) { + return u.OfSystem + } else if !param.IsOmitted(u.OfUser) { + return u.OfUser + } else if !param.IsOmitted(u.OfAssistant) { + return u.OfAssistant + } else if !param.IsOmitted(u.OfTool) { + return u.OfTool + } else if !param.IsOmitted(u.OfFunction) { + return u.OfFunction + } + return nil } -// The role of the messages author, in this case `developer`. -type ChatCompletionMessageParamRole string +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetAudio() *ChatCompletionAssistantMessageParamAudio { + if vt := u.OfAssistant; vt != nil { + return &vt.Audio + } + return nil +} -const ( - ChatCompletionMessageParamRoleDeveloper ChatCompletionMessageParamRole = "developer" - ChatCompletionMessageParamRoleSystem ChatCompletionMessageParamRole = "system" - ChatCompletionMessageParamRoleUser ChatCompletionMessageParamRole = "user" - ChatCompletionMessageParamRoleAssistant ChatCompletionMessageParamRole = "assistant" - ChatCompletionMessageParamRoleTool ChatCompletionMessageParamRole = "tool" - ChatCompletionMessageParamRoleFunction ChatCompletionMessageParamRole = "function" -) +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetFunctionCall() *ChatCompletionAssistantMessageParamFunctionCall { + if vt := u.OfAssistant; vt != nil { + return &vt.FunctionCall + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetRefusal() *string { + if vt := u.OfAssistant; vt != nil && vt.Refusal.IsPresent() { + return &vt.Refusal.Value + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetToolCalls() []ChatCompletionMessageToolCallParam { + if vt := u.OfAssistant; vt != nil { + return vt.ToolCalls + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetToolCallID() *string { + if vt := u.OfTool; vt != nil { + return &vt.ToolCallID + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetRole() *string { + if vt := u.OfDeveloper; vt != nil { + return (*string)(&vt.Role) + } else if vt := u.OfSystem; vt != nil { + return (*string)(&vt.Role) + } else if vt := u.OfUser; vt != nil { + return (*string)(&vt.Role) + } else if vt := u.OfAssistant; vt != nil { + return (*string)(&vt.Role) + } else if vt := u.OfTool; vt != nil { + return (*string)(&vt.Role) + } else if vt := u.OfFunction; vt != nil { + return (*string)(&vt.Role) + } + return nil +} + +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionMessageParamUnion) GetName() *string { + if vt := u.OfDeveloper; vt != nil && vt.Name.IsPresent() { + return &vt.Name.Value + } else if vt := u.OfSystem; vt != nil && vt.Name.IsPresent() { + return &vt.Name.Value + } else if vt := u.OfUser; vt != nil && vt.Name.IsPresent() { + return &vt.Name.Value + } else if vt := u.OfAssistant; vt != nil && vt.Name.IsPresent() { + return &vt.Name.Value + } else if vt := u.OfFunction; vt != nil { + return (*string)(&vt.Name) + } + return nil +} + +// Returns a subunion which exports methods to access subproperties +// +// Or use AsAny() to get the underlying value +func (u ChatCompletionMessageParamUnion) GetContent() (res chatCompletionMessageParamUnionContent) { + if vt := u.OfDeveloper; vt != nil { + res.ofChatCompletionDeveloperMessageContent = &vt.Content + } else if vt := u.OfSystem; vt != nil { + res.ofChatCompletionSystemMessageContent = &vt.Content + } else if vt := u.OfUser; vt != nil { + res.ofChatCompletionUserMessageContent = &vt.Content + } else if vt := u.OfAssistant; vt != nil { + res.ofChatCompletionAssistantMessageContent = &vt.Content + } else if vt := u.OfTool; vt != nil { + res.ofChatCompletionToolMessageContent = &vt.Content + } else if vt := u.OfFunction; vt != nil && vt.Content.IsPresent() { + res.ofString = &vt.Content.Value + } + return +} + +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type chatCompletionMessageParamUnionContent struct { + ofChatCompletionDeveloperMessageContent *ChatCompletionDeveloperMessageParamContentUnion + ofChatCompletionSystemMessageContent *ChatCompletionSystemMessageParamContentUnion + ofChatCompletionUserMessageContent *ChatCompletionUserMessageParamContentUnion + ofChatCompletionAssistantMessageContent *ChatCompletionAssistantMessageParamContentUnion + ofChatCompletionToolMessageContent *ChatCompletionToolMessageParamContentUnion + ofString *string +} -func (r ChatCompletionMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionMessageParamRoleDeveloper, ChatCompletionMessageParamRoleSystem, ChatCompletionMessageParamRoleUser, ChatCompletionMessageParamRoleAssistant, ChatCompletionMessageParamRoleTool, ChatCompletionMessageParamRoleFunction: - return true +// Use the following switch statement to get the type of the union: +// +// switch u.AsAny().(type) { +// case *string: +// case *[]openai.ChatCompletionContentPartTextParam: +// case *[]openai.ChatCompletionContentPartUnionParam: +// case *[]openai.ChatCompletionAssistantMessageParamContentArrayOfContentPartUnion: +// default: +// fmt.Errorf("not present") +// } +func (u chatCompletionMessageParamUnionContent) AsAny() any { + if !param.IsOmitted(u.ofChatCompletionDeveloperMessageContent) { + return u.ofChatCompletionDeveloperMessageContent.asAny() + } else if !param.IsOmitted(u.ofChatCompletionSystemMessageContent) { + return u.ofChatCompletionSystemMessageContent.asAny() + } else if !param.IsOmitted(u.ofChatCompletionUserMessageContent) { + return u.ofChatCompletionUserMessageContent.asAny() + } else if !param.IsOmitted(u.ofChatCompletionAssistantMessageContent) { + return u.ofChatCompletionAssistantMessageContent.asAny() + } else if !param.IsOmitted(u.ofChatCompletionToolMessageContent) { + return u.ofChatCompletionToolMessageContent.asAny() + } else if !param.IsOmitted(u.ofString) { + return u.ofString } - return false + return nil +} + +func init() { + apijson.RegisterUnion[ChatCompletionMessageParamUnion]( + "role", + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionDeveloperMessageParam{}), + DiscriminatorValue: "developer", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionSystemMessageParam{}), + DiscriminatorValue: "system", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionUserMessageParam{}), + DiscriminatorValue: "user", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionAssistantMessageParam{}), + DiscriminatorValue: "assistant", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionToolMessageParam{}), + DiscriminatorValue: "tool", + }, + apijson.UnionVariant{ + TypeFilter: gjson.JSON, + Type: reflect.TypeOf(ChatCompletionFunctionMessageParam{}), + DiscriminatorValue: "function", + }, + ) } type ChatCompletionMessageToolCall struct { @@ -1611,26 +1638,32 @@ type ChatCompletionMessageToolCall struct { // The function that the model called. Function ChatCompletionMessageToolCallFunction `json:"function,required"` // The type of the tool. Currently, only `function` is supported. - Type ChatCompletionMessageToolCallType `json:"type,required"` - JSON chatCompletionMessageToolCallJSON `json:"-"` -} - -// chatCompletionMessageToolCallJSON contains the JSON metadata for the struct -// [ChatCompletionMessageToolCall] -type chatCompletionMessageToolCallJSON struct { - ID apijson.Field - Function apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionMessageToolCall) UnmarshalJSON(data []byte) (err error) { + Type constant.Function `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Function resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessageToolCall) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessageToolCall) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionMessageToolCallJSON) RawJSON() string { - return r.raw +// ToParam converts this ChatCompletionMessageToolCall to a +// ChatCompletionMessageToolCallParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ChatCompletionMessageToolCallParam.IsOverridden() +func (r ChatCompletionMessageToolCall) ToParam() ChatCompletionMessageToolCallParam { + return param.OverrideObj[ChatCompletionMessageToolCallParam](r.RawJSON()) } // The function that the model called. @@ -1641,179 +1674,184 @@ type ChatCompletionMessageToolCallFunction struct { // arguments in your code before calling your function. Arguments string `json:"arguments,required"` // The name of the function to call. - Name string `json:"name,required"` - JSON chatCompletionMessageToolCallFunctionJSON `json:"-"` -} - -// chatCompletionMessageToolCallFunctionJSON contains the JSON metadata for the -// struct [ChatCompletionMessageToolCallFunction] -type chatCompletionMessageToolCallFunctionJSON struct { - Arguments apijson.Field - Name apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionMessageToolCallFunction) UnmarshalJSON(data []byte) (err error) { + Name string `json:"name,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Arguments resp.Field + Name resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionMessageToolCallFunction) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionMessageToolCallFunction) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionMessageToolCallFunctionJSON) RawJSON() string { - return r.raw -} - -// The type of the tool. Currently, only `function` is supported. -type ChatCompletionMessageToolCallType string - -const ( - ChatCompletionMessageToolCallTypeFunction ChatCompletionMessageToolCallType = "function" -) - -func (r ChatCompletionMessageToolCallType) IsKnown() bool { - switch r { - case ChatCompletionMessageToolCallTypeFunction: - return true - } - return false -} - +// The properties ID, Function, Type are required. type ChatCompletionMessageToolCallParam struct { // The ID of the tool call. - ID param.Field[string] `json:"id,required"` + ID string `json:"id,required"` // The function that the model called. - Function param.Field[ChatCompletionMessageToolCallFunctionParam] `json:"function,required"` + Function ChatCompletionMessageToolCallFunctionParam `json:"function,omitzero,required"` // The type of the tool. Currently, only `function` is supported. - Type param.Field[ChatCompletionMessageToolCallType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "function". + Type constant.Function `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionMessageToolCallParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionMessageToolCallParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionMessageToolCallParam + return param.MarshalObject(r, (*shadow)(&r)) } // The function that the model called. +// +// The properties Arguments, Name are required. type ChatCompletionMessageToolCallFunctionParam struct { // The arguments to call the function with, as generated by the model in JSON // format. Note that the model does not always generate valid JSON, and may // hallucinate parameters not defined by your function schema. Validate the // arguments in your code before calling your function. - Arguments param.Field[string] `json:"arguments,required"` + Arguments string `json:"arguments,required"` // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionMessageToolCallFunctionParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionMessageToolCallFunctionParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionMessageToolCallFunctionParam + return param.MarshalObject(r, (*shadow)(&r)) } // Specifies a tool the model should use. Use to force the model to call a specific // function. +// +// The properties Function, Type are required. type ChatCompletionNamedToolChoiceParam struct { - Function param.Field[ChatCompletionNamedToolChoiceFunctionParam] `json:"function,required"` + Function ChatCompletionNamedToolChoiceFunctionParam `json:"function,omitzero,required"` // The type of the tool. Currently, only `function` is supported. - Type param.Field[ChatCompletionNamedToolChoiceType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "function". + Type constant.Function `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNamedToolChoiceParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionNamedToolChoiceParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionNamedToolChoiceParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionNamedToolChoiceParam) implementsChatCompletionToolChoiceOptionUnionParam() {} - +// The property Name is required. type ChatCompletionNamedToolChoiceFunctionParam struct { // The name of the function to call. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` + paramObj } -func (r ChatCompletionNamedToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNamedToolChoiceFunctionParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of the tool. Currently, only `function` is supported. -type ChatCompletionNamedToolChoiceType string - -const ( - ChatCompletionNamedToolChoiceTypeFunction ChatCompletionNamedToolChoiceType = "function" -) - -func (r ChatCompletionNamedToolChoiceType) IsKnown() bool { - switch r { - case ChatCompletionNamedToolChoiceTypeFunction: - return true - } - return false +func (r ChatCompletionNamedToolChoiceFunctionParam) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionNamedToolChoiceFunctionParam + return param.MarshalObject(r, (*shadow)(&r)) } // Static predicted output content, such as the content of a text file that is // being regenerated. +// +// The properties Content, Type are required. type ChatCompletionPredictionContentParam struct { // The content that should be matched when generating a model response. If // generated tokens would match this content, the entire model response can be // returned much more quickly. - Content param.Field[ChatCompletionPredictionContentContentUnionParam] `json:"content,required"` + Content ChatCompletionPredictionContentContentUnionParam `json:"content,omitzero,required"` // The type of the predicted content you want to provide. This type is currently // always `content`. - Type param.Field[ChatCompletionPredictionContentType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "content". + Type constant.Content `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionPredictionContentParam) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionPredictionContentParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionPredictionContentParam + return param.MarshalObject(r, (*shadow)(&r)) } -// The content that should be matched when generating a model response. If -// generated tokens would match this content, the entire model response can be -// returned much more quickly. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionPredictionContentContentArrayOfContentPartsParam]. -type ChatCompletionPredictionContentContentUnionParam interface { - ImplementsChatCompletionPredictionContentContentUnionParam() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionPredictionContentContentUnionParam struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionContentPartTextParam `json:",omitzero,inline"` + paramUnion } -type ChatCompletionPredictionContentContentArrayOfContentPartsParam []ChatCompletionContentPartTextParam - -func (r ChatCompletionPredictionContentContentArrayOfContentPartsParam) ImplementsChatCompletionPredictionContentContentUnionParam() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionPredictionContentContentUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionPredictionContentContentUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionPredictionContentContentUnionParam](u.OfString, u.OfArrayOfContentParts) } -// The type of the predicted content you want to provide. This type is currently -// always `content`. -type ChatCompletionPredictionContentType string - -const ( - ChatCompletionPredictionContentTypeContent ChatCompletionPredictionContentType = "content" -) - -func (r ChatCompletionPredictionContentType) IsKnown() bool { - switch r { - case ChatCompletionPredictionContentTypeContent: - return true +func (u *ChatCompletionPredictionContentContentUnionParam) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } // A chat completion message generated by the model. type ChatCompletionStoreMessage struct { // The identifier of the chat message. - ID string `json:"id,required"` - JSON chatCompletionStoreMessageJSON `json:"-"` + ID string `json:"id,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` ChatCompletionMessage } -// chatCompletionStoreMessageJSON contains the JSON metadata for the struct -// [ChatCompletionStoreMessage] -type chatCompletionStoreMessageJSON struct { - ID apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionStoreMessage) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r ChatCompletionStoreMessage) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionStoreMessage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionStoreMessageJSON) RawJSON() string { - return r.raw -} - // Options for streaming response. Only set this when you set `stream: true`. type ChatCompletionStreamOptionsParam struct { // If set, an additional chunk will be streamed before the `data: [DONE]` message. @@ -1823,58 +1861,69 @@ type ChatCompletionStreamOptionsParam struct { // All other chunks will also include a `usage` field, but with a null value. // **NOTE:** If the stream is interrupted, you may not receive the final usage // chunk which contains the total token usage for the request. - IncludeUsage param.Field[bool] `json:"include_usage"` + IncludeUsage param.Opt[bool] `json:"include_usage,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionStreamOptionsParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionStreamOptionsParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionStreamOptionsParam + return param.MarshalObject(r, (*shadow)(&r)) } // Developer-provided instructions that the model should follow, regardless of // messages sent by the user. With o1 models and newer, use `developer` messages // for this purpose instead. +// +// The properties Content, Role are required. type ChatCompletionSystemMessageParam struct { // The contents of the system message. - Content param.Field[ChatCompletionSystemMessageParamContentUnion] `json:"content,required"` - // The role of the messages author, in this case `system`. - Role param.Field[ChatCompletionSystemMessageParamRole] `json:"role,required"` + Content ChatCompletionSystemMessageParamContentUnion `json:"content,omitzero,required"` // An optional name for the participant. Provides the model information to // differentiate between participants of the same role. - Name param.Field[string] `json:"name"` + Name param.Opt[string] `json:"name,omitzero"` + // The role of the messages author, in this case `system`. + // + // This field can be elided, and will marshal its zero value as "system". + Role constant.System `json:"role,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionSystemMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionSystemMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionSystemMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionSystemMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The contents of the system message. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionSystemMessageParamContentArrayOfContentParts]. -type ChatCompletionSystemMessageParamContentUnion interface { - ImplementsChatCompletionSystemMessageParamContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionSystemMessageParamContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionContentPartTextParam `json:",omitzero,inline"` + paramUnion } -type ChatCompletionSystemMessageParamContentArrayOfContentParts []ChatCompletionContentPartTextParam - -func (r ChatCompletionSystemMessageParamContentArrayOfContentParts) ImplementsChatCompletionSystemMessageParamContentUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionSystemMessageParamContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionSystemMessageParamContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionSystemMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts) } -// The role of the messages author, in this case `system`. -type ChatCompletionSystemMessageParamRole string - -const ( - ChatCompletionSystemMessageParamRoleSystem ChatCompletionSystemMessageParamRole = "system" -) - -func (r ChatCompletionSystemMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionSystemMessageParamRoleSystem: - return true +func (u *ChatCompletionSystemMessageParamContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } type ChatCompletionTokenLogprob struct { @@ -1884,7 +1933,7 @@ type ChatCompletionTokenLogprob struct { // Useful in instances where characters are represented by multiple tokens and // their byte representations must be combined to generate the correct text // representation. Can be `null` if there is no bytes representation for the token. - Bytes []int64 `json:"bytes,required,nullable"` + Bytes []int64 `json:"bytes,required"` // The log probability of this token, if it is within the top 20 most likely // tokens. Otherwise, the value `-9999.0` is used to signify that the token is very // unlikely. @@ -1893,28 +1942,24 @@ type ChatCompletionTokenLogprob struct { // position. In rare cases, there may be fewer than the number of requested // `top_logprobs` returned. TopLogprobs []ChatCompletionTokenLogprobTopLogprob `json:"top_logprobs,required"` - JSON chatCompletionTokenLogprobJSON `json:"-"` -} - -// chatCompletionTokenLogprobJSON contains the JSON metadata for the struct -// [ChatCompletionTokenLogprob] -type chatCompletionTokenLogprobJSON struct { - Token apijson.Field - Bytes apijson.Field - Logprob apijson.Field - TopLogprobs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionTokenLogprob) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Token resp.Field + Bytes resp.Field + Logprob resp.Field + TopLogprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionTokenLogprob) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionTokenLogprob) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionTokenLogprobJSON) RawJSON() string { - return r.raw -} - type ChatCompletionTokenLogprobTopLogprob struct { // The token. Token string `json:"token,required"` @@ -1922,181 +1967,194 @@ type ChatCompletionTokenLogprobTopLogprob struct { // Useful in instances where characters are represented by multiple tokens and // their byte representations must be combined to generate the correct text // representation. Can be `null` if there is no bytes representation for the token. - Bytes []int64 `json:"bytes,required,nullable"` + Bytes []int64 `json:"bytes,required"` // The log probability of this token, if it is within the top 20 most likely // tokens. Otherwise, the value `-9999.0` is used to signify that the token is very // unlikely. - Logprob float64 `json:"logprob,required"` - JSON chatCompletionTokenLogprobTopLogprobJSON `json:"-"` -} - -// chatCompletionTokenLogprobTopLogprobJSON contains the JSON metadata for the -// struct [ChatCompletionTokenLogprobTopLogprob] -type chatCompletionTokenLogprobTopLogprobJSON struct { - Token apijson.Field - Bytes apijson.Field - Logprob apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *ChatCompletionTokenLogprobTopLogprob) UnmarshalJSON(data []byte) (err error) { + Logprob float64 `json:"logprob,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Token resp.Field + Bytes resp.Field + Logprob resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ChatCompletionTokenLogprobTopLogprob) RawJSON() string { return r.JSON.raw } +func (r *ChatCompletionTokenLogprobTopLogprob) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r chatCompletionTokenLogprobTopLogprobJSON) RawJSON() string { - return r.raw -} - +// The properties Function, Type are required. type ChatCompletionToolParam struct { - Function param.Field[shared.FunctionDefinitionParam] `json:"function,required"` + Function shared.FunctionDefinitionParam `json:"function,omitzero,required"` // The type of the tool. Currently, only `function` is supported. - Type param.Field[ChatCompletionToolType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "function". + Type constant.Function `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionToolParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionToolParam + return param.MarshalObject(r, (*shadow)(&r)) } -// The type of the tool. Currently, only `function` is supported. -type ChatCompletionToolType string - -const ( - ChatCompletionToolTypeFunction ChatCompletionToolType = "function" -) - -func (r ChatCompletionToolType) IsKnown() bool { - switch r { - case ChatCompletionToolTypeFunction: - return true - } - return false +func ChatCompletionToolChoiceOptionParamOfChatCompletionNamedToolChoice(function ChatCompletionNamedToolChoiceFunctionParam) ChatCompletionToolChoiceOptionUnionParam { + var variant ChatCompletionNamedToolChoiceParam + variant.Function = function + return ChatCompletionToolChoiceOptionUnionParam{OfChatCompletionNamedToolChoice: &variant} } -// Controls which (if any) tool is called by the model. `none` means the model will -// not call any tool and instead generates a message. `auto` means the model can -// pick between generating a message or calling one or more tools. `required` means -// the model must call one or more tools. Specifying a particular tool via -// `{"type": "function", "function": {"name": "my_function"}}` forces the model to -// call that tool. -// -// `none` is the default when no tools are present. `auto` is the default if tools -// are present. +// Only one field can be non-zero. // -// Satisfied by [ChatCompletionToolChoiceOptionAuto], -// [ChatCompletionNamedToolChoiceParam]. -type ChatCompletionToolChoiceOptionUnionParam interface { - implementsChatCompletionToolChoiceOptionUnionParam() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionToolChoiceOptionUnionParam struct { + // Check if union is this variant with !param.IsOmitted(union.OfAuto) + OfAuto param.Opt[string] `json:",omitzero,inline"` + OfChatCompletionNamedToolChoice *ChatCompletionNamedToolChoiceParam `json:",omitzero,inline"` + paramUnion } -// `none` means the model will not call any tool and instead generates a message. -// `auto` means the model can pick between generating a message or calling one or -// more tools. `required` means the model must call one or more tools. -type ChatCompletionToolChoiceOptionAuto string +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionToolChoiceOptionUnionParam) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionToolChoiceOptionUnionParam) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionToolChoiceOptionUnionParam](u.OfAuto, u.OfChatCompletionNamedToolChoice) +} -const ( - ChatCompletionToolChoiceOptionAutoNone ChatCompletionToolChoiceOptionAuto = "none" - ChatCompletionToolChoiceOptionAutoAuto ChatCompletionToolChoiceOptionAuto = "auto" - ChatCompletionToolChoiceOptionAutoRequired ChatCompletionToolChoiceOptionAuto = "required" -) +func (u *ChatCompletionToolChoiceOptionUnionParam) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfChatCompletionNamedToolChoice) { + return u.OfChatCompletionNamedToolChoice + } + return nil +} -func (r ChatCompletionToolChoiceOptionAuto) IsKnown() bool { - switch r { - case ChatCompletionToolChoiceOptionAutoNone, ChatCompletionToolChoiceOptionAutoAuto, ChatCompletionToolChoiceOptionAutoRequired: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionToolChoiceOptionUnionParam) GetFunction() *ChatCompletionNamedToolChoiceFunctionParam { + if vt := u.OfChatCompletionNamedToolChoice; vt != nil { + return &vt.Function } - return false + return nil } -func (r ChatCompletionToolChoiceOptionAuto) implementsChatCompletionToolChoiceOptionUnionParam() {} +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionToolChoiceOptionUnionParam) GetType() *string { + if vt := u.OfChatCompletionNamedToolChoice; vt != nil { + return (*string)(&vt.Type) + } + return nil +} +// The properties Content, Role, ToolCallID are required. type ChatCompletionToolMessageParam struct { // The contents of the tool message. - Content param.Field[ChatCompletionToolMessageParamContentUnion] `json:"content,required"` - // The role of the messages author, in this case `tool`. - Role param.Field[ChatCompletionToolMessageParamRole] `json:"role,required"` + Content ChatCompletionToolMessageParamContentUnion `json:"content,omitzero,required"` // Tool call that this message is responding to. - ToolCallID param.Field[string] `json:"tool_call_id,required"` + ToolCallID string `json:"tool_call_id,required"` + // The role of the messages author, in this case `tool`. + // + // This field can be elided, and will marshal its zero value as "tool". + Role constant.Tool `json:"role,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionToolMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionToolMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionToolMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionToolMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The contents of the tool message. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionToolMessageParamContentArrayOfContentParts]. -type ChatCompletionToolMessageParamContentUnion interface { - ImplementsChatCompletionToolMessageParamContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionToolMessageParamContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionContentPartTextParam `json:",omitzero,inline"` + paramUnion } -type ChatCompletionToolMessageParamContentArrayOfContentParts []ChatCompletionContentPartTextParam - -func (r ChatCompletionToolMessageParamContentArrayOfContentParts) ImplementsChatCompletionToolMessageParamContentUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionToolMessageParamContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionToolMessageParamContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionToolMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts) } -// The role of the messages author, in this case `tool`. -type ChatCompletionToolMessageParamRole string - -const ( - ChatCompletionToolMessageParamRoleTool ChatCompletionToolMessageParamRole = "tool" -) - -func (r ChatCompletionToolMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionToolMessageParamRoleTool: - return true +func (u *ChatCompletionToolMessageParamContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } // Messages sent by an end user, containing prompts or additional context // information. +// +// The properties Content, Role are required. type ChatCompletionUserMessageParam struct { // The contents of the user message. - Content param.Field[ChatCompletionUserMessageParamContentUnion] `json:"content,required"` - // The role of the messages author, in this case `user`. - Role param.Field[ChatCompletionUserMessageParamRole] `json:"role,required"` + Content ChatCompletionUserMessageParamContentUnion `json:"content,omitzero,required"` // An optional name for the participant. Provides the model information to // differentiate between participants of the same role. - Name param.Field[string] `json:"name"` + Name param.Opt[string] `json:"name,omitzero"` + // The role of the messages author, in this case `user`. + // + // This field can be elided, and will marshal its zero value as "user". + Role constant.User `json:"role,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionUserMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionUserMessageParam) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionUserMessageParam + return param.MarshalObject(r, (*shadow)(&r)) } -func (r ChatCompletionUserMessageParam) implementsChatCompletionMessageParamUnion() {} - -// The contents of the user message. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], -// [ChatCompletionUserMessageParamContentArrayOfContentParts]. -type ChatCompletionUserMessageParamContentUnion interface { - ImplementsChatCompletionUserMessageParamContentUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionUserMessageParamContentUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfContentParts []ChatCompletionContentPartUnionParam `json:",omitzero,inline"` + paramUnion } -type ChatCompletionUserMessageParamContentArrayOfContentParts []ChatCompletionContentPartUnionParam - -func (r ChatCompletionUserMessageParamContentArrayOfContentParts) ImplementsChatCompletionUserMessageParamContentUnion() { +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionUserMessageParamContentUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionUserMessageParamContentUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionUserMessageParamContentUnion](u.OfString, u.OfArrayOfContentParts) } -// The role of the messages author, in this case `user`. -type ChatCompletionUserMessageParamRole string - -const ( - ChatCompletionUserMessageParamRoleUser ChatCompletionUserMessageParamRole = "user" -) - -func (r ChatCompletionUserMessageParamRole) IsKnown() bool { - switch r { - case ChatCompletionUserMessageParamRoleUser: - return true +func (u *ChatCompletionUserMessageParamContentUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfContentParts) { + return &u.OfArrayOfContentParts } - return false + return nil } type ChatCompletionNewParams struct { @@ -2106,57 +2164,25 @@ type ChatCompletionNewParams struct { // [text](https://platform.openai.com/docs/guides/text-generation), // [images](https://platform.openai.com/docs/guides/vision), and // [audio](https://platform.openai.com/docs/guides/audio). - Messages param.Field[[]ChatCompletionMessageParamUnion] `json:"messages,required"` + Messages []ChatCompletionMessageParamUnion `json:"messages,omitzero,required"` // Model ID used to generate the response, like `gpt-4o` or `o1`. OpenAI offers a // wide range of models with different capabilities, performance characteristics, // and price points. Refer to the // [model guide](https://platform.openai.com/docs/models) to browse and compare // available models. - Model param.Field[shared.ChatModel] `json:"model,required"` - // Parameters for audio output. Required when audio output is requested with - // `modalities: ["audio"]`. - // [Learn more](https://platform.openai.com/docs/guides/audio). - Audio param.Field[ChatCompletionAudioParam] `json:"audio"` + Model shared.ChatModel `json:"model,omitzero,required"` // Number between -2.0 and 2.0. Positive values penalize new tokens based on their // existing frequency in the text so far, decreasing the model's likelihood to // repeat the same line verbatim. - FrequencyPenalty param.Field[float64] `json:"frequency_penalty"` - // Deprecated in favor of `tool_choice`. - // - // Controls which (if any) function is called by the model. - // - // `none` means the model will not call a function and instead generates a message. - // - // `auto` means the model can pick between generating a message or calling a - // function. - // - // Specifying a particular function via `{"name": "my_function"}` forces the model - // to call that function. - // - // `none` is the default when no functions are present. `auto` is the default if - // functions are present. - FunctionCall param.Field[ChatCompletionNewParamsFunctionCallUnion] `json:"function_call"` - // Deprecated in favor of `tools`. - // - // A list of functions the model may generate JSON inputs for. - Functions param.Field[[]ChatCompletionNewParamsFunction] `json:"functions"` - // Modify the likelihood of specified tokens appearing in the completion. - // - // Accepts a JSON object that maps tokens (specified by their token ID in the - // tokenizer) to an associated bias value from -100 to 100. Mathematically, the - // bias is added to the logits generated by the model prior to sampling. The exact - // effect will vary per model, but values between -1 and 1 should decrease or - // increase likelihood of selection; values like -100 or 100 should result in a ban - // or exclusive selection of the relevant token. - LogitBias param.Field[map[string]int64] `json:"logit_bias"` + FrequencyPenalty param.Opt[float64] `json:"frequency_penalty,omitzero"` // Whether to return log probabilities of the output tokens or not. If true, // returns the log probabilities of each output token returned in the `content` of // `message`. - Logprobs param.Field[bool] `json:"logprobs"` + Logprobs param.Opt[bool] `json:"logprobs,omitzero"` // An upper bound for the number of tokens that can be generated for a completion, // including visible output tokens and // [reasoning tokens](https://platform.openai.com/docs/guides/reasoning). - MaxCompletionTokens param.Field[int64] `json:"max_completion_tokens"` + MaxCompletionTokens param.Opt[int64] `json:"max_completion_tokens,omitzero"` // The maximum number of [tokens](/tokenizer) that can be generated in the chat // completion. This value can be used to control // [costs](https://openai.com/api/pricing/) for text generated via API. @@ -2164,14 +2190,68 @@ type ChatCompletionNewParams struct { // This value is now deprecated in favor of `max_completion_tokens`, and is not // compatible with // [o1 series models](https://platform.openai.com/docs/guides/reasoning). - MaxTokens param.Field[int64] `json:"max_tokens"` + MaxTokens param.Opt[int64] `json:"max_tokens,omitzero"` + // How many chat completion choices to generate for each input message. Note that + // you will be charged based on the number of generated tokens across all of the + // choices. Keep `n` as `1` to minimize costs. + N param.Opt[int64] `json:"n,omitzero"` + // Number between -2.0 and 2.0. Positive values penalize new tokens based on + // whether they appear in the text so far, increasing the model's likelihood to + // talk about new topics. + PresencePenalty param.Opt[float64] `json:"presence_penalty,omitzero"` + // This feature is in Beta. If specified, our system will make a best effort to + // sample deterministically, such that repeated requests with the same `seed` and + // parameters should return the same result. Determinism is not guaranteed, and you + // should refer to the `system_fingerprint` response parameter to monitor changes + // in the backend. + Seed param.Opt[int64] `json:"seed,omitzero"` + // Whether or not to store the output of this chat completion request for use in + // our [model distillation](https://platform.openai.com/docs/guides/distillation) + // or [evals](https://platform.openai.com/docs/guides/evals) products. + Store param.Opt[bool] `json:"store,omitzero"` + // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will + // make the output more random, while lower values like 0.2 will make it more + // focused and deterministic. We generally recommend altering this or `top_p` but + // not both. + Temperature param.Opt[float64] `json:"temperature,omitzero"` + // An integer between 0 and 20 specifying the number of most likely tokens to + // return at each token position, each with an associated log probability. + // `logprobs` must be set to `true` if this parameter is used. + TopLogprobs param.Opt[int64] `json:"top_logprobs,omitzero"` + // An alternative to sampling with temperature, called nucleus sampling, where the + // model considers the results of the tokens with top_p probability mass. So 0.1 + // means only the tokens comprising the top 10% probability mass are considered. + // + // We generally recommend altering this or `temperature` but not both. + TopP param.Opt[float64] `json:"top_p,omitzero"` + // Whether to enable + // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) + // during tool use. + ParallelToolCalls param.Opt[bool] `json:"parallel_tool_calls,omitzero"` + // A unique identifier representing your end-user, which can help OpenAI to monitor + // and detect abuse. + // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). + User param.Opt[string] `json:"user,omitzero"` + // Parameters for audio output. Required when audio output is requested with + // `modalities: ["audio"]`. + // [Learn more](https://platform.openai.com/docs/guides/audio). + Audio ChatCompletionAudioParam `json:"audio,omitzero"` + // Modify the likelihood of specified tokens appearing in the completion. + // + // Accepts a JSON object that maps tokens (specified by their token ID in the + // tokenizer) to an associated bias value from -100 to 100. Mathematically, the + // bias is added to the logits generated by the model prior to sampling. The exact + // effect will vary per model, but values between -1 and 1 should decrease or + // increase likelihood of selection; values like -100 or 100 should result in a ban + // or exclusive selection of the relevant token. + LogitBias map[string]int64 `json:"logit_bias,omitzero"` // Set of 16 key-value pairs that can be attached to an object. This can be useful // for storing additional information about the object in a structured format, and // querying for objects via API or the dashboard. // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` + Metadata shared.MetadataParam `json:"metadata,omitzero"` // Output types that you would like the model to generate. Most models are capable // of generating text, which is the default: // @@ -2182,46 +2262,16 @@ type ChatCompletionNewParams struct { // this model generate both text and audio responses, you can use: // // `["text", "audio"]` - Modalities param.Field[[]ChatCompletionNewParamsModality] `json:"modalities"` - // How many chat completion choices to generate for each input message. Note that - // you will be charged based on the number of generated tokens across all of the - // choices. Keep `n` as `1` to minimize costs. - N param.Field[int64] `json:"n"` - // Whether to enable - // [parallel function calling](https://platform.openai.com/docs/guides/function-calling#configuring-parallel-function-calling) - // during tool use. - ParallelToolCalls param.Field[bool] `json:"parallel_tool_calls"` - // Static predicted output content, such as the content of a text file that is - // being regenerated. - Prediction param.Field[ChatCompletionPredictionContentParam] `json:"prediction"` - // Number between -2.0 and 2.0. Positive values penalize new tokens based on - // whether they appear in the text so far, increasing the model's likelihood to - // talk about new topics. - PresencePenalty param.Field[float64] `json:"presence_penalty"` + Modalities []string `json:"modalities,omitzero"` // **o-series models only** // // Constrains effort on reasoning for // [reasoning models](https://platform.openai.com/docs/guides/reasoning). Currently // supported values are `low`, `medium`, and `high`. Reducing reasoning effort can // result in faster responses and fewer tokens used on reasoning in a response. - ReasoningEffort param.Field[shared.ReasoningEffort] `json:"reasoning_effort"` - // An object specifying the format that the model must output. - // - // Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured - // Outputs which ensures the model will match your supplied JSON schema. Learn more - // in the - // [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). // - // Setting to `{ "type": "json_object" }` enables the older JSON mode, which - // ensures the message the model generates is valid JSON. Using `json_schema` is - // preferred for models that support it. - ResponseFormat param.Field[ChatCompletionNewParamsResponseFormatUnion] `json:"response_format"` - // This feature is in Beta. If specified, our system will make a best effort to - // sample deterministically, such that repeated requests with the same `seed` and - // parameters should return the same result. Determinism is not guaranteed, and you - // should refer to the `system_fingerprint` response parameter to monitor changes - // in the backend. - Seed param.Field[int64] `json:"seed"` + // Any of "low", "medium", "high". + ReasoningEffort shared.ReasoningEffort `json:"reasoning_effort,omitzero"` // Specifies the latency tier to use for processing the request. This parameter is // relevant for customers subscribed to the scale tier service: // @@ -2236,21 +2286,47 @@ type ChatCompletionNewParams struct { // // When this parameter is set, the response body will include the `service_tier` // utilized. - ServiceTier param.Field[ChatCompletionNewParamsServiceTier] `json:"service_tier"` + // + // Any of "auto", "default". + ServiceTier ChatCompletionNewParamsServiceTier `json:"service_tier,omitzero"` // Up to 4 sequences where the API will stop generating further tokens. The // returned text will not contain the stop sequence. - Stop param.Field[ChatCompletionNewParamsStopUnion] `json:"stop"` - // Whether or not to store the output of this chat completion request for use in - // our [model distillation](https://platform.openai.com/docs/guides/distillation) - // or [evals](https://platform.openai.com/docs/guides/evals) products. - Store param.Field[bool] `json:"store"` + Stop ChatCompletionNewParamsStopUnion `json:"stop,omitzero"` // Options for streaming response. Only set this when you set `stream: true`. - StreamOptions param.Field[ChatCompletionStreamOptionsParam] `json:"stream_options"` - // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will - // make the output more random, while lower values like 0.2 will make it more - // focused and deterministic. We generally recommend altering this or `top_p` but - // not both. - Temperature param.Field[float64] `json:"temperature"` + StreamOptions ChatCompletionStreamOptionsParam `json:"stream_options,omitzero"` + // Deprecated in favor of `tool_choice`. + // + // Controls which (if any) function is called by the model. + // + // `none` means the model will not call a function and instead generates a message. + // + // `auto` means the model can pick between generating a message or calling a + // function. + // + // Specifying a particular function via `{"name": "my_function"}` forces the model + // to call that function. + // + // `none` is the default when no functions are present. `auto` is the default if + // functions are present. + FunctionCall ChatCompletionNewParamsFunctionCallUnion `json:"function_call,omitzero"` + // Deprecated in favor of `tools`. + // + // A list of functions the model may generate JSON inputs for. + Functions []ChatCompletionNewParamsFunction `json:"functions,omitzero"` + // Static predicted output content, such as the content of a text file that is + // being regenerated. + Prediction ChatCompletionPredictionContentParam `json:"prediction,omitzero"` + // An object specifying the format that the model must output. + // + // Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured + // Outputs which ensures the model will match your supplied JSON schema. Learn more + // in the + // [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). + // + // Setting to `{ "type": "json_object" }` enables the older JSON mode, which + // ensures the message the model generates is valid JSON. Using `json_schema` is + // preferred for models that support it. + ResponseFormat ChatCompletionNewParamsResponseFormatUnion `json:"response_format,omitzero"` // Controls which (if any) tool is called by the model. `none` means the model will // not call any tool and instead generates a message. `auto` means the model can // pick between generating a message or calling one or more tools. `required` means @@ -2260,87 +2336,73 @@ type ChatCompletionNewParams struct { // // `none` is the default when no tools are present. `auto` is the default if tools // are present. - ToolChoice param.Field[ChatCompletionToolChoiceOptionUnionParam] `json:"tool_choice"` + ToolChoice ChatCompletionToolChoiceOptionUnionParam `json:"tool_choice,omitzero"` // A list of tools the model may call. Currently, only functions are supported as a // tool. Use this to provide a list of functions the model may generate JSON inputs // for. A max of 128 functions are supported. - Tools param.Field[[]ChatCompletionToolParam] `json:"tools"` - // An integer between 0 and 20 specifying the number of most likely tokens to - // return at each token position, each with an associated log probability. - // `logprobs` must be set to `true` if this parameter is used. - TopLogprobs param.Field[int64] `json:"top_logprobs"` - // An alternative to sampling with temperature, called nucleus sampling, where the - // model considers the results of the tokens with top_p probability mass. So 0.1 - // means only the tokens comprising the top 10% probability mass are considered. - // - // We generally recommend altering this or `temperature` but not both. - TopP param.Field[float64] `json:"top_p"` - // A unique identifier representing your end-user, which can help OpenAI to monitor - // and detect abuse. - // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + Tools []ChatCompletionToolParam `json:"tools,omitzero"` // This tool searches the web for relevant results to use in a response. Learn more // about the // [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). - WebSearchOptions param.Field[ChatCompletionNewParamsWebSearchOptions] `json:"web_search_options"` + WebSearchOptions ChatCompletionNewParamsWebSearchOptions `json:"web_search_options,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r ChatCompletionNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionNewParams + return param.MarshalObject(r, (*shadow)(&r)) } -// Deprecated in favor of `tool_choice`. -// -// Controls which (if any) function is called by the model. -// -// `none` means the model will not call a function and instead generates a message. +// Only one field can be non-zero. // -// `auto` means the model can pick between generating a message or calling a -// function. -// -// Specifying a particular function via `{"name": "my_function"}` forces the model -// to call that function. -// -// `none` is the default when no functions are present. `auto` is the default if -// functions are present. -// -// Satisfied by [ChatCompletionNewParamsFunctionCallFunctionCallMode], -// [ChatCompletionFunctionCallOptionParam]. -// -// Deprecated: deprecated -type ChatCompletionNewParamsFunctionCallUnion interface { - implementsChatCompletionNewParamsFunctionCallUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionNewParamsFunctionCallUnion struct { + // Check if union is this variant with !param.IsOmitted(union.OfFunctionCallMode) + OfFunctionCallMode param.Opt[string] `json:",omitzero,inline"` + OfFunctionCallOption *ChatCompletionFunctionCallOptionParam `json:",omitzero,inline"` + paramUnion } -// `none` means the model will not call a function and instead generates a message. -// `auto` means the model can pick between generating a message or calling a -// function. -type ChatCompletionNewParamsFunctionCallFunctionCallMode string - -const ( - ChatCompletionNewParamsFunctionCallFunctionCallModeNone ChatCompletionNewParamsFunctionCallFunctionCallMode = "none" - ChatCompletionNewParamsFunctionCallFunctionCallModeAuto ChatCompletionNewParamsFunctionCallFunctionCallMode = "auto" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionNewParamsFunctionCallUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionNewParamsFunctionCallUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionNewParamsFunctionCallUnion](u.OfFunctionCallMode, u.OfFunctionCallOption) +} -func (r ChatCompletionNewParamsFunctionCallFunctionCallMode) IsKnown() bool { - switch r { - case ChatCompletionNewParamsFunctionCallFunctionCallModeNone, ChatCompletionNewParamsFunctionCallFunctionCallModeAuto: - return true +func (u *ChatCompletionNewParamsFunctionCallUnion) asAny() any { + if !param.IsOmitted(u.OfFunctionCallMode) { + return &u.OfFunctionCallMode + } else if !param.IsOmitted(u.OfFunctionCallOption) { + return u.OfFunctionCallOption } - return false + return nil } -func (r ChatCompletionNewParamsFunctionCallFunctionCallMode) implementsChatCompletionNewParamsFunctionCallUnion() { +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionNewParamsFunctionCallUnion) GetName() *string { + if vt := u.OfFunctionCallOption; vt != nil { + return &vt.Name + } + return nil } // Deprecated: deprecated +// +// The property Name is required. type ChatCompletionNewParamsFunction struct { // The name of the function to be called. Must be a-z, A-Z, 0-9, or contain // underscores and dashes, with a maximum length of 64. - Name param.Field[string] `json:"name,required"` + Name string `json:"name,required"` // A description of what the function does, used by the model to choose when and // how to call the function. - Description param.Field[string] `json:"description"` + Description param.Opt[string] `json:"description,omitzero"` // The parameters the functions accepts, described as a JSON Schema object. See the // [guide](https://platform.openai.com/docs/guides/function-calling) for examples, // and the @@ -2348,84 +2410,66 @@ type ChatCompletionNewParamsFunction struct { // documentation about the format. // // Omitting `parameters` defines a function with an empty parameter list. - Parameters param.Field[shared.FunctionParameters] `json:"parameters"` + Parameters shared.FunctionParameters `json:"parameters,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNewParamsFunction) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r ChatCompletionNewParamsFunction) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -type ChatCompletionNewParamsModality string - -const ( - ChatCompletionNewParamsModalityText ChatCompletionNewParamsModality = "text" - ChatCompletionNewParamsModalityAudio ChatCompletionNewParamsModality = "audio" -) - -func (r ChatCompletionNewParamsModality) IsKnown() bool { - switch r { - case ChatCompletionNewParamsModalityText, ChatCompletionNewParamsModalityAudio: - return true - } - return false + type shadow ChatCompletionNewParamsFunction + return param.MarshalObject(r, (*shadow)(&r)) } -// An object specifying the format that the model must output. +// Only one field can be non-zero. // -// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured -// Outputs which ensures the model will match your supplied JSON schema. Learn more -// in the -// [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). -// -// Setting to `{ "type": "json_object" }` enables the older JSON mode, which -// ensures the message the model generates is valid JSON. Using `json_schema` is -// preferred for models that support it. -type ChatCompletionNewParamsResponseFormat struct { - // The type of response format being defined. Always `text`. - Type param.Field[ChatCompletionNewParamsResponseFormatType] `json:"type,required"` - JSONSchema param.Field[interface{}] `json:"json_schema"` -} - -func (r ChatCompletionNewParamsResponseFormat) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) -} - -func (r ChatCompletionNewParamsResponseFormat) ImplementsChatCompletionNewParamsResponseFormatUnion() { +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionNewParamsResponseFormatUnion struct { + OfText *shared.ResponseFormatTextParam `json:",omitzero,inline"` + OfJSONSchema *shared.ResponseFormatJSONSchemaParam `json:",omitzero,inline"` + OfJSONObject *shared.ResponseFormatJSONObjectParam `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionNewParamsResponseFormatUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u ChatCompletionNewParamsResponseFormatUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionNewParamsResponseFormatUnion](u.OfText, u.OfJSONSchema, u.OfJSONObject) +} + +func (u *ChatCompletionNewParamsResponseFormatUnion) asAny() any { + if !param.IsOmitted(u.OfText) { + return u.OfText + } else if !param.IsOmitted(u.OfJSONSchema) { + return u.OfJSONSchema + } else if !param.IsOmitted(u.OfJSONObject) { + return u.OfJSONObject + } + return nil } -// An object specifying the format that the model must output. -// -// Setting to `{ "type": "json_schema", "json_schema": {...} }` enables Structured -// Outputs which ensures the model will match your supplied JSON schema. Learn more -// in the -// [Structured Outputs guide](https://platform.openai.com/docs/guides/structured-outputs). -// -// Setting to `{ "type": "json_object" }` enables the older JSON mode, which -// ensures the message the model generates is valid JSON. Using `json_schema` is -// preferred for models that support it. -// -// Satisfied by [shared.ResponseFormatTextParam], -// [shared.ResponseFormatJSONSchemaParam], [shared.ResponseFormatJSONObjectParam], -// [ChatCompletionNewParamsResponseFormat]. -type ChatCompletionNewParamsResponseFormatUnion interface { - ImplementsChatCompletionNewParamsResponseFormatUnion() +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionNewParamsResponseFormatUnion) GetJSONSchema() *shared.ResponseFormatJSONSchemaJSONSchemaParam { + if vt := u.OfJSONSchema; vt != nil { + return &vt.JSONSchema + } + return nil } -// The type of response format being defined. Always `text`. -type ChatCompletionNewParamsResponseFormatType string - -const ( - ChatCompletionNewParamsResponseFormatTypeText ChatCompletionNewParamsResponseFormatType = "text" - ChatCompletionNewParamsResponseFormatTypeJSONSchema ChatCompletionNewParamsResponseFormatType = "json_schema" - ChatCompletionNewParamsResponseFormatTypeJSONObject ChatCompletionNewParamsResponseFormatType = "json_object" -) - -func (r ChatCompletionNewParamsResponseFormatType) IsKnown() bool { - switch r { - case ChatCompletionNewParamsResponseFormatTypeText, ChatCompletionNewParamsResponseFormatTypeJSONSchema, ChatCompletionNewParamsResponseFormatTypeJSONObject: - return true +// Returns a pointer to the underlying variant's property, if present. +func (u ChatCompletionNewParamsResponseFormatUnion) GetType() *string { + if vt := u.OfText; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfJSONSchema; vt != nil { + return (*string)(&vt.Type) + } else if vt := u.OfJSONObject; vt != nil { + return (*string)(&vt.Type) } - return false + return nil } // Specifies the latency tier to use for processing the request. This parameter is @@ -2449,102 +2493,107 @@ const ( ChatCompletionNewParamsServiceTierDefault ChatCompletionNewParamsServiceTier = "default" ) -func (r ChatCompletionNewParamsServiceTier) IsKnown() bool { - switch r { - case ChatCompletionNewParamsServiceTierAuto, ChatCompletionNewParamsServiceTierDefault: - return true - } - return false -} - -// Up to 4 sequences where the API will stop generating further tokens. The -// returned text will not contain the stop sequence. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], [ChatCompletionNewParamsStopArray]. -type ChatCompletionNewParamsStopUnion interface { - ImplementsChatCompletionNewParamsStopUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type ChatCompletionNewParamsStopUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfChatCompletionNewsStopArray []string `json:",omitzero,inline"` + paramUnion } -type ChatCompletionNewParamsStopArray []string +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u ChatCompletionNewParamsStopUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u ChatCompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[ChatCompletionNewParamsStopUnion](u.OfString, u.OfChatCompletionNewsStopArray) +} -func (r ChatCompletionNewParamsStopArray) ImplementsChatCompletionNewParamsStopUnion() {} +func (u *ChatCompletionNewParamsStopUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfChatCompletionNewsStopArray) { + return &u.OfChatCompletionNewsStopArray + } + return nil +} // This tool searches the web for relevant results to use in a response. Learn more // about the // [web search tool](https://platform.openai.com/docs/guides/tools-web-search?api-mode=chat). type ChatCompletionNewParamsWebSearchOptions struct { + // Approximate location parameters for the search. + UserLocation ChatCompletionNewParamsWebSearchOptionsUserLocation `json:"user_location,omitzero"` // High level guidance for the amount of context window space to use for the // search. One of `low`, `medium`, or `high`. `medium` is the default. - SearchContextSize param.Field[ChatCompletionNewParamsWebSearchOptionsSearchContextSize] `json:"search_context_size"` - // Approximate location parameters for the search. - UserLocation param.Field[ChatCompletionNewParamsWebSearchOptionsUserLocation] `json:"user_location"` + // + // Any of "low", "medium", "high". + SearchContextSize string `json:"search_context_size,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNewParamsWebSearchOptions) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionNewParamsWebSearchOptions) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionNewParamsWebSearchOptions + return param.MarshalObject(r, (*shadow)(&r)) } -// High level guidance for the amount of context window space to use for the -// search. One of `low`, `medium`, or `high`. `medium` is the default. -type ChatCompletionNewParamsWebSearchOptionsSearchContextSize string - -const ( - ChatCompletionNewParamsWebSearchOptionsSearchContextSizeLow ChatCompletionNewParamsWebSearchOptionsSearchContextSize = "low" - ChatCompletionNewParamsWebSearchOptionsSearchContextSizeMedium ChatCompletionNewParamsWebSearchOptionsSearchContextSize = "medium" - ChatCompletionNewParamsWebSearchOptionsSearchContextSizeHigh ChatCompletionNewParamsWebSearchOptionsSearchContextSize = "high" -) - -func (r ChatCompletionNewParamsWebSearchOptionsSearchContextSize) IsKnown() bool { - switch r { - case ChatCompletionNewParamsWebSearchOptionsSearchContextSizeLow, ChatCompletionNewParamsWebSearchOptionsSearchContextSizeMedium, ChatCompletionNewParamsWebSearchOptionsSearchContextSizeHigh: - return true - } - return false +func init() { + apijson.RegisterFieldValidator[ChatCompletionNewParamsWebSearchOptions]( + "SearchContextSize", false, "low", "medium", "high", + ) } // Approximate location parameters for the search. +// +// The properties Approximate, Type are required. type ChatCompletionNewParamsWebSearchOptionsUserLocation struct { // Approximate location parameters for the search. - Approximate param.Field[ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate] `json:"approximate,required"` + Approximate ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate `json:"approximate,omitzero,required"` // The type of location approximation. Always `approximate`. - Type param.Field[ChatCompletionNewParamsWebSearchOptionsUserLocationType] `json:"type,required"` + // + // This field can be elided, and will marshal its zero value as "approximate". + Type constant.Approximate `json:"type,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNewParamsWebSearchOptionsUserLocation) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r ChatCompletionNewParamsWebSearchOptionsUserLocation) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionNewParamsWebSearchOptionsUserLocation + return param.MarshalObject(r, (*shadow)(&r)) } // Approximate location parameters for the search. type ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate struct { // Free text input for the city of the user, e.g. `San Francisco`. - City param.Field[string] `json:"city"` + City param.Opt[string] `json:"city,omitzero"` // The two-letter [ISO country code](https://en.wikipedia.org/wiki/ISO_3166-1) of // the user, e.g. `US`. - Country param.Field[string] `json:"country"` + Country param.Opt[string] `json:"country,omitzero"` // Free text input for the region of the user, e.g. `California`. - Region param.Field[string] `json:"region"` + Region param.Opt[string] `json:"region,omitzero"` // The [IANA timezone](https://timeapi.io/documentation/iana-timezones) of the // user, e.g. `America/Los_Angeles`. - Timezone param.Field[string] `json:"timezone"` + Timezone param.Opt[string] `json:"timezone,omitzero"` + paramObj } -func (r ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of location approximation. Always `approximate`. -type ChatCompletionNewParamsWebSearchOptionsUserLocationType string - -const ( - ChatCompletionNewParamsWebSearchOptionsUserLocationTypeApproximate ChatCompletionNewParamsWebSearchOptionsUserLocationType = "approximate" -) - -func (r ChatCompletionNewParamsWebSearchOptionsUserLocationType) IsKnown() bool { - switch r { - case ChatCompletionNewParamsWebSearchOptionsUserLocationTypeApproximate: - return true - } - return false +func (r ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate) MarshalJSON() (data []byte, err error) { + type shadow ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate + return param.MarshalObject(r, (*shadow)(&r)) } type ChatCompletionUpdateParams struct { @@ -2554,29 +2603,42 @@ type ChatCompletionUpdateParams struct { // // Keys are strings with a maximum length of 64 characters. Values are strings with // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata,required"` + Metadata shared.MetadataParam `json:"metadata,omitzero,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionUpdateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r ChatCompletionUpdateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ChatCompletionUpdateParams + return param.MarshalObject(r, (*shadow)(&r)) } type ChatCompletionListParams struct { // Identifier for the last chat completion from the previous pagination request. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // Number of Chat Completions to retrieve. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // The model used to generate the Chat Completions. + Model param.Opt[string] `query:"model,omitzero" json:"-"` // A list of metadata keys to filter the Chat Completions by. Example: // // `metadata[key1]=value1&metadata[key2]=value2` - Metadata param.Field[shared.MetadataParam] `query:"metadata"` - // The model used to generate the Chat Completions. - Model param.Field[string] `query:"model"` + Metadata shared.MetadataParam `query:"metadata,omitzero" json:"-"` // Sort order for Chat Completions by timestamp. Use `asc` for ascending order or // `desc` for descending order. Defaults to `asc`. - Order param.Field[ChatCompletionListParamsOrder] `query:"order"` + // + // Any of "asc", "desc". + Order ChatCompletionListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [ChatCompletionListParams]'s query parameters as // `url.Values`. func (r ChatCompletionListParams) URLQuery() (v url.Values) { @@ -2594,11 +2656,3 @@ const ( ChatCompletionListParamsOrderAsc ChatCompletionListParamsOrder = "asc" ChatCompletionListParamsOrderDesc ChatCompletionListParamsOrder = "desc" ) - -func (r ChatCompletionListParamsOrder) IsKnown() bool { - switch r { - case ChatCompletionListParamsOrderAsc, ChatCompletionListParamsOrderDesc: - return true - } - return false -} diff --git a/chatcompletion_test.go b/chatcompletion_test.go index fa9a1910..8ff66dd5 100644 --- a/chatcompletion_test.go +++ b/chatcompletion_test.go @@ -27,81 +27,89 @@ func TestChatCompletionNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionDeveloperMessageParam{ - Content: openai.F[openai.ChatCompletionDeveloperMessageParamContentUnion](shared.UnionString("string")), - Role: openai.F(openai.ChatCompletionDeveloperMessageParamRoleDeveloper), - Name: openai.F("name"), - }}), - Model: openai.F(shared.ChatModelO3Mini), - Audio: openai.F(openai.ChatCompletionAudioParam{ - Format: openai.F(openai.ChatCompletionAudioParamFormatWAV), - Voice: openai.F(openai.ChatCompletionAudioParamVoiceAlloy), - }), - FrequencyPenalty: openai.F(-2.000000), - FunctionCall: openai.F[openai.ChatCompletionNewParamsFunctionCallUnion](openai.ChatCompletionNewParamsFunctionCallFunctionCallMode(openai.ChatCompletionNewParamsFunctionCallFunctionCallModeNone)), - Functions: openai.F([]openai.ChatCompletionNewParamsFunction{{ - Name: openai.F("name"), - Description: openai.F("description"), - Parameters: openai.F(shared.FunctionParameters{ + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfDeveloper: &openai.ChatCompletionDeveloperMessageParam{ + Content: openai.ChatCompletionDeveloperMessageParamContentUnion{ + OfString: openai.String("string"), + }, + Name: openai.String("name"), + }, + }}, + Model: shared.ChatModelO3Mini, + Audio: openai.ChatCompletionAudioParam{ + Format: openai.ChatCompletionAudioParamFormatWAV, + Voice: openai.ChatCompletionAudioParamVoiceAlloy, + }, + FrequencyPenalty: openai.Float(-2), + FunctionCall: openai.ChatCompletionNewParamsFunctionCallUnion{ + OfFunctionCallMode: openai.String("none"), + }, + Functions: []openai.ChatCompletionNewParamsFunction{{ + Name: "name", + Description: openai.String("description"), + Parameters: shared.FunctionParameters{ "foo": "bar", - }), - }}), - LogitBias: openai.F(map[string]int64{ - "foo": int64(0), - }), - Logprobs: openai.F(true), - MaxCompletionTokens: openai.F(int64(0)), - MaxTokens: openai.F(int64(0)), - Metadata: openai.F(shared.MetadataParam{ + }, + }}, + LogitBias: map[string]int64{ + "foo": 0, + }, + Logprobs: openai.Bool(true), + MaxCompletionTokens: openai.Int(0), + MaxTokens: openai.Int(0), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Modalities: openai.F([]openai.ChatCompletionNewParamsModality{openai.ChatCompletionNewParamsModalityText}), - N: openai.F(int64(1)), - ParallelToolCalls: openai.F(true), - Prediction: openai.F(openai.ChatCompletionPredictionContentParam{ - Content: openai.F[openai.ChatCompletionPredictionContentContentUnionParam](shared.UnionString("string")), - Type: openai.F(openai.ChatCompletionPredictionContentTypeContent), - }), - PresencePenalty: openai.F(-2.000000), - ReasoningEffort: openai.F(shared.ReasoningEffortLow), - ResponseFormat: openai.F[openai.ChatCompletionNewParamsResponseFormatUnion](shared.ResponseFormatTextParam{ - Type: openai.F(shared.ResponseFormatTextTypeText), - }), - Seed: openai.F(int64(-9007199254740991)), - ServiceTier: openai.F(openai.ChatCompletionNewParamsServiceTierAuto), - Stop: openai.F[openai.ChatCompletionNewParamsStopUnion](shared.UnionString("\n")), - Store: openai.F(true), - StreamOptions: openai.F(openai.ChatCompletionStreamOptionsParam{ - IncludeUsage: openai.F(true), - }), - Temperature: openai.F(1.000000), - ToolChoice: openai.F[openai.ChatCompletionToolChoiceOptionUnionParam](openai.ChatCompletionToolChoiceOptionAuto(openai.ChatCompletionToolChoiceOptionAutoNone)), - Tools: openai.F([]openai.ChatCompletionToolParam{{ - Function: openai.F(shared.FunctionDefinitionParam{ - Name: openai.F("name"), - Description: openai.F("description"), - Parameters: openai.F(shared.FunctionParameters{ + }, + Modalities: []string{"text"}, + N: openai.Int(1), + ParallelToolCalls: openai.Bool(true), + Prediction: openai.ChatCompletionPredictionContentParam{ + Content: openai.ChatCompletionPredictionContentContentUnionParam{ + OfString: openai.String("string"), + }, + }, + PresencePenalty: openai.Float(-2), + ReasoningEffort: shared.ReasoningEffortLow, + ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{ + OfText: &shared.ResponseFormatTextParam{}, + }, + Seed: openai.Int(-9007199254740991), + ServiceTier: openai.ChatCompletionNewParamsServiceTierAuto, + Stop: openai.ChatCompletionNewParamsStopUnion{ + OfString: openai.String("\n"), + }, + Store: openai.Bool(true), + StreamOptions: openai.ChatCompletionStreamOptionsParam{ + IncludeUsage: openai.Bool(true), + }, + Temperature: openai.Float(1), + ToolChoice: openai.ChatCompletionToolChoiceOptionUnionParam{ + OfAuto: openai.String("none"), + }, + Tools: []openai.ChatCompletionToolParam{{ + Function: shared.FunctionDefinitionParam{ + Name: "name", + Description: openai.String("description"), + Parameters: shared.FunctionParameters{ "foo": "bar", - }), - Strict: openai.F(true), - }), - Type: openai.F(openai.ChatCompletionToolTypeFunction), - }}), - TopLogprobs: openai.F(int64(0)), - TopP: openai.F(1.000000), - User: openai.F("user-1234"), - WebSearchOptions: openai.F(openai.ChatCompletionNewParamsWebSearchOptions{ - SearchContextSize: openai.F(openai.ChatCompletionNewParamsWebSearchOptionsSearchContextSizeLow), - UserLocation: openai.F(openai.ChatCompletionNewParamsWebSearchOptionsUserLocation{ - Approximate: openai.F(openai.ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate{ - City: openai.F("city"), - Country: openai.F("country"), - Region: openai.F("region"), - Timezone: openai.F("timezone"), - }), - Type: openai.F(openai.ChatCompletionNewParamsWebSearchOptionsUserLocationTypeApproximate), - }), - }), + }, + Strict: openai.Bool(true), + }, + }}, + TopLogprobs: openai.Int(0), + TopP: openai.Float(1), + User: openai.String("user-1234"), + WebSearchOptions: openai.ChatCompletionNewParamsWebSearchOptions{ + SearchContextSize: "low", + UserLocation: openai.ChatCompletionNewParamsWebSearchOptionsUserLocation{ + Approximate: openai.ChatCompletionNewParamsWebSearchOptionsUserLocationApproximate{ + City: openai.String("city"), + Country: openai.String("country"), + Region: openai.String("region"), + Timezone: openai.String("timezone"), + }, + }, + }, }) if err != nil { var apierr *openai.Error @@ -150,9 +158,9 @@ func TestChatCompletionUpdate(t *testing.T) { context.TODO(), "completion_id", openai.ChatCompletionUpdateParams{ - Metadata: openai.F(shared.MetadataParam{ + Metadata: shared.MetadataParam{ "foo": "string", - }), + }, }, ) if err != nil { @@ -177,13 +185,13 @@ func TestChatCompletionListWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Chat.Completions.List(context.TODO(), openai.ChatCompletionListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), - Metadata: openai.F(shared.MetadataParam{ + After: openai.String("after"), + Limit: openai.Int(0), + Metadata: shared.MetadataParam{ "foo": "string", - }), - Model: openai.F("model"), - Order: openai.F(openai.ChatCompletionListParamsOrderAsc), + }, + Model: openai.String("model"), + Order: openai.ChatCompletionListParamsOrderAsc, }) if err != nil { var apierr *openai.Error diff --git a/chatcompletionmessage.go b/chatcompletionmessage.go index 39b38828..6cec9c1d 100644 --- a/chatcompletionmessage.go +++ b/chatcompletionmessage.go @@ -10,10 +10,10 @@ import ( "net/url" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" ) // ChatCompletionMessageService contains methods and other services that help with @@ -29,8 +29,8 @@ type ChatCompletionMessageService struct { // NewChatCompletionMessageService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewChatCompletionMessageService(opts ...option.RequestOption) (r *ChatCompletionMessageService) { - r = &ChatCompletionMessageService{} +func NewChatCompletionMessageService(opts ...option.RequestOption) (r ChatCompletionMessageService) { + r = ChatCompletionMessageService{} r.Options = opts return } @@ -66,14 +66,21 @@ func (r *ChatCompletionMessageService) ListAutoPaging(ctx context.Context, compl type ChatCompletionMessageListParams struct { // Identifier for the last message from the previous pagination request. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // Number of messages to retrieve. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` // Sort order for messages by timestamp. Use `asc` for ascending order or `desc` // for descending order. Defaults to `asc`. - Order param.Field[ChatCompletionMessageListParamsOrder] `query:"order"` + // + // Any of "asc", "desc". + Order ChatCompletionMessageListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ChatCompletionMessageListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [ChatCompletionMessageListParams]'s query parameters as // `url.Values`. func (r ChatCompletionMessageListParams) URLQuery() (v url.Values) { @@ -91,11 +98,3 @@ const ( ChatCompletionMessageListParamsOrderAsc ChatCompletionMessageListParamsOrder = "asc" ChatCompletionMessageListParamsOrderDesc ChatCompletionMessageListParamsOrder = "desc" ) - -func (r ChatCompletionMessageListParamsOrder) IsKnown() bool { - switch r { - case ChatCompletionMessageListParamsOrderAsc, ChatCompletionMessageListParamsOrderDesc: - return true - } - return false -} diff --git a/chatcompletionmessage_test.go b/chatcompletionmessage_test.go index 23e2129a..650f4834 100644 --- a/chatcompletionmessage_test.go +++ b/chatcompletionmessage_test.go @@ -29,9 +29,9 @@ func TestChatCompletionMessageListWithOptionalParams(t *testing.T) { context.TODO(), "completion_id", openai.ChatCompletionMessageListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), - Order: openai.F(openai.ChatCompletionMessageListParamsOrderAsc), + After: openai.String("after"), + Limit: openai.Int(0), + Order: openai.ChatCompletionMessageListParamsOrderAsc, }, ) if err != nil { diff --git a/client.go b/client.go index 3cee6aeb..e99313f7 100644 --- a/client.go +++ b/client.go @@ -9,6 +9,7 @@ import ( "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/responses" ) // Client creates a struct with services and top level methods that help with @@ -16,19 +17,20 @@ import ( // directly, and instead use the [NewClient] method instead. type Client struct { Options []option.RequestOption - Completions *CompletionService - Chat *ChatService - Embeddings *EmbeddingService - Files *FileService - Images *ImageService - Audio *AudioService - Moderations *ModerationService - Models *ModelService - FineTuning *FineTuningService - VectorStores *VectorStoreService - Beta *BetaService - Batches *BatchService - Uploads *UploadService + Completions CompletionService + Chat ChatService + Embeddings EmbeddingService + Files FileService + Images ImageService + Audio AudioService + Moderations ModerationService + Models ModelService + FineTuning FineTuningService + VectorStores VectorStoreService + Beta BetaService + Batches BatchService + Uploads UploadService + Responses responses.ResponseService } // DefaultClientOptions read from the environment (OPENAI_API_KEY, OPENAI_ORG_ID, @@ -51,10 +53,10 @@ func DefaultClientOptions() []option.RequestOption { // environment (OPENAI_API_KEY, OPENAI_ORG_ID, OPENAI_PROJECT_ID). The option // passed in as arguments are applied after these default arguments, and all option // will be passed down to the services and requests that this client makes. -func NewClient(opts ...option.RequestOption) (r *Client) { +func NewClient(opts ...option.RequestOption) (r Client) { opts = append(DefaultClientOptions(), opts...) - r = &Client{Options: opts} + r = Client{Options: opts} r.Completions = NewCompletionService(opts...) r.Chat = NewChatService(opts...) @@ -69,6 +71,7 @@ func NewClient(opts ...option.RequestOption) (r *Client) { r.Beta = NewBetaService(opts...) r.Batches = NewBatchService(opts...) r.Uploads = NewUploadService(opts...) + r.Responses = responses.NewResponseService(opts...) return } diff --git a/client_test.go b/client_test.go index ac460b62..38b94119 100644 --- a/client_test.go +++ b/client_test.go @@ -40,11 +40,14 @@ func TestUserAgentHeader(t *testing.T) { }), ) client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if userAgent != fmt.Sprintf("OpenAI/Go %s", internal.PackageVersion) { t.Errorf("Expected User-Agent to be correct, but got: %#v", userAgent) @@ -69,11 +72,14 @@ func TestRetryAfter(t *testing.T) { }), ) _, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("Expected there to be a cancel error") @@ -109,11 +115,14 @@ func TestDeleteRetryCountHeader(t *testing.T) { option.WithHeaderDel("X-Stainless-Retry-Count"), ) _, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("Expected there to be a cancel error") @@ -144,11 +153,14 @@ func TestOverwriteRetryCountHeader(t *testing.T) { option.WithHeader("X-Stainless-Retry-Count", "42"), ) _, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("Expected there to be a cancel error") @@ -178,11 +190,14 @@ func TestRetryAfterMs(t *testing.T) { }), ) _, err := client.Chat.Completions.New(context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("Expected there to be a cancel error") @@ -206,11 +221,14 @@ func TestContextCancel(t *testing.T) { cancelCtx, cancel := context.WithCancel(context.Background()) cancel() _, err := client.Chat.Completions.New(cancelCtx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("Expected there to be a cancel error") @@ -231,11 +249,14 @@ func TestContextCancelDelay(t *testing.T) { cancelCtx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond) defer cancel() _, err := client.Chat.Completions.New(cancelCtx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("expected there to be a cancel error") @@ -262,11 +283,14 @@ func TestContextDeadline(t *testing.T) { }), ) _, err := client.Chat.Completions.New(deadlineCtx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionUserMessageParam{ - Role: openai.F(openai.ChatCompletionUserMessageParamRoleUser), - Content: openai.F[openai.ChatCompletionUserMessageParamContentUnion](shared.UnionString("Say this is a test")), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfUser: &openai.ChatCompletionUserMessageParam{ + Content: openai.ChatCompletionUserMessageParamContentUnion{ + OfString: openai.String("Say this is a test"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) if err == nil { t.Error("expected there to be a deadline error") @@ -312,11 +336,14 @@ func TestContextDeadlineStreaming(t *testing.T) { }), ) stream := client.Chat.Completions.NewStreaming(deadlineCtx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionDeveloperMessageParam{ - Content: openai.F[openai.ChatCompletionDeveloperMessageParamContentUnion](shared.UnionString("string")), - Role: openai.F(openai.ChatCompletionDeveloperMessageParamRoleDeveloper), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfDeveloper: &openai.ChatCompletionDeveloperMessageParam{ + Content: openai.ChatCompletionDeveloperMessageParamContentUnion{ + OfString: openai.String("string"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }) for stream.Next() { _ = stream.Current() @@ -364,11 +391,14 @@ func TestContextDeadlineStreamingWithRequestTimeout(t *testing.T) { stream := client.Chat.Completions.NewStreaming( context.Background(), openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{openai.ChatCompletionDeveloperMessageParam{ - Content: openai.F[openai.ChatCompletionDeveloperMessageParamContentUnion](shared.UnionString("string")), - Role: openai.F(openai.ChatCompletionDeveloperMessageParamRoleDeveloper), - }}), - Model: openai.F(shared.ChatModelO3Mini), + Messages: []openai.ChatCompletionMessageParamUnion{{ + OfDeveloper: &openai.ChatCompletionDeveloperMessageParam{ + Content: openai.ChatCompletionDeveloperMessageParamContentUnion{ + OfString: openai.String("string"), + }, + }, + }}, + Model: shared.ChatModelO3Mini, }, option.WithRequestTimeout((100 * time.Millisecond)), ) diff --git a/completion.go b/completion.go index d28edd40..82fb57fd 100644 --- a/completion.go +++ b/completion.go @@ -7,10 +7,12 @@ import ( "net/http" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/packages/ssestream" + "github.com/openai/openai-go/shared/constant" ) // CompletionService contains methods and other services that help with interacting @@ -26,8 +28,8 @@ type CompletionService struct { // NewCompletionService generates a new service that applies the given options to // each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewCompletionService(opts ...option.RequestOption) (r *CompletionService) { - r = &CompletionService{} +func NewCompletionService(opts ...option.RequestOption) (r CompletionService) { + r = CompletionService{} r.Options = opts return } @@ -65,7 +67,7 @@ type Completion struct { // The model used for completion. Model string `json:"model,required"` // The object type, which is always "text_completion" - Object CompletionObject `json:"object,required"` + Object constant.TextCompletion `json:"object,required"` // This fingerprint represents the backend configuration that the model runs with. // // Can be used in conjunction with the `seed` request parameter to understand when @@ -73,76 +75,56 @@ type Completion struct { SystemFingerprint string `json:"system_fingerprint"` // Usage statistics for the completion request. Usage CompletionUsage `json:"usage"` - JSON completionJSON `json:"-"` -} - -// completionJSON contains the JSON metadata for the struct [Completion] -type completionJSON struct { - ID apijson.Field - Choices apijson.Field - Created apijson.Field - Model apijson.Field - Object apijson.Field - SystemFingerprint apijson.Field - Usage apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Completion) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Choices resp.Field + Created resp.Field + Model resp.Field + Object resp.Field + SystemFingerprint resp.Field + Usage resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Completion) RawJSON() string { return r.JSON.raw } +func (r *Completion) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always "text_completion" -type CompletionObject string - -const ( - CompletionObjectTextCompletion CompletionObject = "text_completion" -) - -func (r CompletionObject) IsKnown() bool { - switch r { - case CompletionObjectTextCompletion: - return true - } - return false -} - type CompletionChoice struct { // The reason the model stopped generating tokens. This will be `stop` if the model // hit a natural stop point or a provided stop sequence, `length` if the maximum // number of tokens specified in the request was reached, or `content_filter` if // content was omitted due to a flag from our content filters. + // + // Any of "stop", "length", "content_filter". FinishReason CompletionChoiceFinishReason `json:"finish_reason,required"` Index int64 `json:"index,required"` - Logprobs CompletionChoiceLogprobs `json:"logprobs,required,nullable"` + Logprobs CompletionChoiceLogprobs `json:"logprobs,required"` Text string `json:"text,required"` - JSON completionChoiceJSON `json:"-"` -} - -// completionChoiceJSON contains the JSON metadata for the struct -// [CompletionChoice] -type completionChoiceJSON struct { - FinishReason apijson.Field - Index apijson.Field - Logprobs apijson.Field - Text apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CompletionChoice) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FinishReason resp.Field + Index resp.Field + Logprobs resp.Field + Text resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CompletionChoice) RawJSON() string { return r.JSON.raw } +func (r *CompletionChoice) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionChoiceJSON) RawJSON() string { - return r.raw -} - // The reason the model stopped generating tokens. This will be `stop` if the model // hit a natural stop point or a provided stop sequence, `length` if the maximum // number of tokens specified in the request was reached, or `content_filter` if @@ -155,41 +137,29 @@ const ( CompletionChoiceFinishReasonContentFilter CompletionChoiceFinishReason = "content_filter" ) -func (r CompletionChoiceFinishReason) IsKnown() bool { - switch r { - case CompletionChoiceFinishReasonStop, CompletionChoiceFinishReasonLength, CompletionChoiceFinishReasonContentFilter: - return true - } - return false -} - type CompletionChoiceLogprobs struct { - TextOffset []int64 `json:"text_offset"` - TokenLogprobs []float64 `json:"token_logprobs"` - Tokens []string `json:"tokens"` - TopLogprobs []map[string]float64 `json:"top_logprobs"` - JSON completionChoiceLogprobsJSON `json:"-"` -} - -// completionChoiceLogprobsJSON contains the JSON metadata for the struct -// [CompletionChoiceLogprobs] -type completionChoiceLogprobsJSON struct { - TextOffset apijson.Field - TokenLogprobs apijson.Field - Tokens apijson.Field - TopLogprobs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CompletionChoiceLogprobs) UnmarshalJSON(data []byte) (err error) { + TextOffset []int64 `json:"text_offset"` + TokenLogprobs []float64 `json:"token_logprobs"` + Tokens []string `json:"tokens"` + TopLogprobs []map[string]float64 `json:"top_logprobs"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + TextOffset resp.Field + TokenLogprobs resp.Field + Tokens resp.Field + TopLogprobs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CompletionChoiceLogprobs) RawJSON() string { return r.JSON.raw } +func (r *CompletionChoiceLogprobs) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionChoiceLogprobsJSON) RawJSON() string { - return r.raw -} - // Usage statistics for the completion request. type CompletionUsage struct { // Number of tokens in the generated completion. @@ -202,28 +172,25 @@ type CompletionUsage struct { CompletionTokensDetails CompletionUsageCompletionTokensDetails `json:"completion_tokens_details"` // Breakdown of tokens used in the prompt. PromptTokensDetails CompletionUsagePromptTokensDetails `json:"prompt_tokens_details"` - JSON completionUsageJSON `json:"-"` -} - -// completionUsageJSON contains the JSON metadata for the struct [CompletionUsage] -type completionUsageJSON struct { - CompletionTokens apijson.Field - PromptTokens apijson.Field - TotalTokens apijson.Field - CompletionTokensDetails apijson.Field - PromptTokensDetails apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CompletionUsage) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + CompletionTokens resp.Field + PromptTokens resp.Field + TotalTokens resp.Field + CompletionTokensDetails resp.Field + PromptTokensDetails resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CompletionUsage) RawJSON() string { return r.JSON.raw } +func (r *CompletionUsage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionUsageJSON) RawJSON() string { - return r.raw -} - // Breakdown of tokens used in a completion. type CompletionUsageCompletionTokensDetails struct { // When using Predicted Outputs, the number of tokens in the prediction that @@ -237,69 +204,61 @@ type CompletionUsageCompletionTokensDetails struct { // not appear in the completion. However, like reasoning tokens, these tokens are // still counted in the total completion tokens for purposes of billing, output, // and context window limits. - RejectedPredictionTokens int64 `json:"rejected_prediction_tokens"` - JSON completionUsageCompletionTokensDetailsJSON `json:"-"` -} - -// completionUsageCompletionTokensDetailsJSON contains the JSON metadata for the -// struct [CompletionUsageCompletionTokensDetails] -type completionUsageCompletionTokensDetailsJSON struct { - AcceptedPredictionTokens apijson.Field - AudioTokens apijson.Field - ReasoningTokens apijson.Field - RejectedPredictionTokens apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CompletionUsageCompletionTokensDetails) UnmarshalJSON(data []byte) (err error) { + RejectedPredictionTokens int64 `json:"rejected_prediction_tokens"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + AcceptedPredictionTokens resp.Field + AudioTokens resp.Field + ReasoningTokens resp.Field + RejectedPredictionTokens resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CompletionUsageCompletionTokensDetails) RawJSON() string { return r.JSON.raw } +func (r *CompletionUsageCompletionTokensDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionUsageCompletionTokensDetailsJSON) RawJSON() string { - return r.raw -} - // Breakdown of tokens used in the prompt. type CompletionUsagePromptTokensDetails struct { // Audio input tokens present in the prompt. AudioTokens int64 `json:"audio_tokens"` // Cached tokens present in the prompt. - CachedTokens int64 `json:"cached_tokens"` - JSON completionUsagePromptTokensDetailsJSON `json:"-"` -} - -// completionUsagePromptTokensDetailsJSON contains the JSON metadata for the struct -// [CompletionUsagePromptTokensDetails] -type completionUsagePromptTokensDetailsJSON struct { - AudioTokens apijson.Field - CachedTokens apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CompletionUsagePromptTokensDetails) UnmarshalJSON(data []byte) (err error) { + CachedTokens int64 `json:"cached_tokens"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + AudioTokens resp.Field + CachedTokens resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CompletionUsagePromptTokensDetails) RawJSON() string { return r.JSON.raw } +func (r *CompletionUsagePromptTokensDetails) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r completionUsagePromptTokensDetailsJSON) RawJSON() string { - return r.raw -} - type CompletionNewParams struct { - // ID of the model to use. You can use the - // [List models](https://platform.openai.com/docs/api-reference/models/list) API to - // see all of your available models, or see our - // [Model overview](https://platform.openai.com/docs/models) for descriptions of - // them. - Model param.Field[CompletionNewParamsModel] `json:"model,required"` // The prompt(s) to generate completions for, encoded as a string, array of // strings, array of tokens, or array of token arrays. // // Note that <|endoftext|> is the document separator that the model sees during // training, so if a prompt is not specified the model will generate as if from the // beginning of a new document. - Prompt param.Field[CompletionNewParamsPromptUnion] `json:"prompt,required"` + Prompt CompletionNewParamsPromptUnion `json:"prompt,omitzero,required"` + // ID of the model to use. You can use the + // [List models](https://platform.openai.com/docs/api-reference/models/list) API to + // see all of your available models, or see our + // [Model overview](https://platform.openai.com/docs/models) for descriptions of + // them. + Model string `json:"model,omitzero,required"` // Generates `best_of` completions server-side and returns the "best" (the one with // the highest log probability per token). Results cannot be streamed. // @@ -309,35 +268,22 @@ type CompletionNewParams struct { // **Note:** Because this parameter generates many completions, it can quickly // consume your token quota. Use carefully and ensure that you have reasonable // settings for `max_tokens` and `stop`. - BestOf param.Field[int64] `json:"best_of"` + BestOf param.Opt[int64] `json:"best_of,omitzero"` // Echo back the prompt in addition to the completion - Echo param.Field[bool] `json:"echo"` + Echo param.Opt[bool] `json:"echo,omitzero"` // Number between -2.0 and 2.0. Positive values penalize new tokens based on their // existing frequency in the text so far, decreasing the model's likelihood to // repeat the same line verbatim. // // [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) - FrequencyPenalty param.Field[float64] `json:"frequency_penalty"` - // Modify the likelihood of specified tokens appearing in the completion. - // - // Accepts a JSON object that maps tokens (specified by their token ID in the GPT - // tokenizer) to an associated bias value from -100 to 100. You can use this - // [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. - // Mathematically, the bias is added to the logits generated by the model prior to - // sampling. The exact effect will vary per model, but values between -1 and 1 - // should decrease or increase likelihood of selection; values like -100 or 100 - // should result in a ban or exclusive selection of the relevant token. - // - // As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token - // from being generated. - LogitBias param.Field[map[string]int64] `json:"logit_bias"` + FrequencyPenalty param.Opt[float64] `json:"frequency_penalty,omitzero"` // Include the log probabilities on the `logprobs` most likely output tokens, as // well the chosen tokens. For example, if `logprobs` is 5, the API will return a // list of the 5 most likely tokens. The API will always return the `logprob` of // the sampled token, so there may be up to `logprobs+1` elements in the response. // // The maximum value for `logprobs` is 5. - Logprobs param.Field[int64] `json:"logprobs"` + Logprobs param.Opt[int64] `json:"logprobs,omitzero"` // The maximum number of [tokens](/tokenizer) that can be generated in the // completion. // @@ -345,112 +291,128 @@ type CompletionNewParams struct { // context length. // [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) // for counting tokens. - MaxTokens param.Field[int64] `json:"max_tokens"` + MaxTokens param.Opt[int64] `json:"max_tokens,omitzero"` // How many completions to generate for each prompt. // // **Note:** Because this parameter generates many completions, it can quickly // consume your token quota. Use carefully and ensure that you have reasonable // settings for `max_tokens` and `stop`. - N param.Field[int64] `json:"n"` + N param.Opt[int64] `json:"n,omitzero"` // Number between -2.0 and 2.0. Positive values penalize new tokens based on // whether they appear in the text so far, increasing the model's likelihood to // talk about new topics. // // [See more information about frequency and presence penalties.](https://platform.openai.com/docs/guides/text-generation) - PresencePenalty param.Field[float64] `json:"presence_penalty"` + PresencePenalty param.Opt[float64] `json:"presence_penalty,omitzero"` // If specified, our system will make a best effort to sample deterministically, // such that repeated requests with the same `seed` and parameters should return // the same result. // // Determinism is not guaranteed, and you should refer to the `system_fingerprint` // response parameter to monitor changes in the backend. - Seed param.Field[int64] `json:"seed"` - // Up to 4 sequences where the API will stop generating further tokens. The - // returned text will not contain the stop sequence. - Stop param.Field[CompletionNewParamsStopUnion] `json:"stop"` - // Options for streaming response. Only set this when you set `stream: true`. - StreamOptions param.Field[ChatCompletionStreamOptionsParam] `json:"stream_options"` + Seed param.Opt[int64] `json:"seed,omitzero"` // The suffix that comes after a completion of inserted text. // // This parameter is only supported for `gpt-3.5-turbo-instruct`. - Suffix param.Field[string] `json:"suffix"` + Suffix param.Opt[string] `json:"suffix,omitzero"` // What sampling temperature to use, between 0 and 2. Higher values like 0.8 will // make the output more random, while lower values like 0.2 will make it more // focused and deterministic. // // We generally recommend altering this or `top_p` but not both. - Temperature param.Field[float64] `json:"temperature"` + Temperature param.Opt[float64] `json:"temperature,omitzero"` // An alternative to sampling with temperature, called nucleus sampling, where the // model considers the results of the tokens with top_p probability mass. So 0.1 // means only the tokens comprising the top 10% probability mass are considered. // // We generally recommend altering this or `temperature` but not both. - TopP param.Field[float64] `json:"top_p"` + TopP param.Opt[float64] `json:"top_p,omitzero"` // A unique identifier representing your end-user, which can help OpenAI to monitor // and detect abuse. // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + User param.Opt[string] `json:"user,omitzero"` + // Modify the likelihood of specified tokens appearing in the completion. + // + // Accepts a JSON object that maps tokens (specified by their token ID in the GPT + // tokenizer) to an associated bias value from -100 to 100. You can use this + // [tokenizer tool](/tokenizer?view=bpe) to convert text to token IDs. + // Mathematically, the bias is added to the logits generated by the model prior to + // sampling. The exact effect will vary per model, but values between -1 and 1 + // should decrease or increase likelihood of selection; values like -100 or 100 + // should result in a ban or exclusive selection of the relevant token. + // + // As an example, you can pass `{"50256": -100}` to prevent the <|endoftext|> token + // from being generated. + LogitBias map[string]int64 `json:"logit_bias,omitzero"` + // Up to 4 sequences where the API will stop generating further tokens. The + // returned text will not contain the stop sequence. + Stop CompletionNewParamsStopUnion `json:"stop,omitzero"` + // Options for streaming response. Only set this when you set `stream: true`. + StreamOptions ChatCompletionStreamOptionsParam `json:"stream_options,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f CompletionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r CompletionNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow CompletionNewParams + return param.MarshalObject(r, (*shadow)(&r)) } -// ID of the model to use. You can use the -// [List models](https://platform.openai.com/docs/api-reference/models/list) API to -// see all of your available models, or see our -// [Model overview](https://platform.openai.com/docs/models) for descriptions of -// them. -type CompletionNewParamsModel string - -const ( - CompletionNewParamsModelGPT3_5TurboInstruct CompletionNewParamsModel = "gpt-3.5-turbo-instruct" - CompletionNewParamsModelDavinci002 CompletionNewParamsModel = "davinci-002" - CompletionNewParamsModelBabbage002 CompletionNewParamsModel = "babbage-002" -) - -func (r CompletionNewParamsModel) IsKnown() bool { - switch r { - case CompletionNewParamsModelGPT3_5TurboInstruct, CompletionNewParamsModelDavinci002, CompletionNewParamsModelBabbage002: - return true +// Only one field can be non-zero. +// +// Use [param.IsOmitted] to confirm if a field is set. +type CompletionNewParamsPromptUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfStrings []string `json:",omitzero,inline"` + OfArrayOfTokens []int64 `json:",omitzero,inline"` + OfArrayOfTokenArrays [][]int64 `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u CompletionNewParamsPromptUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u CompletionNewParamsPromptUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[CompletionNewParamsPromptUnion](u.OfString, u.OfArrayOfStrings, u.OfArrayOfTokens, u.OfArrayOfTokenArrays) +} + +func (u *CompletionNewParamsPromptUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfStrings) { + return &u.OfArrayOfStrings + } else if !param.IsOmitted(u.OfArrayOfTokens) { + return &u.OfArrayOfTokens + } else if !param.IsOmitted(u.OfArrayOfTokenArrays) { + return &u.OfArrayOfTokenArrays } - return false + return nil } -// The prompt(s) to generate completions for, encoded as a string, array of -// strings, array of tokens, or array of token arrays. +// Only one field can be non-zero. // -// Note that <|endoftext|> is the document separator that the model sees during -// training, so if a prompt is not specified the model will generate as if from the -// beginning of a new document. -// -// Satisfied by [shared.UnionString], [CompletionNewParamsPromptArrayOfStrings], -// [CompletionNewParamsPromptArrayOfTokens], -// [CompletionNewParamsPromptArrayOfTokenArrays]. -type CompletionNewParamsPromptUnion interface { - ImplementsCompletionNewParamsPromptUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type CompletionNewParamsStopUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfCompletionNewsStopArray []string `json:",omitzero,inline"` + paramUnion } -type CompletionNewParamsPromptArrayOfStrings []string - -func (r CompletionNewParamsPromptArrayOfStrings) ImplementsCompletionNewParamsPromptUnion() {} - -type CompletionNewParamsPromptArrayOfTokens []int64 - -func (r CompletionNewParamsPromptArrayOfTokens) ImplementsCompletionNewParamsPromptUnion() {} - -type CompletionNewParamsPromptArrayOfTokenArrays [][]int64 - -func (r CompletionNewParamsPromptArrayOfTokenArrays) ImplementsCompletionNewParamsPromptUnion() {} - -// Up to 4 sequences where the API will stop generating further tokens. The -// returned text will not contain the stop sequence. -// -// Satisfied by [shared.UnionString], [CompletionNewParamsStopArray]. -type CompletionNewParamsStopUnion interface { - ImplementsCompletionNewParamsStopUnion() +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u CompletionNewParamsStopUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u CompletionNewParamsStopUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[CompletionNewParamsStopUnion](u.OfString, u.OfCompletionNewsStopArray) } -type CompletionNewParamsStopArray []string - -func (r CompletionNewParamsStopArray) ImplementsCompletionNewParamsStopUnion() {} +func (u *CompletionNewParamsStopUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfCompletionNewsStopArray) { + return &u.OfCompletionNewsStopArray + } + return nil +} diff --git a/completion_test.go b/completion_test.go index b8f91248..58fc4f81 100644 --- a/completion_test.go +++ b/completion_test.go @@ -11,7 +11,6 @@ import ( "github.com/openai/openai-go" "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" - "github.com/openai/openai-go/shared" ) func TestCompletionNewWithOptionalParams(t *testing.T) { @@ -27,27 +26,31 @@ func TestCompletionNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Completions.New(context.TODO(), openai.CompletionNewParams{ - Model: openai.F(openai.CompletionNewParamsModelGPT3_5TurboInstruct), - Prompt: openai.F[openai.CompletionNewParamsPromptUnion](shared.UnionString("This is a test.")), - BestOf: openai.F(int64(0)), - Echo: openai.F(true), - FrequencyPenalty: openai.F(-2.000000), - LogitBias: openai.F(map[string]int64{ - "foo": int64(0), - }), - Logprobs: openai.F(int64(0)), - MaxTokens: openai.F(int64(16)), - N: openai.F(int64(1)), - PresencePenalty: openai.F(-2.000000), - Seed: openai.F(int64(0)), - Stop: openai.F[openai.CompletionNewParamsStopUnion](shared.UnionString("\n")), - StreamOptions: openai.F(openai.ChatCompletionStreamOptionsParam{ - IncludeUsage: openai.F(true), - }), - Suffix: openai.F("test."), - Temperature: openai.F(1.000000), - TopP: openai.F(1.000000), - User: openai.F("user-1234"), + Model: "gpt-3.5-turbo-instruct", + Prompt: openai.CompletionNewParamsPromptUnion{ + OfString: openai.String("This is a test."), + }, + BestOf: openai.Int(0), + Echo: openai.Bool(true), + FrequencyPenalty: openai.Float(-2), + LogitBias: map[string]int64{ + "foo": 0, + }, + Logprobs: openai.Int(0), + MaxTokens: openai.Int(16), + N: openai.Int(1), + PresencePenalty: openai.Float(-2), + Seed: openai.Int(0), + Stop: openai.CompletionNewParamsStopUnion{ + OfString: openai.String("\n"), + }, + StreamOptions: openai.ChatCompletionStreamOptionsParam{ + IncludeUsage: openai.Bool(true), + }, + Suffix: openai.String("test."), + Temperature: openai.Float(1), + TopP: openai.Float(1), + User: openai.String("user-1234"), }) if err != nil { var apierr *openai.Error diff --git a/embedding.go b/embedding.go index 489fdea3..388067fa 100644 --- a/embedding.go +++ b/embedding.go @@ -7,9 +7,11 @@ import ( "net/http" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" + "github.com/openai/openai-go/shared/constant" ) // EmbeddingService contains methods and other services that help with interacting @@ -25,8 +27,8 @@ type EmbeddingService struct { // NewEmbeddingService generates a new service that applies the given options to // each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewEmbeddingService(opts ...option.RequestOption) (r *EmbeddingService) { - r = &EmbeddingService{} +func NewEmbeddingService(opts ...option.RequestOption) (r EmbeddingService) { + r = EmbeddingService{} r.Options = opts return } @@ -45,72 +47,49 @@ type CreateEmbeddingResponse struct { // The name of the model used to generate the embedding. Model string `json:"model,required"` // The object type, which is always "list". - Object CreateEmbeddingResponseObject `json:"object,required"` + Object constant.List `json:"object,required"` // The usage information for the request. Usage CreateEmbeddingResponseUsage `json:"usage,required"` - JSON createEmbeddingResponseJSON `json:"-"` -} - -// createEmbeddingResponseJSON contains the JSON metadata for the struct -// [CreateEmbeddingResponse] -type createEmbeddingResponseJSON struct { - Data apijson.Field - Model apijson.Field - Object apijson.Field - Usage apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CreateEmbeddingResponse) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Data resp.Field + Model resp.Field + Object resp.Field + Usage resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CreateEmbeddingResponse) RawJSON() string { return r.JSON.raw } +func (r *CreateEmbeddingResponse) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r createEmbeddingResponseJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always "list". -type CreateEmbeddingResponseObject string - -const ( - CreateEmbeddingResponseObjectList CreateEmbeddingResponseObject = "list" -) - -func (r CreateEmbeddingResponseObject) IsKnown() bool { - switch r { - case CreateEmbeddingResponseObjectList: - return true - } - return false -} - // The usage information for the request. type CreateEmbeddingResponseUsage struct { // The number of tokens used by the prompt. PromptTokens int64 `json:"prompt_tokens,required"` // The total number of tokens used by the request. - TotalTokens int64 `json:"total_tokens,required"` - JSON createEmbeddingResponseUsageJSON `json:"-"` -} - -// createEmbeddingResponseUsageJSON contains the JSON metadata for the struct -// [CreateEmbeddingResponseUsage] -type createEmbeddingResponseUsageJSON struct { - PromptTokens apijson.Field - TotalTokens apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *CreateEmbeddingResponseUsage) UnmarshalJSON(data []byte) (err error) { + TotalTokens int64 `json:"total_tokens,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + PromptTokens resp.Field + TotalTokens resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CreateEmbeddingResponseUsage) RawJSON() string { return r.JSON.raw } +func (r *CreateEmbeddingResponseUsage) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r createEmbeddingResponseUsageJSON) RawJSON() string { - return r.raw -} - // Represents an embedding vector returned by embedding endpoint. type Embedding struct { // The embedding vector, which is a list of floats. The length of vector depends on @@ -120,42 +99,24 @@ type Embedding struct { // The index of the embedding in the list of embeddings. Index int64 `json:"index,required"` // The object type, which is always "embedding". - Object EmbeddingObject `json:"object,required"` - JSON embeddingJSON `json:"-"` -} - -// embeddingJSON contains the JSON metadata for the struct [Embedding] -type embeddingJSON struct { - Embedding apijson.Field - Index apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Embedding) UnmarshalJSON(data []byte) (err error) { + Object constant.Embedding `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Embedding resp.Field + Index resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r Embedding) RawJSON() string { return r.JSON.raw } +func (r *Embedding) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r embeddingJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always "embedding". -type EmbeddingObject string - -const ( - EmbeddingObjectEmbedding EmbeddingObject = "embedding" -) - -func (r EmbeddingObject) IsKnown() bool { - switch r { - case EmbeddingObjectEmbedding: - return true - } - return false -} - type EmbeddingModel = string const ( @@ -173,57 +134,68 @@ type EmbeddingNewParams struct { // [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) // for counting tokens. Some models may also impose a limit on total number of // tokens summed across inputs. - Input param.Field[EmbeddingNewParamsInputUnion] `json:"input,required"` + Input EmbeddingNewParamsInputUnion `json:"input,omitzero,required"` // ID of the model to use. You can use the // [List models](https://platform.openai.com/docs/api-reference/models/list) API to // see all of your available models, or see our // [Model overview](https://platform.openai.com/docs/models) for descriptions of // them. - Model param.Field[EmbeddingModel] `json:"model,required"` + Model EmbeddingModel `json:"model,omitzero,required"` // The number of dimensions the resulting output embeddings should have. Only // supported in `text-embedding-3` and later models. - Dimensions param.Field[int64] `json:"dimensions"` - // The format to return the embeddings in. Can be either `float` or - // [`base64`](https://pypi.org/project/pybase64/). - EncodingFormat param.Field[EmbeddingNewParamsEncodingFormat] `json:"encoding_format"` + Dimensions param.Opt[int64] `json:"dimensions,omitzero"` // A unique identifier representing your end-user, which can help OpenAI to monitor // and detect abuse. // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + User param.Opt[string] `json:"user,omitzero"` + // The format to return the embeddings in. Can be either `float` or + // [`base64`](https://pypi.org/project/pybase64/). + // + // Any of "float", "base64". + EncodingFormat EmbeddingNewParamsEncodingFormat `json:"encoding_format,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f EmbeddingNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r EmbeddingNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow EmbeddingNewParams + return param.MarshalObject(r, (*shadow)(&r)) } -// Input text to embed, encoded as a string or array of tokens. To embed multiple -// inputs in a single request, pass an array of strings or array of token arrays. -// The input must not exceed the max input tokens for the model (8192 tokens for -// `text-embedding-ada-002`), cannot be an empty string, and any array must be 2048 -// dimensions or less. -// [Example Python code](https://cookbook.openai.com/examples/how_to_count_tokens_with_tiktoken) -// for counting tokens. Some models may also impose a limit on total number of -// tokens summed across inputs. +// Only one field can be non-zero. // -// Satisfied by [shared.UnionString], [EmbeddingNewParamsInputArrayOfStrings], -// [EmbeddingNewParamsInputArrayOfTokens], -// [EmbeddingNewParamsInputArrayOfTokenArrays]. -type EmbeddingNewParamsInputUnion interface { - ImplementsEmbeddingNewParamsInputUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type EmbeddingNewParamsInputUnion struct { + OfString param.Opt[string] `json:",omitzero,inline"` + OfArrayOfStrings []string `json:",omitzero,inline"` + OfArrayOfTokens []int64 `json:",omitzero,inline"` + OfArrayOfTokenArrays [][]int64 `json:",omitzero,inline"` + paramUnion +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u EmbeddingNewParamsInputUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() } +func (u EmbeddingNewParamsInputUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[EmbeddingNewParamsInputUnion](u.OfString, u.OfArrayOfStrings, u.OfArrayOfTokens, u.OfArrayOfTokenArrays) +} + +func (u *EmbeddingNewParamsInputUnion) asAny() any { + if !param.IsOmitted(u.OfString) { + return &u.OfString.Value + } else if !param.IsOmitted(u.OfArrayOfStrings) { + return &u.OfArrayOfStrings + } else if !param.IsOmitted(u.OfArrayOfTokens) { + return &u.OfArrayOfTokens + } else if !param.IsOmitted(u.OfArrayOfTokenArrays) { + return &u.OfArrayOfTokenArrays + } + return nil } -type EmbeddingNewParamsInputArrayOfStrings []string - -func (r EmbeddingNewParamsInputArrayOfStrings) ImplementsEmbeddingNewParamsInputUnion() {} - -type EmbeddingNewParamsInputArrayOfTokens []int64 - -func (r EmbeddingNewParamsInputArrayOfTokens) ImplementsEmbeddingNewParamsInputUnion() {} - -type EmbeddingNewParamsInputArrayOfTokenArrays [][]int64 - -func (r EmbeddingNewParamsInputArrayOfTokenArrays) ImplementsEmbeddingNewParamsInputUnion() {} - // The format to return the embeddings in. Can be either `float` or // [`base64`](https://pypi.org/project/pybase64/). type EmbeddingNewParamsEncodingFormat string @@ -232,11 +204,3 @@ const ( EmbeddingNewParamsEncodingFormatFloat EmbeddingNewParamsEncodingFormat = "float" EmbeddingNewParamsEncodingFormatBase64 EmbeddingNewParamsEncodingFormat = "base64" ) - -func (r EmbeddingNewParamsEncodingFormat) IsKnown() bool { - switch r { - case EmbeddingNewParamsEncodingFormatFloat, EmbeddingNewParamsEncodingFormatBase64: - return true - } - return false -} diff --git a/embedding_test.go b/embedding_test.go index 0eee8ecd..0ca6b784 100644 --- a/embedding_test.go +++ b/embedding_test.go @@ -11,7 +11,6 @@ import ( "github.com/openai/openai-go" "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" - "github.com/openai/openai-go/shared" ) func TestEmbeddingNewWithOptionalParams(t *testing.T) { @@ -27,11 +26,13 @@ func TestEmbeddingNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Embeddings.New(context.TODO(), openai.EmbeddingNewParams{ - Input: openai.F[openai.EmbeddingNewParamsInputUnion](shared.UnionString("The quick brown fox jumped over the lazy dog")), - Model: openai.F(openai.EmbeddingModelTextEmbeddingAda002), - Dimensions: openai.F(int64(1)), - EncodingFormat: openai.F(openai.EmbeddingNewParamsEncodingFormatFloat), - User: openai.F("user-1234"), + Input: openai.EmbeddingNewParamsInputUnion{ + OfString: openai.String("The quick brown fox jumped over the lazy dog"), + }, + Model: openai.EmbeddingModelTextEmbeddingAda002, + Dimensions: openai.Int(1), + EncodingFormat: openai.EmbeddingNewParamsEncodingFormatFloat, + User: openai.String("user-1234"), }) if err != nil { var apierr *openai.Error diff --git a/examples/audio-text-to-speech/main.go b/examples/audio-text-to-speech/main.go index 1415b7b5..e432ae99 100644 --- a/examples/audio-text-to-speech/main.go +++ b/examples/audio-text-to-speech/main.go @@ -13,10 +13,10 @@ func main() { ctx := context.Background() res, err := client.Audio.Speech.New(ctx, openai.AudioSpeechNewParams{ - Model: openai.F(openai.SpeechModelTTS1), - Input: openai.String(`Why did the chicken cross the road? To get to the other side.`), - ResponseFormat: openai.F(openai.AudioSpeechNewParamsResponseFormatPCM), - Voice: openai.F(openai.AudioSpeechNewParamsVoiceAlloy), + Model: openai.SpeechModelTTS1, + Input: `Why did the chicken cross the road? To get to the other side.`, + ResponseFormat: openai.AudioSpeechNewParamsResponseFormatPCM, + Voice: openai.AudioSpeechNewParamsVoiceAlloy, }) defer res.Body.Close() if err != nil { diff --git a/examples/audio-transcriptions/main.go b/examples/audio-transcriptions/main.go index 354a1d39..b5c3b39a 100644 --- a/examples/audio-transcriptions/main.go +++ b/examples/audio-transcriptions/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "io" "os" "github.com/openai/openai-go" @@ -18,8 +17,8 @@ func main() { } transcription, err := client.Audio.Transcriptions.New(ctx, openai.AudioTranscriptionNewParams{ - Model: openai.F(openai.AudioModelWhisper1), - File: openai.F[io.Reader](file), + Model: openai.AudioModelWhisper1, + File: file, }) if err != nil { panic(err) diff --git a/examples/assistant-streaming/main.go b/examples/beta/assistant-streaming/main.go similarity index 61% rename from examples/assistant-streaming/main.go rename to examples/beta/assistant-streaming/main.go index 9df7c2b3..0991582b 100644 --- a/examples/assistant-streaming/main.go +++ b/examples/beta/assistant-streaming/main.go @@ -5,13 +5,10 @@ import ( "fmt" "github.com/openai/openai-go" - "github.com/openai/openai-go/option" ) func main() { - client := openai.NewClient( - option.WithHeader("OpenAI-Beta", "assistants=v2"), - ) + client := openai.NewClient() ctx := context.Background() @@ -20,11 +17,12 @@ func main() { assistant, err := client.Beta.Assistants.New(ctx, openai.BetaAssistantNewParams{ Name: openai.String("Math Tutor"), Instructions: openai.String("You are a personal math tutor. Write and run code to answer math questions."), - Tools: openai.F([]openai.AssistantToolUnionParam{ - openai.CodeInterpreterToolParam{Type: openai.F(openai.CodeInterpreterToolTypeCodeInterpreter)}, - }), - Model: openai.String("gpt-4-1106-preview"), + Tools: []openai.AssistantToolUnionParam{ + {OfCodeInterpreter: &openai.CodeInterpreterToolParam{Type: "code_interpreter"}}, + }, + Model: openai.ChatModelGPT4_1106Preview, }) + if err != nil { panic(err) } @@ -39,13 +37,10 @@ func main() { // Create a message in the thread println("Create a message") _, err = client.Beta.Threads.Messages.New(ctx, thread.ID, openai.BetaThreadMessageNewParams{ - Role: openai.F(openai.BetaThreadMessageNewParamsRoleAssistant), - Content: openai.F([]openai.MessageContentPartParamUnion{ - openai.TextContentBlockParam{ - Type: openai.F(openai.TextContentBlockParamTypeText), - Text: openai.String("I need to solve the equation `3x + 11 = 14`. Can you help me?"), - }, - }), + Role: openai.BetaThreadMessageNewParamsRoleAssistant, + Content: openai.BetaThreadMessageNewParamsContentUnion{ + OfString: openai.String("I need to solve the equation `3x + 11 = 14`. Can you help me?"), + }, }) if err != nil { panic(err) @@ -54,15 +49,16 @@ func main() { // Create a run println("Create a run") stream := client.Beta.Threads.Runs.NewStreaming(ctx, thread.ID, openai.BetaThreadRunNewParams{ - AssistantID: openai.String(assistant.ID), + AssistantID: assistant.ID, Instructions: openai.String("Please address the user as Jane Doe. The user has a premium account."), }) - if err != nil { - panic(err) - } for stream.Next() { evt := stream.Current() println(fmt.Sprintf("%T", evt.Data)) } + + if stream.Err() != nil { + panic(stream.Err()) + } } diff --git a/examples/beta/assistants/main.go b/examples/beta/assistants/main.go index db0af695..13ad3bc8 100644 --- a/examples/beta/assistants/main.go +++ b/examples/beta/assistants/main.go @@ -11,7 +11,7 @@ func main() { client := openai.NewClient() assistant, err := client.Beta.Assistants.New(ctx, openai.BetaAssistantNewParams{ - Model: openai.F(openai.ChatModelGPT4_1106Preview), + Model: openai.ChatModelGPT4_1106Preview, Name: openai.String("Math tutor"), Instructions: openai.String("You are a personal math tutor. Write and run code to answer math questions."), }) @@ -25,17 +25,14 @@ func main() { prompt := "I need to solve the equation 3x + 11 = 14. Can you help me?" thread, err := client.Beta.Threads.New(ctx, openai.BetaThreadNewParams{ - Messages: openai.F([]openai.BetaThreadNewParamsMessage{ + Messages: []openai.BetaThreadNewParamsMessage{ { - Content: openai.F([]openai.MessageContentPartParamUnion{ - openai.TextContentBlockParam{ - Text: openai.String(prompt), - Type: openai.F(openai.TextContentBlockParamTypeText), - }, - }), - Role: openai.F(openai.BetaThreadNewParamsMessagesRoleUser), + Content: openai.BetaThreadNewParamsMessageContentUnion{ + OfString: openai.String(prompt), + }, + Role: "user", }, - }), + }, }) if err != nil { @@ -46,7 +43,7 @@ func main() { // pollIntervalMs of 0 uses default polling interval. run, err := client.Beta.Threads.Runs.NewAndPoll(ctx, thread.ID, openai.BetaThreadRunNewParams{ - AssistantID: openai.F(assistant.ID), + AssistantID: assistant.ID, AdditionalInstructions: openai.String("Please address the user as Jane Doe. The user has a premium account."), }, 0) diff --git a/examples/chat-completion-accumulating/main.go b/examples/chat-completion-accumulating/main.go index da3eac86..445fc464 100644 --- a/examples/chat-completion-accumulating/main.go +++ b/examples/chat-completion-accumulating/main.go @@ -6,75 +6,58 @@ import ( "github.com/openai/openai-go" ) -// Mock function to simulate weather data retrieval -func getWeather(location string) string { - // In a real implementation, this function would call a weather API - return "Sunny, 25°C" -} - func main() { client := openai.NewClient() ctx := context.Background() - question := "Begin a very brief introduction of Greece, then incorporate the local weather of a few towns" + sysprompt := "Share only a brief description of the place in 50 words. Then immediately make some tool calls and announce them." + + question := "Tell me about Greece's largest city." + + messages := []openai.ChatCompletionMessageParamUnion{ + openai.SystemMessage(sysprompt), + openai.UserMessage(question), + } print("> ") println(question) println() params := openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ - openai.UserMessage(question), - }), - Seed: openai.Int(0), - Model: openai.F(openai.ChatModelGPT4o), - Tools: openai.F([]openai.ChatCompletionToolParam{ - { - Type: openai.F(openai.ChatCompletionToolTypeFunction), - Function: openai.F(openai.FunctionDefinitionParam{ - Name: openai.String("get_live_weather"), - Description: openai.String("Get weather at the given location"), - Parameters: openai.F(openai.FunctionParameters{ - "type": "object", - "properties": map[string]interface{}{ - "location": map[string]string{ - "type": "string", - }, - }, - "required": []string{"location"}, - }), - }), - }, - }), + Messages: messages, + Seed: openai.Int(0), + Model: openai.ChatModelGPT4o, + Tools: tools, } stream := client.Chat.Completions.NewStreaming(ctx, params) - acc := openai.ChatCompletionAccumulator{} for stream.Next() { chunk := stream.Current() + acc.AddChunk(chunk) // When this fires, the current chunk value will not contain content data - if content, ok := acc.JustFinishedContent(); ok { - println("Content stream finished:", content) + if _, ok := acc.JustFinishedContent(); ok { println() + println("finish-event: Content stream finished") } - if tool, ok := acc.JustFinishedToolCall(); ok { - println("Tool call stream finished:", tool.Index, tool.Name, tool.Arguments) + if refusal, ok := acc.JustFinishedRefusal(); ok { + println() + println("finish-event: refusal stream finished:", refusal) println() } - if refusal, ok := acc.JustFinishedRefusal(); ok { - println("Refusal stream finished:", refusal) - println() + if tool, ok := acc.JustFinishedToolCall(); ok { + println("finish-event: tool call stream finished:", tool.Index, tool.Name, tool.Arguments) } - // It's best to use chunks after handling JustFinished events - if len(chunk.Choices) > 0 { - println(chunk.Choices[0].Delta.JSON.RawJSON()) + // It's best to use chunks after handling JustFinished events. + // Here we print the delta of the content, if it exists. + if len(chunk.Choices) > 0 && chunk.Choices[0].Delta.Content != "" { + print(chunk.Choices[0].Delta.Content) } } @@ -82,9 +65,59 @@ func main() { panic(err) } - // After the stream is finished, acc can be used like a ChatCompletion - _ = acc.Choices[0].Message.Content + if acc.Usage.TotalTokens > 0 { + println("Total Tokens:", acc.Usage.TotalTokens) + } +} + +var tools = []openai.ChatCompletionToolParam{ + { + Function: openai.FunctionDefinitionParam{ + Name: "get_live_weather", + Description: openai.String("Get weather at the given location"), + Parameters: openai.FunctionParameters{ + "type": "object", + "properties": map[string]interface{}{ + "location": map[string]string{ + "type": "string", + }, + }, + "required": []string{"location"}, + }, + }, + }, + { + Function: openai.FunctionDefinitionParam{ + Name: "get_population", + Description: openai.String("Get population of a given town"), + Parameters: openai.FunctionParameters{ + "type": "object", + "properties": map[string]interface{}{ + "town": map[string]string{ + "type": "string", + }, + "nation": map[string]string{ + "type": "string", + }, + "rounding": map[string]string{ + "type": "integer", + "description": "Nearest base 10 to round to, e.g. 1000 or 1000000", + }, + }, + "required": []string{"town", "nation"}, + }, + }, + }, +} + +// Mock function to simulate weather data retrieval +func getWeather(location string) string { + // In a real implementation, this function would call a weather API + return "Sunny, 25°C" +} - println("Total Tokens:", acc.Usage.TotalTokens) - println("Finish Reason:", acc.Choices[0].FinishReason) +// Mock function to simulate population data retrieval +func getPopulation(town, nation string, rounding int) string { + // In a real implementation, this function would call a population API + return "Athens, Greece: 664,046" } diff --git a/examples/chat-completion-streaming/main.go b/examples/chat-completion-streaming/main.go index 19c8f612..dd48a10f 100644 --- a/examples/chat-completion-streaming/main.go +++ b/examples/chat-completion-streaming/main.go @@ -18,11 +18,11 @@ func main() { println() stream := client.Chat.Completions.NewStreaming(ctx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), - Seed: openai.Int(1), - Model: openai.F(openai.ChatModelGPT4o), + }, + Seed: openai.Int(0), + Model: openai.ChatModelGPT4o, }) for stream.Next() { @@ -34,6 +34,6 @@ func main() { println() if err := stream.Err(); err != nil { - panic(err) + panic(err.Error()) } } diff --git a/examples/chat-completion-tool-calling/main.go b/examples/chat-completion-tool-calling/main.go index 9607ed95..529207b6 100644 --- a/examples/chat-completion-tool-calling/main.go +++ b/examples/chat-completion-tool-calling/main.go @@ -19,16 +19,15 @@ func main() { println(question) params := openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), - Tools: openai.F([]openai.ChatCompletionToolParam{ + }, + Tools: []openai.ChatCompletionToolParam{ { - Type: openai.F(openai.ChatCompletionToolTypeFunction), - Function: openai.F(openai.FunctionDefinitionParam{ - Name: openai.String("get_weather"), + Function: openai.FunctionDefinitionParam{ + Name: "get_weather", Description: openai.String("Get weather at the given location"), - Parameters: openai.F(openai.FunctionParameters{ + Parameters: openai.FunctionParameters{ "type": "object", "properties": map[string]interface{}{ "location": map[string]string{ @@ -36,12 +35,12 @@ func main() { }, }, "required": []string{"location"}, - }), - }), + }, + }, }, - }), + }, Seed: openai.Int(0), - Model: openai.F(openai.ChatModelGPT4o), + Model: openai.ChatModelGPT4o, } // Make initial chat completion request @@ -52,19 +51,20 @@ func main() { toolCalls := completion.Choices[0].Message.ToolCalls - // Abort early if there are no tool calls + // Return early if there are no tool calls if len(toolCalls) == 0 { fmt.Printf("No function call") return } - // If there is a function call, continue the conversation - params.Messages.Value = append(params.Messages.Value, completion.Choices[0].Message) + // If there is a was a function call, continue the conversation + params.Messages = append(params.Messages, completion.Choices[0].Message.ToParam()) for _, toolCall := range toolCalls { if toolCall.Function.Name == "get_weather" { // Extract the location from the function call arguments var args map[string]interface{} - if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args); err != nil { + err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args) + if err != nil { panic(err) } location := args["location"].(string) @@ -75,7 +75,7 @@ func main() { // Print the weather data fmt.Printf("Weather in %s: %s\n", location, weatherData) - params.Messages.Value = append(params.Messages.Value, openai.ToolMessage(toolCall.ID, weatherData)) + params.Messages = append(params.Messages, openai.ToolMessage(weatherData, toolCall.ID)) } } diff --git a/examples/chat-completion/main.go b/examples/chat-completion/main.go index 399c2946..56768965 100644 --- a/examples/chat-completion/main.go +++ b/examples/chat-completion/main.go @@ -16,14 +16,16 @@ func main() { print("> ") println(question) println() - - completion, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + params := openai.ChatCompletionNewParams{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), - Seed: openai.Int(1), - Model: openai.F(openai.ChatModelGPT4o), - }) + }, + Seed: openai.Int(0), + Model: openai.ChatModelGPT4o, + } + + completion, err := client.Chat.Completions.New(ctx, params) + if err != nil { panic(err) } diff --git a/examples/fine-tuning/main.go b/examples/fine-tuning/main.go index 3c8aeb7d..f9a22bb6 100644 --- a/examples/fine-tuning/main.go +++ b/examples/fine-tuning/main.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "io" "os" "time" @@ -18,8 +17,8 @@ func main() { data, err := os.Open("./fine-tuning-data.jsonl") file, err := client.Files.New(ctx, openai.FileNewParams{ - File: openai.F[io.Reader](data), - Purpose: openai.F(openai.FilePurposeFineTune), + File: data, + Purpose: openai.FilePurposeFineTune, }) if err != nil { panic(err) @@ -42,8 +41,8 @@ func main() { fmt.Println("") fmt.Println("==> Starting fine-tuning") fineTune, err := client.FineTuning.Jobs.New(ctx, openai.FineTuningJobNewParams{ - Model: openai.F(openai.FineTuningJobNewParamsModelGPT3_5Turbo), - TrainingFile: openai.F(file.ID), + Model: openai.ChatModelGPT3_5Turbo, + TrainingFile: file.ID, }) if err != nil { panic(err) diff --git a/examples/go.mod b/examples/go.mod index a060547e..10d5e519 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -20,6 +20,6 @@ require ( github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/sjson v1.2.5 // indirect github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.29.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/go.sum b/examples/go.sum index a357a056..0cdb2b19 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -29,8 +29,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/examples/image-generation/main.go b/examples/image-generation/main.go index fe3939ef..ee3cd7d7 100644 --- a/examples/image-generation/main.go +++ b/examples/image-generation/main.go @@ -22,9 +22,9 @@ func main() { // Image URL image, err := client.Images.Generate(ctx, openai.ImageGenerateParams{ - Prompt: openai.String(prompt), - Model: openai.F(openai.ImageModelDallE3), - ResponseFormat: openai.F(openai.ImageGenerateParamsResponseFormatURL), + Prompt: prompt, + Model: openai.ImageModelDallE3, + ResponseFormat: openai.ImageGenerateParamsResponseFormatURL, N: openai.Int(1), }) if err != nil { @@ -37,9 +37,9 @@ func main() { // Base64 image, err = client.Images.Generate(ctx, openai.ImageGenerateParams{ - Prompt: openai.String(prompt), - Model: openai.F(openai.ImageModelDallE3), - ResponseFormat: openai.F(openai.ImageGenerateParamsResponseFormatB64JSON), + Prompt: prompt, + Model: openai.ImageModelDallE3, + ResponseFormat: openai.ImageGenerateParamsResponseFormatB64JSON, N: openai.Int(1), }) if err != nil { diff --git a/examples/responses-streaming/main.go b/examples/responses-streaming/main.go new file mode 100644 index 00000000..da1b26e1 --- /dev/null +++ b/examples/responses-streaming/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "context" + + "github.com/openai/openai-go" + "github.com/openai/openai-go/responses" +) + +func main() { + client := openai.NewClient() + ctx := context.Background() + + question := "Tell me about briefly about Doug Engelbart" + + stream := client.Responses.NewStreaming(ctx, responses.ResponseNewParams{ + Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)}, + Model: openai.ChatModelGPT4, + }) + + var completeText string + + for stream.Next() { + data := stream.Current() + print(data.Delta) + if data.JSON.Text.IsPresent() { + println() + println("Finished Content") + completeText = data.Text + break + } + } + + if stream.Err() != nil { + panic(stream.Err()) + } + + _ = completeText +} diff --git a/examples/responses/main.go b/examples/responses/main.go new file mode 100644 index 00000000..82215324 --- /dev/null +++ b/examples/responses/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "context" + + "github.com/openai/openai-go" + "github.com/openai/openai-go/responses" +) + +func main() { + client := openai.NewClient() + ctx := context.Background() + + question := "Write me a haiku about computers" + + resp, err := client.Responses.New(ctx, responses.ResponseNewParams{ + Input: responses.ResponseNewParamsInputUnion{OfString: openai.String(question)}, + Model: openai.ChatModelGPT4, + }) + + if err != nil { + panic(err) + } + + println(resp.OutputText()) +} diff --git a/examples/structured-outputs/main.go b/examples/structured-outputs/main.go index 6270ec10..f7fa153d 100644 --- a/examples/structured-outputs/main.go +++ b/examples/structured-outputs/main.go @@ -47,25 +47,22 @@ func main() { println(question) schemaParam := openai.ResponseFormatJSONSchemaJSONSchemaParam{ - Name: openai.F("biography"), - Description: openai.F("Notable information about a person"), - Schema: openai.F(HistoricalComputerResponseSchema), + Name: "historical_computer", + Description: openai.String("Notable information about a computer"), + Schema: HistoricalComputerResponseSchema, Strict: openai.Bool(true), } // Query the Chat Completions API chat, err := client.Chat.Completions.New(ctx, openai.ChatCompletionNewParams{ - Messages: openai.F([]openai.ChatCompletionMessageParamUnion{ + Messages: []openai.ChatCompletionMessageParamUnion{ openai.UserMessage(question), - }), - ResponseFormat: openai.F[openai.ChatCompletionNewParamsResponseFormatUnion]( - openai.ResponseFormatJSONSchemaParam{ - Type: openai.F(openai.ResponseFormatJSONSchemaTypeJSONSchema), - JSONSchema: openai.F(schemaParam), - }, - ), + }, + ResponseFormat: openai.ChatCompletionNewParamsResponseFormatUnion{ + OfJSONSchema: &openai.ResponseFormatJSONSchemaParam{JSONSchema: schemaParam}, + }, // Only certain models can perform structured outputs - Model: openai.F(openai.ChatModelGPT4o2024_08_06), + Model: openai.ChatModelGPT4o2024_08_06, }) if err != nil { @@ -73,7 +70,7 @@ func main() { } // The model responds with a JSON string, so parse it into a struct - historicalComputer := HistoricalComputer{} + var historicalComputer HistoricalComputer err = json.Unmarshal([]byte(chat.Choices[0].Message.Content), &historicalComputer) if err != nil { panic(err.Error()) diff --git a/examples/beta/vectorstorefilebatch/main.go b/examples/vectorstorefilebatch/main.go similarity index 64% rename from examples/beta/vectorstorefilebatch/main.go rename to examples/vectorstorefilebatch/main.go index 7d07476b..c38786f6 100644 --- a/examples/beta/vectorstorefilebatch/main.go +++ b/examples/vectorstorefilebatch/main.go @@ -2,7 +2,6 @@ package main import ( "context" - "io" "os" "github.com/openai/openai-go" @@ -26,8 +25,8 @@ func main() { } fileParams = append(fileParams, openai.FileNewParams{ - File: openai.F[io.Reader](rdr), - Purpose: openai.F(openai.FilePurposeAssistants), + File: rdr, + Purpose: openai.FilePurposeAssistants, }) } @@ -36,13 +35,12 @@ func main() { ctx := context.Background() client := openai.NewClient() - vectorStore, err := client.Beta.VectorStores.New( + vectorStore, err := client.VectorStores.New( ctx, - openai.BetaVectorStoreNewParams{ - ExpiresAfter: openai.F(openai.BetaVectorStoreNewParamsExpiresAfter{ - Anchor: openai.F(openai.BetaVectorStoreNewParamsExpiresAfterAnchorLastActiveAt), - Days: openai.Int(1), - }), + openai.VectorStoreNewParams{ + ExpiresAfter: openai.VectorStoreNewParamsExpiresAfter{ + Days: 1, + }, Name: openai.String("Test vector store"), }, ) @@ -52,7 +50,7 @@ func main() { } // 0 uses default polling interval - batch, err := client.Beta.VectorStores.FileBatches.UploadAndPoll(ctx, vectorStore.ID, fileParams, + batch, err := client.VectorStores.FileBatches.UploadAndPoll(ctx, vectorStore.ID, fileParams, []string{}, 0) if err != nil { @@ -61,8 +59,13 @@ func main() { println("Listing the files from the vector store") - filesCursor, err := client.Beta.VectorStores.FileBatches.ListFiles(ctx, vectorStore.ID, batch.ID, - openai.BetaVectorStoreFileBatchListFilesParams{}) + vector := openai.VectorStoreFileBatchListFilesParams{ + Order: openai.VectorStoreFileBatchListFilesParamsOrderAsc, + } + + println("Vector JSON:", vector.URLQuery()) + + filesCursor, err := client.VectorStores.FileBatches.ListFiles(ctx, vectorStore.ID, batch.ID, vector) if err != nil { panic(err) diff --git a/field.go b/field.go index 27fd57f6..affd8998 100644 --- a/field.go +++ b/field.go @@ -1,43 +1,28 @@ package openai import ( - "github.com/openai/openai-go/internal/param" + "github.com/openai/openai-go/packages/param" "io" + "time" ) -// F is a param field helper used to initialize a [param.Field] generic struct. -// This helps specify null, zero values, and overrides, as well as normal values. -// You can read more about this in our [README]. -// -// [README]: https://pkg.go.dev/github.com/openai/openai-go#readme-request-fields -func F[T any](value T) param.Field[T] { return param.Field[T]{Value: value, Present: true} } +func String(s string) param.Opt[string] { return param.NewOpt(s) } +func Int(i int64) param.Opt[int64] { return param.NewOpt(i) } +func Bool(b bool) param.Opt[bool] { return param.NewOpt(b) } +func Float(f float64) param.Opt[float64] { return param.NewOpt(f) } +func Time(t time.Time) param.Opt[time.Time] { return param.NewOpt(t) } -// Null is a param field helper which explicitly sends null to the API. -func Null[T any]() param.Field[T] { return param.Field[T]{Null: true, Present: true} } +func Opt[T comparable](v T) param.Opt[T] { return param.NewOpt(v) } +func Ptr[T any](v T) *T { return &v } -// Raw is a param field helper for specifying values for fields when the -// type you are looking to send is different from the type that is specified in -// the SDK. For example, if the type of the field is an integer, but you want -// to send a float, you could do that by setting the corresponding field with -// Raw[int](0.5). -func Raw[T any](value any) param.Field[T] { return param.Field[T]{Raw: value, Present: true} } +func IntPtr(v int64) *int64 { return &v } +func BoolPtr(v bool) *bool { return &v } +func FloatPtr(v float64) *float64 { return &v } +func StringPtr(v string) *string { return &v } +func TimePtr(v time.Time) *time.Time { return &v } -// Int is a param field helper which helps specify integers. This is -// particularly helpful when specifying integer constants for fields. -func Int(value int64) param.Field[int64] { return F(value) } - -// String is a param field helper which helps specify strings. -func String(value string) param.Field[string] { return F(value) } - -// Float is a param field helper which helps specify floats. -func Float(value float64) param.Field[float64] { return F(value) } - -// Bool is a param field helper which helps specify bools. -func Bool(value bool) param.Field[bool] { return F(value) } - -// FileParam is a param field helper which helps files with a mime content-type. -func FileParam(reader io.Reader, filename string, contentType string) param.Field[io.Reader] { - return F[io.Reader](&file{reader, filename, contentType}) +func File(rdr io.Reader, filename string, contentType string) file { + return file{rdr, filename, contentType} } type file struct { @@ -46,5 +31,15 @@ type file struct { contentType string } -func (f *file) ContentType() string { return f.contentType } -func (f *file) Filename() string { return f.name } +func (f file) Filename() string { + if f.name != "" { + return f.name + } else if named, ok := f.Reader.(interface{ Name() string }); ok { + return named.Name() + } + return "" +} + +func (f file) ContentType() string { + return f.contentType +} diff --git a/file.go b/file.go index 9b6a424a..5f77b397 100644 --- a/file.go +++ b/file.go @@ -15,10 +15,12 @@ import ( "github.com/openai/openai-go/internal/apiform" "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" + "github.com/openai/openai-go/shared/constant" ) // FileService contains methods and other services that help with interacting with @@ -34,8 +36,8 @@ type FileService struct { // NewFileService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewFileService(opts ...option.RequestOption) (r *FileService) { - r = &FileService{} +func NewFileService(opts ...option.RequestOption) (r FileService) { + r = FileService{} r.Options = opts return } @@ -129,43 +131,26 @@ func (r *FileService) Content(ctx context.Context, fileID string, opts ...option } type FileDeleted struct { - ID string `json:"id,required"` - Deleted bool `json:"deleted,required"` - Object FileDeletedObject `json:"object,required"` - JSON fileDeletedJSON `json:"-"` + ID string `json:"id,required"` + Deleted bool `json:"deleted,required"` + Object constant.File `json:"object,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Deleted resp.Field + Object resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// fileDeletedJSON contains the JSON metadata for the struct [FileDeleted] -type fileDeletedJSON struct { - ID apijson.Field - Deleted apijson.Field - Object apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileDeleted) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r FileDeleted) RawJSON() string { return r.JSON.raw } +func (r *FileDeleted) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileDeletedJSON) RawJSON() string { - return r.raw -} - -type FileDeletedObject string - -const ( - FileDeletedObjectFile FileDeletedObject = "file" -) - -func (r FileDeletedObject) IsKnown() bool { - switch r { - case FileDeletedObjectFile: - return true - } - return false -} - // The `File` object represents a document that has been uploaded to OpenAI. type FileObject struct { // The file identifier, which can be referenced in the API endpoints. @@ -177,14 +162,19 @@ type FileObject struct { // The name of the file. Filename string `json:"filename,required"` // The object type, which is always `file`. - Object FileObjectObject `json:"object,required"` + Object constant.File `json:"object,required"` // The intended purpose of the file. Supported values are `assistants`, // `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results` // and `vision`. + // + // Any of "assistants", "assistants_output", "batch", "batch_output", "fine-tune", + // "fine-tune-results", "vision". Purpose FileObjectPurpose `json:"purpose,required"` // Deprecated. The current status of the file, which can be either `uploaded`, // `processed`, or `error`. // + // Any of "uploaded", "processed", "error". + // // Deprecated: deprecated Status FileObjectStatus `json:"status,required"` // The Unix timestamp (in seconds) for when the file will expire. @@ -193,48 +183,30 @@ type FileObject struct { // see the `error` field on `fine_tuning.job`. // // Deprecated: deprecated - StatusDetails string `json:"status_details"` - JSON fileObjectJSON `json:"-"` + StatusDetails string `json:"status_details"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + Bytes resp.Field + CreatedAt resp.Field + Filename resp.Field + Object resp.Field + Purpose resp.Field + Status resp.Field + ExpiresAt resp.Field + StatusDetails resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// fileObjectJSON contains the JSON metadata for the struct [FileObject] -type fileObjectJSON struct { - ID apijson.Field - Bytes apijson.Field - CreatedAt apijson.Field - Filename apijson.Field - Object apijson.Field - Purpose apijson.Field - Status apijson.Field - ExpiresAt apijson.Field - StatusDetails apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FileObject) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r FileObject) RawJSON() string { return r.JSON.raw } +func (r *FileObject) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fileObjectJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always `file`. -type FileObjectObject string - -const ( - FileObjectObjectFile FileObjectObject = "file" -) - -func (r FileObjectObject) IsKnown() bool { - switch r { - case FileObjectObjectFile: - return true - } - return false -} - // The intended purpose of the file. Supported values are `assistants`, // `assistants_output`, `batch`, `batch_output`, `fine-tune`, `fine-tune-results` // and `vision`. @@ -250,14 +222,6 @@ const ( FileObjectPurposeVision FileObjectPurpose = "vision" ) -func (r FileObjectPurpose) IsKnown() bool { - switch r { - case FileObjectPurposeAssistants, FileObjectPurposeAssistantsOutput, FileObjectPurposeBatch, FileObjectPurposeBatchOutput, FileObjectPurposeFineTune, FileObjectPurposeFineTuneResults, FileObjectPurposeVision: - return true - } - return false -} - // Deprecated. The current status of the file, which can be either `uploaded`, // `processed`, or `error`. type FileObjectStatus string @@ -268,14 +232,6 @@ const ( FileObjectStatusError FileObjectStatus = "error" ) -func (r FileObjectStatus) IsKnown() bool { - switch r { - case FileObjectStatusUploaded, FileObjectStatusProcessed, FileObjectStatusError: - return true - } - return false -} - // The intended purpose of the uploaded file. One of: - `assistants`: Used in the // Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for // fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: @@ -291,24 +247,23 @@ const ( FilePurposeEvals FilePurpose = "evals" ) -func (r FilePurpose) IsKnown() bool { - switch r { - case FilePurposeAssistants, FilePurposeBatch, FilePurposeFineTune, FilePurposeVision, FilePurposeUserData, FilePurposeEvals: - return true - } - return false -} - type FileNewParams struct { // The File object (not file name) to be uploaded. - File param.Field[io.Reader] `json:"file,required" format:"binary"` + File io.Reader `json:"file,required" format:"binary"` // The intended purpose of the uploaded file. One of: - `assistants`: Used in the // Assistants API - `batch`: Used in the Batch API - `fine-tune`: Used for // fine-tuning - `vision`: Images used for vision fine-tuning - `user_data`: // Flexible file type for any purpose - `evals`: Used for eval data sets - Purpose param.Field[FilePurpose] `json:"purpose,required"` + // + // Any of "assistants", "batch", "fine-tune", "vision", "user_data", "evals". + Purpose FilePurpose `json:"purpose,omitzero,required"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FileNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r FileNewParams) MarshalMultipart() (data []byte, contentType string, err error) { buf := bytes.NewBuffer(nil) writer := multipart.NewWriter(buf) @@ -329,17 +284,24 @@ type FileListParams struct { // in the list. For instance, if you make a list request and receive 100 objects, // ending with obj_foo, your subsequent call can include after=obj_foo in order to // fetch the next page of the list. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // A limit on the number of objects to be returned. Limit can range between 1 and // 10,000, and the default is 10,000. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // Only return files with the given purpose. + Purpose param.Opt[string] `query:"purpose,omitzero" json:"-"` // Sort order by the `created_at` timestamp of the objects. `asc` for ascending // order and `desc` for descending order. - Order param.Field[FileListParamsOrder] `query:"order"` - // Only return files with the given purpose. - Purpose param.Field[string] `query:"purpose"` + // + // Any of "asc", "desc". + Order FileListParamsOrder `query:"order,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FileListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [FileListParams]'s query parameters as `url.Values`. func (r FileListParams) URLQuery() (v url.Values) { return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ @@ -356,11 +318,3 @@ const ( FileListParamsOrderAsc FileListParamsOrder = "asc" FileListParamsOrderDesc FileListParamsOrder = "desc" ) - -func (r FileListParamsOrder) IsKnown() bool { - switch r { - case FileListParamsOrderAsc, FileListParamsOrderDesc: - return true - } - return false -} diff --git a/file_test.go b/file_test.go index aec6f07a..74c60ccd 100644 --- a/file_test.go +++ b/file_test.go @@ -30,8 +30,8 @@ func TestFileNew(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Files.New(context.TODO(), openai.FileNewParams{ - File: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Purpose: openai.F(openai.FilePurposeAssistants), + File: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Purpose: openai.FilePurposeAssistants, }) if err != nil { var apierr *openai.Error @@ -77,10 +77,10 @@ func TestFileListWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Files.List(context.TODO(), openai.FileListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), - Order: openai.F(openai.FileListParamsOrderAsc), - Purpose: openai.F("purpose"), + After: openai.String("after"), + Limit: openai.Int(0), + Order: openai.FileListParamsOrderAsc, + Purpose: openai.String("purpose"), }) if err != nil { var apierr *openai.Error diff --git a/finetuning.go b/finetuning.go index 88fa9c58..873e33c7 100644 --- a/finetuning.go +++ b/finetuning.go @@ -14,14 +14,14 @@ import ( // the [NewFineTuningService] method instead. type FineTuningService struct { Options []option.RequestOption - Jobs *FineTuningJobService + Jobs FineTuningJobService } // NewFineTuningService generates a new service that applies the given options to // each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewFineTuningService(opts ...option.RequestOption) (r *FineTuningService) { - r = &FineTuningService{} +func NewFineTuningService(opts ...option.RequestOption) (r FineTuningService) { + r = FineTuningService{} r.Options = opts r.Jobs = NewFineTuningJobService(opts...) return diff --git a/finetuningjob.go b/finetuningjob.go index 33ebb5da..1c6e4a3a 100644 --- a/finetuningjob.go +++ b/finetuningjob.go @@ -4,20 +4,21 @@ package openai import ( "context" + "encoding/json" "errors" "fmt" "net/http" "net/url" - "reflect" "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" "github.com/openai/openai-go/shared" - "github.com/tidwall/gjson" + "github.com/openai/openai-go/shared/constant" ) // FineTuningJobService contains methods and other services that help with @@ -28,14 +29,14 @@ import ( // the [NewFineTuningJobService] method instead. type FineTuningJobService struct { Options []option.RequestOption - Checkpoints *FineTuningJobCheckpointService + Checkpoints FineTuningJobCheckpointService } // NewFineTuningJobService generates a new service that applies the given options // to each request. These options are applied after the parent client's options (if // there is one), and before any request-specific options. -func NewFineTuningJobService(opts ...option.RequestOption) (r *FineTuningJobService) { - r = &FineTuningJobService{} +func NewFineTuningJobService(opts ...option.RequestOption) (r FineTuningJobService) { + r = FineTuningJobService{} r.Options = opts r.Checkpoints = NewFineTuningJobCheckpointService(opts...) return @@ -140,20 +141,20 @@ type FineTuningJob struct { CreatedAt int64 `json:"created_at,required"` // For fine-tuning jobs that have `failed`, this will contain more information on // the cause of the failure. - Error FineTuningJobError `json:"error,required,nullable"` + Error FineTuningJobError `json:"error,required"` // The name of the fine-tuned model that is being created. The value will be null // if the fine-tuning job is still running. - FineTunedModel string `json:"fine_tuned_model,required,nullable"` + FineTunedModel string `json:"fine_tuned_model,required"` // The Unix timestamp (in seconds) for when the fine-tuning job was finished. The // value will be null if the fine-tuning job is still running. - FinishedAt int64 `json:"finished_at,required,nullable"` + FinishedAt int64 `json:"finished_at,required"` // The hyperparameters used for the fine-tuning job. This value will only be // returned when running `supervised` jobs. Hyperparameters FineTuningJobHyperparameters `json:"hyperparameters,required"` // The base model that is being fine-tuned. Model string `json:"model,required"` // The object type, which is always "fine_tuning.job". - Object FineTuningJobObject `json:"object,required"` + Object constant.FineTuningJob `json:"object,required"` // The organization that owns the fine-tuning job. OrganizationID string `json:"organization_id,required"` // The compiled results file ID(s) for the fine-tuning job. You can retrieve the @@ -164,17 +165,20 @@ type FineTuningJob struct { Seed int64 `json:"seed,required"` // The current status of the fine-tuning job, which can be either // `validating_files`, `queued`, `running`, `succeeded`, `failed`, or `cancelled`. + // + // Any of "validating_files", "queued", "running", "succeeded", "failed", + // "cancelled". Status FineTuningJobStatus `json:"status,required"` // The total number of billable tokens processed by this fine-tuning job. The value // will be null if the fine-tuning job is still running. - TrainedTokens int64 `json:"trained_tokens,required,nullable"` + TrainedTokens int64 `json:"trained_tokens,required"` // The file ID used for training. You can retrieve the training data with the // [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents). TrainingFile string `json:"training_file,required"` // The file ID used for validation. You can retrieve the validation results with // the // [Files API](https://platform.openai.com/docs/api-reference/files/retrieve-contents). - ValidationFile string `json:"validation_file,required,nullable"` + ValidationFile string `json:"validation_file,required"` // The Unix timestamp (in seconds) for when the fine-tuning job is estimated to // finish. The value will be null if the fine-tuning job is not running. EstimatedFinish int64 `json:"estimated_finish,nullable"` @@ -189,42 +193,39 @@ type FineTuningJob struct { Metadata shared.Metadata `json:"metadata,nullable"` // The method used for fine-tuning. Method FineTuningJobMethod `json:"method"` - JSON fineTuningJobJSON `json:"-"` -} - -// fineTuningJobJSON contains the JSON metadata for the struct [FineTuningJob] -type fineTuningJobJSON struct { - ID apijson.Field - CreatedAt apijson.Field - Error apijson.Field - FineTunedModel apijson.Field - FinishedAt apijson.Field - Hyperparameters apijson.Field - Model apijson.Field - Object apijson.Field - OrganizationID apijson.Field - ResultFiles apijson.Field - Seed apijson.Field - Status apijson.Field - TrainedTokens apijson.Field - TrainingFile apijson.Field - ValidationFile apijson.Field - EstimatedFinish apijson.Field - Integrations apijson.Field - Metadata apijson.Field - Method apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJob) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CreatedAt resp.Field + Error resp.Field + FineTunedModel resp.Field + FinishedAt resp.Field + Hyperparameters resp.Field + Model resp.Field + Object resp.Field + OrganizationID resp.Field + ResultFiles resp.Field + Seed resp.Field + Status resp.Field + TrainedTokens resp.Field + TrainingFile resp.Field + ValidationFile resp.Field + EstimatedFinish resp.Field + Integrations resp.Field + Metadata resp.Field + Method resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJob) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJob) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobJSON) RawJSON() string { - return r.raw -} - // For fine-tuning jobs that have `failed`, this will contain more information on // the cause of the failure. type FineTuningJobError struct { @@ -234,28 +235,24 @@ type FineTuningJobError struct { Message string `json:"message,required"` // The parameter that was invalid, usually `training_file` or `validation_file`. // This field will be null if the failure was not parameter-specific. - Param string `json:"param,required,nullable"` - JSON fineTuningJobErrorJSON `json:"-"` -} - -// fineTuningJobErrorJSON contains the JSON metadata for the struct -// [FineTuningJobError] -type fineTuningJobErrorJSON struct { - Code apijson.Field - Message apijson.Field - Param apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobError) UnmarshalJSON(data []byte) (err error) { + Param string `json:"param,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Code resp.Field + Message resp.Field + Param resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobError) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobError) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobErrorJSON) RawJSON() string { - return r.raw -} - // The hyperparameters used for the fine-tuning job. This value will only be // returned when running `supervised` jobs. type FineTuningJobHyperparameters struct { @@ -268,163 +265,132 @@ type FineTuningJobHyperparameters struct { // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. NEpochs FineTuningJobHyperparametersNEpochsUnion `json:"n_epochs"` - JSON fineTuningJobHyperparametersJSON `json:"-"` -} - -// fineTuningJobHyperparametersJSON contains the JSON metadata for the struct -// [FineTuningJobHyperparameters] -type fineTuningJobHyperparametersJSON struct { - BatchSize apijson.Field - LearningRateMultiplier apijson.Field - NEpochs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobHyperparameters) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + BatchSize resp.Field + LearningRateMultiplier resp.Field + NEpochs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobHyperparameters) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobHyperparameters) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobHyperparametersJSON) RawJSON() string { - return r.raw -} - -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// FineTuningJobHyperparametersBatchSizeUnion contains all possible properties and +// values from [constant.Auto], [int64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [FineTuningJobHyperparametersBatchSizeAuto] or -// [shared.UnionInt]. -type FineTuningJobHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobHyperparametersBatchSizeUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobHyperparametersBatchSizeUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobHyperparametersBatchSizeUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobHyperparametersBatchSizeUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobHyperparametersBatchSizeAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) +func (u FineTuningJobHyperparametersBatchSizeUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobHyperparametersBatchSizeAuto string - -const ( - FineTuningJobHyperparametersBatchSizeAutoAuto FineTuningJobHyperparametersBatchSizeAuto = "auto" -) - -func (r FineTuningJobHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobHyperparametersBatchSizeAutoAuto: - return true - } - return false -} +// Returns the unmodified JSON received from the API +func (u FineTuningJobHyperparametersBatchSizeUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobHyperparametersBatchSizeAuto) ImplementsFineTuningJobHyperparametersBatchSizeUnion() { +func (r *FineTuningJobHyperparametersBatchSizeUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// FineTuningJobHyperparametersLearningRateMultiplierUnion contains all possible +// properties and values from [constant.Auto], [float64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [FineTuningJobHyperparametersLearningRateMultiplierAuto] or -// [shared.UnionFloat]. -type FineTuningJobHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobHyperparametersLearningRateMultiplierUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfFloat] +type FineTuningJobHyperparametersLearningRateMultiplierUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [float64] instead of an object. + OfFloat float64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfFloat resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobHyperparametersLearningRateMultiplierUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobHyperparametersLearningRateMultiplierUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobHyperparametersLearningRateMultiplierAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionFloat(0)), - }, - ) +func (u FineTuningJobHyperparametersLearningRateMultiplierUnion) AsFloat() (v float64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobHyperparametersLearningRateMultiplierAutoAuto FineTuningJobHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false -} +// Returns the unmodified JSON received from the API +func (u FineTuningJobHyperparametersLearningRateMultiplierUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobHyperparametersLearningRateMultiplierUnion() { +func (r *FineTuningJobHyperparametersLearningRateMultiplierUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// FineTuningJobHyperparametersNEpochsUnion contains all possible properties and +// values from [constant.Auto], [int64]. // -// Union satisfied by [FineTuningJobHyperparametersNEpochsAuto] or -// [shared.UnionInt]. -type FineTuningJobHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobHyperparametersNEpochsUnion() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobHyperparametersNEpochsUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobHyperparametersNEpochsAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) -} - -type FineTuningJobHyperparametersNEpochsAuto string - -const ( - FineTuningJobHyperparametersNEpochsAutoAuto FineTuningJobHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobHyperparametersNEpochsAutoAuto: - return true - } - return false +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobHyperparametersNEpochsUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobHyperparametersNEpochsUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r FineTuningJobHyperparametersNEpochsAuto) ImplementsFineTuningJobHyperparametersNEpochsUnion() { +func (u FineTuningJobHyperparametersNEpochsUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The object type, which is always "fine_tuning.job". -type FineTuningJobObject string - -const ( - FineTuningJobObjectFineTuningJob FineTuningJobObject = "fine_tuning.job" -) +// Returns the unmodified JSON received from the API +func (u FineTuningJobHyperparametersNEpochsUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobObject) IsKnown() bool { - switch r { - case FineTuningJobObjectFineTuningJob: - return true - } - return false +func (r *FineTuningJobHyperparametersNEpochsUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // The current status of the fine-tuning job, which can be either @@ -440,14 +406,6 @@ const ( FineTuningJobStatusCancelled FineTuningJobStatus = "cancelled" ) -func (r FineTuningJobStatus) IsKnown() bool { - switch r { - case FineTuningJobStatusValidatingFiles, FineTuningJobStatusQueued, FineTuningJobStatusRunning, FineTuningJobStatusSucceeded, FineTuningJobStatusFailed, FineTuningJobStatusCancelled: - return true - } - return false -} - // The method used for fine-tuning. type FineTuningJobMethod struct { // Configuration for the DPO fine-tuning method. @@ -455,51 +413,45 @@ type FineTuningJobMethod struct { // Configuration for the supervised fine-tuning method. Supervised FineTuningJobMethodSupervised `json:"supervised"` // The type of method. Is either `supervised` or `dpo`. - Type FineTuningJobMethodType `json:"type"` - JSON fineTuningJobMethodJSON `json:"-"` -} - -// fineTuningJobMethodJSON contains the JSON metadata for the struct -// [FineTuningJobMethod] -type fineTuningJobMethodJSON struct { - Dpo apijson.Field - Supervised apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobMethod) UnmarshalJSON(data []byte) (err error) { + // + // Any of "supervised", "dpo". + Type string `json:"type"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Dpo resp.Field + Supervised resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobMethod) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobMethod) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobMethodJSON) RawJSON() string { - return r.raw -} - // Configuration for the DPO fine-tuning method. type FineTuningJobMethodDpo struct { // The hyperparameters used for the fine-tuning job. Hyperparameters FineTuningJobMethodDpoHyperparameters `json:"hyperparameters"` - JSON fineTuningJobMethodDpoJSON `json:"-"` -} - -// fineTuningJobMethodDpoJSON contains the JSON metadata for the struct -// [FineTuningJobMethodDpo] -type fineTuningJobMethodDpoJSON struct { - Hyperparameters apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobMethodDpo) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Hyperparameters resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobMethodDpo) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobMethodDpo) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobMethodDpoJSON) RawJSON() string { - return r.raw -} - // The hyperparameters used for the fine-tuning job. type FineTuningJobMethodDpoHyperparameters struct { // Number of examples in each batch. A larger batch size means that model @@ -514,216 +466,193 @@ type FineTuningJobMethodDpoHyperparameters struct { // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. NEpochs FineTuningJobMethodDpoHyperparametersNEpochsUnion `json:"n_epochs"` - JSON fineTuningJobMethodDpoHyperparametersJSON `json:"-"` -} - -// fineTuningJobMethodDpoHyperparametersJSON contains the JSON metadata for the -// struct [FineTuningJobMethodDpoHyperparameters] -type fineTuningJobMethodDpoHyperparametersJSON struct { - BatchSize apijson.Field - Beta apijson.Field - LearningRateMultiplier apijson.Field - NEpochs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobMethodDpoHyperparameters) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + BatchSize resp.Field + Beta resp.Field + LearningRateMultiplier resp.Field + NEpochs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobMethodDpoHyperparameters) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobMethodDpoHyperparameters) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobMethodDpoHyperparametersJSON) RawJSON() string { - return r.raw -} - -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// FineTuningJobMethodDpoHyperparametersBatchSizeUnion contains all possible +// properties and values from [constant.Auto], [int64]. // -// Union satisfied by [FineTuningJobMethodDpoHyperparametersBatchSizeAuto] or -// [shared.UnionInt]. -type FineTuningJobMethodDpoHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobMethodDpoHyperparametersBatchSizeUnion() +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobMethodDpoHyperparametersBatchSizeUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodDpoHyperparametersBatchSizeUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodDpoHyperparametersBatchSizeUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodDpoHyperparametersBatchSizeAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) +func (u FineTuningJobMethodDpoHyperparametersBatchSizeUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodDpoHyperparametersBatchSizeAuto string - -const ( - FineTuningJobMethodDpoHyperparametersBatchSizeAutoAuto FineTuningJobMethodDpoHyperparametersBatchSizeAuto = "auto" -) +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodDpoHyperparametersBatchSizeUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobMethodDpoHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodDpoHyperparametersBatchSizeAutoAuto: - return true - } - return false -} - -func (r FineTuningJobMethodDpoHyperparametersBatchSizeAuto) ImplementsFineTuningJobMethodDpoHyperparametersBatchSizeUnion() { +func (r *FineTuningJobMethodDpoHyperparametersBatchSizeUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The beta value for the DPO method. A higher beta value will increase the weight -// of the penalty between the policy and reference model. +// FineTuningJobMethodDpoHyperparametersBetaUnion contains all possible properties +// and values from [constant.Auto], [float64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [FineTuningJobMethodDpoHyperparametersBetaAuto] or -// [shared.UnionFloat]. -type FineTuningJobMethodDpoHyperparametersBetaUnion interface { - ImplementsFineTuningJobMethodDpoHyperparametersBetaUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfFloat] +type FineTuningJobMethodDpoHyperparametersBetaUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [float64] instead of an object. + OfFloat float64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfFloat resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodDpoHyperparametersBetaUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodDpoHyperparametersBetaUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodDpoHyperparametersBetaAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionFloat(0)), - }, - ) +func (u FineTuningJobMethodDpoHyperparametersBetaUnion) AsFloat() (v float64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodDpoHyperparametersBetaAuto string - -const ( - FineTuningJobMethodDpoHyperparametersBetaAutoAuto FineTuningJobMethodDpoHyperparametersBetaAuto = "auto" -) - -func (r FineTuningJobMethodDpoHyperparametersBetaAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodDpoHyperparametersBetaAutoAuto: - return true - } - return false -} +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodDpoHyperparametersBetaUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobMethodDpoHyperparametersBetaAuto) ImplementsFineTuningJobMethodDpoHyperparametersBetaUnion() { +func (r *FineTuningJobMethodDpoHyperparametersBetaUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion contains all +// possible properties and values from [constant.Auto], [float64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by -// [FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto] or -// [shared.UnionFloat]. -type FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfFloat] +type FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [float64] instead of an object. + OfFloat float64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfFloat resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionFloat(0)), - }, - ) +func (u FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion) AsFloat() (v float64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAutoAuto FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion) RawJSON() string { + return u.JSON.raw } -func (r FineTuningJobMethodDpoHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion() { +func (r *FineTuningJobMethodDpoHyperparametersLearningRateMultiplierUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// FineTuningJobMethodDpoHyperparametersNEpochsUnion contains all possible +// properties and values from [constant.Auto], [int64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [FineTuningJobMethodDpoHyperparametersNEpochsAuto] or -// [shared.UnionInt]. -type FineTuningJobMethodDpoHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobMethodDpoHyperparametersNEpochsUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobMethodDpoHyperparametersNEpochsUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodDpoHyperparametersNEpochsUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodDpoHyperparametersNEpochsUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodDpoHyperparametersNEpochsAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) +func (u FineTuningJobMethodDpoHyperparametersNEpochsUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodDpoHyperparametersNEpochsAuto string - -const ( - FineTuningJobMethodDpoHyperparametersNEpochsAutoAuto FineTuningJobMethodDpoHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobMethodDpoHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodDpoHyperparametersNEpochsAutoAuto: - return true - } - return false -} +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodDpoHyperparametersNEpochsUnion) RawJSON() string { return u.JSON.raw } -func (r FineTuningJobMethodDpoHyperparametersNEpochsAuto) ImplementsFineTuningJobMethodDpoHyperparametersNEpochsUnion() { +func (r *FineTuningJobMethodDpoHyperparametersNEpochsUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Configuration for the supervised fine-tuning method. type FineTuningJobMethodSupervised struct { // The hyperparameters used for the fine-tuning job. Hyperparameters FineTuningJobMethodSupervisedHyperparameters `json:"hyperparameters"` - JSON fineTuningJobMethodSupervisedJSON `json:"-"` -} - -// fineTuningJobMethodSupervisedJSON contains the JSON metadata for the struct -// [FineTuningJobMethodSupervised] -type fineTuningJobMethodSupervisedJSON struct { - Hyperparameters apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobMethodSupervised) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Hyperparameters resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobMethodSupervised) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobMethodSupervised) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobMethodSupervisedJSON) RawJSON() string { - return r.raw -} - // The hyperparameters used for the fine-tuning job. type FineTuningJobMethodSupervisedHyperparameters struct { // Number of examples in each batch. A larger batch size means that model @@ -735,165 +664,136 @@ type FineTuningJobMethodSupervisedHyperparameters struct { // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. NEpochs FineTuningJobMethodSupervisedHyperparametersNEpochsUnion `json:"n_epochs"` - JSON fineTuningJobMethodSupervisedHyperparametersJSON `json:"-"` -} - -// fineTuningJobMethodSupervisedHyperparametersJSON contains the JSON metadata for -// the struct [FineTuningJobMethodSupervisedHyperparameters] -type fineTuningJobMethodSupervisedHyperparametersJSON struct { - BatchSize apijson.Field - LearningRateMultiplier apijson.Field - NEpochs apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobMethodSupervisedHyperparameters) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + BatchSize resp.Field + LearningRateMultiplier resp.Field + NEpochs resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobMethodSupervisedHyperparameters) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobMethodSupervisedHyperparameters) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobMethodSupervisedHyperparametersJSON) RawJSON() string { - return r.raw -} - -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion contains all possible +// properties and values from [constant.Auto], [int64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by [FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto] -// or [shared.UnionInt]. -type FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobMethodSupervisedHyperparametersBatchSizeUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) +func (u FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto string - -const ( - FineTuningJobMethodSupervisedHyperparametersBatchSizeAutoAuto FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto = "auto" -) - -func (r FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodSupervisedHyperparametersBatchSizeAutoAuto: - return true - } - return false +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion) RawJSON() string { + return u.JSON.raw } -func (r FineTuningJobMethodSupervisedHyperparametersBatchSizeAuto) ImplementsFineTuningJobMethodSupervisedHyperparametersBatchSizeUnion() { +func (r *FineTuningJobMethodSupervisedHyperparametersBatchSizeUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion contains +// all possible properties and values from [constant.Auto], [float64]. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. // -// Union satisfied by -// [FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto] or -// [shared.UnionFloat]. -type FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion() +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfFloat] +type FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [float64] instead of an object. + OfFloat float64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfFloat resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionFloat(0)), - }, - ) +func (u FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion) AsFloat() (v float64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -type FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAutoAuto FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion) RawJSON() string { + return u.JSON.raw } -func (r FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion() { +func (r *FineTuningJobMethodSupervisedHyperparametersLearningRateMultiplierUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// FineTuningJobMethodSupervisedHyperparametersNEpochsUnion contains all possible +// properties and values from [constant.Auto], [int64]. // -// Union satisfied by [FineTuningJobMethodSupervisedHyperparametersNEpochsAuto] or -// [shared.UnionInt]. -type FineTuningJobMethodSupervisedHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobMethodSupervisedHyperparametersNEpochsUnion() -} - -func init() { - apijson.RegisterUnion( - reflect.TypeOf((*FineTuningJobMethodSupervisedHyperparametersNEpochsUnion)(nil)).Elem(), - "", - apijson.UnionVariant{ - TypeFilter: gjson.String, - Type: reflect.TypeOf(FineTuningJobMethodSupervisedHyperparametersNEpochsAuto("")), - }, - apijson.UnionVariant{ - TypeFilter: gjson.Number, - Type: reflect.TypeOf(shared.UnionInt(0)), - }, - ) -} - -type FineTuningJobMethodSupervisedHyperparametersNEpochsAuto string - -const ( - FineTuningJobMethodSupervisedHyperparametersNEpochsAutoAuto FineTuningJobMethodSupervisedHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobMethodSupervisedHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobMethodSupervisedHyperparametersNEpochsAutoAuto: - return true - } - return false +// Use the methods beginning with 'As' to cast the union to one of its variants. +// +// If the underlying value is not a json object, one of the following properties +// will be valid: OfAuto OfInt] +type FineTuningJobMethodSupervisedHyperparametersNEpochsUnion struct { + // This field will be present if the value is a [constant.Auto] instead of an + // object. + OfAuto constant.Auto `json:",inline"` + // This field will be present if the value is a [int64] instead of an object. + OfInt int64 `json:",inline"` + JSON struct { + OfAuto resp.Field + OfInt resp.Field + raw string + } `json:"-"` +} + +func (u FineTuningJobMethodSupervisedHyperparametersNEpochsUnion) AsAuto() (v constant.Auto) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -func (r FineTuningJobMethodSupervisedHyperparametersNEpochsAuto) ImplementsFineTuningJobMethodSupervisedHyperparametersNEpochsUnion() { +func (u FineTuningJobMethodSupervisedHyperparametersNEpochsUnion) AsInt() (v int64) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return } -// The type of method. Is either `supervised` or `dpo`. -type FineTuningJobMethodType string +// Returns the unmodified JSON received from the API +func (u FineTuningJobMethodSupervisedHyperparametersNEpochsUnion) RawJSON() string { return u.JSON.raw } -const ( - FineTuningJobMethodTypeSupervised FineTuningJobMethodType = "supervised" - FineTuningJobMethodTypeDpo FineTuningJobMethodType = "dpo" -) - -func (r FineTuningJobMethodType) IsKnown() bool { - switch r { - case FineTuningJobMethodTypeSupervised, FineTuningJobMethodTypeDpo: - return true - } - return false +func (r *FineTuningJobMethodSupervisedHyperparametersNEpochsUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) } // Fine-tuning job event object @@ -903,40 +803,40 @@ type FineTuningJobEvent struct { // The Unix timestamp (in seconds) for when the fine-tuning job was created. CreatedAt int64 `json:"created_at,required"` // The log level of the event. + // + // Any of "info", "warn", "error". Level FineTuningJobEventLevel `json:"level,required"` // The message of the event. Message string `json:"message,required"` // The object type, which is always "fine_tuning.job.event". - Object FineTuningJobEventObject `json:"object,required"` + Object constant.FineTuningJobEvent `json:"object,required"` // The data associated with the event. Data interface{} `json:"data"` // The type of event. + // + // Any of "message", "metrics". Type FineTuningJobEventType `json:"type"` - JSON fineTuningJobEventJSON `json:"-"` -} - -// fineTuningJobEventJSON contains the JSON metadata for the struct -// [FineTuningJobEvent] -type fineTuningJobEventJSON struct { - ID apijson.Field - CreatedAt apijson.Field - Level apijson.Field - Message apijson.Field - Object apijson.Field - Data apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobEvent) UnmarshalJSON(data []byte) (err error) { + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CreatedAt resp.Field + Level resp.Field + Message resp.Field + Object resp.Field + Data resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobEvent) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobEventJSON) RawJSON() string { - return r.raw -} - // The log level of the event. type FineTuningJobEventLevel string @@ -946,29 +846,6 @@ const ( FineTuningJobEventLevelError FineTuningJobEventLevel = "error" ) -func (r FineTuningJobEventLevel) IsKnown() bool { - switch r { - case FineTuningJobEventLevelInfo, FineTuningJobEventLevelWarn, FineTuningJobEventLevelError: - return true - } - return false -} - -// The object type, which is always "fine_tuning.job.event". -type FineTuningJobEventObject string - -const ( - FineTuningJobEventObjectFineTuningJobEvent FineTuningJobEventObject = "fine_tuning.job.event" -) - -func (r FineTuningJobEventObject) IsKnown() bool { - switch r { - case FineTuningJobEventObjectFineTuningJobEvent: - return true - } - return false -} - // The type of event. type FineTuningJobEventType string @@ -977,14 +854,6 @@ const ( FineTuningJobEventTypeMetrics FineTuningJobEventType = "metrics" ) -func (r FineTuningJobEventType) IsKnown() bool { - switch r { - case FineTuningJobEventTypeMessage, FineTuningJobEventTypeMetrics: - return true - } - return false -} - // The settings for your integration with Weights and Biases. This payload // specifies the project that metrics will be sent to. Optionally, you can set an // explicit display name for your run, add tags to your run, and set a default @@ -1002,76 +871,53 @@ type FineTuningJobWandbIntegration struct { // A list of tags to be attached to the newly created run. These tags are passed // through directly to WandB. Some default tags are generated by OpenAI: // "openai/finetune", "openai/{base-model}", "openai/{ftjob-abcdef}". - Tags []string `json:"tags"` - JSON fineTuningJobWandbIntegrationJSON `json:"-"` -} - -// fineTuningJobWandbIntegrationJSON contains the JSON metadata for the struct -// [FineTuningJobWandbIntegration] -type fineTuningJobWandbIntegrationJSON struct { - Project apijson.Field - Entity apijson.Field - Name apijson.Field - Tags apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobWandbIntegration) UnmarshalJSON(data []byte) (err error) { + Tags []string `json:"tags"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Project resp.Field + Entity resp.Field + Name resp.Field + Tags resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobWandbIntegration) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobWandbIntegration) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobWandbIntegrationJSON) RawJSON() string { - return r.raw -} - type FineTuningJobWandbIntegrationObject struct { // The type of the integration being enabled for the fine-tuning job - Type FineTuningJobWandbIntegrationObjectType `json:"type,required"` + Type constant.Wandb `json:"type,required"` // The settings for your integration with Weights and Biases. This payload // specifies the project that metrics will be sent to. Optionally, you can set an // explicit display name for your run, add tags to your run, and set a default // entity (team, username, etc) to be associated with your run. - Wandb FineTuningJobWandbIntegration `json:"wandb,required"` - JSON fineTuningJobWandbIntegrationObjectJSON `json:"-"` -} - -// fineTuningJobWandbIntegrationObjectJSON contains the JSON metadata for the -// struct [FineTuningJobWandbIntegrationObject] -type fineTuningJobWandbIntegrationObjectJSON struct { - Type apijson.Field - Wandb apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobWandbIntegrationObject) UnmarshalJSON(data []byte) (err error) { + Wandb FineTuningJobWandbIntegration `json:"wandb,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Type resp.Field + Wandb resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r FineTuningJobWandbIntegrationObject) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobWandbIntegrationObject) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobWandbIntegrationObjectJSON) RawJSON() string { - return r.raw -} - -// The type of the integration being enabled for the fine-tuning job -type FineTuningJobWandbIntegrationObjectType string - -const ( - FineTuningJobWandbIntegrationObjectTypeWandb FineTuningJobWandbIntegrationObjectType = "wandb" -) - -func (r FineTuningJobWandbIntegrationObjectType) IsKnown() bool { - switch r { - case FineTuningJobWandbIntegrationObjectTypeWandb: - return true - } - return false -} - type FineTuningJobNewParams struct { // The name of the model to fine-tune. You can select one of the // [supported models](https://platform.openai.com/docs/guides/fine-tuning#which-models-can-be-fine-tuned). - Model param.Field[FineTuningJobNewParamsModel] `json:"model,required"` + Model string `json:"model,omitzero,required"` // The ID of an uploaded file that contains training data. // // See [upload file](https://platform.openai.com/docs/api-reference/files/create) @@ -1089,31 +935,17 @@ type FineTuningJobNewParams struct { // // See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning) // for more details. - TrainingFile param.Field[string] `json:"training_file,required"` - // The hyperparameters used for the fine-tuning job. This value is now deprecated - // in favor of `method`, and should be passed in under the `method` parameter. - Hyperparameters param.Field[FineTuningJobNewParamsHyperparameters] `json:"hyperparameters"` - // A list of integrations to enable for your fine-tuning job. - Integrations param.Field[[]FineTuningJobNewParamsIntegration] `json:"integrations"` - // Set of 16 key-value pairs that can be attached to an object. This can be useful - // for storing additional information about the object in a structured format, and - // querying for objects via API or the dashboard. - // - // Keys are strings with a maximum length of 64 characters. Values are strings with - // a maximum length of 512 characters. - Metadata param.Field[shared.MetadataParam] `json:"metadata"` - // The method used for fine-tuning. - Method param.Field[FineTuningJobNewParamsMethod] `json:"method"` + TrainingFile string `json:"training_file,required"` // The seed controls the reproducibility of the job. Passing in the same seed and // job parameters should produce the same results, but may differ in rare cases. If // a seed is not specified, one will be generated for you. - Seed param.Field[int64] `json:"seed"` + Seed param.Opt[int64] `json:"seed,omitzero"` // A string of up to 64 characters that will be added to your fine-tuned model // name. // // For example, a `suffix` of "custom-model-name" would produce a model name like // `ft:gpt-4o-mini:openai:custom-model-name:7p4lURel`. - Suffix param.Field[string] `json:"suffix"` + Suffix param.Opt[string] `json:"suffix,omitzero"` // The ID of an uploaded file that contains validation data. // // If you provide this file, the data is used to generate validation metrics @@ -1126,30 +958,31 @@ type FineTuningJobNewParams struct { // // See the [fine-tuning guide](https://platform.openai.com/docs/guides/fine-tuning) // for more details. - ValidationFile param.Field[string] `json:"validation_file"` -} - -func (r FineTuningJobNewParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + ValidationFile param.Opt[string] `json:"validation_file,omitzero"` + // A list of integrations to enable for your fine-tuning job. + Integrations []FineTuningJobNewParamsIntegration `json:"integrations,omitzero"` + // Set of 16 key-value pairs that can be attached to an object. This can be useful + // for storing additional information about the object in a structured format, and + // querying for objects via API or the dashboard. + // + // Keys are strings with a maximum length of 64 characters. Values are strings with + // a maximum length of 512 characters. + Metadata shared.MetadataParam `json:"metadata,omitzero"` + // The hyperparameters used for the fine-tuning job. This value is now deprecated + // in favor of `method`, and should be passed in under the `method` parameter. + Hyperparameters FineTuningJobNewParamsHyperparameters `json:"hyperparameters,omitzero"` + // The method used for fine-tuning. + Method FineTuningJobNewParamsMethod `json:"method,omitzero"` + paramObj } -// The name of the model to fine-tune. You can select one of the -// [supported models](https://platform.openai.com/docs/guides/fine-tuning#which-models-can-be-fine-tuned). -type FineTuningJobNewParamsModel string - -const ( - FineTuningJobNewParamsModelBabbage002 FineTuningJobNewParamsModel = "babbage-002" - FineTuningJobNewParamsModelDavinci002 FineTuningJobNewParamsModel = "davinci-002" - FineTuningJobNewParamsModelGPT3_5Turbo FineTuningJobNewParamsModel = "gpt-3.5-turbo" - FineTuningJobNewParamsModelGPT4oMini FineTuningJobNewParamsModel = "gpt-4o-mini" -) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } -func (r FineTuningJobNewParamsModel) IsKnown() bool { - switch r { - case FineTuningJobNewParamsModelBabbage002, FineTuningJobNewParamsModelDavinci002, FineTuningJobNewParamsModelGPT3_5Turbo, FineTuningJobNewParamsModelGPT4oMini: - return true - } - return false +func (r FineTuningJobNewParams) MarshalJSON() (data []byte, err error) { + type shadow FineTuningJobNewParams + return param.MarshalObject(r, (*shadow)(&r)) } // The hyperparameters used for the fine-tuning job. This value is now deprecated @@ -1159,434 +992,499 @@ func (r FineTuningJobNewParamsModel) IsKnown() bool { type FineTuningJobNewParamsHyperparameters struct { // Number of examples in each batch. A larger batch size means that model // parameters are updated less frequently, but with lower variance. - BatchSize param.Field[FineTuningJobNewParamsHyperparametersBatchSizeUnion] `json:"batch_size"` + BatchSize FineTuningJobNewParamsHyperparametersBatchSizeUnion `json:"batch_size,omitzero"` // Scaling factor for the learning rate. A smaller learning rate may be useful to // avoid overfitting. - LearningRateMultiplier param.Field[FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion] `json:"learning_rate_multiplier"` + LearningRateMultiplier FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion `json:"learning_rate_multiplier,omitzero"` // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. - NEpochs param.Field[FineTuningJobNewParamsHyperparametersNEpochsUnion] `json:"n_epochs"` + NEpochs FineTuningJobNewParamsHyperparametersNEpochsUnion `json:"n_epochs,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsHyperparameters) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r FineTuningJobNewParamsHyperparameters) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsHyperparameters + return param.MarshalObject(r, (*shadow)(&r)) } -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsHyperparametersBatchSizeAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobNewParamsHyperparametersBatchSizeUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsHyperparametersBatchSizeUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsHyperparametersBatchSizeAuto string - -const ( - FineTuningJobNewParamsHyperparametersBatchSizeAutoAuto FineTuningJobNewParamsHyperparametersBatchSizeAuto = "auto" -) - -func (r FineTuningJobNewParamsHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsHyperparametersBatchSizeAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsHyperparametersBatchSizeUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsHyperparametersBatchSizeUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsHyperparametersBatchSizeUnion](u.OfAuto, u.OfInt) } -func (r FineTuningJobNewParamsHyperparametersBatchSizeAuto) ImplementsFineTuningJobNewParamsHyperparametersBatchSizeUnion() { +func (u *FineTuningJobNewParamsHyperparametersBatchSizeUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value + } + return nil } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto], -// [shared.UnionFloat]. -type FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfFloat param.Opt[float64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobNewParamsHyperparametersLearningRateMultiplierAutoAuto FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion](u.OfAuto, u.OfFloat) } -func (r FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion() { +func (u *FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfFloat) { + return &u.OfFloat.Value + } + return nil } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsHyperparametersNEpochsAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobNewParamsHyperparametersNEpochsUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsHyperparametersNEpochsUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsHyperparametersNEpochsAuto string - -const ( - FineTuningJobNewParamsHyperparametersNEpochsAutoAuto FineTuningJobNewParamsHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobNewParamsHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsHyperparametersNEpochsAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsHyperparametersNEpochsUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsHyperparametersNEpochsUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsHyperparametersNEpochsUnion](u.OfAuto, u.OfInt) } -func (r FineTuningJobNewParamsHyperparametersNEpochsAuto) ImplementsFineTuningJobNewParamsHyperparametersNEpochsUnion() { +func (u *FineTuningJobNewParamsHyperparametersNEpochsUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value + } + return nil } +// The properties Type, Wandb are required. type FineTuningJobNewParamsIntegration struct { - // The type of integration to enable. Currently, only "wandb" (Weights and Biases) - // is supported. - Type param.Field[FineTuningJobNewParamsIntegrationsType] `json:"type,required"` // The settings for your integration with Weights and Biases. This payload // specifies the project that metrics will be sent to. Optionally, you can set an // explicit display name for your run, add tags to your run, and set a default // entity (team, username, etc) to be associated with your run. - Wandb param.Field[FineTuningJobNewParamsIntegrationsWandb] `json:"wandb,required"` + Wandb FineTuningJobNewParamsIntegrationWandb `json:"wandb,omitzero,required"` + // The type of integration to enable. Currently, only "wandb" (Weights and Biases) + // is supported. + // + // This field can be elided, and will marshal its zero value as "wandb". + Type constant.Wandb `json:"type,required"` + paramObj } -func (r FineTuningJobNewParamsIntegration) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsIntegration) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } - -// The type of integration to enable. Currently, only "wandb" (Weights and Biases) -// is supported. -type FineTuningJobNewParamsIntegrationsType string - -const ( - FineTuningJobNewParamsIntegrationsTypeWandb FineTuningJobNewParamsIntegrationsType = "wandb" -) - -func (r FineTuningJobNewParamsIntegrationsType) IsKnown() bool { - switch r { - case FineTuningJobNewParamsIntegrationsTypeWandb: - return true - } - return false +func (r FineTuningJobNewParamsIntegration) MarshalJSON() (data []byte, err error) { + type shadow FineTuningJobNewParamsIntegration + return param.MarshalObject(r, (*shadow)(&r)) } // The settings for your integration with Weights and Biases. This payload // specifies the project that metrics will be sent to. Optionally, you can set an // explicit display name for your run, add tags to your run, and set a default // entity (team, username, etc) to be associated with your run. -type FineTuningJobNewParamsIntegrationsWandb struct { +// +// The property Project is required. +type FineTuningJobNewParamsIntegrationWandb struct { // The name of the project that the new run will be created under. - Project param.Field[string] `json:"project,required"` + Project string `json:"project,required"` // The entity to use for the run. This allows you to set the team or username of // the WandB user that you would like associated with the run. If not set, the // default entity for the registered WandB API key is used. - Entity param.Field[string] `json:"entity"` + Entity param.Opt[string] `json:"entity,omitzero"` // A display name to set for the run. If not set, we will use the Job ID as the // name. - Name param.Field[string] `json:"name"` + Name param.Opt[string] `json:"name,omitzero"` // A list of tags to be attached to the newly created run. These tags are passed // through directly to WandB. Some default tags are generated by OpenAI: // "openai/finetune", "openai/{base-model}", "openai/{ftjob-abcdef}". - Tags param.Field[[]string] `json:"tags"` + Tags []string `json:"tags,omitzero"` + paramObj } -func (r FineTuningJobNewParamsIntegrationsWandb) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsIntegrationWandb) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} +func (r FineTuningJobNewParamsIntegrationWandb) MarshalJSON() (data []byte, err error) { + type shadow FineTuningJobNewParamsIntegrationWandb + return param.MarshalObject(r, (*shadow)(&r)) } // The method used for fine-tuning. type FineTuningJobNewParamsMethod struct { // Configuration for the DPO fine-tuning method. - Dpo param.Field[FineTuningJobNewParamsMethodDpo] `json:"dpo"` + Dpo FineTuningJobNewParamsMethodDpo `json:"dpo,omitzero"` // Configuration for the supervised fine-tuning method. - Supervised param.Field[FineTuningJobNewParamsMethodSupervised] `json:"supervised"` + Supervised FineTuningJobNewParamsMethodSupervised `json:"supervised,omitzero"` // The type of method. Is either `supervised` or `dpo`. - Type param.Field[FineTuningJobNewParamsMethodType] `json:"type"` + // + // Any of "supervised", "dpo". + Type string `json:"type,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsMethod) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r FineTuningJobNewParamsMethod) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsMethod + return param.MarshalObject(r, (*shadow)(&r)) +} + +func init() { + apijson.RegisterFieldValidator[FineTuningJobNewParamsMethod]( + "Type", false, "supervised", "dpo", + ) } // Configuration for the DPO fine-tuning method. type FineTuningJobNewParamsMethodDpo struct { // The hyperparameters used for the fine-tuning job. - Hyperparameters param.Field[FineTuningJobNewParamsMethodDpoHyperparameters] `json:"hyperparameters"` + Hyperparameters FineTuningJobNewParamsMethodDpoHyperparameters `json:"hyperparameters,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsMethodDpo) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } func (r FineTuningJobNewParamsMethodDpo) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsMethodDpo + return param.MarshalObject(r, (*shadow)(&r)) } // The hyperparameters used for the fine-tuning job. type FineTuningJobNewParamsMethodDpoHyperparameters struct { // Number of examples in each batch. A larger batch size means that model // parameters are updated less frequently, but with lower variance. - BatchSize param.Field[FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion] `json:"batch_size"` + BatchSize FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion `json:"batch_size,omitzero"` // The beta value for the DPO method. A higher beta value will increase the weight // of the penalty between the policy and reference model. - Beta param.Field[FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion] `json:"beta"` + Beta FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion `json:"beta,omitzero"` // Scaling factor for the learning rate. A smaller learning rate may be useful to // avoid overfitting. - LearningRateMultiplier param.Field[FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion] `json:"learning_rate_multiplier"` + LearningRateMultiplier FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion `json:"learning_rate_multiplier,omitzero"` // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. - NEpochs param.Field[FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion] `json:"n_epochs"` + NEpochs FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion `json:"n_epochs,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsMethodDpoHyperparameters) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r FineTuningJobNewParamsMethodDpoHyperparameters) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsMethodDpoHyperparameters + return param.MarshalObject(r, (*shadow)(&r)) } -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto string - -const ( - FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAutoAuto FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion](u.OfAuto, u.OfInt) } -func (r FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto) ImplementsFineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion() { +func (u *FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value + } + return nil } -// The beta value for the DPO method. A higher beta value will increase the weight -// of the penalty between the policy and reference model. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto], -// [shared.UnionFloat]. -type FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion interface { - ImplementsFineTuningJobNewParamsMethodDpoHyperparametersBetaUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfFloat param.Opt[float64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto string - -const ( - FineTuningJobNewParamsMethodDpoHyperparametersBetaAutoAuto FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodDpoHyperparametersBetaAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion](u.OfAuto, u.OfFloat) } -func (r FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto) ImplementsFineTuningJobNewParamsMethodDpoHyperparametersBetaUnion() { +func (u *FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfFloat) { + return &u.OfFloat.Value + } + return nil } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// Only one field can be non-zero. // -// Satisfied by -// [FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto], -// [shared.UnionFloat]. -type FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfFloat param.Opt[float64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAutoAuto FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion](u.OfAuto, u.OfFloat) } -func (r FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion() { +func (u *FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfFloat) { + return &u.OfFloat.Value + } + return nil } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto string - -const ( - FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAutoAuto FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion](u.OfAuto, u.OfInt) } -func (r FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto) ImplementsFineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion() { +func (u *FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value + } + return nil } // Configuration for the supervised fine-tuning method. type FineTuningJobNewParamsMethodSupervised struct { // The hyperparameters used for the fine-tuning job. - Hyperparameters param.Field[FineTuningJobNewParamsMethodSupervisedHyperparameters] `json:"hyperparameters"` + Hyperparameters FineTuningJobNewParamsMethodSupervisedHyperparameters `json:"hyperparameters,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsMethodSupervised) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r FineTuningJobNewParamsMethodSupervised) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsMethodSupervised + return param.MarshalObject(r, (*shadow)(&r)) } // The hyperparameters used for the fine-tuning job. type FineTuningJobNewParamsMethodSupervisedHyperparameters struct { // Number of examples in each batch. A larger batch size means that model // parameters are updated less frequently, but with lower variance. - BatchSize param.Field[FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion] `json:"batch_size"` + BatchSize FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion `json:"batch_size,omitzero"` // Scaling factor for the learning rate. A smaller learning rate may be useful to // avoid overfitting. - LearningRateMultiplier param.Field[FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion] `json:"learning_rate_multiplier"` + LearningRateMultiplier FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion `json:"learning_rate_multiplier,omitzero"` // The number of epochs to train the model for. An epoch refers to one full cycle // through the training dataset. - NEpochs param.Field[FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion] `json:"n_epochs"` + NEpochs FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion `json:"n_epochs,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobNewParamsMethodSupervisedHyperparameters) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() +} func (r FineTuningJobNewParamsMethodSupervisedHyperparameters) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow FineTuningJobNewParamsMethodSupervisedHyperparameters + return param.MarshalObject(r, (*shadow)(&r)) } -// Number of examples in each batch. A larger batch size means that model -// parameters are updated less frequently, but with lower variance. +// Only one field can be non-zero. // -// Satisfied by -// [FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion interface { - ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto string - -const ( - FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAutoAuto FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion](u.OfAuto, u.OfInt) } -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto) ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion() { +func (u *FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value + } + return nil } -// Scaling factor for the learning rate. A smaller learning rate may be useful to -// avoid overfitting. +// Only one field can be non-zero. // -// Satisfied by -// [FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto], -// [shared.UnionFloat]. -type FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion interface { - ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfFloat param.Opt[float64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto string - -const ( - FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAutoAuto FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() +} +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion](u.OfAuto, u.OfFloat) } -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto) ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion() { +func (u *FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfFloat) { + return &u.OfFloat.Value + } + return nil } -// The number of epochs to train the model for. An epoch refers to one full cycle -// through the training dataset. +// Only one field can be non-zero. // -// Satisfied by [FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto], -// [shared.UnionInt]. -type FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion interface { - ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion() +// Use [param.IsOmitted] to confirm if a field is set. +type FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion struct { + // Construct this variant with constant.New[constant.Auto]() Check if union is this + // variant with !param.IsOmitted(union.OfAuto) + OfAuto constant.Auto `json:",omitzero,inline"` + OfInt param.Opt[int64] `json:",omitzero,inline"` + paramUnion } -type FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto string - -const ( - FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAutoAuto FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto = "auto" -) - -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAutoAuto: - return true - } - return false +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion) IsPresent() bool { + return !param.IsOmitted(u) && !u.IsNull() } - -func (r FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto) ImplementsFineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion() { +func (u FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion) MarshalJSON() ([]byte, error) { + return param.MarshalUnion[FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion](u.OfAuto, u.OfInt) } -// The type of method. Is either `supervised` or `dpo`. -type FineTuningJobNewParamsMethodType string - -const ( - FineTuningJobNewParamsMethodTypeSupervised FineTuningJobNewParamsMethodType = "supervised" - FineTuningJobNewParamsMethodTypeDpo FineTuningJobNewParamsMethodType = "dpo" -) - -func (r FineTuningJobNewParamsMethodType) IsKnown() bool { - switch r { - case FineTuningJobNewParamsMethodTypeSupervised, FineTuningJobNewParamsMethodTypeDpo: - return true +func (u *FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion) asAny() any { + if !param.IsOmitted(u.OfAuto) { + return &u.OfAuto + } else if !param.IsOmitted(u.OfInt) { + return &u.OfInt.Value } - return false + return nil } type FineTuningJobListParams struct { // Identifier for the last job from the previous pagination request. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // Number of fine-tuning jobs to retrieve. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` // Optional metadata filter. To filter, use the syntax `metadata[k]=v`. // Alternatively, set `metadata=null` to indicate no metadata. - Metadata param.Field[map[string]string] `query:"metadata"` + Metadata map[string]string `query:"metadata,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [FineTuningJobListParams]'s query parameters as // `url.Values`. func (r FineTuningJobListParams) URLQuery() (v url.Values) { @@ -1598,11 +1496,16 @@ func (r FineTuningJobListParams) URLQuery() (v url.Values) { type FineTuningJobListEventsParams struct { // Identifier for the last event from the previous pagination request. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // Number of events to retrieve. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobListEventsParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + // URLQuery serializes [FineTuningJobListEventsParams]'s query parameters as // `url.Values`. func (r FineTuningJobListEventsParams) URLQuery() (v url.Values) { diff --git a/finetuningjob_test.go b/finetuningjob_test.go index 5a241400..88905f46 100644 --- a/finetuningjob_test.go +++ b/finetuningjob_test.go @@ -12,6 +12,7 @@ import ( "github.com/openai/openai-go/internal/testutil" "github.com/openai/openai-go/option" "github.com/openai/openai-go/shared" + "github.com/openai/openai-go/shared/constant" ) func TestFineTuningJobNewWithOptionalParams(t *testing.T) { @@ -27,46 +28,65 @@ func TestFineTuningJobNewWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.FineTuning.Jobs.New(context.TODO(), openai.FineTuningJobNewParams{ - Model: openai.F(openai.FineTuningJobNewParamsModelBabbage002), - TrainingFile: openai.F("file-abc123"), - Hyperparameters: openai.F(openai.FineTuningJobNewParamsHyperparameters{ - BatchSize: openai.F[openai.FineTuningJobNewParamsHyperparametersBatchSizeUnion](openai.FineTuningJobNewParamsHyperparametersBatchSizeAuto(openai.FineTuningJobNewParamsHyperparametersBatchSizeAutoAuto)), - LearningRateMultiplier: openai.F[openai.FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion](openai.FineTuningJobNewParamsHyperparametersLearningRateMultiplierAuto(openai.FineTuningJobNewParamsHyperparametersLearningRateMultiplierAutoAuto)), - NEpochs: openai.F[openai.FineTuningJobNewParamsHyperparametersNEpochsUnion](openai.FineTuningJobNewParamsHyperparametersNEpochsAuto(openai.FineTuningJobNewParamsHyperparametersNEpochsAutoAuto)), - }), - Integrations: openai.F([]openai.FineTuningJobNewParamsIntegration{{ - Type: openai.F(openai.FineTuningJobNewParamsIntegrationsTypeWandb), - Wandb: openai.F(openai.FineTuningJobNewParamsIntegrationsWandb{ - Project: openai.F("my-wandb-project"), - Entity: openai.F("entity"), - Name: openai.F("name"), - Tags: openai.F([]string{"custom-tag"}), - }), - }}), - Metadata: openai.F(shared.MetadataParam{ + Model: "babbage-002", + TrainingFile: "file-abc123", + Hyperparameters: openai.FineTuningJobNewParamsHyperparameters{ + BatchSize: openai.FineTuningJobNewParamsHyperparametersBatchSizeUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + LearningRateMultiplier: openai.FineTuningJobNewParamsHyperparametersLearningRateMultiplierUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + NEpochs: openai.FineTuningJobNewParamsHyperparametersNEpochsUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + }, + Integrations: []openai.FineTuningJobNewParamsIntegration{{ + Wandb: openai.FineTuningJobNewParamsIntegrationWandb{ + Project: "my-wandb-project", + Entity: openai.String("entity"), + Name: openai.String("name"), + Tags: []string{"custom-tag"}, + }, + }}, + Metadata: shared.MetadataParam{ "foo": "string", - }), - Method: openai.F(openai.FineTuningJobNewParamsMethod{ - Dpo: openai.F(openai.FineTuningJobNewParamsMethodDpo{ - Hyperparameters: openai.F(openai.FineTuningJobNewParamsMethodDpoHyperparameters{ - BatchSize: openai.F[openai.FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion](openai.FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAuto(openai.FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeAutoAuto)), - Beta: openai.F[openai.FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion](openai.FineTuningJobNewParamsMethodDpoHyperparametersBetaAuto(openai.FineTuningJobNewParamsMethodDpoHyperparametersBetaAutoAuto)), - LearningRateMultiplier: openai.F[openai.FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion](openai.FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAuto(openai.FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierAutoAuto)), - NEpochs: openai.F[openai.FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion](openai.FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAuto(openai.FineTuningJobNewParamsMethodDpoHyperparametersNEpochsAutoAuto)), - }), - }), - Supervised: openai.F(openai.FineTuningJobNewParamsMethodSupervised{ - Hyperparameters: openai.F(openai.FineTuningJobNewParamsMethodSupervisedHyperparameters{ - BatchSize: openai.F[openai.FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion](openai.FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAuto(openai.FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeAutoAuto)), - LearningRateMultiplier: openai.F[openai.FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion](openai.FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAuto(openai.FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierAutoAuto)), - NEpochs: openai.F[openai.FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion](openai.FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAuto(openai.FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsAutoAuto)), - }), - }), - Type: openai.F(openai.FineTuningJobNewParamsMethodTypeSupervised), - }), - Seed: openai.F(int64(42)), - Suffix: openai.F("x"), - ValidationFile: openai.F("file-abc123"), + }, + Method: openai.FineTuningJobNewParamsMethod{ + Dpo: openai.FineTuningJobNewParamsMethodDpo{ + Hyperparameters: openai.FineTuningJobNewParamsMethodDpoHyperparameters{ + BatchSize: openai.FineTuningJobNewParamsMethodDpoHyperparametersBatchSizeUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + Beta: openai.FineTuningJobNewParamsMethodDpoHyperparametersBetaUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + LearningRateMultiplier: openai.FineTuningJobNewParamsMethodDpoHyperparametersLearningRateMultiplierUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + NEpochs: openai.FineTuningJobNewParamsMethodDpoHyperparametersNEpochsUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + }, + }, + Supervised: openai.FineTuningJobNewParamsMethodSupervised{ + Hyperparameters: openai.FineTuningJobNewParamsMethodSupervisedHyperparameters{ + BatchSize: openai.FineTuningJobNewParamsMethodSupervisedHyperparametersBatchSizeUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + LearningRateMultiplier: openai.FineTuningJobNewParamsMethodSupervisedHyperparametersLearningRateMultiplierUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + NEpochs: openai.FineTuningJobNewParamsMethodSupervisedHyperparametersNEpochsUnion{ + OfAuto: constant.ValueOf[constant.Auto](), + }, + }, + }, + Type: "supervised", + }, + Seed: openai.Int(42), + Suffix: openai.String("x"), + ValidationFile: openai.String("file-abc123"), }) if err != nil { var apierr *openai.Error @@ -112,11 +132,11 @@ func TestFineTuningJobListWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.FineTuning.Jobs.List(context.TODO(), openai.FineTuningJobListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), - Metadata: openai.F(map[string]string{ + After: openai.String("after"), + Limit: openai.Int(0), + Metadata: map[string]string{ "foo": "string", - }), + }, }) if err != nil { var apierr *openai.Error @@ -165,8 +185,8 @@ func TestFineTuningJobListEventsWithOptionalParams(t *testing.T) { context.TODO(), "ft-AF1WoRqd3aJAHsqc9NY7iL8F", openai.FineTuningJobListEventsParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), + After: openai.String("after"), + Limit: openai.Int(0), }, ) if err != nil { diff --git a/finetuningjobcheckpoint.go b/finetuningjobcheckpoint.go index 7c53e5d8..641588fb 100644 --- a/finetuningjobcheckpoint.go +++ b/finetuningjobcheckpoint.go @@ -11,10 +11,12 @@ import ( "github.com/openai/openai-go/internal/apijson" "github.com/openai/openai-go/internal/apiquery" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" "github.com/openai/openai-go/packages/pagination" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" + "github.com/openai/openai-go/shared/constant" ) // FineTuningJobCheckpointService contains methods and other services that help @@ -30,8 +32,8 @@ type FineTuningJobCheckpointService struct { // NewFineTuningJobCheckpointService generates a new service that applies the given // options to each request. These options are applied after the parent client's // options (if there is one), and before any request-specific options. -func NewFineTuningJobCheckpointService(opts ...option.RequestOption) (r *FineTuningJobCheckpointService) { - r = &FineTuningJobCheckpointService{} +func NewFineTuningJobCheckpointService(opts ...option.RequestOption) (r FineTuningJobCheckpointService) { + r = FineTuningJobCheckpointService{} r.Options = opts return } @@ -77,88 +79,72 @@ type FineTuningJobCheckpoint struct { // Metrics at the step number during the fine-tuning job. Metrics FineTuningJobCheckpointMetrics `json:"metrics,required"` // The object type, which is always "fine_tuning.job.checkpoint". - Object FineTuningJobCheckpointObject `json:"object,required"` + Object constant.FineTuningJobCheckpoint `json:"object,required"` // The step number that the checkpoint was created at. - StepNumber int64 `json:"step_number,required"` - JSON fineTuningJobCheckpointJSON `json:"-"` + StepNumber int64 `json:"step_number,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + ID resp.Field + CreatedAt resp.Field + FineTunedModelCheckpoint resp.Field + FineTuningJobID resp.Field + Metrics resp.Field + Object resp.Field + StepNumber resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// fineTuningJobCheckpointJSON contains the JSON metadata for the struct -// [FineTuningJobCheckpoint] -type fineTuningJobCheckpointJSON struct { - ID apijson.Field - CreatedAt apijson.Field - FineTunedModelCheckpoint apijson.Field - FineTuningJobID apijson.Field - Metrics apijson.Field - Object apijson.Field - StepNumber apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobCheckpoint) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r FineTuningJobCheckpoint) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobCheckpoint) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobCheckpointJSON) RawJSON() string { - return r.raw -} - // Metrics at the step number during the fine-tuning job. type FineTuningJobCheckpointMetrics struct { - FullValidLoss float64 `json:"full_valid_loss"` - FullValidMeanTokenAccuracy float64 `json:"full_valid_mean_token_accuracy"` - Step float64 `json:"step"` - TrainLoss float64 `json:"train_loss"` - TrainMeanTokenAccuracy float64 `json:"train_mean_token_accuracy"` - ValidLoss float64 `json:"valid_loss"` - ValidMeanTokenAccuracy float64 `json:"valid_mean_token_accuracy"` - JSON fineTuningJobCheckpointMetricsJSON `json:"-"` + FullValidLoss float64 `json:"full_valid_loss"` + FullValidMeanTokenAccuracy float64 `json:"full_valid_mean_token_accuracy"` + Step float64 `json:"step"` + TrainLoss float64 `json:"train_loss"` + TrainMeanTokenAccuracy float64 `json:"train_mean_token_accuracy"` + ValidLoss float64 `json:"valid_loss"` + ValidMeanTokenAccuracy float64 `json:"valid_mean_token_accuracy"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + FullValidLoss resp.Field + FullValidMeanTokenAccuracy resp.Field + Step resp.Field + TrainLoss resp.Field + TrainMeanTokenAccuracy resp.Field + ValidLoss resp.Field + ValidMeanTokenAccuracy resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// fineTuningJobCheckpointMetricsJSON contains the JSON metadata for the struct -// [FineTuningJobCheckpointMetrics] -type fineTuningJobCheckpointMetricsJSON struct { - FullValidLoss apijson.Field - FullValidMeanTokenAccuracy apijson.Field - Step apijson.Field - TrainLoss apijson.Field - TrainMeanTokenAccuracy apijson.Field - ValidLoss apijson.Field - ValidMeanTokenAccuracy apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *FineTuningJobCheckpointMetrics) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r FineTuningJobCheckpointMetrics) RawJSON() string { return r.JSON.raw } +func (r *FineTuningJobCheckpointMetrics) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r fineTuningJobCheckpointMetricsJSON) RawJSON() string { - return r.raw -} - -// The object type, which is always "fine_tuning.job.checkpoint". -type FineTuningJobCheckpointObject string - -const ( - FineTuningJobCheckpointObjectFineTuningJobCheckpoint FineTuningJobCheckpointObject = "fine_tuning.job.checkpoint" -) - -func (r FineTuningJobCheckpointObject) IsKnown() bool { - switch r { - case FineTuningJobCheckpointObjectFineTuningJobCheckpoint: - return true - } - return false -} - type FineTuningJobCheckpointListParams struct { // Identifier for the last checkpoint ID from the previous pagination request. - After param.Field[string] `query:"after"` + After param.Opt[string] `query:"after,omitzero" json:"-"` // Number of checkpoints to retrieve. - Limit param.Field[int64] `query:"limit"` + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + paramObj +} + +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f FineTuningJobCheckpointListParams) IsPresent() bool { + return !param.IsOmitted(f) && !f.IsNull() } // URLQuery serializes [FineTuningJobCheckpointListParams]'s query parameters as diff --git a/finetuningjobcheckpoint_test.go b/finetuningjobcheckpoint_test.go index 6f6cafca..1de9ecb0 100644 --- a/finetuningjobcheckpoint_test.go +++ b/finetuningjobcheckpoint_test.go @@ -29,8 +29,8 @@ func TestFineTuningJobCheckpointListWithOptionalParams(t *testing.T) { context.TODO(), "ft-AF1WoRqd3aJAHsqc9NY7iL8F", openai.FineTuningJobCheckpointListParams{ - After: openai.F("after"), - Limit: openai.F(int64(0)), + After: openai.String("after"), + Limit: openai.Int(0), }, ) if err != nil { diff --git a/go.mod b/go.mod index f0a0b76c..7c5f1246 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/openai/openai-go go 1.21 require ( - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 github.com/tidwall/gjson v1.14.4 github.com/tidwall/sjson v1.2.5 @@ -18,8 +18,8 @@ require ( github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect + golang.org/x/crypto v0.32.0 // indirect + golang.org/x/net v0.34.0 // indirect + golang.org/x/sys v0.29.0 // indirect + golang.org/x/text v0.21.0 // indirect ) diff --git a/go.sum b/go.sum index 77c3f767..347c1185 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 h1:g0EZJwz7xkXQiZAI5xi9f3WWFYBlX1CPTrR+NDToRkQ= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= @@ -18,8 +18,8 @@ github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmd github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= @@ -30,14 +30,14 @@ github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= +golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= +golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= +golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/go.work b/go.work deleted file mode 100644 index a864d2f1..00000000 --- a/go.work +++ /dev/null @@ -1,3 +0,0 @@ -go 1.22.4 - -use ./examples diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index 0d57a9b9..00000000 --- a/go.work.sum +++ /dev/null @@ -1,27 +0,0 @@ -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0 h1:GJHeeA2N7xrG3q30L2UXDyuWRzDM900/65j70wcM4Ww= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.13.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0 h1:nyQWyZvwGTvunIMxi1Y9uXkcyr+I7TeNrr/foo4Kpk8= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0/go.mod h1:l38EPgmsp71HHLq9j7De57JcKOWPyhrsW1Awm1JS6K0= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= diff --git a/image.go b/image.go index f52ef80a..774e11d5 100644 --- a/image.go +++ b/image.go @@ -11,9 +11,10 @@ import ( "github.com/openai/openai-go/internal/apiform" "github.com/openai/openai-go/internal/apijson" - "github.com/openai/openai-go/internal/param" "github.com/openai/openai-go/internal/requestconfig" "github.com/openai/openai-go/option" + "github.com/openai/openai-go/packages/param" + "github.com/openai/openai-go/packages/resp" ) // ImageService contains methods and other services that help with interacting with @@ -29,8 +30,8 @@ type ImageService struct { // NewImageService generates a new service that applies the given options to each // request. These options are applied after the parent client's options (if there // is one), and before any request-specific options. -func NewImageService(opts ...option.RequestOption) (r *ImageService) { - r = &ImageService{} +func NewImageService(opts ...option.RequestOption) (r ImageService) { + r = ImageService{} r.Options = opts return } @@ -68,27 +69,24 @@ type Image struct { // prompt. RevisedPrompt string `json:"revised_prompt"` // The URL of the generated image, if `response_format` is `url` (default). - URL string `json:"url"` - JSON imageJSON `json:"-"` + URL string `json:"url"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + B64JSON resp.Field + RevisedPrompt resp.Field + URL resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -// imageJSON contains the JSON metadata for the struct [Image] -type imageJSON struct { - B64JSON apijson.Field - RevisedPrompt apijson.Field - URL apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Image) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r Image) RawJSON() string { return r.JSON.raw } +func (r *Image) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imageJSON) RawJSON() string { - return r.raw -} - type ImageModel = string const ( @@ -97,50 +95,56 @@ const ( ) type ImagesResponse struct { - Created int64 `json:"created,required"` - Data []Image `json:"data,required"` - JSON imagesResponseJSON `json:"-"` -} - -// imagesResponseJSON contains the JSON metadata for the struct [ImagesResponse] -type imagesResponseJSON struct { - Created apijson.Field - Data apijson.Field - raw string - ExtraFields map[string]apijson.Field + Created int64 `json:"created,required"` + Data []Image `json:"data,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Created resp.Field + Data resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` } -func (r *ImagesResponse) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r ImagesResponse) RawJSON() string { return r.JSON.raw } +func (r *ImagesResponse) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r imagesResponseJSON) RawJSON() string { - return r.raw -} - type ImageNewVariationParams struct { // The image to use as the basis for the variation(s). Must be a valid PNG file, // less than 4MB, and square. - Image param.Field[io.Reader] `json:"image,required" format:"binary"` - // The model to use for image generation. Only `dall-e-2` is supported at this - // time. - Model param.Field[ImageModel] `json:"model"` + Image io.Reader `json:"image,required" format:"binary"` // The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only // `n=1` is supported. - N param.Field[int64] `json:"n"` + N param.Opt[int64] `json:"n,omitzero"` + // A unique identifier representing your end-user, which can help OpenAI to monitor + // and detect abuse. + // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). + User param.Opt[string] `json:"user,omitzero"` + // The model to use for image generation. Only `dall-e-2` is supported at this + // time. + Model ImageModel `json:"model,omitzero"` // The format in which the generated images are returned. Must be one of `url` or // `b64_json`. URLs are only valid for 60 minutes after the image has been // generated. - ResponseFormat param.Field[ImageNewVariationParamsResponseFormat] `json:"response_format"` + // + // Any of "url", "b64_json". + ResponseFormat ImageNewVariationParamsResponseFormat `json:"response_format,omitzero"` // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024`. - Size param.Field[ImageNewVariationParamsSize] `json:"size"` - // A unique identifier representing your end-user, which can help OpenAI to monitor - // and detect abuse. - // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + // + // Any of "256x256", "512x512", "1024x1024". + Size ImageNewVariationParamsSize `json:"size,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageNewVariationParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r ImageNewVariationParams) MarshalMultipart() (data []byte, contentType string, err error) { buf := bytes.NewBuffer(nil) writer := multipart.NewWriter(buf) @@ -166,14 +170,6 @@ const ( ImageNewVariationParamsResponseFormatB64JSON ImageNewVariationParamsResponseFormat = "b64_json" ) -func (r ImageNewVariationParamsResponseFormat) IsKnown() bool { - switch r { - case ImageNewVariationParamsResponseFormatURL, ImageNewVariationParamsResponseFormatB64JSON: - return true - } - return false -} - // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024`. type ImageNewVariationParamsSize string @@ -184,43 +180,44 @@ const ( ImageNewVariationParamsSize1024x1024 ImageNewVariationParamsSize = "1024x1024" ) -func (r ImageNewVariationParamsSize) IsKnown() bool { - switch r { - case ImageNewVariationParamsSize256x256, ImageNewVariationParamsSize512x512, ImageNewVariationParamsSize1024x1024: - return true - } - return false -} - type ImageEditParams struct { // The image to edit. Must be a valid PNG file, less than 4MB, and square. If mask // is not provided, image must have transparency, which will be used as the mask. - Image param.Field[io.Reader] `json:"image,required" format:"binary"` + Image io.Reader `json:"image,required" format:"binary"` // A text description of the desired image(s). The maximum length is 1000 // characters. - Prompt param.Field[string] `json:"prompt,required"` - // An additional image whose fully transparent areas (e.g. where alpha is zero) - // indicate where `image` should be edited. Must be a valid PNG file, less than - // 4MB, and have the same dimensions as `image`. - Mask param.Field[io.Reader] `json:"mask" format:"binary"` + Prompt string `json:"prompt,required"` + // The number of images to generate. Must be between 1 and 10. + N param.Opt[int64] `json:"n,omitzero"` + // A unique identifier representing your end-user, which can help OpenAI to monitor + // and detect abuse. + // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). + User param.Opt[string] `json:"user,omitzero"` // The model to use for image generation. Only `dall-e-2` is supported at this // time. - Model param.Field[ImageModel] `json:"model"` - // The number of images to generate. Must be between 1 and 10. - N param.Field[int64] `json:"n"` + Model ImageModel `json:"model,omitzero"` // The format in which the generated images are returned. Must be one of `url` or // `b64_json`. URLs are only valid for 60 minutes after the image has been // generated. - ResponseFormat param.Field[ImageEditParamsResponseFormat] `json:"response_format"` + // + // Any of "url", "b64_json". + ResponseFormat ImageEditParamsResponseFormat `json:"response_format,omitzero"` // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024`. - Size param.Field[ImageEditParamsSize] `json:"size"` - // A unique identifier representing your end-user, which can help OpenAI to monitor - // and detect abuse. - // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + // + // Any of "256x256", "512x512", "1024x1024". + Size ImageEditParamsSize `json:"size,omitzero"` + // An additional image whose fully transparent areas (e.g. where alpha is zero) + // indicate where `image` should be edited. Must be a valid PNG file, less than + // 4MB, and have the same dimensions as `image`. + Mask io.Reader `json:"mask" format:"binary"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageEditParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r ImageEditParams) MarshalMultipart() (data []byte, contentType string, err error) { buf := bytes.NewBuffer(nil) writer := multipart.NewWriter(buf) @@ -246,14 +243,6 @@ const ( ImageEditParamsResponseFormatB64JSON ImageEditParamsResponseFormat = "b64_json" ) -func (r ImageEditParamsResponseFormat) IsKnown() bool { - switch r { - case ImageEditParamsResponseFormatURL, ImageEditParamsResponseFormatB64JSON: - return true - } - return false -} - // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024`. type ImageEditParamsSize string @@ -264,48 +253,54 @@ const ( ImageEditParamsSize1024x1024 ImageEditParamsSize = "1024x1024" ) -func (r ImageEditParamsSize) IsKnown() bool { - switch r { - case ImageEditParamsSize256x256, ImageEditParamsSize512x512, ImageEditParamsSize1024x1024: - return true - } - return false -} - type ImageGenerateParams struct { // A text description of the desired image(s). The maximum length is 1000 // characters for `dall-e-2` and 4000 characters for `dall-e-3`. - Prompt param.Field[string] `json:"prompt,required"` - // The model to use for image generation. - Model param.Field[ImageModel] `json:"model"` + Prompt string `json:"prompt,required"` // The number of images to generate. Must be between 1 and 10. For `dall-e-3`, only // `n=1` is supported. - N param.Field[int64] `json:"n"` - // The quality of the image that will be generated. `hd` creates images with finer - // details and greater consistency across the image. This param is only supported - // for `dall-e-3`. - Quality param.Field[ImageGenerateParamsQuality] `json:"quality"` + N param.Opt[int64] `json:"n,omitzero"` + // A unique identifier representing your end-user, which can help OpenAI to monitor + // and detect abuse. + // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). + User param.Opt[string] `json:"user,omitzero"` + // The model to use for image generation. + Model ImageModel `json:"model,omitzero"` // The format in which the generated images are returned. Must be one of `url` or // `b64_json`. URLs are only valid for 60 minutes after the image has been // generated. - ResponseFormat param.Field[ImageGenerateParamsResponseFormat] `json:"response_format"` + // + // Any of "url", "b64_json". + ResponseFormat ImageGenerateParamsResponseFormat `json:"response_format,omitzero"` // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024` for `dall-e-2`. Must be one of `1024x1024`, `1792x1024`, or // `1024x1792` for `dall-e-3` models. - Size param.Field[ImageGenerateParamsSize] `json:"size"` + // + // Any of "256x256", "512x512", "1024x1024", "1792x1024", "1024x1792". + Size ImageGenerateParamsSize `json:"size,omitzero"` // The style of the generated images. Must be one of `vivid` or `natural`. Vivid // causes the model to lean towards generating hyper-real and dramatic images. // Natural causes the model to produce more natural, less hyper-real looking // images. This param is only supported for `dall-e-3`. - Style param.Field[ImageGenerateParamsStyle] `json:"style"` - // A unique identifier representing your end-user, which can help OpenAI to monitor - // and detect abuse. - // [Learn more](https://platform.openai.com/docs/guides/safety-best-practices#end-user-ids). - User param.Field[string] `json:"user"` + // + // Any of "vivid", "natural". + Style ImageGenerateParamsStyle `json:"style,omitzero"` + // The quality of the image that will be generated. `hd` creates images with finer + // details and greater consistency across the image. This param is only supported + // for `dall-e-3`. + // + // Any of "standard", "hd". + Quality ImageGenerateParamsQuality `json:"quality,omitzero"` + paramObj } +// IsPresent returns true if the field's value is not omitted and not the JSON +// "null". To check if this field is omitted, use [param.IsOmitted]. +func (f ImageGenerateParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() } + func (r ImageGenerateParams) MarshalJSON() (data []byte, err error) { - return apijson.MarshalRoot(r) + type shadow ImageGenerateParams + return param.MarshalObject(r, (*shadow)(&r)) } // The quality of the image that will be generated. `hd` creates images with finer @@ -318,14 +313,6 @@ const ( ImageGenerateParamsQualityHD ImageGenerateParamsQuality = "hd" ) -func (r ImageGenerateParamsQuality) IsKnown() bool { - switch r { - case ImageGenerateParamsQualityStandard, ImageGenerateParamsQualityHD: - return true - } - return false -} - // The format in which the generated images are returned. Must be one of `url` or // `b64_json`. URLs are only valid for 60 minutes after the image has been // generated. @@ -336,14 +323,6 @@ const ( ImageGenerateParamsResponseFormatB64JSON ImageGenerateParamsResponseFormat = "b64_json" ) -func (r ImageGenerateParamsResponseFormat) IsKnown() bool { - switch r { - case ImageGenerateParamsResponseFormatURL, ImageGenerateParamsResponseFormatB64JSON: - return true - } - return false -} - // The size of the generated images. Must be one of `256x256`, `512x512`, or // `1024x1024` for `dall-e-2`. Must be one of `1024x1024`, `1792x1024`, or // `1024x1792` for `dall-e-3` models. @@ -357,14 +336,6 @@ const ( ImageGenerateParamsSize1024x1792 ImageGenerateParamsSize = "1024x1792" ) -func (r ImageGenerateParamsSize) IsKnown() bool { - switch r { - case ImageGenerateParamsSize256x256, ImageGenerateParamsSize512x512, ImageGenerateParamsSize1024x1024, ImageGenerateParamsSize1792x1024, ImageGenerateParamsSize1024x1792: - return true - } - return false -} - // The style of the generated images. Must be one of `vivid` or `natural`. Vivid // causes the model to lean towards generating hyper-real and dramatic images. // Natural causes the model to produce more natural, less hyper-real looking @@ -375,11 +346,3 @@ const ( ImageGenerateParamsStyleVivid ImageGenerateParamsStyle = "vivid" ImageGenerateParamsStyleNatural ImageGenerateParamsStyle = "natural" ) - -func (r ImageGenerateParamsStyle) IsKnown() bool { - switch r { - case ImageGenerateParamsStyleVivid, ImageGenerateParamsStyleNatural: - return true - } - return false -} diff --git a/image_test.go b/image_test.go index f4334ee2..e8f2b627 100644 --- a/image_test.go +++ b/image_test.go @@ -28,12 +28,12 @@ func TestImageNewVariationWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Images.NewVariation(context.TODO(), openai.ImageNewVariationParams{ - Image: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Model: openai.F(openai.ImageModelDallE2), - N: openai.F(int64(1)), - ResponseFormat: openai.F(openai.ImageNewVariationParamsResponseFormatURL), - Size: openai.F(openai.ImageNewVariationParamsSize256x256), - User: openai.F("user-1234"), + Image: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Model: openai.ImageModelDallE2, + N: openai.Int(1), + ResponseFormat: openai.ImageNewVariationParamsResponseFormatURL, + Size: openai.ImageNewVariationParamsSize256x256, + User: openai.String("user-1234"), }) if err != nil { var apierr *openai.Error @@ -57,14 +57,14 @@ func TestImageEditWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Images.Edit(context.TODO(), openai.ImageEditParams{ - Image: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Prompt: openai.F("A cute baby sea otter wearing a beret"), - Mask: openai.F(io.Reader(bytes.NewBuffer([]byte("some file contents")))), - Model: openai.F(openai.ImageModelDallE2), - N: openai.F(int64(1)), - ResponseFormat: openai.F(openai.ImageEditParamsResponseFormatURL), - Size: openai.F(openai.ImageEditParamsSize256x256), - User: openai.F("user-1234"), + Image: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Prompt: "A cute baby sea otter wearing a beret", + Mask: io.Reader(bytes.NewBuffer([]byte("some file contents"))), + Model: openai.ImageModelDallE2, + N: openai.Int(1), + ResponseFormat: openai.ImageEditParamsResponseFormatURL, + Size: openai.ImageEditParamsSize256x256, + User: openai.String("user-1234"), }) if err != nil { var apierr *openai.Error @@ -88,14 +88,14 @@ func TestImageGenerateWithOptionalParams(t *testing.T) { option.WithAPIKey("My API Key"), ) _, err := client.Images.Generate(context.TODO(), openai.ImageGenerateParams{ - Prompt: openai.F("A cute baby sea otter"), - Model: openai.F(openai.ImageModelDallE2), - N: openai.F(int64(1)), - Quality: openai.F(openai.ImageGenerateParamsQualityStandard), - ResponseFormat: openai.F(openai.ImageGenerateParamsResponseFormatURL), - Size: openai.F(openai.ImageGenerateParamsSize256x256), - Style: openai.F(openai.ImageGenerateParamsStyleVivid), - User: openai.F("user-1234"), + Prompt: "A cute baby sea otter", + Model: openai.ImageModelDallE2, + N: openai.Int(1), + Quality: openai.ImageGenerateParamsQualityStandard, + ResponseFormat: openai.ImageGenerateParamsResponseFormatURL, + Size: openai.ImageGenerateParamsSize256x256, + Style: openai.ImageGenerateParamsStyleVivid, + User: openai.String("user-1234"), }) if err != nil { var apierr *openai.Error diff --git a/internal/apierror/apierror.go b/internal/apierror/apierror.go index 81fa67c1..ef0419b1 100644 --- a/internal/apierror/apierror.go +++ b/internal/apierror/apierror.go @@ -8,43 +8,41 @@ import ( "net/http/httputil" "github.com/openai/openai-go/internal/apijson" + "github.com/openai/openai-go/packages/resp" ) // Error represents an error that originates from the API, i.e. when a request is // made and the API returns a response with a HTTP status code. Other errors are // not wrapped by this SDK. type Error struct { - Code string `json:"code,required,nullable"` - Message string `json:"message,required"` - Param string `json:"param,required,nullable"` - Type string `json:"type,required"` - JSON errorJSON `json:"-"` + Code string `json:"code,required"` + Message string `json:"message,required"` + Param string `json:"param,required"` + Type string `json:"type,required"` + // Metadata for the response, check the presence of optional fields with the + // [resp.Field.IsPresent] method. + JSON struct { + Code resp.Field + Message resp.Field + Param resp.Field + Type resp.Field + ExtraFields map[string]resp.Field + raw string + } `json:"-"` StatusCode int Request *http.Request Response *http.Response } -// errorJSON contains the JSON metadata for the struct [Error] -type errorJSON struct { - Code apijson.Field - Message apijson.Field - Param apijson.Field - Type apijson.Field - raw string - ExtraFields map[string]apijson.Field -} - -func (r *Error) UnmarshalJSON(data []byte) (err error) { +// Returns the unmodified JSON received from the API +func (r Error) RawJSON() string { return r.JSON.raw } +func (r *Error) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (r errorJSON) RawJSON() string { - return r.raw -} - func (r *Error) Error() string { // Attempt to re-populate the response body - return fmt.Sprintf("%s \"%s\": %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.RawJSON()) + return fmt.Sprintf("%s %q: %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.raw) } func (r *Error) DumpRequest(body bool) []byte { diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go index 148fcb5b..50a63f3d 100644 --- a/internal/apiform/encoder.go +++ b/internal/apiform/encoder.go @@ -13,7 +13,8 @@ import ( "sync" "time" - "github.com/openai/openai-go/internal/param" + internalparam "github.com/openai/openai-go/internal/param" + "github.com/openai/openai-go/packages/param" ) var encoders sync.Map // map[encoderEntry]encoderFunc @@ -180,10 +181,14 @@ func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc { } func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { - if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) { + if t.Implements(reflect.TypeOf((*internalparam.FieldLike)(nil)).Elem()) { return e.newFieldTypeEncoder(t) } + if idx, ok := param.OptionalPrimitiveTypes[t]; ok { + return e.newRichFieldTypeEncoder(t, idx) + } + encoderFields := []encoderField{} extraEncoder := (*encoderField)(nil) @@ -217,7 +222,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx} continue } - if ptag.name == "-" { + if ptag.name == "-" || ptag.name == "" { continue } @@ -231,7 +236,20 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { e.dateFormat = "2006-01-02" } } - encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx}) + + var encoderFn encoderFunc + if ptag.omitzero { + typeEncoderFn := e.typeEncoder(field.Type) + encoderFn = func(key string, value reflect.Value, writer *multipart.Writer) error { + if value.IsZero() { + return nil + } + return typeEncoderFn(key, value, writer) + } + } else { + encoderFn = e.typeEncoder(field.Type) + } + encoderFields = append(encoderFields, encoderField{ptag, encoderFn, idx}) e.dateFormat = oldFormat } } diff --git a/internal/apiform/richparam.go b/internal/apiform/richparam.go new file mode 100644 index 00000000..4a9c5347 --- /dev/null +++ b/internal/apiform/richparam.go @@ -0,0 +1,20 @@ +package apiform + +import ( + "github.com/openai/openai-go/packages/param" + "mime/multipart" + "reflect" +) + +func (e *encoder) newRichFieldTypeEncoder(t reflect.Type, underlyingValueIdx []int) encoderFunc { + underlying := t.FieldByIndex(underlyingValueIdx) + primitiveEncoder := e.newPrimitiveTypeEncoder(underlying.Type) + return func(key string, value reflect.Value, writer *multipart.Writer) error { + if opt, ok := value.Interface().(param.Optional); ok && opt.IsPresent() { + return primitiveEncoder(key, value.FieldByIndex(underlyingValueIdx), writer) + } else if ok && opt.IsNull() { + return writer.WriteField(key, "null") + } + return nil + } +} diff --git a/internal/apiform/tag.go b/internal/apiform/tag.go index b22e054f..736fc1ea 100644 --- a/internal/apiform/tag.go +++ b/internal/apiform/tag.go @@ -14,6 +14,7 @@ type parsedStructTag struct { required bool extras bool metadata bool + omitzero bool } func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) { @@ -37,6 +38,8 @@ func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool tag.extras = true case "metadata": tag.metadata = true + case "omitzero": + tag.omitzero = true } } return diff --git a/internal/apijson/decoder.go b/internal/apijson/decoder.go index 68b7ed6b..b3bd8327 100644 --- a/internal/apijson/decoder.go +++ b/internal/apijson/decoder.go @@ -173,6 +173,9 @@ func (d *decoderBuilder) newTypeDecoder(t reflect.Type) decoderFunc { return nil } case reflect.Struct: + if isEmbeddedUnion(t) { + return d.newEmbeddedUnionDecoder(t) + } return d.newStructTypeDecoder(t) case reflect.Array: fallthrough @@ -343,7 +346,7 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { decoderFields := map[string]decoderField{} anonymousDecoders := []decoderField{} extraDecoder := (*decoderField)(nil) - inlineDecoder := (*decoderField)(nil) + var inlineDecoders []decoderField for i := 0; i < t.NumField(); i++ { idx := []int{i} @@ -373,7 +376,8 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { continue } if ptag.inline { - inlineDecoder = &decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name} + df := decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name} + inlineDecoders = append(inlineDecoders, df) continue } if ptag.metadata { @@ -406,12 +410,13 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { decoder.fn(node, value.FieldByIndex(decoder.idx), state) } - if inlineDecoder != nil { + for _, inlineDecoder := range inlineDecoders { var meta Field dest := value.FieldByIndex(inlineDecoder.idx) isValid := false if dest.IsValid() && node.Type != gjson.Null { - err = inlineDecoder.fn(node, dest, state) + inlineState := decoderState{exactness: state.exactness, strict: true} + err = inlineDecoder.fn(node, dest, &inlineState) if err == nil { isValid = true } @@ -423,20 +428,18 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { status: null, } } else if !isValid { - meta = Field{ - raw: node.Raw, - status: invalid, + // If an inline decoder fails, unset the field and move on. + if dest.IsValid() { + dest.SetZero() } + continue } else if isValid { meta = Field{ raw: node.Raw, status: valid, } } - if metadata := getSubField(value, inlineDecoder.idx, inlineDecoder.goname); metadata.IsValid() { - metadata.Set(reflect.ValueOf(meta)) - } - return err + setMetadataSubField(value, inlineDecoder.idx, inlineDecoder.goname, meta) } typedExtraType := reflect.Type(nil) @@ -489,9 +492,7 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { } if explicit { - if metadata := getSubField(value, df.idx, df.goname); metadata.IsValid() { - metadata.Set(reflect.ValueOf(meta)) - } + setMetadataSubField(value, df.idx, df.goname, meta) } if !explicit { untypedExtraFields[fieldName] = meta @@ -510,8 +511,8 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc { state.exactness = extras } - if metadata := getSubField(value, []int{-1}, "ExtraFields"); metadata.IsValid() && len(untypedExtraFields) > 0 { - metadata.Set(reflect.ValueOf(untypedExtraFields)) + if len(untypedExtraFields) > 0 { + setMetadataExtraFields(value, []int{-1}, "ExtraFields", untypedExtraFields) } return nil } @@ -662,9 +663,17 @@ func canParseAsNumber(str string) bool { return err == nil } +var stringType = reflect.TypeOf(string("")) + func guardUnknown(state *decoderState, v reflect.Value) bool { if have, ok := v.Interface().(interface{ IsKnown() bool }); guardStrict(state, ok && !have.IsKnown()) { return true } + + constantString, ok := v.Interface().(interface{ Default() string }) + named := v.Type() != stringType + if guardStrict(state, ok && named && v.Equal(reflect.ValueOf(constantString.Default()))) { + return true + } return false } diff --git a/internal/apijson/encoder.go b/internal/apijson/encoder.go index 71b3f4ec..79bc698a 100644 --- a/internal/apijson/encoder.go +++ b/internal/apijson/encoder.go @@ -381,7 +381,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error) return json, nil } -func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc { +func (e *encoder) newMapEncoder(_ reflect.Type) encoderFunc { return func(value reflect.Value) ([]byte, error) { json := []byte("{}") var err error diff --git a/internal/apijson/enum.go b/internal/apijson/enum.go new file mode 100644 index 00000000..ec98f8ca --- /dev/null +++ b/internal/apijson/enum.go @@ -0,0 +1,87 @@ +package apijson + +import ( + "fmt" + "reflect" + "sync" +) + +/********************/ +/* Validating Enums */ +/********************/ + +type validationEntry struct { + field reflect.StructField + nullable bool + legalValues []reflect.Value +} + +type validatorFunc func(reflect.Value) exactness + +var validators sync.Map +var validationRegistry = map[reflect.Type][]validationEntry{} + +func RegisterFieldValidator[T any, V string | bool | int](fieldName string, nullable bool, values ...V) { + var t T + parentType := reflect.TypeOf(t) + + if _, ok := validationRegistry[parentType]; !ok { + validationRegistry[parentType] = []validationEntry{} + } + + // The following checks run at initialization time, + // it is impossible for them to panic if any tests pass. + if parentType.Kind() != reflect.Struct { + panic(fmt.Sprintf("apijson: cannot initialize validator for non-struct %s", parentType.String())) + } + field, found := parentType.FieldByName(fieldName) + if !found { + panic(fmt.Sprintf("apijson: cannot initialize validator for unknown field %q in %s", fieldName, parentType.String())) + } + + newEntry := validationEntry{field, nullable, make([]reflect.Value, len(values))} + for i, value := range values { + newEntry.legalValues[i] = reflect.ValueOf(value) + } + + // Store the information necessary to create a validator, so that we can use it + // lazily create the validator function when did. + validationRegistry[parentType] = append(validationRegistry[parentType], newEntry) +} + +// Enums are the only types which are validated +func typeValidator(t reflect.Type) validatorFunc { + entry, ok := validationRegistry[t] + if !ok { + return nil + } + + if fi, ok := validators.Load(t); ok { + return fi.(validatorFunc) + } + + fi, _ := validators.LoadOrStore(t, validatorFunc(func(v reflect.Value) exactness { + return validateEnum(v, entry) + })) + return fi.(validatorFunc) +} + +func validateEnum(v reflect.Value, entry []validationEntry) exactness { + if v.Kind() != reflect.Struct { + return loose + } + + for _, check := range entry { + field := v.FieldByIndex(check.field.Index) + if !field.IsValid() { + return loose + } + for _, opt := range check.legalValues { + if field.Equal(opt) { + return exact + } + } + } + + return loose +} diff --git a/internal/apijson/field.go b/internal/apijson/field.go index 3ef207c5..854d6dd7 100644 --- a/internal/apijson/field.go +++ b/internal/apijson/field.go @@ -1,7 +1,5 @@ package apijson -import "reflect" - type status uint8 const ( @@ -23,19 +21,3 @@ func (j Field) IsNull() bool { return j.status <= null } func (j Field) IsMissing() bool { return j.status == missing } func (j Field) IsInvalid() bool { return j.status == invalid } func (j Field) Raw() string { return j.raw } - -func getSubField(root reflect.Value, index []int, name string) reflect.Value { - strct := root.FieldByIndex(index[:len(index)-1]) - if !strct.IsValid() { - panic("couldn't find encapsulating struct for field " + name) - } - meta := strct.FieldByName("JSON") - if !meta.IsValid() { - return reflect.Value{} - } - field := meta.FieldByName(name) - if !field.IsValid() { - return reflect.Value{} - } - return field -} diff --git a/internal/apijson/json_test.go b/internal/apijson/json_test.go index e6563448..0c4de119 100644 --- a/internal/apijson/json_test.go +++ b/internal/apijson/json_test.go @@ -86,8 +86,8 @@ type JSONFieldStruct struct { B int64 `json:"b"` C string `json:"c"` D string `json:"d"` - ExtraFields map[string]int64 `json:"-,extras"` - JSON JSONFieldStructJSON `json:"-,metadata"` + ExtraFields map[string]int64 `json:",extras"` + JSON JSONFieldStructJSON `json:",metadata"` } type JSONFieldStructJSON struct { @@ -112,13 +112,13 @@ type Union interface { } type Inline struct { - InlineField Primitives `json:"-,inline"` - JSON InlineJSON `json:"-,metadata"` + InlineField Primitives `json:",inline"` + JSON InlineJSON `json:",metadata"` } type InlineArray struct { - InlineField []string `json:"-,inline"` - JSON InlineJSON `json:"-,metadata"` + InlineField []string `json:",inline"` + JSON InlineJSON `json:",metadata"` } type InlineJSON struct { @@ -150,7 +150,7 @@ type UnionTime time.Time func (UnionTime) union() {} func init() { - RegisterUnion(reflect.TypeOf((*Union)(nil)).Elem(), "type", + RegisterUnion[Union]("type", UnionVariant{ TypeFilter: gjson.String, Type: reflect.TypeOf(UnionTime{}), @@ -237,7 +237,7 @@ func (r *UnmarshalStruct) UnmarshalJSON(json []byte) error { func (ComplexUnionTypeB) complexUnion() {} func init() { - RegisterUnion(reflect.TypeOf((*ComplexUnion)(nil)).Elem(), "", + RegisterUnion[ComplexUnion]("", UnionVariant{ TypeFilter: gjson.JSON, Type: reflect.TypeOf(ComplexUnionA{}), @@ -300,8 +300,7 @@ func (r *MarshallingUnionB) UnmarshalJSON(data []byte) (err error) { } func init() { - RegisterUnion( - reflect.TypeOf((*MarshallingUnion)(nil)).Elem(), + RegisterUnion[MarshallingUnion]( "", UnionVariant{ TypeFilter: gjson.JSON, diff --git a/internal/apijson/port.go b/internal/apijson/port.go index 502ab778..b40013c1 100644 --- a/internal/apijson/port.go +++ b/internal/apijson/port.go @@ -53,7 +53,7 @@ func Port(from any, to any) error { for i := 0; i < t.NumField(); i++ { field := t.Field(i) ptag, ok := parseJSONStructTag(field) - if !ok || ptag.name == "-" { + if !ok || ptag.name == "-" || ptag.name == "" { continue } values[ptag.name] = v.Field(i) diff --git a/internal/apijson/registry.go b/internal/apijson/registry.go index 119cc5ff..e82c1d50 100644 --- a/internal/apijson/registry.go +++ b/internal/apijson/registry.go @@ -20,7 +20,8 @@ type unionEntry struct { variants []UnionVariant } -func RegisterUnion(typ reflect.Type, discriminator string, variants ...UnionVariant) { +func RegisterUnion[T any](discriminator string, variants ...UnionVariant) { + typ := reflect.TypeOf((*T)(nil)).Elem() unionRegistry[typ] = unionEntry{ discriminatorKey: discriminator, variants: variants, diff --git a/internal/apijson/subfield.go b/internal/apijson/subfield.go new file mode 100644 index 00000000..6f9e2bdb --- /dev/null +++ b/internal/apijson/subfield.go @@ -0,0 +1,67 @@ +package apijson + +import ( + "github.com/openai/openai-go/packages/resp" + "reflect" +) + +func getSubField(root reflect.Value, index []int, name string) reflect.Value { + strct := root.FieldByIndex(index[:len(index)-1]) + if !strct.IsValid() { + panic("couldn't find encapsulating struct for field " + name) + } + meta := strct.FieldByName("JSON") + if !meta.IsValid() { + return reflect.Value{} + } + field := meta.FieldByName(name) + if !field.IsValid() { + return reflect.Value{} + } + return field +} + +func setMetadataSubField(root reflect.Value, index []int, name string, meta Field) { + target := getSubField(root, index, name) + if !target.IsValid() { + return + } + + if target.Type() == reflect.TypeOf(meta) { + target.Set(reflect.ValueOf(meta)) + } else if respMeta := meta.toRespField(); target.Type() == reflect.TypeOf(respMeta) { + target.Set(reflect.ValueOf(respMeta)) + } +} + +func setMetadataExtraFields(root reflect.Value, index []int, name string, metaExtras map[string]Field) { + target := getSubField(root, index, name) + if !target.IsValid() { + return + } + + if target.Type() == reflect.TypeOf(metaExtras) { + target.Set(reflect.ValueOf(metaExtras)) + return + } + + newMap := make(map[string]resp.Field, len(metaExtras)) + if target.Type() == reflect.TypeOf(newMap) { + for k, v := range metaExtras { + newMap[k] = v.toRespField() + } + target.Set(reflect.ValueOf(newMap)) + } +} + +func (f Field) toRespField() resp.Field { + if f.IsNull() { + return resp.NewNullField() + } else if f.IsMissing() { + return resp.Field{} + } else if f.IsInvalid() { + return resp.NewInvalidField(f.raw) + } else { + return resp.NewValidField(f.raw) + } +} diff --git a/internal/apijson/union.go b/internal/apijson/union.go new file mode 100644 index 00000000..2ff01190 --- /dev/null +++ b/internal/apijson/union.go @@ -0,0 +1,101 @@ +package apijson + +import ( + "errors" + "github.com/openai/openai-go/packages/param" + "reflect" + + "github.com/tidwall/gjson" +) + +func isEmbeddedUnion(t reflect.Type) bool { + var apiunion param.APIUnion + for i := 0; i < t.NumField(); i++ { + if t.Field(i).Type == reflect.TypeOf(apiunion) && t.Field(i).Anonymous { + return true + } + } + return false +} + +func RegisterDiscriminatedUnion[T any](key string, mappings map[string]reflect.Type) { + var t T + entry := unionEntry{ + discriminatorKey: key, + variants: []UnionVariant{}, + } + for k, typ := range mappings { + entry.variants = append(entry.variants, UnionVariant{ + DiscriminatorValue: k, + Type: typ, + }) + } + unionRegistry[reflect.TypeOf(t)] = entry +} + +func (d *decoderBuilder) newEmbeddedUnionDecoder(t reflect.Type) decoderFunc { + decoders := []decoderFunc{} + + for i := 0; i < t.NumField(); i++ { + variant := t.Field(i) + decoder := d.typeDecoder(variant.Type) + decoders = append(decoders, decoder) + } + + unionEntry := unionEntry{ + variants: []UnionVariant{}, + } + + return func(n gjson.Result, v reflect.Value, state *decoderState) error { + // If there is a discriminator match, circumvent the exactness logic entirely + for idx, variant := range unionEntry.variants { + decoder := decoders[idx] + if variant.TypeFilter != n.Type { + continue + } + + if len(unionEntry.discriminatorKey) != 0 { + discriminatorValue := n.Get(unionEntry.discriminatorKey).Value() + if discriminatorValue == variant.DiscriminatorValue { + inner := reflect.New(variant.Type).Elem() + err := decoder(n, inner, state) + v.Set(inner) + return err + } + } + } + + // Set bestExactness to worse than loose + bestExactness := loose - 1 + for idx, variant := range unionEntry.variants { + decoder := decoders[idx] + if variant.TypeFilter != n.Type { + continue + } + sub := decoderState{strict: state.strict, exactness: exact} + inner := reflect.New(variant.Type).Elem() + err := decoder(n, inner, &sub) + if err != nil { + continue + } + if sub.exactness == exact { + v.Set(inner) + return nil + } + if sub.exactness > bestExactness { + v.Set(inner) + bestExactness = sub.exactness + } + } + + if bestExactness < loose { + return errors.New("apijson: was not able to coerce type as union") + } + + if guardStrict(state, bestExactness != exact) { + return errors.New("apijson: was not able to coerce type as union strictly") + } + + return nil + } +} diff --git a/internal/apiquery/encoder.go b/internal/apiquery/encoder.go index ed8c4a29..806cfc52 100644 --- a/internal/apiquery/encoder.go +++ b/internal/apiquery/encoder.go @@ -9,7 +9,8 @@ import ( "sync" "time" - "github.com/openai/openai-go/internal/param" + internalparam "github.com/openai/openai-go/internal/param" + "github.com/openai/openai-go/packages/param" ) var encoders sync.Map // map[reflect.Type]encoderFunc @@ -85,7 +86,8 @@ func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc { if t.ConvertibleTo(reflect.TypeOf(time.Time{})) { return e.newTimeTypeEncoder(t) } - if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) { + + if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) && param.OptionalPrimitiveTypes[t] == nil { return marshalerEncoder } e.root = false @@ -115,10 +117,14 @@ func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc { } func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { - if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) { + if t.Implements(reflect.TypeOf((*internalparam.FieldLike)(nil)).Elem()) { return e.newFieldTypeEncoder(t) } + if idx, ok := param.OptionalPrimitiveTypes[t]; ok { + return e.newRichFieldTypeEncoder(t, idx) + } + encoderFields := []encoderField{} // This helper allows us to recursively collect field encoders into a flat @@ -145,7 +151,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { continue } - if ptag.name == "-" && !ptag.inline { + if (ptag.name == "-" || ptag.name == "") && !ptag.inline { continue } @@ -159,7 +165,19 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { e.dateFormat = "2006-01-02" } } - encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx}) + var encoderFn encoderFunc + if ptag.omitzero { + typeEncoderFn := e.typeEncoder(field.Type) + encoderFn = func(key string, value reflect.Value) []Pair { + if value.IsZero() { + return nil + } + return typeEncoderFn(key, value) + } + } else { + encoderFn = e.typeEncoder(field.Type) + } + encoderFields = append(encoderFields, encoderField{ptag, encoderFn, idx}) e.dateFormat = oldFormat } } diff --git a/internal/apiquery/query_test.go b/internal/apiquery/query_test.go index 1e740d6a..5718d4a6 100644 --- a/internal/apiquery/query_test.go +++ b/internal/apiquery/query_test.go @@ -4,6 +4,8 @@ import ( "net/url" "testing" "time" + + "github.com/openai/openai-go/packages/param" ) func P[T any](v T) *T { return &v } @@ -101,6 +103,15 @@ type DeeplyNested3 struct { D *string `query:"d"` } +type RichPrimitives struct { + A param.Opt[string] `query:"a"` +} + +type QueryOmitTest struct { + A param.Opt[string] `query:"a,omitzero"` + B string `query:"b,omitzero"` +} + var tests = map[string]struct { enc string val interface{} @@ -320,6 +331,29 @@ var tests = map[string]struct { }, QuerySettings{NestedFormat: NestedQueryFormatDots}, }, + + "rich_primitives": { + `a=hello`, + RichPrimitives{ + A: param.Opt[string]{Value: "hello"}, + }, + QuerySettings{}, + }, + + "rich_primitives_omit": { + ``, + QueryOmitTest{ + A: param.Opt[string]{}, + }, + QuerySettings{}, + }, + "query_omit": { + `a=hello`, + QueryOmitTest{ + A: param.Opt[string]{Value: "hello"}, + }, + QuerySettings{}, + }, } func TestEncode(t *testing.T) { diff --git a/internal/apiquery/richparam.go b/internal/apiquery/richparam.go new file mode 100644 index 00000000..36d23bb9 --- /dev/null +++ b/internal/apiquery/richparam.go @@ -0,0 +1,20 @@ +package apiquery + +import ( + "reflect" + + "github.com/openai/openai-go/packages/param" +) + +func (e *encoder) newRichFieldTypeEncoder(t reflect.Type, underlyingValueIdx []int) encoderFunc { + underlying := t.FieldByIndex(underlyingValueIdx) + primitiveEncoder := e.newPrimitiveTypeEncoder(underlying.Type) + return func(key string, value reflect.Value) []Pair { + if fielder, ok := value.Interface().(param.Optional); ok && fielder.IsPresent() { + return primitiveEncoder(key, value.FieldByIndex(underlyingValueIdx)) + } else if ok && fielder.IsNull() { + return []Pair{{key, "null"}} + } + return nil + } +} diff --git a/internal/apiquery/tag.go b/internal/apiquery/tag.go index 7ccd739c..772c40e1 100644 --- a/internal/apiquery/tag.go +++ b/internal/apiquery/tag.go @@ -11,6 +11,7 @@ const formatStructTag = "format" type parsedStructTag struct { name string omitempty bool + omitzero bool inline bool } @@ -26,6 +27,8 @@ func parseQueryStructTag(field reflect.StructField) (tag parsedStructTag, ok boo tag.name = parts[0] for _, part := range parts[1:] { switch part { + case "omitzero": + tag.omitzero = true case "omitempty": tag.omitempty = true case "inline": diff --git a/internal/encoding/json/decode.go b/internal/encoding/json/decode.go new file mode 100644 index 00000000..93214331 --- /dev/null +++ b/internal/encoding/json/decode.go @@ -0,0 +1,1324 @@ +// Vendored from Go 1.24.0-pre-release +// To find alterations, check package shims, and comments beginning in SHIM(). +// +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "encoding" + "encoding/base64" + "fmt" + "github.com/openai/openai-go/internal/encoding/json/shims" + "reflect" + "strconv" + "strings" + "unicode" + "unicode/utf16" + "unicode/utf8" + _ "unsafe" // for linkname +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. If v is nil or not a pointer, +// Unmarshal returns an [InvalidUnmarshalError]. +// +// Unmarshal uses the inverse of the encodings that +// [Marshal] uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a value implementing [Unmarshaler], +// Unmarshal calls that value's [Unmarshaler.UnmarshalJSON] method, including +// when the input is a JSON null. +// Otherwise, if the value implements [encoding.TextUnmarshaler] +// and the input is a JSON quoted string, Unmarshal calls +// [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by [Marshal] (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. By +// default, object keys which don't have a corresponding struct field are +// ignored (see [Decoder.DisallowUnknownFields] for an alternative). +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// - bool, for JSON booleans +// - float64, for JSON numbers +// - string, for JSON strings +// - []any, for JSON arrays +// - map[string]any, for JSON objects +// - nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a map, Unmarshal first establishes a map to +// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal +// reuses the existing map, keeping existing entries. Unmarshal then stores +// key-value pairs from the JSON object into the map. The map's key type must +// either be any string type, an integer, or implement [encoding.TextUnmarshaler]. +// +// If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError]. +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshaling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an [UnmarshalTypeError] describing the earliest such error. In any +// case, it's not guaranteed that all the remaining fields following +// the problematic one will be unmarshaled into the target object. +// +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// “not present,” unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +func Unmarshal(data []byte, v any) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + var d decodeState + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + d.init(data) + return d.unmarshal(v) +} + +// Unmarshaler is the interface implemented by types +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +// +// By convention, to approximate the behavior of [Unmarshal] itself, +// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes + Struct string // name of the struct type containing the field + Field string // the full path from root node to the field, include embedded struct +} + +func (e *UnmarshalTypeError) Error() string { + if e.Struct != "" || e.Field != "" { + return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() + } + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal]. +// (The argument to [Unmarshal] must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Pointer { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v any) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Pointer || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + d.scanWhile(scanSkipSpace) + // We decode rv not rv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + err := d.value(rv) + if err != nil { + return d.addErrorContext(err) + } + return d.savedError +} + +// A Number represents a JSON number literal. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// An errorContext provides context for type errors during decoding. +type errorContext struct { + Struct reflect.Type + FieldStack []string +} + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // next read offset in data + opcode int // last read result + scan scanner + errorContext *errorContext + savedError error + useNumber bool + disallowUnknownFields bool +} + +// readIndex returns the position of the last byte read. +func (d *decodeState) readIndex() int { + return d.off - 1 +} + +// phasePanicMsg is used as a panic message when we end up with something that +// shouldn't happen. It can indicate a bug in the JSON decoder, or that +// something is editing the data slice while the decoder executes. +const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?" + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + if d.errorContext != nil { + d.errorContext.Struct = nil + // Reuse the allocated space for the FieldStack slice. + d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + } + return d +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = d.addErrorContext(err) + } +} + +// addErrorContext returns a new error enhanced with information from d.errorContext +func (d *decodeState) addErrorContext(err error) error { + if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { + switch err := err.(type) { + case *UnmarshalTypeError: + err.Struct = d.errorContext.Struct.Name() + fieldStack := d.errorContext.FieldStack + if err.Field != "" { + fieldStack = append(fieldStack, err.Field) + } + err.Field = strings.Join(fieldStack, ".") + } + } + return err +} + +// skip scans to the end of what was started. +func (d *decodeState) skip() { + s, data, i := &d.scan, d.data, d.off + depth := len(s.parseState) + for { + op := s.step(s, data[i]) + i++ + if len(s.parseState) < depth { + d.off = i + d.opcode = op + return + } + } +} + +// scanNext processes the byte at d.data[d.off]. +func (d *decodeState) scanNext() { + if d.off < len(d.data) { + d.opcode = d.scan.step(&d.scan, d.data[d.off]) + d.off++ + } else { + d.opcode = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +func (d *decodeState) scanWhile(op int) { + s, data, i := &d.scan, d.data, d.off + for i < len(data) { + newOp := s.step(s, data[i]) + i++ + if newOp != op { + d.opcode = newOp + d.off = i + return + } + } + + d.off = len(data) + 1 // mark processed EOF with len+1 + d.opcode = d.scan.eof() +} + +// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the +// common case where we're decoding a literal. The decoder scans the input +// twice, once for syntax errors and to check the length of the value, and the +// second to perform the decoding. +// +// Only in the second step do we use decodeState to tokenize literals, so we +// know there aren't any syntax errors. We can take advantage of that knowledge, +// and scan a literal's bytes much more quickly. +func (d *decodeState) rescanLiteral() { + data, i := d.data, d.off +Switch: + switch data[i-1] { + case '"': // string + for ; i < len(data); i++ { + switch data[i] { + case '\\': + i++ // escaped char + case '"': + i++ // tokenize the closing quote too + break Switch + } + } + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number + for ; i < len(data); i++ { + switch data[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', 'e', 'E', '+', '-': + default: + break Switch + } + } + case 't': // true + i += len("rue") + case 'f': // false + i += len("alse") + case 'n': // null + i += len("ull") + } + if i < len(data) { + d.opcode = stateEndValue(&d.scan, data[i]) + } else { + d.opcode = scanEnd + } + d.off = i + 1 +} + +// value consumes a JSON value from d.data[d.off-1:], decoding into v, and +// reads the following byte ahead. If v is invalid, the value is discarded. +// The first byte of the value has been read already. +func (d *decodeState) value(v reflect.Value) error { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray: + if v.IsValid() { + if err := d.array(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginObject: + if v.IsValid() { + if err := d.object(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginLiteral: + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + if v.IsValid() { + if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { + return err + } + } + } + return nil +} + +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() any { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray, scanBeginObject: + d.skip() + d.scanNext() + + case scanBeginLiteral: + v := d.literalInterface() + switch v.(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// If it encounters an Unmarshaler, indirect stops and returns that. +// If decodingNull is true, indirect stops at the first settable pointer so it +// can be set to nil. +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // Issue #24153 indicates that it is generally not a guaranteed property + // that you may round-trip a reflect.Value by calling Value.Addr().Elem() + // and expect the value to still be settable for values derived from + // unexported embedded struct fields. + // + // The logic below effectively does this when it first addresses the value + // (to satisfy possible pointer methods) and continues to dereference + // subsequent pointers as necessary. + // + // After the first round-trip, we set v back to the original value to + // preserve the original RW flags contained in reflect.Value. + v0 := v + haveAddr := false + + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() { + haveAddr = true + v = v.Addr() + } + for { + // Load value from interface, but only if the result will be + // usefully addressable. + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) { + haveAddr = false + v = e + continue + } + } + + if v.Kind() != reflect.Pointer { + break + } + + if decodingNull && v.CanSet() { + break + } + + // Prevent infinite loop if v is an interface pointing to its own address: + // var v any + // v = &v + if v.Elem().Kind() == reflect.Interface && v.Elem().Elem().Equal(v) { + v = v.Elem() + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 && v.CanInterface() { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, nil, reflect.Value{} + } + if !decodingNull { + if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return nil, u, reflect.Value{} + } + } + } + + if haveAddr { + v = v0 // restore original value after round-trip Value.Addr().Elem() + haveAddr = false + } else { + v = v.Elem() + } + } + return nil, nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into v. +// The first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + + // Check type of target. + switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + ai := d.arrayInterface() + v.Set(reflect.ValueOf(ai)) + return nil + } + // Otherwise it's invalid. + fallthrough + default: + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + case reflect.Array, reflect.Slice: + break + } + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + // Expand slice length, growing the slice if necessary. + if v.Kind() == reflect.Slice { + if i >= v.Cap() { + v.Grow(1) + } + if i >= v.Len() { + v.SetLen(i + 1) + } + } + + if i < v.Len() { + // Decode into element. + if err := d.value(v.Index(i)); err != nil { + return err + } + } else { + // Ran out of fixed array: skip. + if err := d.value(reflect.Value{}); err != nil { + return err + } + } + i++ + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + + if i < v.Len() { + if v.Kind() == reflect.Array { + for ; i < v.Len(); i++ { + v.Index(i).SetZero() // zero remainder of array + } + } else { + v.SetLen(i) // truncate the slice + } + } + if i == 0 && v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } + return nil +} + +var nullLiteral = []byte("null") + +// SHIM(reflect): reflect.TypeFor[T]() reflect.T +var textUnmarshalerType = shims.TypeFor[encoding.TextUnmarshaler]() + +// object consumes an object from d.data[d.off-1:], decoding into v. +// The first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + t := v.Type() + + // Decoding into nil interface? Switch to non-reflect code. + if v.Kind() == reflect.Interface && v.NumMethod() == 0 { + oi := d.objectInterface() + v.Set(reflect.ValueOf(oi)) + return nil + } + + var fields structFields + + // Check type of target: + // struct or + // map[T1]T2 where T1 is string, an integer type, + // or an encoding.TextUnmarshaler + switch v.Kind() { + case reflect.Map: + // Map key must either have string kind, have an integer kind, + // or be an encoding.TextUnmarshaler. + switch t.Key().Kind() { + case reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + default: + if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) { + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + fields = cachedTypeFields(t) + // ok + default: + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + + var mapElem reflect.Value + var origErrorContext errorContext + if d.errorContext != nil { + origErrorContext = *d.errorContext + } + + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquoteBytes(item) + if !ok { + panic(phasePanicMsg) + } + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if v.Kind() == reflect.Map { + elemType := t.Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.SetZero() + } + subv = mapElem + } else { + f := fields.byExactName[string(key)] + if f == nil { + f = fields.byFoldedName[string(foldName(key))] + } + if f != nil { + subv = v + destring = f.quoted + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + for i, ind := range f.index { + if subv.Kind() == reflect.Pointer { + if subv.IsNil() { + // If a struct embeds a pointer to an unexported type, + // it is not possible to set a newly allocated value + // since the field is unexported. + // + // See https://golang.org/issue/21357 + if !subv.CanSet() { + d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) + // Invalidate subv to ensure d.value(subv) skips over + // the JSON value without assigning it to subv. + subv = reflect.Value{} + destring = false + break + } + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + if i < len(f.index)-1 { + d.errorContext.FieldStack = append( + d.errorContext.FieldStack, + subv.Type().Field(ind).Name, + ) + } + subv = subv.Field(ind) + } + d.errorContext.Struct = t + d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) + } else if d.disallowUnknownFields { + d.saveError(fmt.Errorf("json: unknown field %q", key)) + } + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + if destring { + switch qv := d.valueQuoted().(type) { + case nil: + if err := d.literalStore(nullLiteral, subv, false); err != nil { + return err + } + case string: + if err := d.literalStore([]byte(qv), subv, true); err != nil { + return err + } + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) + } + } else { + if err := d.value(subv); err != nil { + return err + } + } + + // Write value back to map; + // if using struct, subv points into struct already. + if v.Kind() == reflect.Map { + kt := t.Key() + var kv reflect.Value + if reflect.PointerTo(kt).Implements(textUnmarshalerType) { + kv = reflect.New(kt) + if err := d.literalStore(item, kv, true); err != nil { + return err + } + kv = kv.Elem() + } else { + switch kt.Kind() { + case reflect.String: + kv = reflect.New(kt).Elem() + kv.SetString(string(key)) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + s := string(key) + n, err := strconv.ParseInt(s, 10, 64) + // SHIM(reflect): reflect.Type.OverflowInt(int64) bool + okt := shims.OverflowableType{Type: kt} + if err != nil || okt.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.New(kt).Elem() + kv.SetInt(n) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + s := string(key) + n, err := strconv.ParseUint(s, 10, 64) + // SHIM(reflect): reflect.Type.OverflowUint(uint64) bool + okt := shims.OverflowableType{Type: kt} + if err != nil || okt.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.New(kt).Elem() + kv.SetUint(n) + default: + panic("json: Unexpected key type") // should never occur + } + } + if kv.IsValid() { + v.SetMapIndex(kv, subv) + } + } + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.errorContext != nil { + // Reset errorContext to its original state. + // Keep the same underlying array for FieldStack, to reuse the + // space and avoid unnecessary allocs. + d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] + d.errorContext.Struct = origErrorContext.Struct + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return nil +} + +// convertNumber converts the number literal s to a float64 or a Number +// depending on the setting of d.useNumber. +func (d *decodeState) convertNumber(s string) (any, error) { + if d.useNumber { + return Number(s), nil + } + f, err := strconv.ParseFloat(s, 64) + if err != nil { + // SHIM(reflect): reflect.TypeFor[T]() reflect.Type + return nil, &UnmarshalTypeError{Value: "number " + s, Type: shims.TypeFor[float64](), Offset: int64(d.off)} + } + return f, nil +} + +// SHIM(reflect): TypeFor[T]() reflect.Type +var numberType = shims.TypeFor[Number]() + +// literalStore decodes a literal stored in item into v. +// +// fromQuoted indicates whether this literal came from unwrapping a +// string from the ",string" struct tag option. this is used only to +// produce more helpful error messages. +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { + // Check for unmarshaler. + if len(item) == 0 { + // Empty string given. + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + isNull := item[0] == 'n' // null + u, ut, pv := indirect(v, isNull) + if u != nil { + return u.UnmarshalJSON(item) + } + if ut != nil { + if item[0] != '"' { + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + val := "number" + switch item[0] { + case 'n': + val = "null" + case 't', 'f': + val = "bool" + } + d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) + return nil + } + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + return ut.UnmarshalText(s) + } + + v = pv + + switch c := item[0]; c { + case 'n': // null + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "null" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice: + v.SetZero() + // otherwise, ignore null for primitives/string + } + case 't', 'f': // true, false + value := item[0] == 't' + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "true" && string(item) != "false" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + default: + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Slice: + if v.Type().Elem().Kind() != reflect.Uint8 { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.SetBytes(b[:n]) + case reflect.String: + t := string(s) + if v.Type() == numberType && !isValidNumber(t) { + return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) + } + v.SetString(t) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + switch v.Kind() { + default: + if v.Kind() == reflect.String && v.Type() == numberType { + // s must be a valid number, because it's + // already been tokenized. + v.SetString(string(item)) + break + } + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Interface: + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + break + } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.ParseInt(string(item), 10, 64) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.ParseUint(string(item), 10, 64) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.ParseFloat(string(item), v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetFloat(n) + } + } + return nil +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns any. +func (d *decodeState) valueInterface() (val any) { + switch d.opcode { + default: + panic(phasePanicMsg) + case scanBeginArray: + val = d.arrayInterface() + d.scanNext() + case scanBeginObject: + val = d.objectInterface() + d.scanNext() + case scanBeginLiteral: + val = d.literalInterface() + } + return +} + +// arrayInterface is like array but returns []any. +func (d *decodeState) arrayInterface() []any { + var v = make([]any, 0) + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + return v +} + +// objectInterface is like object but returns map[string]any. +func (d *decodeState) objectInterface() map[string]any { + m := make(map[string]any) + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read string key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return m +} + +// literalInterface consumes and returns a literal from d.data[d.off-1:] and +// it reads the following byte ahead. The first byte of the literal has been +// read already (that's how the caller knows it's a literal). +func (d *decodeState) literalInterface() any { + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + item := d.data[start:d.readIndex()] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + panic(phasePanicMsg) + } + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + } + return n + } +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + var r rune + for _, c := range s[2:6] { + switch { + case '0' <= c && c <= '9': + c = c - '0' + case 'a' <= c && c <= 'f': + c = c - 'a' + 10 + case 'A' <= c && c <= 'F': + c = c - 'A' + 10 + default: + return -1 + } + r = r*16 + rune(c) + } + return r +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +// unquoteBytes should be an internal detail, +// but widely used packages access it using linkname. +// Notable members of the hall of shame include: +// - github.com/bytedance/sonic +// +// Do not remove or change the type signature. +// See go.dev/issue/67401. +// +//go:linkname unquoteBytes +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/internal/encoding/json/encode.go b/internal/encoding/json/encode.go new file mode 100644 index 00000000..ce65c22a --- /dev/null +++ b/internal/encoding/json/encode.go @@ -0,0 +1,1398 @@ +// Vendored from Go 1.24.0-pre-release +// To find alterations, check package shims, and comments beginning in SHIM(). +// +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package json implements encoding and decoding of JSON as defined in +// RFC 7159. The mapping between JSON and Go values is described +// in the documentation for the Marshal and Unmarshal functions. +// +// See "JSON and Go" for an introduction to this package: +// https://golang.org/doc/articles/json_and_go.html +package json + +import ( + "bytes" + "cmp" + "encoding" + "encoding/base64" + "fmt" + "github.com/openai/openai-go/internal/encoding/json/sentinel" + "github.com/openai/openai-go/internal/encoding/json/shims" + "math" + "reflect" + "slices" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" + _ "unsafe" // for linkname +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements [Marshaler] +// and is not a nil pointer, Marshal calls [Marshaler.MarshalJSON] +// to produce JSON. If no [Marshaler.MarshalJSON] method is present but the +// value implements [encoding.TextMarshaler] instead, Marshal calls +// [encoding.TextMarshaler.MarshalText] and encodes the result as a JSON string. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// [Unmarshaler.UnmarshalJSON]. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and [Number] values encode as JSON numbers. +// NaN and +/-Inf values will return an [UnsupportedValueError]. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// So that the JSON will be safe to embed inside HTML