promptgun 0.8.7 → 0.10.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.
package/README.md CHANGED
@@ -20,7 +20,7 @@ for await (const chunk of stream) {
20
20
  ```typescript
21
21
  const count /* type: boolean */ = await ai
22
22
  .chat('How many countries are in the EU')
23
- .to(o => o.number())
23
+ .toNumber()
24
24
  ```
25
25
  Promptgun will both tell the LLM what shape its output data should be, parse that data to JS types and –if you use Typescript– return the matching Typescript type.
26
26
 
@@ -28,12 +28,10 @@ You can do this for types of any complexity:
28
28
  ```typescript
29
29
  const restaurants /* type: {name: string, address: string}[] */ = await ai
30
30
  .chat('Give 5 top restaurants in London')
31
- .to(o => o
32
- .array(e => e
33
- .object(o => o
34
- .hasString('name')
35
- .hasString('address')
36
- )
31
+ .toArray(o => o
32
+ .object(o => o
33
+ .hasString('name')
34
+ .hasString('address')
37
35
  )
38
36
  )
39
37
  ```
@@ -41,12 +39,10 @@ const restaurants /* type: {name: string, address: string}[] */ = await ai
41
39
  You can also put instructions to the LLM in your type spec:
42
40
  ```typescript
43
41
  const restaurants /* type: {name: string, address: string}[] */ = await ai
44
- .chat('Give 5 top restaurants in London')
45
- .to(o => o
46
- .object(o => o
47
- .hasString('name')
48
- .hasString('description', 'A 50 character description')
49
- )
42
+ .chat('Give the top restaurant in London')
43
+ .toObject(o => o
44
+ .hasString('name')
45
+ .hasString('description', 'A 50 character description')
50
46
  )
51
47
  ```
52
48
 
@@ -63,23 +59,19 @@ await ai
63
59
  )
64
60
  )
65
61
  )
66
- .onElement(restaurantStream => restaurantStream
67
- .onCompleteAs(restaurant => {
68
- // do stuff every time a restaurant has come through
69
- })
70
- )
62
+ .onElement(restaurantStream /* type safe */ => {
63
+ console.log(await restaurantStream)
64
+ })
71
65
  ```
72
- #### Streamed, "dumb"
73
- You can also simply get the partial data, "what has come in so far". The data is parsed for you, even as the underlying JSON that is received is incomplete.
66
+
67
+ And iterating (not awaiting) any streamed json element simply gives the stream of accumulated partial data, "what has come in so far" as it comes in. The data is parsed for you, even as the underlying JSON that is received is incomplete.
74
68
  ```typescript
75
69
  const parsedPartialJsonStream = ai
76
70
  .chat('What are the top 5 restaurants in New York City?')
