Many-in-one AI client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
2.5 KiB

  1. import { TextCompletionModel } from '../models';
  2. import {
  3. DataEventId,
  4. FinishableChoiceBase,
  5. CreatedResource,
  6. } from '../common';
  7. import {
  8. CompletionUsage,
  9. UsageMetadata,
  10. } from '../usage';
  11. import { ConsumeStream, DoFetch } from '../../../packages/request';
  12. import { PlatformApiError } from '../../../common';
  13. export enum DataEventObjectType {
  14. TEXT_COMPLETION = 'text_completion',
  15. }
  16. export interface CreateTextCompletionParams {
  17. model: TextCompletionModel;
  18. prompt: string;
  19. temperature?: number;
  20. topP?: number;
  21. n?: number;
  22. stop?: string | string[];
  23. maxTokens?: number;
  24. logprobs?: number;
  25. echo?: boolean;
  26. bestOf?: number;
  27. logitBias?: Record<string, number>;
  28. user?: string;
  29. presencePenalty?: number;
  30. frequencyPenalty?: number;
  31. }
  32. export interface TextCompletionChoice extends FinishableChoiceBase {
  33. text: string;
  34. logprobs?: number;
  35. }
  36. export interface CreateTextCompletionDataEvent<
  37. C extends Partial<FinishableChoiceBase>
  38. > extends CreatedResource {
  39. id: DataEventId;
  40. object: DataEventObjectType;
  41. model: TextCompletionModel;
  42. choices: C[];
  43. }
  44. export interface TextCompletion
  45. extends CreateTextCompletionDataEvent<Partial<TextCompletionChoice>>,
  46. UsageMetadata<CompletionUsage> {}
  47. export type TextCompletionChunkDataEvent = CreateTextCompletionDataEvent<TextCompletionChoice>;
  48. export function createTextCompletion(
  49. this: NodeJS.EventEmitter,
  50. doFetch: DoFetch,
  51. consumeStream: ConsumeStream,
  52. params: CreateTextCompletionParams,
  53. ) {
  54. doFetch('POST', '/completions', {
  55. model: params.model ?? TextCompletionModel.TEXT_DAVINCI_003,
  56. prompt: params.prompt,
  57. temperature: params.temperature ?? 1,
  58. top_p: params.topP ?? 1,
  59. n: params.n ?? 1,
  60. stop: params.stop ?? null,
  61. stream: true,
  62. max_tokens: params.maxTokens,
  63. logprobs: params.logprobs,
  64. echo: params.echo,
  65. best_of: params.bestOf,
  66. logit_bias: params.logitBias,
  67. user: params.user,
  68. presence_penalty: params.presencePenalty,
  69. frequency_penalty: params.frequencyPenalty,
  70. } as Record<string, unknown>)
  71. .then(async (response) => {
  72. if (!response.ok) {
  73. this.emit('error', new PlatformApiError(
  74. // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
  75. `Create text completion returned with status: ${response.status}`,
  76. response,
  77. ));
  78. this.emit('end');
  79. return;
  80. }
  81. await consumeStream(response);
  82. this.emit('end');
  83. })
  84. .catch((err) => {
  85. this.emit('error', err as Error);
  86. this.emit('end');
  87. });
  88. }