@planet-matrix/mobius-model 0.5.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (379) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +123 -36
  3. package/dist/index.js +715 -4
  4. package/dist/index.js.map +981 -13
  5. package/oxlint.config.ts +6 -0
  6. package/package.json +36 -18
  7. package/src/abort/README.md +92 -0
  8. package/src/abort/abort-manager.ts +278 -0
  9. package/src/abort/abort-signal-listener-manager.ts +81 -0
  10. package/src/abort/index.ts +2 -0
  11. package/src/ai/README.md +1 -0
  12. package/src/ai/ai.ts +107 -0
  13. package/src/ai/chat-completion-ai/aihubmix-chat-completion.ts +78 -0
  14. package/src/ai/chat-completion-ai/chat-completion-ai.ts +270 -0
  15. package/src/ai/chat-completion-ai/chat-completion.ts +189 -0
  16. package/src/ai/chat-completion-ai/index.ts +7 -0
  17. package/src/ai/chat-completion-ai/lingyiwanwu-chat-completion.ts +78 -0
  18. package/src/ai/chat-completion-ai/ohmygpt-chat-completion.ts +78 -0
  19. package/src/ai/chat-completion-ai/openai-next-chat-completion.ts +78 -0
  20. package/src/ai/embedding-ai/embedding-ai.ts +63 -0
  21. package/src/ai/embedding-ai/embedding.ts +50 -0
  22. package/src/ai/embedding-ai/index.ts +4 -0
  23. package/src/ai/embedding-ai/openai-next-embedding.ts +23 -0
  24. package/src/ai/index.ts +4 -0
  25. package/src/aio/README.md +100 -0
  26. package/src/aio/content.ts +141 -0
  27. package/src/aio/index.ts +3 -0
  28. package/src/aio/json.ts +127 -0
  29. package/src/aio/prompt.ts +246 -0
  30. package/src/basic/README.md +72 -116
  31. package/src/basic/error.ts +19 -5
  32. package/src/basic/function.ts +83 -64
  33. package/src/basic/index.ts +1 -0
  34. package/src/basic/is.ts +152 -71
  35. package/src/basic/promise.ts +29 -8
  36. package/src/basic/schedule.ts +111 -0
  37. package/src/basic/stream.ts +135 -25
  38. package/src/basic/string.ts +2 -33
  39. package/src/color/README.md +105 -0
  40. package/src/color/index.ts +3 -0
  41. package/src/color/internal.ts +42 -0
  42. package/src/color/rgb/analyze.ts +236 -0
  43. package/src/color/rgb/construct.ts +130 -0
  44. package/src/color/rgb/convert.ts +227 -0
  45. package/src/color/rgb/derive.ts +303 -0
  46. package/src/color/rgb/index.ts +6 -0
  47. package/src/color/rgb/internal.ts +208 -0
  48. package/src/color/rgb/parse.ts +302 -0
  49. package/src/color/rgb/serialize.ts +144 -0
  50. package/src/color/types.ts +57 -0
  51. package/src/color/xyz/analyze.ts +80 -0
  52. package/src/color/xyz/construct.ts +19 -0
  53. package/src/color/xyz/convert.ts +71 -0
  54. package/src/color/xyz/index.ts +3 -0
  55. package/src/color/xyz/internal.ts +23 -0
  56. package/src/credential/README.md +107 -0
  57. package/src/credential/api-key.ts +158 -0
  58. package/src/credential/bearer.ts +73 -0
  59. package/src/credential/index.ts +4 -0
  60. package/src/credential/json-web-token.ts +96 -0
  61. package/src/credential/password.ts +170 -0
  62. package/src/cron/README.md +86 -0
  63. package/src/cron/cron.ts +87 -0
  64. package/src/cron/index.ts +1 -0
  65. package/src/css/README.md +93 -0
  66. package/src/css/class.ts +559 -0
  67. package/src/css/index.ts +1 -0
  68. package/src/drizzle/README.md +1 -0
  69. package/src/drizzle/drizzle.ts +1 -0
  70. package/src/drizzle/helper.ts +47 -0
  71. package/src/drizzle/index.ts +5 -0
  72. package/src/drizzle/infer.ts +52 -0
  73. package/src/drizzle/kysely.ts +8 -0
  74. package/src/drizzle/pagination.ts +200 -0
  75. package/src/email/README.md +1 -0
  76. package/src/email/index.ts +1 -0
  77. package/src/email/resend.ts +25 -0
  78. package/src/encoding/README.md +66 -79
  79. package/src/encoding/base64.ts +13 -4
  80. package/src/environment/README.md +97 -0
  81. package/src/environment/basic.ts +26 -0
  82. package/src/environment/device.ts +311 -0
  83. package/src/environment/feature.ts +285 -0
  84. package/src/environment/geo.ts +337 -0
  85. package/src/environment/index.ts +7 -0
  86. package/src/environment/runtime.ts +400 -0
  87. package/src/environment/snapshot.ts +60 -0
  88. package/src/environment/variable.ts +239 -0
  89. package/src/event/README.md +90 -0
  90. package/src/event/class-event-proxy.ts +229 -0
  91. package/src/event/common.ts +29 -0
  92. package/src/event/event-manager.ts +203 -0
  93. package/src/event/index.ts +4 -0
  94. package/src/event/instance-event-proxy.ts +187 -0
  95. package/src/event/internal.ts +24 -0
  96. package/src/exception/README.md +96 -0
  97. package/src/exception/browser.ts +219 -0
  98. package/src/exception/index.ts +4 -0
  99. package/src/exception/nodejs.ts +169 -0
  100. package/src/exception/normalize.ts +106 -0
  101. package/src/exception/types.ts +99 -0
  102. package/src/form/README.md +25 -0
  103. package/src/form/index.ts +1 -0
  104. package/src/form/inputor-controller/base.ts +874 -0
  105. package/src/form/inputor-controller/boolean.ts +39 -0
  106. package/src/form/inputor-controller/file.ts +39 -0
  107. package/src/form/inputor-controller/form.ts +181 -0
  108. package/src/form/inputor-controller/helper.ts +117 -0
  109. package/src/form/inputor-controller/index.ts +17 -0
  110. package/src/form/inputor-controller/multi-select.ts +99 -0
  111. package/src/form/inputor-controller/number.ts +116 -0
  112. package/src/form/inputor-controller/select.ts +109 -0
  113. package/src/form/inputor-controller/text.ts +82 -0
  114. package/src/http/READMD.md +1 -0
  115. package/src/http/api/api-core.ts +84 -0
  116. package/src/http/api/api-handler.ts +79 -0
  117. package/src/http/api/api-host.ts +47 -0
  118. package/src/http/api/api-result.ts +56 -0
  119. package/src/http/api/api-schema.ts +154 -0
  120. package/src/http/api/api-server.ts +130 -0
  121. package/src/http/api/api-test.ts +142 -0
  122. package/src/http/api/api-type.ts +37 -0
  123. package/src/http/api/api.ts +81 -0
  124. package/src/http/api/index.ts +11 -0
  125. package/src/http/api-adapter/api-core-node-http.ts +260 -0
  126. package/src/http/api-adapter/api-host-node-http.ts +156 -0
  127. package/src/http/api-adapter/api-result-arktype.ts +297 -0
  128. package/src/http/api-adapter/api-result-zod.ts +286 -0
  129. package/src/http/api-adapter/index.ts +5 -0
  130. package/src/http/bin/gen-api-list/gen-api-list.ts +126 -0
  131. package/src/http/bin/gen-api-list/index.ts +1 -0
  132. package/src/http/bin/gen-api-test/gen-api-test.ts +136 -0
  133. package/src/http/bin/gen-api-test/index.ts +1 -0
  134. package/src/http/bin/gen-api-type/calc-code.ts +25 -0
  135. package/src/http/bin/gen-api-type/gen-api-type.ts +127 -0
  136. package/src/http/bin/gen-api-type/index.ts +2 -0
  137. package/src/http/bin/index.ts +2 -0
  138. package/src/http/index.ts +3 -0
  139. package/src/huawei/README.md +1 -0
  140. package/src/huawei/index.ts +2 -0
  141. package/src/huawei/moderation/index.ts +1 -0
  142. package/src/huawei/moderation/moderation.ts +355 -0
  143. package/src/huawei/obs/esdk-obs-nodejs.d.ts +87 -0
  144. package/src/huawei/obs/index.ts +1 -0
  145. package/src/huawei/obs/obs.ts +42 -0
  146. package/src/identifier/README.md +92 -0
  147. package/src/identifier/id.ts +119 -0
  148. package/src/identifier/index.ts +2 -0
  149. package/src/identifier/uuid.ts +187 -0
  150. package/src/index.ts +33 -1
  151. package/src/json/README.md +92 -0
  152. package/src/json/index.ts +1 -0
  153. package/src/json/repair.ts +18 -0
  154. package/src/log/README.md +79 -0
  155. package/src/log/index.ts +5 -0
  156. package/src/log/log-emitter.ts +72 -0
  157. package/src/log/log-record.ts +10 -0
  158. package/src/log/log-scheduler.ts +74 -0
  159. package/src/log/log-type.ts +8 -0
  160. package/src/log/logger.ts +554 -0
  161. package/src/openai/README.md +1 -0
  162. package/src/openai/index.ts +1 -0
  163. package/src/openai/openai.ts +510 -0
  164. package/src/orchestration/README.md +91 -0
  165. package/src/orchestration/coordination/barrier.ts +214 -0
  166. package/src/orchestration/coordination/count-down-latch.ts +215 -0
  167. package/src/orchestration/coordination/errors.ts +98 -0
  168. package/src/orchestration/coordination/index.ts +16 -0
  169. package/src/orchestration/coordination/internal/wait-constraints.ts +95 -0
  170. package/src/orchestration/coordination/internal/wait-queue.ts +109 -0
  171. package/src/orchestration/coordination/keyed-lock.ts +168 -0
  172. package/src/orchestration/coordination/mutex.ts +257 -0
  173. package/src/orchestration/coordination/permit.ts +127 -0
  174. package/src/orchestration/coordination/read-write-lock.ts +444 -0
  175. package/src/orchestration/coordination/semaphore.ts +280 -0
  176. package/src/orchestration/dispatching/dispatcher.ts +83 -0
  177. package/src/orchestration/dispatching/index.ts +2 -0
  178. package/src/orchestration/dispatching/selector/base-selector.ts +39 -0
  179. package/src/orchestration/dispatching/selector/down-count-selector.ts +119 -0
  180. package/src/orchestration/dispatching/selector/index.ts +2 -0
  181. package/src/orchestration/index.ts +3 -0
  182. package/src/orchestration/scheduling/index.ts +2 -0
  183. package/src/orchestration/scheduling/scheduler.ts +103 -0
  184. package/src/orchestration/scheduling/task.ts +32 -0
  185. package/src/random/README.md +56 -86
  186. package/src/random/base.ts +66 -0
  187. package/src/random/index.ts +5 -1
  188. package/src/random/random-boolean.ts +40 -0
  189. package/src/random/random-integer.ts +60 -0
  190. package/src/random/random-number.ts +72 -0
  191. package/src/random/random-string.ts +66 -0
  192. package/src/reactor/README.md +4 -0
  193. package/src/reactor/reactor-core/primitive.ts +9 -9
  194. package/src/reactor/reactor-core/reactive-system.ts +5 -5
  195. package/src/request/README.md +108 -0
  196. package/src/request/fetch/base.ts +108 -0
  197. package/src/request/fetch/browser.ts +285 -0
  198. package/src/request/fetch/general.ts +20 -0
  199. package/src/request/fetch/index.ts +4 -0
  200. package/src/request/fetch/nodejs.ts +285 -0
  201. package/src/request/index.ts +2 -0
  202. package/src/request/request/base.ts +250 -0
  203. package/src/request/request/general.ts +64 -0
  204. package/src/request/request/index.ts +3 -0
  205. package/src/request/request/resource.ts +68 -0
  206. package/src/result/README.md +4 -0
  207. package/src/result/controller.ts +54 -0
  208. package/src/result/either.ts +193 -0
  209. package/src/result/index.ts +2 -0
  210. package/src/route/README.md +105 -0
  211. package/src/route/adapter/browser.ts +122 -0
  212. package/src/route/adapter/driver.ts +56 -0
  213. package/src/route/adapter/index.ts +2 -0
  214. package/src/route/index.ts +3 -0
  215. package/src/route/router/index.ts +2 -0
  216. package/src/route/router/route.ts +630 -0
  217. package/src/route/router/router.ts +1642 -0
  218. package/src/route/uri/hash.ts +308 -0
  219. package/src/route/uri/index.ts +7 -0
  220. package/src/route/uri/pathname.ts +376 -0
  221. package/src/route/uri/search.ts +413 -0
  222. package/src/singleton/README.md +79 -0
  223. package/src/singleton/factory.ts +55 -0
  224. package/src/singleton/index.ts +2 -0
  225. package/src/singleton/manager.ts +204 -0
  226. package/src/socket/README.md +105 -0
  227. package/src/socket/client/index.ts +2 -0
  228. package/src/socket/client/socket-unit.ts +660 -0
  229. package/src/socket/client/socket.ts +203 -0
  230. package/src/socket/common/index.ts +2 -0
  231. package/src/socket/common/socket-unit-common.ts +23 -0
  232. package/src/socket/common/socket-unit-heartbeat.ts +427 -0
  233. package/src/socket/index.ts +3 -0
  234. package/src/socket/server/index.ts +3 -0
  235. package/src/socket/server/server.ts +183 -0
  236. package/src/socket/server/socket-unit.ts +449 -0
  237. package/src/socket/server/socket.ts +264 -0
  238. package/src/storage/README.md +107 -0
  239. package/src/storage/index.ts +1 -0
  240. package/src/storage/table.ts +449 -0
  241. package/src/timer/README.md +86 -0
  242. package/src/timer/expiration/expiration-manager.ts +594 -0
  243. package/src/timer/expiration/index.ts +3 -0
  244. package/src/timer/expiration/min-heap.ts +208 -0
  245. package/src/timer/expiration/remaining-manager.ts +241 -0
  246. package/src/timer/index.ts +1 -0
  247. package/src/tube/README.md +99 -0
  248. package/src/tube/helper.ts +138 -0
  249. package/src/tube/index.ts +2 -0
  250. package/src/tube/tube.ts +880 -0
  251. package/src/type/README.md +54 -307
  252. package/src/type/class.ts +2 -2
  253. package/src/type/index.ts +14 -14
  254. package/src/type/is.ts +265 -2
  255. package/src/type/object.ts +37 -0
  256. package/src/type/string.ts +7 -2
  257. package/src/type/tuple.ts +6 -6
  258. package/src/type/union.ts +16 -0
  259. package/src/web/README.md +77 -0
  260. package/src/web/capture.ts +35 -0
  261. package/src/web/clipboard.ts +97 -0
  262. package/src/web/dom.ts +117 -0
  263. package/src/web/download.ts +16 -0
  264. package/src/web/event.ts +46 -0
  265. package/src/web/index.ts +10 -0
  266. package/src/web/local-storage.ts +113 -0
  267. package/src/web/location.ts +28 -0
  268. package/src/web/permission.ts +172 -0
  269. package/src/web/script-loader.ts +432 -0
  270. package/src/weixin/README.md +1 -0
  271. package/src/weixin/index.ts +2 -0
  272. package/src/weixin/official-account/authorization.ts +159 -0
  273. package/src/weixin/official-account/index.ts +2 -0
  274. package/src/weixin/official-account/js-api.ts +134 -0
  275. package/src/weixin/open/index.ts +1 -0
  276. package/src/weixin/open/oauth2.ts +133 -0
  277. package/tests/unit/abort/abort-manager.spec.ts +225 -0
  278. package/tests/unit/abort/abort-signal-listener-manager.spec.ts +62 -0
  279. package/tests/unit/ai/ai.spec.ts +85 -0
  280. package/tests/unit/aio/content.spec.ts +105 -0
  281. package/tests/unit/aio/json.spec.ts +147 -0
  282. package/tests/unit/aio/prompt.spec.ts +111 -0
  283. package/tests/unit/basic/array.spec.ts +1 -1
  284. package/tests/unit/basic/error.spec.ts +16 -4
  285. package/tests/unit/basic/schedule.spec.ts +74 -0
  286. package/tests/unit/basic/stream.spec.ts +91 -38
  287. package/tests/unit/basic/string.spec.ts +0 -9
  288. package/tests/unit/color/rgb/analyze.spec.ts +110 -0
  289. package/tests/unit/color/rgb/construct.spec.ts +56 -0
  290. package/tests/unit/color/rgb/convert.spec.ts +60 -0
  291. package/tests/unit/color/rgb/derive.spec.ts +103 -0
  292. package/tests/unit/color/rgb/parse.spec.ts +66 -0
  293. package/tests/unit/color/rgb/serialize.spec.ts +46 -0
  294. package/tests/unit/color/xyz/analyze.spec.ts +33 -0
  295. package/tests/unit/color/xyz/construct.spec.ts +10 -0
  296. package/tests/unit/color/xyz/convert.spec.ts +18 -0
  297. package/tests/unit/credential/api-key.spec.ts +37 -0
  298. package/tests/unit/credential/bearer.spec.ts +23 -0
  299. package/tests/unit/credential/json-web-token.spec.ts +23 -0
  300. package/tests/unit/credential/password.spec.ts +41 -0
  301. package/tests/unit/cron/cron.spec.ts +84 -0
  302. package/tests/unit/css/class.spec.ts +157 -0
  303. package/tests/unit/environment/basic.spec.ts +20 -0
  304. package/tests/unit/environment/device.spec.ts +146 -0
  305. package/tests/unit/environment/feature.spec.ts +388 -0
  306. package/tests/unit/environment/geo.spec.ts +111 -0
  307. package/tests/unit/environment/runtime.spec.ts +364 -0
  308. package/tests/unit/environment/snapshot.spec.ts +4 -0
  309. package/tests/unit/environment/variable.spec.ts +190 -0
  310. package/tests/unit/event/class-event-proxy.spec.ts +225 -0
  311. package/tests/unit/event/event-manager.spec.ts +246 -0
  312. package/tests/unit/event/instance-event-proxy.spec.ts +187 -0
  313. package/tests/unit/exception/browser.spec.ts +213 -0
  314. package/tests/unit/exception/nodejs.spec.ts +144 -0
  315. package/tests/unit/exception/normalize.spec.ts +57 -0
  316. package/tests/unit/form/inputor-controller/base.spec.ts +458 -0
  317. package/tests/unit/form/inputor-controller/boolean.spec.ts +30 -0
  318. package/tests/unit/form/inputor-controller/file.spec.ts +27 -0
  319. package/tests/unit/form/inputor-controller/form.spec.ts +120 -0
  320. package/tests/unit/form/inputor-controller/helper.spec.ts +67 -0
  321. package/tests/unit/form/inputor-controller/multi-select.spec.ts +34 -0
  322. package/tests/unit/form/inputor-controller/number.spec.ts +36 -0
  323. package/tests/unit/form/inputor-controller/select.spec.ts +49 -0
  324. package/tests/unit/form/inputor-controller/text.spec.ts +34 -0
  325. package/tests/unit/http/api/api-core-host.spec.ts +207 -0
  326. package/tests/unit/http/api/api-schema.spec.ts +120 -0
  327. package/tests/unit/http/api/api-server.spec.ts +363 -0
  328. package/tests/unit/http/api/api-test.spec.ts +117 -0
  329. package/tests/unit/http/api/api.spec.ts +121 -0
  330. package/tests/unit/http/api-adapter/node-http.spec.ts +191 -0
  331. package/tests/unit/identifier/id.spec.ts +71 -0
  332. package/tests/unit/identifier/uuid.spec.ts +85 -0
  333. package/tests/unit/json/repair.spec.ts +11 -0
  334. package/tests/unit/log/log-emitter.spec.ts +33 -0
  335. package/tests/unit/log/log-scheduler.spec.ts +40 -0
  336. package/tests/unit/log/log-type.spec.ts +7 -0
  337. package/tests/unit/log/logger.spec.ts +237 -0
  338. package/tests/unit/openai/openai.spec.ts +64 -0
  339. package/tests/unit/orchestration/coordination/barrier.spec.ts +96 -0
  340. package/tests/unit/orchestration/coordination/count-down-latch.spec.ts +63 -0
  341. package/tests/unit/orchestration/coordination/errors.spec.ts +29 -0
  342. package/tests/unit/orchestration/coordination/keyed-lock.spec.ts +109 -0
  343. package/tests/unit/orchestration/coordination/mutex.spec.ts +132 -0
  344. package/tests/unit/orchestration/coordination/permit.spec.ts +43 -0
  345. package/tests/unit/orchestration/coordination/read-write-lock.spec.ts +154 -0
  346. package/tests/unit/orchestration/coordination/semaphore.spec.ts +135 -0
  347. package/tests/unit/orchestration/dispatching/dispatcher.spec.ts +41 -0
  348. package/tests/unit/orchestration/dispatching/selector/down-count-selector.spec.ts +81 -0
  349. package/tests/unit/orchestration/scheduling/scheduler.spec.ts +103 -0
  350. package/tests/unit/random/base.spec.ts +58 -0
  351. package/tests/unit/random/random-boolean.spec.ts +25 -0
  352. package/tests/unit/random/random-integer.spec.ts +32 -0
  353. package/tests/unit/random/random-number.spec.ts +33 -0
  354. package/tests/unit/random/random-string.spec.ts +22 -0
  355. package/tests/unit/reactor/alien-signals-effect.spec.ts +11 -10
  356. package/tests/unit/reactor/preact-signal.spec.ts +1 -2
  357. package/tests/unit/request/fetch/browser.spec.ts +222 -0
  358. package/tests/unit/request/fetch/general.spec.ts +43 -0
  359. package/tests/unit/request/fetch/nodejs.spec.ts +225 -0
  360. package/tests/unit/request/request/base.spec.ts +385 -0
  361. package/tests/unit/request/request/general.spec.ts +161 -0
  362. package/tests/unit/route/router/route.spec.ts +431 -0
  363. package/tests/unit/route/router/router.spec.ts +407 -0
  364. package/tests/unit/route/uri/hash.spec.ts +72 -0
  365. package/tests/unit/route/uri/pathname.spec.ts +147 -0
  366. package/tests/unit/route/uri/search.spec.ts +107 -0
  367. package/tests/unit/singleton/singleton.spec.ts +49 -0
  368. package/tests/unit/socket/client.spec.ts +208 -0
  369. package/tests/unit/socket/server.spec.ts +135 -0
  370. package/tests/unit/socket/socket-unit-heartbeat.spec.ts +214 -0
  371. package/tests/unit/storage/table.spec.ts +620 -0
  372. package/tests/unit/timer/expiration/expiration-manager.spec.ts +464 -0
  373. package/tests/unit/timer/expiration/min-heap.spec.ts +71 -0
  374. package/tests/unit/timer/expiration/remaining-manager.spec.ts +234 -0
  375. package/tests/unit/tube/helper.spec.ts +139 -0
  376. package/tests/unit/tube/tube.spec.ts +501 -0
  377. package/.oxlintrc.json +0 -5
  378. package/src/random/uuid.ts +0 -103
  379. package/tests/unit/random/uuid.spec.ts +0 -37