77
- .json(d => d
78
- .canBeArray(el => el
79
- .canBeObject(obj => obj
80
- .hasString('name')
81
- .hasString('address')
82
- )
71
+ .toArray(o => o
72
+ .object(o => o
73
+ .hasString('name')
74
+ .hasString('address')
83
75
  )
84
76
  )
85
77
  for await (const parsedPartialJson of parsedPartialJsonStream) {
@@ -87,6 +79,25 @@ for await (const parsedPartialJson of parsedPartialJsonStream) {
87
79
  }
88
80
  ```
89
81
 
82
+ ### Image out
83
+ ```typescript
84
+ await ai
85
+ .image('A black hole')
86
+ .imageSize('1024x1024') // optional
87
+ .model('gpt-image-1') // optional, default: gpt-image-1
88
+ .toFile('blackhole.png')
89
+ ```
90
+ This writes the file, but it also returns a reference to that file:
91
+ ```typescript
92
+ const file = await ai
93
+ .image('A black hole')
94
+ .toFile('blackhole.png')
95
+ ```
96
+ You can also avoid writing a file altogether and get the byte array directly:
97
+ ```typescript
98
+ const byteArray = await ai.image('A black hole')
99
+ ```
100
+
90
101
  ## Setup
91
102
  Before you do any prompts, do:
92
103
  ```typescript
package/build/index.d.ts CHANGED
@@ -18,6 +18,7 @@ export declare class AIClient {
18
18
  chat<T extends undefined>(toPrompt: (args?: T) => Prompt): BasicPrompt<T>;
19
19
  chat<T>(toPrompt: (args: T) => Prompt, args: T): BasicPrompt<T>;
20
20
  chat<T = undefined>(toPrompt: (args?: T) => Prompt, args?: T): BasicPrompt<T>;
21
+ image(prompt: string): ImagePrompt;
21
22
  }
22
23
 
23
24
  export declare const AiModel: {
@@ -862,7 +863,12 @@ export declare class BasicPrompt<PSArgs> implements AsyncGenerator<string>, Prom
862
863
  finally(onfinally?: (() => void) | null | undefined): Promise<string>;
863
864
  get [Symbol.toStringTag](): string;
864
865
  to<Json extends AnyJson = AnyJson>(type: (value: EmptyTypeSpec<unknown>) => TypeSpec<Json>): JsonPrompt<PSArgs, Json>;
865
- toJson(): JsonPrompt<PSArgs, AnyJson>;
866
+ toBoolean(): JsonPrompt<PSArgs, boolean>;
867
+ toString(): JsonPrompt<PSArgs, string>;
868
+ toNumber(): JsonPrompt<PSArgs, number>;
869
+ toObject<T_obj extends {}>(properties: (arg: TypeMemberSpec<{}>) => TypeMemberSpec<T_obj>): JsonPrompt<PSArgs, T_obj>;
870
+ toArray<T_arr extends AnyJson>(element: (arg: EmptyTypeSpec<unknown>) => TypeSpec<T_arr>): JsonPrompt<PSArgs, T_arr[]>;
871
+ toAny(): JsonPrompt<PSArgs, AnyJson>;
866
872
  private getResponseAsString;
867
873
  }
868
874
 
@@ -885,6 +891,8 @@ export declare type DeepPartial<T> = T extends object ? {
885
891
  [P in keyof T]?: DeepPartial<T[P]>;
886
892
  } : T;
887
893
 
894
+ export declare type ElementType<ArrayType extends AnyJson> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
895
+
888
896
  export declare class EmptyPropTypeSpec<T> extends PropTypeSpec<T> {
889
897
  array<T_arr = unknown>(element: (arg: EmptyTypeSpec<unknown>) => TypeSpec<T_arr>): FullPropTypeSpec<Combine<T, T_arr[]>>;
890
898
  object<T_obj extends {}>(properties: (arg: TypeMemberSpec<{}>) => TypeMemberSpec<T_obj>): FullPropTypeSpec<Combine<T, T_obj>>;
@@ -905,6 +913,7 @@ export declare class EmptyTypeSpec<T> extends TypeSpec<T> {
905
913
  constant<Value extends (string | number | boolean)>(value: Value, ...otherValues: Value[]): FullPropTypeSpec<Combine<T, Value>>;
906
914
  null(): FullTypeSpec<Combine<T, null>>;
907
915
  undefined(): FullTypeSpec<Combine<T, undefined>>;
916
+ any(): FullTypeSpec<Combine<T, AnyJson>>;
908
917
  }
909
918
 
910
919
  export declare class FullPropTypeSpec<T> extends PropTypeSpec<T> {
@@ -936,6 +945,52 @@ export declare type HandshakeData = {
936
945
  withinQuotum: boolean;
937
946
  };
938
947
 
948
+ export declare class ImageFilePrompt implements Promise<File> {
949
+ private prompt;
950
+ private _model;
951
+ private _imageSize;
952
+ private fileName;
953
+ private aiClient;
954
+ constructor(prompt: string, _model: OpenaiImageModelId | undefined, _imageSize: ImageSize | undefined, fileName: string, aiClient: AIClient);
955
+ then<TResult1 = File, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2>;
956
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined): Promise<File | TResult>;
957
+ finally(onfinally?: (() => void) | null | undefined): Promise<File>;
958
+ get [Symbol.toStringTag](): string;
959
+ model(model: OpenaiImageModelId): this;
960
+ /**
961
+ * The size of the generated images. Must be one of `1024x1024`, `1536x1024`
962
+ * (landscape), `1024x1536` (portrait), or `auto` (default value) for
963
+ * `gpt-image-1`, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and
964
+ * one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`.
965
+ */
966
+ size(imageSize: ImageSize): this;
967
+ private getResponseAsFile;
968
+ }
969
+
970
+ export declare class ImagePrompt implements Promise<Buffer> {
971
+ private prompt;
972
+ private _model;
973
+ private _imageSize;
974
+ private aiClient;
975
+ constructor(prompt: string, _model: OpenaiImageModelId | undefined, _imageSize: ImageSize | undefined, aiClient: AIClient);
976
+ then<TResult1 = Buffer, TResult2 = never>(onfulfilled?: ((value: any) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2>;
977
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined): Promise<Buffer | TResult>;
978
+ finally(onfinally?: (() => void) | null | undefined): Promise<Buffer>;
979
+ get [Symbol.toStringTag](): string;
980
+ model(model: OpenaiImageModelId): this;
981
+ /**
982
+ * The size of the generated images. Must be one of `1024x1024`, `1536x1024`
983
+ * (landscape), `1024x1536` (portrait), or `auto` (default value) for
984
+ * `gpt-image-1`, one of `256x256`, `512x512`, or `1024x1024` for `dall-e-2`, and
985
+ * one of `1024x1024`, `1792x1024`, or `1024x1792` for `dall-e-3`.
986
+ */
987
+ size(imageSize: ImageSize): this;
988
+ toFile(fileName: string): ImageFilePrompt;
989
+ private getResponseAsString;
990
+ }
991
+
992
+ export declare type ImageSize = '1024x1024' | '1536x1024' | '1024x1536' | '256x256' | '512x512' | '1792x1024' | '1024x1792';
993
+
939
994
  export declare type JsonArray = AnyJson[];
940
995
 
941
996
  export declare type JsonExcerpt = {
@@ -947,7 +1002,7 @@ export declare type JsonObject = {
947
1002
  [key: string]: AnyJson;
948
1003
  };
949
1004
 
950
- export declare class JsonPrompt<PSArgs, Json extends AnyJson = AnyJson> extends StreamedJsonChildElement implements AsyncGenerator<AnyJson>, Promise<Json> {
1005
+ export declare class JsonPrompt<PSArgs, Json extends AnyJson = AnyJson> extends StreamedJsonChildElement<Json> implements AsyncGenerator<AnyJson>, Promise<Json> {
951
1006
  private aiClient;
952
1007
  private promptSupplier;
953
1008
  private promptSupplierArgs;
@@ -995,16 +1050,10 @@ export declare class JsonPrompt<PSArgs, Json extends AnyJson = AnyJson> extends
995
1050
 
996
1051
  export declare type Message = SystemMessage | UserMessage | AssistantMessage;
997
1052
 
998
- export declare class ModelNotSupportedError extends Error {
999
- }
1000
-
1001
1053
  export declare function newAIClient(promptGridApiKey: string): AIClient;
1002
1054
 
1003
1055
  export declare function newAIClient(config: PromptGunConfig): AIClient;
1004
1056
 
1005
- export declare class NoAiCredientialsError extends Error {
1006
- }
1007
-
1008
1057
  export declare type NullType = BaseType<'null'>;
1009
1058
 
1010
1059
  export declare type NumberType = BaseType<'number'>;
@@ -1022,6 +1071,14 @@ export declare function obtainAiClientData(config: PromptGunConfig): {
1022
1071
  openai: Promise<string | undefined>;
1023
1072
  };
1024
1073
 
1074
+ export declare const OpenaiImageModel: {
1075
+ readonly dall_e_2: "dall-e-2";
1076
+ readonly dall_e_3: "dall-e-3";
1077
+ readonly gpt_image_1: "gpt-image-1";
1078
+ };
1079
+
1080
+ export declare type OpenaiImageModelId = (typeof OpenaiImageModel)[keyof typeof OpenaiImageModel];
1081
+
1025
1082
  export declare type Opts = {
1026
1083
  model?: 'gpt-4o';
1027
1084
  };
@@ -1046,11 +1103,7 @@ export declare type PromptGunConfig = {
1046
1103
  apiKeys?: AccessTokens;
1047
1104
  };
1048
1105
 
1049
- export declare function promptLLM<T>(args: T, toPrompt: (args: T) => Prompt): Flux<string>;
1050
-
1051
- export declare function promptLLM<T>(args: T, toPrompt: (args: T) => Prompt, json: true): StreamedJsonRootElement;
1052
-
1053
- export declare function promptLLM<T>(args: T, toPrompt: (args: T) => Prompt, json?: boolean): Flux<string> | StreamedJsonRootElement;
1106
+ export declare type PropType<ObjectType extends AnyJson, PropName extends string> = ObjectType extends Record<PropName, infer PropType extends AnyJson> ? PropType : never;
1054
1107
 
1055
1108
  export declare abstract class PropTypeSpec<T> extends TypeSpec<T> {
1056
1109
  private _comments;
@@ -1063,11 +1116,11 @@ export declare abstract class PropTypeSpec<T> extends TypeSpec<T> {
1063
1116
 
1064
1117
  export declare function setupAI(arg: string | PromptGunConfig): void;
1065
1118
 
1066
- export declare class StreamedJsonChildElement extends StreamedJsonElement {
1119
+ export declare class StreamedJsonChildElement<T extends AnyJson> extends StreamedJsonElement<T> {
1067
1120
  constructor();
1068
1121
  }
1069
1122
 
1070
- export declare abstract class StreamedJsonElement {
1123
+ export declare abstract class StreamedJsonElement<T extends AnyJson> implements Promise<T> {
1071
1124
  protected readonly receivedJson: string[];
1072
1125
  private readonly propertyCallbacks;
1073
1126
  private onElementCallbacks;
@@ -1076,19 +1129,24 @@ export declare abstract class StreamedJsonElement {
1076
1129
  private currentToken?;
1077
1130
  private state;
1078
1131
  private receivedExcerpts;
1079
- onElement(callback: (value: StreamedJsonElement) => void): this;
1080
- onProperty(propertyName: string, callback: (element: StreamedJsonElement) => void): this;
1132
+ onElement(callback: (value: StreamedJsonElement<ElementType<T>>) => void): this;
1133
+ onProperty<P extends string>(propertyName: P, callback: (element: StreamedJsonElement<PropType<T, P>>) => void): this;
1081
1134
  /**
1082
1135
  * @deprecated Does not work right now because FIELD_NAME
1083
1136
  * token comes after string value is already streaming
1084
1137
  */
1085
- onJsonStringProperty(propertyName: string, callback: (element: StreamedJsonElement) => void): this;
1138
+ onJsonStringProperty<P extends string>(propertyName: P, callback: (element: StreamedJsonElement<PropType<T, P>>) => void): this;
1086
1139
  onEachExcerpt(callback: (value: JsonExcerpt) => void): this;
1140
+ then<TResult1 = T, TResult2 = never>(onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null | undefined): Promise<TResult1 | TResult2>;
1141
+ catch<TResult = never>(onrejected?: ((reason: any) => TResult | PromiseLike<TResult>) | null | undefined): Promise<T | TResult>;
1142
+ finally(onfinally?: (() => void) | null | undefined): Promise<T>;
1143
+ get [Symbol.toStringTag](): string;
1144
+ private getResponseAsPromise;
1087
1145
  /**
1088
1146
  * @param onComplete - a callback that will receive the complete JSON
1089
1147
  * string for this element once it's done streaming
1090
1148
  */
1091
- onComplete(onComplete: (value: string) => void): void;
1149
+ private onComplete;
1092
1150
  private _onComplete;
1093
1151
  onCompleteAsync(onComplete: (value: string) => Promise<void>): void;
1094
1152
  onCompleteAs<T>(onComplete: (value: T) => void): void;
@@ -1111,7 +1169,7 @@ export declare abstract class StreamedJsonElement {
1111
1169
  private toAsync;
1112
1170
  }
1113
1171
 
1114
- export declare class StreamedJsonRootElement extends StreamedJsonElement {
1172
+ export declare class StreamedJsonRootElement<T extends AnyJson> extends StreamedJsonElement<T> {
1115
1173
  protected readonly jsonTokenFlux: Flux<JsonExcerpt>;
1116
1174
  constructor(jsonTokenFlux: Flux<JsonExcerpt>);
1117
1175
  whenComplete(): Promise<string>;