@@ -0,0 +1,78 @@
1
+ import type * as Openai from "#Source/openai/index.ts"
2
+
3
+ import type { BaseChatCompletionOptions, ChatCompletionOptions, ChatCompletionResult } from "./chat-completion.ts"
4
+ import { BaseChatCompletion } from "./chat-completion.ts"
5
+
6
+ export interface AihubmixChatCompletionOptions extends BaseChatCompletionOptions {
7
+ openai: Openai.Openai
8
+ }
9
+ export class AihubmixChatCompletion extends BaseChatCompletion {
10
+ protected readonly openai: Openai.Openai
11
+
12
+ constructor(options: AihubmixChatCompletionOptions) {
13
+ super(options)
14
+ this.logger.setDefaultName("AihubmixChatCompletion")
15
+
16
+ this.openai = options.openai
17
+ }
18
+
19
+ protected transformOptions(options: ChatCompletionOptions): Openai.CustomChatCompletionOptions {
20
+ const transformedOptions: Openai.CustomChatCompletionOptions = {
21
+ messages: options.messages.map((message) => {
22
+ const { role, content } = message
23
+ if (role === "system") {
24
+ return message
25
+ }
26
+ if (role === "user") {
27
+ if (typeof content === "string") {
28
+ return {
29
+ role,
30
+ content,
31
+ }
32
+ }
33
+ if (Array.isArray(content)) {
34
+ return {
35
+ role,
36
+ content: content.map((item) => {
37
+ if (item.type === "image_url") {
38
+ return {
39
+ type: item.type,
40
+ image_url: item.imageUrl,
41
+ }
42
+ }
43
+ else {
44
+ return item
45
+ }
46
+ }),
47
+ }
48
+ }
49
+ throw new Error("Invalid content")
50
+ }
51
+ if (role === "assistant") {
52
+ return message
53
+ }
54
+ throw new Error("Invalid role")
55
+ }),
56
+ model: options.model,
57
+ ...(options.frequencyPenalty !== undefined ? { frequency_penalty: options.frequencyPenalty } : {}),
58
+ ...(options.logitBias !== undefined ? { logit_bias: options.logitBias } : {}),
59
+ ...(options.logprobs !== undefined ? { logprobs: options.logprobs } : {}),
60
+ ...(options.maxCompletionTokens !== undefined ? { max_completion_tokens: options.maxCompletionTokens } : {}),
61
+ ...(options.maxTokens !== undefined ? { max_tokens: options.maxTokens } : {}),
62
+ ...(options.presencePenalty !== undefined ? { presence_penalty: options.presencePenalty } : {}),
63
+ ...(options.responseFormat !== undefined ? { response_format: options.responseFormat } : {}),
64
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
65
+ ...(options.topLogprobs !== undefined ? { top_logprobs: options.topLogprobs } : {}),
66
+ ...(options.topP !== undefined ? { top_p: options.topP } : {}),
67
+ timeout: options.timeoutFirstChunk ?? undefined,
68
+ abortSignal: options.abortSignal,
69
+ }
70
+ return transformedOptions
71
+ }
72
+
73
+ async chatCompletion(options: ChatCompletionOptions): Promise<ChatCompletionResult> {
74
+ const transformedOptions = this.transformOptions(options)
75
+ const result = await this.openai.customChatCompletionStreaming(transformedOptions)
76
+ return result
77
+ }
78
+ }
@@ -0,0 +1,270 @@
1
+ import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
2
+ import type { AbortManager } from "#Source/abort/index.ts"
3
+
4
+ import { Logger } from "#Source/log/index.ts"
5
+ import { Dispatcher } from "#Source/orchestration/index.ts"
6
+ import { fromWithAbortSignal } from "#Source/abort/index.ts"
7
+ import { controllerFromEitherType, eitherToTuple } from "#Source/result/index.ts"
8
+ import { scheduleMacroTask } from "#Source/basic/index.ts"
9
+ import { connectTube, Tube } from "#Source/tube/index.ts"
10
+ import * as Aio from "#Source/aio/index.ts"
11
+
12
+ import type { BaseChatCompletion, ChatCompletionOptions, ChatCompletionResult, Completion } from "./chat-completion.ts"
13
+
14
+ export interface ChatCompletionAiOptions extends LoggerFriendlyOptions {
15
+ chatCompletionInstanceList: BaseChatCompletion[]
16
+ /**
17
+ * The timeout for the first chunk of data to be received, in milliseconds.
18
+ *
19
+ * @default timeoutPerChunk | 30_000
20
+ */
21
+ timeoutFirstChunk?: number | undefined
22
+ /**
23
+ * The timeout for each chunk of data to be received, in milliseconds.
24
+ *
25
+ * @default 30_000
26
+ */
27
+ timeoutPerChunk?: number | undefined
28
+ /**
29
+ * The maximum number of tries for the request.
30
+ *
31
+ * @default 3
32
+ */
33
+ maxTries?: number | undefined
34
+ }
35
+ interface ResolvedChatCompletionAiOptions {
36
+ chatCompletionInstanceList: BaseChatCompletion[]
37
+ timeoutFirstChunk: number
38
+ timeoutPerChunk: number
39
+ maxTries: number
40
+ }
41
+ export class ChatCompletionAi implements LoggerFriendly {
42
+ protected readonly options: ResolvedChatCompletionAiOptions
43
+
44
+ readonly logger: Logger
45
+ private dispatcher: Dispatcher<BaseChatCompletion>
46
+
47
+ constructor(options: ChatCompletionAiOptions) {
48
+ this.options = {
49
+ chatCompletionInstanceList: options.chatCompletionInstanceList,
50
+ timeoutFirstChunk: options.timeoutFirstChunk ?? options.timeoutPerChunk ?? 30_000,
51
+ timeoutPerChunk: options.timeoutPerChunk ?? 30_000,
52
+ maxTries: options.maxTries ?? 3,
53
+ }
54
+
55
+ this.logger = Logger.fromOptions(options).setDefaultName("ChatCompletionAi")
56
+
57
+ this.dispatcher = new Dispatcher({
58
+ itemList: this.options.chatCompletionInstanceList,
59
+ logger: this.logger,
60
+ })
61
+ }
62
+
63
+ async chatCompletion(
64
+ options: ChatCompletionOptions
65
+ ): Promise<ChatCompletionResult> {
66
+ const controller = controllerFromEitherType<ChatCompletionResult>()
67
+
68
+ const completionTube = new Tube<Completion>({
69
+ historyCount: Infinity,
70
+ replayHistory: true
71
+ })
72
+
73
+ scheduleMacroTask({
74
+ task: async () => {
75
+ await this.request(options, completionTube)
76
+ },
77
+ })
78
+
79
+ return await controller.returnRight({
80
+ completionTube,
81
+ })
82
+ }
83
+
84
+ private async request(
85
+ options: ChatCompletionOptions,
86
+ targetCompletionTube: Tube<Completion>,
87
+ ): Promise<void> {
88
+ const { selector, destroy } = this.dispatcher.getSelector({
89
+ filter: (item) => {
90
+ return item.isSupportModel(options.model) === true
91
+ },
92
+ })
93
+ targetCompletionTube.subscribeEndEvent({
94
+ subscriber: () => {
95
+ destroy()
96
+ },
97
+ })
98
+
99
+ const latestCompletion: Completion = {
100
+ content: {
101
+ deltaList: [],
102
+ total: "",
103
+ },
104
+ token: {
105
+ deltaList: [],
106
+ total: 0,
107
+ },
108
+ }
109
+
110
+ const maxTries = options.maxTries ?? this.options.maxTries
111
+
112
+ interface HandleTryErrorOptions {
113
+ tryIndex: number
114
+ abortManager: AbortManager
115
+ }
116
+ const handleTryError = async (options: HandleTryErrorOptions): Promise<void> => {
117
+ const { tryIndex, abortManager } = options
118
+
119
+ this.logger.log(`Handle try error, current failure count: ${tryIndex + 1}, max tries: ${maxTries}`)
120
+
121
+ if (abortManager.isAborted()) {
122
+ this.logger.log("Chat completion aborted by invoker.")
123
+ await targetCompletionTube.pushError(new Error("Chat completion aborted by invoker."))
124
+ abortManager.abort("Chat completion aborted by invoker.")
125
+ return
126
+ }
127
+ else {
128
+ this.logger.log("Chat completion not aborted by invoker.")
129
+ }
130
+ // 清理资源
131
+ abortManager.abort("Failed request")
132
+
133
+ // 重置数据
134
+ latestCompletion.content = Aio.applyDeltaToTextContent(latestCompletion.content, {
135
+ type: "reset",
136
+ })
137
+ latestCompletion.token = Aio.applyDeltaToNumberContent(latestCompletion.token, {
138
+ type: "reset",
139
+ })
140
+ await targetCompletionTube.pushData(structuredClone(latestCompletion))
141
+
142
+ // 如果尝试次数未达到上限,则继续尝试
143
+ const nextTryIndex = tryIndex + 1
144
+ if (nextTryIndex < maxTries) {
145
+ this.logger.log(`Not exceed maximum tries (${maxTries}) for chat completion, try again`)
146
+ scheduleMacroTask({
147
+ task: async () => {
148
+ await startTry(nextTryIndex)
149
+ },
150
+ timeout: 500,
151
+ })
152
+ }
153
+ else {
154
+ this.logger.log(`Exceeded maximum tries (${maxTries}) for chat completion`)
155
+ await targetCompletionTube.pushError(new Error("Exceeded maximum tries."))
156
+ }
157
+ }
158
+ const startTry = async (tryIndex: number): Promise<void> => {
159
+ this.logger.log(`Start try, tries ${tryIndex + 1} of ${maxTries}`)
160
+
161
+ const abortManager = fromWithAbortSignal(options)
162
+ const [getItemLeft, getItemRight] = eitherToTuple(await selector.getItem())
163
+ if (getItemLeft !== undefined) {
164
+ await handleTryError({ tryIndex, abortManager })
165
+ return
166
+ }
167
+ const { item, markUnavailable } = getItemRight
168
+ this.logger.log(`${item.logger.getName()} is selected from pool`)
169
+ const [leftResult, rightResult] = eitherToTuple(await this.requestAndConstrainSpeed(
170
+ {
171
+ ...options,
172
+ abortSignal: abortManager.abortSignal,
173
+ },
174
+ item,
175
+ ))
176
+ if (leftResult !== undefined) {
177
+ await handleTryError({ tryIndex, abortManager })
178
+ return
179
+ }
180
+ const { completionTube: sourceCompletionTube } = rightResult
181
+ sourceCompletionTube.subscribeEndEvent({
182
+ subscriber: async (): Promise<void> => {
183
+ if (sourceCompletionTube.isError()) {
184
+ this.logger.log("Source completion tube ended with error")
185
+ markUnavailable()
186
+ await handleTryError({ tryIndex, abortManager })
187
+ }
188
+ else {
189
+ this.logger.log("Source completion tube ended normally")
190
+ await targetCompletionTube.end()
191
+ }
192
+ },
193
+ })
194
+ sourceCompletionTube.subscribeData({
195
+ subscriber: async (data: Completion): Promise<void> => {
196
+ await targetCompletionTube.pushData(data)
197
+ },
198
+ })
199
+ }
200
+
201
+ await startTry(0)
202
+ }
203
+
204
+ /**
205
+ * 发起请求并对返回结果施加时间约束,当发生以下情况时,将被视为请求失败:
206
+ * 1. 首个数据块超时;
207
+ * 2. 相邻数据块超时;
208
+ */
209
+ private async requestAndConstrainSpeed(
210
+ options: ChatCompletionOptions,
211
+ instance: BaseChatCompletion,
212
+ ): Promise<ChatCompletionResult> {
213
+ const controller = controllerFromEitherType<ChatCompletionResult>()
214
+
215
+ const [chatCompletionLeft, chatCompletionRight] = eitherToTuple(await instance.chatCompletion(options))
216
+ if (chatCompletionLeft !== undefined) {
217
+ return await controller.returnLeft(chatCompletionLeft)
218
+ }
219
+ const { completionTube } = chatCompletionRight
220
+
221
+ const newCompletionTube = new Tube<Completion>({ historyCount: Infinity, replayHistory: true })
222
+ // 无异常的情况下,上游数据直接传递给下游即可
223
+ connectTube(completionTube, newCompletionTube)
224
+
225
+ const timeoutFirstChunk = options.timeoutFirstChunk ?? this.options.timeoutFirstChunk
226
+ const timeoutPerChunk = options.timeoutPerChunk ?? this.options.timeoutPerChunk
227
+
228
+ // 定义首个数据块超时的处理逻辑
229
+ let hasReceivedFirstChunk = false
230
+ const firstChunkTimeoutTimer: NodeJS.Timeout = setTimeout(() => {
231
+ if (hasReceivedFirstChunk === false) {
232
+ this.logger.addOnceTags(["ConstrainSpeed"]).log("First chunk timeout")
233
+ void newCompletionTube.pushError(new Error("FirstChunkTimeout"))
234
+ }
235
+ }, timeoutFirstChunk)
236
+
237
+ // 定义相邻数据块超时的处理逻辑
238
+ let perChunkTimeoutTimer: NodeJS.Timeout | undefined
239
+ completionTube.subscribeData({
240
+ subscriber: () => {
241
+ if (hasReceivedFirstChunk === false) {
242
+ this.logger.addOnceTags(["ConstrainSpeed"]).log("Received first chunk, clear first chunk timeout timer")
243
+ hasReceivedFirstChunk = true
244
+ // Clear the timeout timer for the first chunk
245
+ clearTimeout(firstChunkTimeoutTimer)
246
+ }
247
+ else {
248
+ // Reset the timeout timer for each chunk
249
+ clearTimeout(perChunkTimeoutTimer)
250
+ }
251
+ // Set a new timeout timer for the next chunk
252
+ perChunkTimeoutTimer = setTimeout(() => {
253
+ this.logger.addOnceTags(["ConstrainSpeed"]).log("Per chunk timeout")
254
+ void newCompletionTube.pushError(new Error("PerChunkTimeout"))
255
+ }, timeoutPerChunk)
256
+ },
257
+ })
258
+ completionTube.subscribeEndEvent({
259
+ subscriber: () => {
260
+ this.logger.addOnceTags(["ConstrainSpeed"]).log("Source completion tube ended")
261
+ clearTimeout(firstChunkTimeoutTimer)
262
+ clearTimeout(perChunkTimeoutTimer)
263
+ },
264
+ })
265
+
266
+ return await controller.returnRight({
267
+ completionTube: newCompletionTube,
268
+ })
269
+ }
270
+ }
@@ -0,0 +1,189 @@
1
+ import type * as Aio from "#Source/aio/index.ts"
2
+ import type { WithAbortSignal } from "#Source/abort/index.ts"
3
+ import type { Either } from "#Source/result/index.ts"
4
+ import type { Tube } from "#Source/tube/index.ts"
5
+ import type { StringWithAutoCompleteOptions } from "#Source/type/index.ts"
6
+ import type { LoggerFriendly, LoggerFriendlyOptions } from "#Source/log/index.ts"
7
+ import { Logger } from "#Source/log/index.ts"
8
+
9
+ export interface ChatCompletionContentPartText {
10
+ /**
11
+ * The text content.
12
+ */
13
+ text: string
14
+ /**
15
+ * The type of the content part.
16
+ */
17
+ type: "text"
18
+ }
19
+ export interface ChatCompletionContentPartRefusal {
20
+ /**
21
+ * The refusal message generated by the model.
22
+ */
23
+ refusal: string
24
+ /**
25
+ * The type of the content part.
26
+ */
27
+ type: "refusal"
28
+ }
29
+ export interface ChatCompletionContentPartImage {
30
+ imageUrl: {
31
+ /**
32
+ * Either a URL of the image or the base64 encoded image data.
33
+ */
34
+ url: string
35
+ /**
36
+ * Specifies the detail level of the image. Learn more in the
37
+ * [Vision guide](https://platform.openai.com/docs/guides/vision/low-or-high-fidelity-image-understanding).
38
+ */
39
+ detail?: "auto" | "low" | "high"
40
+ }
41
+ /**
42
+ * The type of the content part.
43
+ */
44
+ type: "image_url"
45
+ }
46
+ export interface ChatCompletionSystemMessage {
47
+ /**
48
+ * The contents of the system message.
49
+ */
50
+ content: string | ChatCompletionContentPartText[]
51
+ /**
52
+ * The role of the messages author, in this case `system`.
53
+ */
54
+ role: "system"
55
+ }
56
+ export interface ChatCompletionUserMessage {
57
+ /**
58
+ * The contents of the user message.
59
+ */
60
+ content: string | Array<ChatCompletionContentPartText | ChatCompletionContentPartImage>
61
+ /**
62
+ * The role of the messages author, in this case `user`.
63
+ */
64
+ role: "user"
65
+ }
66
+ export interface ChatCompletionAssistantMessage {
67
+ /**
68
+ * The contents of the assistant message. Required unless `tool_calls` or
69
+ * `function_call` is specified.
70
+ */
71
+ content: string | Array<ChatCompletionContentPartText | ChatCompletionContentPartRefusal>
72
+ /**
73
+ * The role of the messages author, in this case `assistant`.
74
+ */
75
+ role: "assistant"
76
+ }
77
+ export type ChatCompletionMessage =
78
+ | ChatCompletionSystemMessage
79
+ | ChatCompletionUserMessage
80
+ | ChatCompletionAssistantMessage
81
+ const CHAT_COMPLETION_MODEL_LIST = [
82
+ "o1-preview",
83
+ "o1-preview-2024-09-12",
84
+ "o1-mini",
85
+ "o1-mini-2024-09-12",
86
+ "gpt-4o",
87
+ "gpt-4o-2024-08-06",
88
+ "gpt-4o-2024-05-13",
89
+ "gpt-4o-realtime-preview-2024-10-01",
90
+ "chatgpt-4o-latest",
91
+ "gpt-4o-mini",
92
+ "gpt-4o-mini-2024-07-18",
93
+ "gpt-4-turbo",
94
+ "gpt-4-turbo-2024-04-09",
95
+ "gpt-4-0125-preview",
96
+ "gpt-4-turbo-preview",
97
+ "gpt-4-1106-preview",
98
+ "gpt-4-vision-preview",
99
+ "gpt-4",
100
+ "gpt-4-0314",
101
+ "gpt-4-0613",
102
+ "gpt-4-32k",
103
+ "gpt-4-32k-0314",
104
+ "gpt-4-32k-0613",
105
+ "gpt-3.5-turbo",
106
+ "gpt-3.5-turbo-16k",
107
+ "gpt-3.5-turbo-0301",
108
+ "gpt-3.5-turbo-0613",
109
+ "gpt-3.5-turbo-1106",
110
+ "gpt-3.5-turbo-0125",
111
+ "gpt-3.5-turbo-16k-0613",
112
+ "yi-lightning",
113
+ "hunyuan-standard",
114
+ "grok-3",
115
+ "gemini-2.0-flash-lite-preview-02-05",
116
+ "deepseek-r1",
117
+ "deepseek-v3",
118
+ ] as const
119
+ export type ChatCompletionModel = typeof CHAT_COMPLETION_MODEL_LIST[number]
120
+ export interface ResponseFormatText {
121
+ /**
122
+ * The type of response format being defined: `text`
123
+ */
124
+ type: "text"
125
+ }
126
+ export interface ResponseFormatJSONObject {
127
+ /**
128
+ * The type of response format being defined: `json_object`
129
+ */
130
+ type: "json_object"
131
+ }
132
+ export type ResponseFormat = ResponseFormatText | ResponseFormatJSONObject
133
+ export interface ChatCompletionOptions extends WithAbortSignal {
134
+ messages: ChatCompletionMessage[]
135
+ model: ChatCompletionModel
136
+ frequencyPenalty?: number | null
137
+ logitBias?: Record<string, number> | null
138
+ logprobs?: boolean | null
139
+ maxCompletionTokens?: number | null
140
+ maxTokens?: number | null
141
+ presencePenalty?: number | null
142
+ responseFormat?: ResponseFormat
143
+ temperature?: number | null
144
+ topLogprobs?: number | null
145
+ topP?: number | null
146
+ /**
147
+ * The timeout for the first chunk of data to be received, in milliseconds.
148
+ */
149
+ timeoutFirstChunk?: number | undefined
150
+ /**
151
+ * The timeout for each chunk of data to be received, in milliseconds.
152
+ */
153
+ timeoutPerChunk?: number | undefined
154
+ /**
155
+ * The maximum number of tries for the request.
156
+ */
157
+ maxTries?: number | undefined
158
+ }
159
+
160
+ export interface ChatCompletionLeft {
161
+ code: StringWithAutoCompleteOptions<never>
162
+ }
163
+ export interface Completion {
164
+ content: Aio.TextContent
165
+ token: Aio.NumberContent
166
+ }
167
+ export interface ChatCompletionRight {
168
+ completionTube: Tube<Completion>
169
+ }
170
+ export type ChatCompletionResult = Either<ChatCompletionLeft, ChatCompletionRight>
171
+
172
+ export interface BaseChatCompletionOptions extends LoggerFriendlyOptions {
173
+ }
174
+ export abstract class BaseChatCompletion implements LoggerFriendly {
175
+ readonly logger: Logger
176
+ private readonly supportedModelList: ChatCompletionModel[]
177
+
178
+ constructor(options: BaseChatCompletionOptions) {
179
+ this.logger = Logger.fromOptions(options).setDefaultName("BaseChatCompletion")
180
+
181
+ this.supportedModelList = [...CHAT_COMPLETION_MODEL_LIST]
182
+ }
183
+
184
+ isSupportModel(model: ChatCompletionModel): boolean {
185
+ return this.supportedModelList.includes(model)
186
+ }
187
+
188
+ abstract chatCompletion(options: ChatCompletionOptions): Promise<ChatCompletionResult>
189
+ }
@@ -0,0 +1,7 @@
1
+ export * as ChatCompletionAi from "./chat-completion-ai.ts"
2
+
3
+ export * as ChatCompletion from "./chat-completion.ts"
4
+ export * as OpenaiNextChatCompletion from "./openai-next-chat-completion.ts"
5
+ export * as OhmygptChatCompletion from "./ohmygpt-chat-completion.ts"
6
+ export * as LingyiwanwuChatCompletion from "./lingyiwanwu-chat-completion.ts"
7
+ export * as AihubmixChatCompletion from "./aihubmix-chat-completion.ts"
@@ -0,0 +1,78 @@
1
+ import type * as Openai from "#Source/openai/index.ts"
2
+
3
+ import type { BaseChatCompletionOptions, ChatCompletionOptions, ChatCompletionResult } from "./chat-completion.ts"
4
+ import { BaseChatCompletion } from "./chat-completion.ts"
5
+
6
+ export interface LingyiwanwuChatCompletionOptions extends BaseChatCompletionOptions {
7
+ openai: Openai.Openai
8
+ }
9
+ export class LingyiwanwuChatCompletion extends BaseChatCompletion {
10
+ protected readonly openai: Openai.Openai
11
+
12
+ constructor(options: LingyiwanwuChatCompletionOptions) {
13
+ super(options)
14
+ this.logger.setDefaultName("LingyiwanwuChatCompletion")
15
+
16
+ this.openai = options.openai
17
+ }
18
+
19
+ protected transformOptions(options: ChatCompletionOptions): Openai.CustomChatCompletionOptions {
20
+ const transformedOptions: Openai.CustomChatCompletionOptions = {
21
+ messages: options.messages.map((message) => {
22
+ const { role, content } = message
23
+ if (role === "system") {
24
+ return message
25
+ }
26
+ if (role === "user") {
27
+ if (typeof content === "string") {
28
+ return {
29
+ role,
30
+ content,
31
+ }
32
+ }
33
+ if (Array.isArray(content)) {
34
+ return {
35
+ role,
36
+ content: content.map((item) => {
37
+ if (item.type === "image_url") {
38
+ return {
39
+ type: item.type,
40
+ image_url: item.imageUrl,
41
+ }
42
+ }
43
+ else {
44
+ return item
45
+ }
46
+ }),
47
+ }
48
+ }
49
+ throw new Error("Invalid content")
50
+ }
51
+ if (role === "assistant") {
52
+ return message
53
+ }
54
+ throw new Error("Invalid role")
55
+ }),
56
+ model: options.model,
57
+ ...(options.frequencyPenalty !== undefined ? { frequency_penalty: options.frequencyPenalty } : {}),
58
+ ...(options.logitBias !== undefined ? { logit_bias: options.logitBias } : {}),
59
+ ...(options.logprobs !== undefined ? { logprobs: options.logprobs } : {}),
60
+ ...(options.maxCompletionTokens !== undefined ? { max_completion_tokens: options.maxCompletionTokens } : {}),
61
+ ...(options.maxTokens !== undefined ? { max_tokens: options.maxTokens } : {}),
62
+ ...(options.presencePenalty !== undefined ? { presence_penalty: options.presencePenalty } : {}),
63
+ ...(options.responseFormat !== undefined ? { response_format: options.responseFormat } : {}),
64
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
65
+ ...(options.topLogprobs !== undefined ? { top_logprobs: options.topLogprobs } : {}),
66
+ ...(options.topP !== undefined ? { top_p: options.topP } : {}),
67
+ timeout: options.timeoutFirstChunk ?? undefined,
68
+ abortSignal: options.abortSignal,
69
+ }
70
+ return transformedOptions
71
+ }
72
+
73
+ async chatCompletion(options: ChatCompletionOptions): Promise<ChatCompletionResult> {
74
+ const transformedOptions = this.transformOptions(options)
75
+ const result = await this.openai.customChatCompletionStreaming(transformedOptions)
76
+ return result
77
+ }
78
+ }
@@ -0,0 +1,78 @@
1
+ import type * as Openai from "#Source/openai/index.ts"
2
+
3
+ import type { BaseChatCompletionOptions, ChatCompletionOptions, ChatCompletionResult } from "./chat-completion.ts"
4
+ import { BaseChatCompletion } from "./chat-completion.ts"
5
+
6
+ export interface OhmygptChatCompletionOptions extends BaseChatCompletionOptions {
7
+ openai: Openai.Openai
8
+ }
9
+ export class OhmygptChatCompletion extends BaseChatCompletion {
10
+ protected readonly openai: Openai.Openai
11
+
12
+ constructor(options: OhmygptChatCompletionOptions) {
13
+ super(options)
14
+ this.logger.setDefaultName("OhmygptChatCompletion")
15
+
16
+ this.openai = options.openai
17
+ }
18
+
19
+ protected transformOptions(options: ChatCompletionOptions): Openai.CustomChatCompletionOptions {
20
+ const transformedOptions: Openai.CustomChatCompletionOptions = {
21
+ messages: options.messages.map((message) => {
22
+ const { role, content } = message
23
+ if (role === "system") {
24
+ return message
25
+ }
26
+ if (role === "user") {
27
+ if (typeof content === "string") {
28
+ return {
29
+ role,
30
+ content,
31
+ }
32
+ }
33
+ if (Array.isArray(content)) {
34
+ return {
35
+ role,
36
+ content: content.map((item) => {
37
+ if (item.type === "image_url") {
38
+ return {
39
+ type: item.type,
40
+ image_url: item.imageUrl,
41
+ }
42
+ }
43
+ else {
44
+ return item
45
+ }
46
+ }),
47
+ }
48
+ }
49
+ throw new Error("Invalid content")
50
+ }
51
+ if (role === "assistant") {
52
+ return message
53
+ }
54
+ throw new Error("Invalid role")
55
+ }),
56
+ model: options.model,
57
+ ...(options.frequencyPenalty !== undefined ? { frequency_penalty: options.frequencyPenalty } : {}),
58
+ ...(options.logitBias !== undefined ? { logit_bias: options.logitBias } : {}),
59
+ ...(options.logprobs !== undefined ? { logprobs: options.logprobs } : {}),
60
+ ...(options.maxCompletionTokens !== undefined ? { max_completion_tokens: options.maxCompletionTokens } : {}),
61
+ ...(options.maxTokens !== undefined ? { max_tokens: options.maxTokens } : {}),
62
+ ...(options.presencePenalty !== undefined ? { presence_penalty: options.presencePenalty } : {}),
63
+ ...(options.responseFormat !== undefined ? { response_format: options.responseFormat } : {}),
64
+ ...(options.temperature !== undefined ? { temperature: options.temperature } : {}),
65
+ ...(options.topLogprobs !== undefined ? { top_logprobs: options.topLogprobs } : {}),
66
+ ...(options.topP !== undefined ? { top_p: options.topP } : {}),
67
+ timeout: options.timeoutFirstChunk ?? undefined,
68
+ abortSignal: options.abortSignal,
69
+ }
70
+ return transformedOptions
71
+ }
72
+
73
+ async chatCompletion(options: ChatCompletionOptions): Promise<ChatCompletionResult> {
74
+ const transformedOptions = this.transformOptions(options)
75
+ const result = await this.openai.customChatCompletionStreaming(transformedOptions)
76
+ return result
77
+ }
78
+ }