hazo_llm_api 1.2.12 → 1.3.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 +321 -8
- package/config/hazo_llm_api_config.ini +33 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +2 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/llm_call_inspector/index.d.ts +6 -0
- package/dist/components/llm_call_inspector/index.d.ts.map +1 -0
- package/dist/components/llm_call_inspector/index.js +5 -0
- package/dist/components/llm_call_inspector/index.js.map +1 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.d.ts +18 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.d.ts.map +1 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.js +103 -0
- package/dist/components/llm_call_inspector/llm_call_inspector.js.map +1 -0
- package/dist/components/llm_cost_dashboard/index.d.ts +6 -0
- package/dist/components/llm_cost_dashboard/index.d.ts.map +1 -0
- package/dist/components/llm_cost_dashboard/index.js +5 -0
- package/dist/components/llm_cost_dashboard/index.js.map +1 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts +16 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.d.ts.map +1 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js +154 -0
- package/dist/components/llm_cost_dashboard/llm_cost_dashboard.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/lib/cascade/cascade_runner.d.ts +50 -0
- package/dist/lib/cascade/cascade_runner.d.ts.map +1 -0
- package/dist/lib/cascade/cascade_runner.js +115 -0
- package/dist/lib/cascade/cascade_runner.js.map +1 -0
- package/dist/lib/cascade/index.d.ts +5 -0
- package/dist/lib/cascade/index.d.ts.map +1 -0
- package/dist/lib/cascade/index.js +4 -0
- package/dist/lib/cascade/index.js.map +1 -0
- package/dist/lib/cascade/types.d.ts +35 -0
- package/dist/lib/cascade/types.d.ts.map +1 -0
- package/dist/lib/cascade/types.js +14 -0
- package/dist/lib/cascade/types.js.map +1 -0
- package/dist/lib/cost_cap/cost_cap.d.ts +40 -0
- package/dist/lib/cost_cap/cost_cap.d.ts.map +1 -0
- package/dist/lib/cost_cap/cost_cap.js +150 -0
- package/dist/lib/cost_cap/cost_cap.js.map +1 -0
- package/dist/lib/cost_cap/index.d.ts +3 -0
- package/dist/lib/cost_cap/index.d.ts.map +1 -0
- package/dist/lib/cost_cap/index.js +2 -0
- package/dist/lib/cost_cap/index.js.map +1 -0
- package/dist/lib/database/init_api_log.d.ts +10 -0
- package/dist/lib/database/init_api_log.d.ts.map +1 -0
- package/dist/lib/database/init_api_log.js +91 -0
- package/dist/lib/database/init_api_log.js.map +1 -0
- package/dist/lib/hazo_connect/direct_db_connect.d.ts +11 -7
- package/dist/lib/hazo_connect/direct_db_connect.d.ts.map +1 -1
- package/dist/lib/hazo_connect/direct_db_connect.js +59 -6
- package/dist/lib/hazo_connect/direct_db_connect.js.map +1 -1
- package/dist/lib/hazo_connect/types.d.ts +35 -3
- package/dist/lib/hazo_connect/types.d.ts.map +1 -1
- package/dist/lib/llm_api/embed_cache.d.ts +15 -0
- package/dist/lib/llm_api/embed_cache.d.ts.map +1 -0
- package/dist/lib/llm_api/embed_cache.js +53 -0
- package/dist/lib/llm_api/embed_cache.js.map +1 -0
- package/dist/lib/llm_api/hazo_llm_document_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_document_text.js +56 -14
- package/dist/lib/llm_api/hazo_llm_document_text.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js +19 -1
- package/dist/lib/llm_api/hazo_llm_dynamic_data_extract.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_embed.d.ts +10 -0
- package/dist/lib/llm_api/hazo_llm_embed.d.ts.map +1 -0
- package/dist/lib/llm_api/hazo_llm_embed.js +80 -0
- package/dist/lib/llm_api/hazo_llm_embed.js.map +1 -0
- package/dist/lib/llm_api/hazo_llm_image_image.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_image.js +56 -14
- package/dist/lib/llm_api/hazo_llm_image_image.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_image_text.js +56 -14
- package/dist/lib/llm_api/hazo_llm_image_text.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_prompt_chain.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_prompt_chain.js +17 -1
- package/dist/lib/llm_api/hazo_llm_prompt_chain.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_image.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_image.js +56 -14
- package/dist/lib/llm_api/hazo_llm_text_image.js.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_text.d.ts.map +1 -1
- package/dist/lib/llm_api/hazo_llm_text_text.js +90 -15
- package/dist/lib/llm_api/hazo_llm_text_text.js.map +1 -1
- package/dist/lib/llm_api/index.d.ts +29 -1
- package/dist/lib/llm_api/index.d.ts.map +1 -1
- package/dist/lib/llm_api/index.js +433 -6
- package/dist/lib/llm_api/index.js.map +1 -1
- package/dist/lib/llm_api/prompt_parts_helper.d.ts +15 -0
- package/dist/lib/llm_api/prompt_parts_helper.d.ts.map +1 -0
- package/dist/lib/llm_api/prompt_parts_helper.js +9 -0
- package/dist/lib/llm_api/prompt_parts_helper.js.map +1 -0
- package/dist/lib/llm_api/types.d.ts +187 -2
- package/dist/lib/llm_api/types.d.ts.map +1 -1
- package/dist/lib/llm_api/types.js +4 -0
- package/dist/lib/llm_api/types.js.map +1 -1
- package/dist/lib/maintenance/purge_log_job.d.ts +23 -0
- package/dist/lib/maintenance/purge_log_job.d.ts.map +1 -0
- package/dist/lib/maintenance/purge_log_job.js +42 -0
- package/dist/lib/maintenance/purge_log_job.js.map +1 -0
- package/dist/lib/observability/log_context.d.ts +15 -0
- package/dist/lib/observability/log_context.d.ts.map +1 -0
- package/dist/lib/observability/log_context.js +32 -0
- package/dist/lib/observability/log_context.js.map +1 -0
- package/dist/lib/observability/log_writer.d.ts +35 -0
- package/dist/lib/observability/log_writer.d.ts.map +1 -0
- package/dist/lib/observability/log_writer.js +106 -0
- package/dist/lib/observability/log_writer.js.map +1 -0
- package/dist/lib/observability/queries.d.ts +15 -0
- package/dist/lib/observability/queries.d.ts.map +1 -0
- package/dist/lib/observability/queries.js +78 -0
- package/dist/lib/observability/queries.js.map +1 -0
- package/dist/lib/observability/types.d.ts +77 -0
- package/dist/lib/observability/types.d.ts.map +1 -0
- package/dist/lib/observability/types.js +8 -0
- package/dist/lib/observability/types.js.map +1 -0
- package/dist/lib/pricing/pricing.d.ts +49 -0
- package/dist/lib/pricing/pricing.d.ts.map +1 -0
- package/dist/lib/pricing/pricing.js +153 -0
- package/dist/lib/pricing/pricing.js.map +1 -0
- package/dist/lib/pricing/pricing.json +75 -0
- package/dist/lib/pricing/types.d.ts +58 -0
- package/dist/lib/pricing/types.d.ts.map +1 -0
- package/dist/lib/pricing/types.js +8 -0
- package/dist/lib/pricing/types.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_client.d.ts +71 -0
- package/dist/lib/providers/anthropic/anthropic_client.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_client.js +134 -0
- package/dist/lib/providers/anthropic/anthropic_client.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_provider.d.ts +60 -0
- package/dist/lib/providers/anthropic/anthropic_provider.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_provider.js +273 -0
- package/dist/lib/providers/anthropic/anthropic_provider.js.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.js +46 -0
- package/dist/lib/providers/anthropic/anthropic_response_to_usage.js.map +1 -0
- package/dist/lib/providers/anthropic/index.d.ts +3 -0
- package/dist/lib/providers/anthropic/index.d.ts.map +1 -0
- package/dist/lib/providers/anthropic/index.js +2 -0
- package/dist/lib/providers/anthropic/index.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_client.d.ts +55 -0
- package/dist/lib/providers/deepseek/deepseek_client.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_client.js +129 -0
- package/dist/lib/providers/deepseek/deepseek_client.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_provider.d.ts +50 -0
- package/dist/lib/providers/deepseek/deepseek_provider.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_provider.js +147 -0
- package/dist/lib/providers/deepseek/deepseek_provider.js.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.js +40 -0
- package/dist/lib/providers/deepseek/deepseek_response_to_usage.js.map +1 -0
- package/dist/lib/providers/deepseek/index.d.ts +3 -0
- package/dist/lib/providers/deepseek/index.d.ts.map +1 -0
- package/dist/lib/providers/deepseek/index.js +2 -0
- package/dist/lib/providers/deepseek/index.js.map +1 -0
- package/dist/lib/providers/gemini/gemini_provider.d.ts.map +1 -1
- package/dist/lib/providers/gemini/gemini_provider.js +40 -4
- package/dist/lib/providers/gemini/gemini_provider.js.map +1 -1
- package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts +37 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.js +49 -0
- package/dist/lib/providers/gemini/gemini_response_to_usage.js.map +1 -0
- package/dist/lib/providers/index.d.ts +3 -0
- package/dist/lib/providers/index.d.ts.map +1 -1
- package/dist/lib/providers/index.js +3 -0
- package/dist/lib/providers/index.js.map +1 -1
- package/dist/lib/providers/openai/index.d.ts +3 -0
- package/dist/lib/providers/openai/index.d.ts.map +1 -0
- package/dist/lib/providers/openai/index.js +2 -0
- package/dist/lib/providers/openai/index.js.map +1 -0
- package/dist/lib/providers/openai/openai_client.d.ts +99 -0
- package/dist/lib/providers/openai/openai_client.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_client.js +187 -0
- package/dist/lib/providers/openai/openai_client.js.map +1 -0
- package/dist/lib/providers/openai/openai_provider.d.ts +66 -0
- package/dist/lib/providers/openai/openai_provider.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_provider.js +297 -0
- package/dist/lib/providers/openai/openai_provider.js.map +1 -0
- package/dist/lib/providers/openai/openai_response_to_usage.d.ts +21 -0
- package/dist/lib/providers/openai/openai_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/openai/openai_response_to_usage.js +50 -0
- package/dist/lib/providers/openai/openai_response_to_usage.js.map +1 -0
- package/dist/lib/providers/qwen/qwen_provider.d.ts.map +1 -1
- package/dist/lib/providers/qwen/qwen_provider.js +52 -5
- package/dist/lib/providers/qwen/qwen_provider.js.map +1 -1
- package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts +36 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.d.ts.map +1 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.js +50 -0
- package/dist/lib/providers/qwen/qwen_response_to_usage.js.map +1 -0
- package/dist/lib/providers/types.d.ts +16 -6
- package/dist/lib/providers/types.d.ts.map +1 -1
- package/dist/lib/providers/types.js +1 -0
- package/dist/lib/providers/types.js.map +1 -1
- package/dist/lib/utils.d.ts +13 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +16 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/server.d.ts +16 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +29 -2
- package/dist/server.js.map +1 -1
- package/migrations/hazo_llm_api_log.sql +69 -0
- package/package.json +26 -11
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI API Client Module
|
|
3
|
+
*
|
|
4
|
+
* Handles communication with the OpenAI Chat Completions API and Image Generation API.
|
|
5
|
+
* Uses the standard OpenAI API format (also compatible with many other providers).
|
|
6
|
+
*/
|
|
7
|
+
import type { LLMStreamChunk } from '../../llm_api/types.js';
|
|
8
|
+
/**
|
|
9
|
+
* OpenAI message role
|
|
10
|
+
*/
|
|
11
|
+
export interface OpenAIMessage {
|
|
12
|
+
role: 'user' | 'assistant' | 'system';
|
|
13
|
+
content: string | OpenAIContentItem[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* OpenAI content item for multimodal messages
|
|
17
|
+
*/
|
|
18
|
+
export type OpenAIContentItem = {
|
|
19
|
+
type: 'text';
|
|
20
|
+
text: string;
|
|
21
|
+
} | {
|
|
22
|
+
type: 'image_url';
|
|
23
|
+
image_url: {
|
|
24
|
+
url: string;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* OpenAI generation configuration parameters
|
|
29
|
+
*/
|
|
30
|
+
export interface OpenAIGenerationConfig {
|
|
31
|
+
/** Controls randomness in output (0.0-2.0). Lower = more deterministic */
|
|
32
|
+
temperature?: number;
|
|
33
|
+
/** Nucleus sampling probability (0.0-1.0) */
|
|
34
|
+
top_p?: number;
|
|
35
|
+
/** Maximum number of tokens in the response */
|
|
36
|
+
max_tokens?: number;
|
|
37
|
+
/** Penalizes new tokens based on whether they appear in the text so far */
|
|
38
|
+
frequency_penalty?: number;
|
|
39
|
+
/** Penalizes new tokens based on whether they appear in the text at all */
|
|
40
|
+
presence_penalty?: number;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Call the OpenAI Chat Completions API (non-streaming)
|
|
44
|
+
* @param opts - API call options
|
|
45
|
+
* @returns Raw API response and HTTP status code
|
|
46
|
+
*/
|
|
47
|
+
export declare function call_openai_api(opts: {
|
|
48
|
+
api_key: string;
|
|
49
|
+
api_url: string;
|
|
50
|
+
model: string;
|
|
51
|
+
messages: OpenAIMessage[];
|
|
52
|
+
generation_config?: OpenAIGenerationConfig;
|
|
53
|
+
}): Promise<{
|
|
54
|
+
raw: Record<string, unknown>;
|
|
55
|
+
status: number;
|
|
56
|
+
}>;
|
|
57
|
+
/**
|
|
58
|
+
* Call the OpenAI Image Generation API
|
|
59
|
+
* @param opts - API call options
|
|
60
|
+
* @returns Raw API response and HTTP status code
|
|
61
|
+
*/
|
|
62
|
+
export declare function call_openai_image_api(opts: {
|
|
63
|
+
api_key: string;
|
|
64
|
+
api_url_image: string;
|
|
65
|
+
model: string;
|
|
66
|
+
prompt: string;
|
|
67
|
+
}): Promise<{
|
|
68
|
+
raw: Record<string, unknown>;
|
|
69
|
+
status: number;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* Call the OpenAI Embeddings API
|
|
73
|
+
* @param opts - API call options
|
|
74
|
+
* @returns Raw API response and HTTP status code
|
|
75
|
+
*/
|
|
76
|
+
export declare function call_openai_embed_api(opts: {
|
|
77
|
+
api_key: string;
|
|
78
|
+
api_url_embed: string;
|
|
79
|
+
model: string;
|
|
80
|
+
input: string | string[];
|
|
81
|
+
}): Promise<{
|
|
82
|
+
raw: Record<string, unknown>;
|
|
83
|
+
status: number;
|
|
84
|
+
}>;
|
|
85
|
+
/**
|
|
86
|
+
* Call the OpenAI Chat Completions API with streaming enabled.
|
|
87
|
+
* Yields LLMStreamChunk objects as SSE events arrive.
|
|
88
|
+
*
|
|
89
|
+
* @param opts - API call options
|
|
90
|
+
* @yields LLMStreamChunk objects with text deltas or done/error signals
|
|
91
|
+
*/
|
|
92
|
+
export declare function call_openai_api_stream(opts: {
|
|
93
|
+
api_key: string;
|
|
94
|
+
api_url: string;
|
|
95
|
+
model: string;
|
|
96
|
+
messages: OpenAIMessage[];
|
|
97
|
+
generation_config?: OpenAIGenerationConfig;
|
|
98
|
+
}): AsyncGenerator<LLMStreamChunk, void, unknown>;
|
|
99
|
+
//# sourceMappingURL=openai_client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai_client.d.ts","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM7D;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;CACvC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,2EAA2E;IAC3E,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CAC5C,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAmC5D;AAMD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAkB5D;AAMD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa5D;AAMD;;;;;;GAMG;AACH,wBAAuB,sBAAsB,CAAC,IAAI,EAAE;IAClD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;CAC5C,GAAG,cAAc,CAAC,cAAc,EAAE,IAAI,EAAE,OAAO,CAAC,CAuFhD"}
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI API Client Module
|
|
3
|
+
*
|
|
4
|
+
* Handles communication with the OpenAI Chat Completions API and Image Generation API.
|
|
5
|
+
* Uses the standard OpenAI API format (also compatible with many other providers).
|
|
6
|
+
*/
|
|
7
|
+
// =============================================================================
|
|
8
|
+
// OpenAI Chat Completions API Client
|
|
9
|
+
// =============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Call the OpenAI Chat Completions API (non-streaming)
|
|
12
|
+
* @param opts - API call options
|
|
13
|
+
* @returns Raw API response and HTTP status code
|
|
14
|
+
*/
|
|
15
|
+
export async function call_openai_api(opts) {
|
|
16
|
+
const body = {
|
|
17
|
+
model: opts.model,
|
|
18
|
+
messages: opts.messages,
|
|
19
|
+
};
|
|
20
|
+
if (opts.generation_config) {
|
|
21
|
+
if (opts.generation_config.temperature !== undefined) {
|
|
22
|
+
body.temperature = opts.generation_config.temperature;
|
|
23
|
+
}
|
|
24
|
+
if (opts.generation_config.top_p !== undefined) {
|
|
25
|
+
body.top_p = opts.generation_config.top_p;
|
|
26
|
+
}
|
|
27
|
+
if (opts.generation_config.max_tokens !== undefined) {
|
|
28
|
+
body.max_tokens = opts.generation_config.max_tokens;
|
|
29
|
+
}
|
|
30
|
+
if (opts.generation_config.frequency_penalty !== undefined) {
|
|
31
|
+
body.frequency_penalty = opts.generation_config.frequency_penalty;
|
|
32
|
+
}
|
|
33
|
+
if (opts.generation_config.presence_penalty !== undefined) {
|
|
34
|
+
body.presence_penalty = opts.generation_config.presence_penalty;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const response = await fetch(opts.api_url, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
headers: {
|
|
40
|
+
'Authorization': `Bearer ${opts.api_key}`,
|
|
41
|
+
'Content-Type': 'application/json',
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify(body),
|
|
44
|
+
});
|
|
45
|
+
const raw = (await response.json());
|
|
46
|
+
return { raw, status: response.status };
|
|
47
|
+
}
|
|
48
|
+
// =============================================================================
|
|
49
|
+
// OpenAI Image Generation API Client
|
|
50
|
+
// =============================================================================
|
|
51
|
+
/**
|
|
52
|
+
* Call the OpenAI Image Generation API
|
|
53
|
+
* @param opts - API call options
|
|
54
|
+
* @returns Raw API response and HTTP status code
|
|
55
|
+
*/
|
|
56
|
+
export async function call_openai_image_api(opts) {
|
|
57
|
+
const body = {
|
|
58
|
+
model: opts.model,
|
|
59
|
+
prompt: opts.prompt,
|
|
60
|
+
response_format: 'b64_json',
|
|
61
|
+
};
|
|
62
|
+
const response = await fetch(opts.api_url_image, {
|
|
63
|
+
method: 'POST',
|
|
64
|
+
headers: {
|
|
65
|
+
'Authorization': `Bearer ${opts.api_key}`,
|
|
66
|
+
'Content-Type': 'application/json',
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify(body),
|
|
69
|
+
});
|
|
70
|
+
const raw = (await response.json());
|
|
71
|
+
return { raw, status: response.status };
|
|
72
|
+
}
|
|
73
|
+
// =============================================================================
|
|
74
|
+
// OpenAI Streaming API Client
|
|
75
|
+
// =============================================================================
|
|
76
|
+
/**
|
|
77
|
+
* Call the OpenAI Embeddings API
|
|
78
|
+
* @param opts - API call options
|
|
79
|
+
* @returns Raw API response and HTTP status code
|
|
80
|
+
*/
|
|
81
|
+
export async function call_openai_embed_api(opts) {
|
|
82
|
+
const { api_key, api_url_embed, model, input } = opts;
|
|
83
|
+
const response = await fetch(api_url_embed, {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: {
|
|
86
|
+
'Authorization': `Bearer ${api_key}`,
|
|
87
|
+
'Content-Type': 'application/json',
|
|
88
|
+
},
|
|
89
|
+
body: JSON.stringify({ model, input }),
|
|
90
|
+
});
|
|
91
|
+
const raw = (await response.json());
|
|
92
|
+
return { raw, status: response.status };
|
|
93
|
+
}
|
|
94
|
+
// =============================================================================
|
|
95
|
+
// OpenAI Streaming API Client
|
|
96
|
+
// =============================================================================
|
|
97
|
+
/**
|
|
98
|
+
* Call the OpenAI Chat Completions API with streaming enabled.
|
|
99
|
+
* Yields LLMStreamChunk objects as SSE events arrive.
|
|
100
|
+
*
|
|
101
|
+
* @param opts - API call options
|
|
102
|
+
* @yields LLMStreamChunk objects with text deltas or done/error signals
|
|
103
|
+
*/
|
|
104
|
+
export async function* call_openai_api_stream(opts) {
|
|
105
|
+
const body = {
|
|
106
|
+
model: opts.model,
|
|
107
|
+
messages: opts.messages,
|
|
108
|
+
stream: true,
|
|
109
|
+
};
|
|
110
|
+
if (opts.generation_config) {
|
|
111
|
+
if (opts.generation_config.temperature !== undefined) {
|
|
112
|
+
body.temperature = opts.generation_config.temperature;
|
|
113
|
+
}
|
|
114
|
+
if (opts.generation_config.top_p !== undefined) {
|
|
115
|
+
body.top_p = opts.generation_config.top_p;
|
|
116
|
+
}
|
|
117
|
+
if (opts.generation_config.max_tokens !== undefined) {
|
|
118
|
+
body.max_tokens = opts.generation_config.max_tokens;
|
|
119
|
+
}
|
|
120
|
+
if (opts.generation_config.frequency_penalty !== undefined) {
|
|
121
|
+
body.frequency_penalty = opts.generation_config.frequency_penalty;
|
|
122
|
+
}
|
|
123
|
+
if (opts.generation_config.presence_penalty !== undefined) {
|
|
124
|
+
body.presence_penalty = opts.generation_config.presence_penalty;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
let response;
|
|
128
|
+
try {
|
|
129
|
+
response = await fetch(opts.api_url, {
|
|
130
|
+
method: 'POST',
|
|
131
|
+
headers: {
|
|
132
|
+
'Authorization': `Bearer ${opts.api_key}`,
|
|
133
|
+
'Content-Type': 'application/json',
|
|
134
|
+
},
|
|
135
|
+
body: JSON.stringify(body),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
140
|
+
yield { text: '', done: false, error: `OpenAI network error: ${msg}` };
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
if (!response.ok || !response.body) {
|
|
144
|
+
yield { text: '', done: false, error: `OpenAI API error: ${response.status}` };
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const reader = response.body.getReader();
|
|
148
|
+
const decoder = new TextDecoder();
|
|
149
|
+
let buffer = '';
|
|
150
|
+
try {
|
|
151
|
+
while (true) {
|
|
152
|
+
const { done, value } = await reader.read();
|
|
153
|
+
if (done)
|
|
154
|
+
break;
|
|
155
|
+
buffer += decoder.decode(value, { stream: true });
|
|
156
|
+
const lines = buffer.split('\n');
|
|
157
|
+
buffer = lines.pop() ?? '';
|
|
158
|
+
for (const line of lines) {
|
|
159
|
+
if (!line.startsWith('data: '))
|
|
160
|
+
continue;
|
|
161
|
+
const data_str = line.slice(6).trim();
|
|
162
|
+
if (!data_str)
|
|
163
|
+
continue;
|
|
164
|
+
if (data_str === '[DONE]') {
|
|
165
|
+
yield { text: '', done: true };
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
try {
|
|
169
|
+
const data = JSON.parse(data_str);
|
|
170
|
+
const choices = data.choices;
|
|
171
|
+
const delta = choices?.[0]?.delta;
|
|
172
|
+
const content = delta?.content;
|
|
173
|
+
if (content !== null && content !== undefined) {
|
|
174
|
+
yield { text: content, done: false };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
// Ignore malformed SSE data lines
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
reader.releaseLock();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=openai_client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai_client.js","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Provider Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements the LLMProvider interface for the OpenAI API.
|
|
5
|
+
* Handles text generation, image understanding, image generation, and streaming.
|
|
6
|
+
*/
|
|
7
|
+
import type { LLMProvider, LLMCapabilities, ServiceType } from '../types.js';
|
|
8
|
+
import type { TextTextParams, ImageTextParams, TextImageParams, ImageImageParams, DocumentTextParams, EmbedParams, EmbedResponse, LLMResponse, LLMStreamResponse, Logger } from '../../llm_api/types.js';
|
|
9
|
+
import { type OpenAIGenerationConfig } from './openai_client.js';
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for the OpenAI provider
|
|
12
|
+
*/
|
|
13
|
+
export interface OpenAIProviderConfig {
|
|
14
|
+
/** API key from .env.local (OPENAI_API_KEY) */
|
|
15
|
+
api_key: string;
|
|
16
|
+
/** Chat completions API URL (default: 'https://api.openai.com/v1/chat/completions') */
|
|
17
|
+
api_url?: string;
|
|
18
|
+
/** Image generation API URL (default: 'https://api.openai.com/v1/images/generations') */
|
|
19
|
+
api_url_image?: string;
|
|
20
|
+
/** Embeddings API URL (default: 'https://api.openai.com/v1/embeddings') */
|
|
21
|
+
api_url_embed?: string;
|
|
22
|
+
/** Model for text_text service (default: 'gpt-4o') */
|
|
23
|
+
model_text_text?: string;
|
|
24
|
+
/** Model for image_text service (default: 'gpt-4o') */
|
|
25
|
+
model_image_text?: string;
|
|
26
|
+
/** Model for text_image service (default: 'gpt-image-1') */
|
|
27
|
+
model_text_image?: string;
|
|
28
|
+
/** Model for embed service (default: 'text-embedding-3-small') */
|
|
29
|
+
model_embed?: string;
|
|
30
|
+
/** Generation parameters applied to text calls */
|
|
31
|
+
generation_config?: OpenAIGenerationConfig;
|
|
32
|
+
/** Capabilities this provider supports (overrides defaults when specified) */
|
|
33
|
+
capabilities?: ServiceType[];
|
|
34
|
+
/** Logger instance */
|
|
35
|
+
logger: Logger;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* OpenAI LLM Provider
|
|
39
|
+
* Implements the LLMProvider interface for the OpenAI API
|
|
40
|
+
*/
|
|
41
|
+
export declare class OpenAIProvider implements LLMProvider {
|
|
42
|
+
private readonly name;
|
|
43
|
+
private readonly api_key;
|
|
44
|
+
private readonly api_url;
|
|
45
|
+
private readonly api_url_image;
|
|
46
|
+
private readonly api_url_embed;
|
|
47
|
+
private readonly model_text_text;
|
|
48
|
+
private readonly model_image_text;
|
|
49
|
+
private readonly model_text_image;
|
|
50
|
+
private readonly model_embed;
|
|
51
|
+
private readonly generation_config;
|
|
52
|
+
private readonly capabilities;
|
|
53
|
+
private readonly logger;
|
|
54
|
+
constructor(config: OpenAIProviderConfig);
|
|
55
|
+
get_name(): string;
|
|
56
|
+
get_capabilities(): LLMCapabilities;
|
|
57
|
+
get_model_for_service(service_type: ServiceType): string | undefined;
|
|
58
|
+
text_text(params: TextTextParams, _logger: Logger): Promise<LLMResponse>;
|
|
59
|
+
image_text(params: ImageTextParams, _logger: Logger): Promise<LLMResponse>;
|
|
60
|
+
text_image(params: TextImageParams, _logger: Logger): Promise<LLMResponse>;
|
|
61
|
+
text_text_stream(params: TextTextParams, _logger: Logger): Promise<LLMStreamResponse>;
|
|
62
|
+
embed(params: EmbedParams, _logger: Logger): Promise<EmbedResponse>;
|
|
63
|
+
image_image(_params: ImageImageParams, _logger: Logger): Promise<LLMResponse>;
|
|
64
|
+
document_text(_params: DocumentTextParams, _logger: Logger): Promise<LLMResponse>;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=openai_provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai_provider.d.ts","sourceRoot":"","sources":["../../../../src/lib/providers/openai/openai_provider.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,eAAe,EACf,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,MAAM,EACP,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAML,KAAK,sBAAsB,EAC5B,MAAM,oBAAoB,CAAC;AAmB5B;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAC;IAEhB,uFAAuF;IACvF,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yFAAyF;IACzF,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,2EAA2E;IAC3E,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,sDAAsD;IACtD,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,4DAA4D;IAC5D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,kDAAkD;IAClD,iBAAiB,CAAC,EAAE,sBAAsB,CAAC;IAE3C,8EAA8E;IAC9E,YAAY,CAAC,EAAE,WAAW,EAAE,CAAC;IAE7B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAMD;;;GAGG;AACH,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAY;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAS;IAC1C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAqC;IACvE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAkB;IAC/C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;gBAEpB,MAAM,EAAE,oBAAoB;IA6BxC,QAAQ,IAAI,MAAM;IAIlB,gBAAgB,IAAI,eAAe;IAInC,qBAAqB,CAAC,YAAY,EAAE,WAAW,GAAG,MAAM,GAAG,SAAS;IAmB9D,SAAS,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqDxE,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IA6D1E,UAAU,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAqD1E,gBAAgB,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAmBrF,KAAK,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAqDnE,WAAW,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAO7E,aAAa,CAAC,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;CAMxF"}
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Provider Implementation
|
|
3
|
+
*
|
|
4
|
+
* Implements the LLMProvider interface for the OpenAI API.
|
|
5
|
+
* Handles text generation, image understanding, image generation, and streaming.
|
|
6
|
+
*/
|
|
7
|
+
import { SERVICE_TYPES } from '../types.js';
|
|
8
|
+
import { call_openai_api, call_openai_image_api, call_openai_api_stream, call_openai_embed_api, } from './openai_client.js';
|
|
9
|
+
import { openai_response_to_usage } from './openai_response_to_usage.js';
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Default constants
|
|
12
|
+
// =============================================================================
|
|
13
|
+
const DEFAULT_API_URL = 'https://api.openai.com/v1/chat/completions';
|
|
14
|
+
const DEFAULT_API_URL_IMAGE = 'https://api.openai.com/v1/images/generations';
|
|
15
|
+
const DEFAULT_API_URL_EMBED = 'https://api.openai.com/v1/embeddings';
|
|
16
|
+
const DEFAULT_MODEL_TEXT_TEXT = 'gpt-4o';
|
|
17
|
+
const DEFAULT_MODEL_IMAGE_TEXT = 'gpt-4o';
|
|
18
|
+
const DEFAULT_MODEL_TEXT_IMAGE = 'gpt-image-1';
|
|
19
|
+
const DEFAULT_MODEL_EMBED = 'text-embedding-3-small';
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// OpenAI Provider Class
|
|
22
|
+
// =============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* OpenAI LLM Provider
|
|
25
|
+
* Implements the LLMProvider interface for the OpenAI API
|
|
26
|
+
*/
|
|
27
|
+
export class OpenAIProvider {
|
|
28
|
+
constructor(config) {
|
|
29
|
+
this.name = 'openai';
|
|
30
|
+
this.api_key = config.api_key;
|
|
31
|
+
this.api_url = config.api_url ?? DEFAULT_API_URL;
|
|
32
|
+
this.api_url_image = config.api_url_image ?? DEFAULT_API_URL_IMAGE;
|
|
33
|
+
this.api_url_embed = config.api_url_embed ?? DEFAULT_API_URL_EMBED;
|
|
34
|
+
this.model_text_text = config.model_text_text ?? DEFAULT_MODEL_TEXT_TEXT;
|
|
35
|
+
this.model_image_text = config.model_image_text ?? DEFAULT_MODEL_IMAGE_TEXT;
|
|
36
|
+
this.model_text_image = config.model_text_image ?? DEFAULT_MODEL_TEXT_IMAGE;
|
|
37
|
+
this.model_embed = config.model_embed ?? DEFAULT_MODEL_EMBED;
|
|
38
|
+
this.generation_config = config.generation_config;
|
|
39
|
+
this.logger = config.logger;
|
|
40
|
+
if (config.capabilities && config.capabilities.length > 0) {
|
|
41
|
+
this.capabilities = new Set(config.capabilities);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
this.capabilities = new Set([
|
|
45
|
+
SERVICE_TYPES.TEXT_TEXT,
|
|
46
|
+
SERVICE_TYPES.IMAGE_TEXT,
|
|
47
|
+
SERVICE_TYPES.TEXT_IMAGE,
|
|
48
|
+
SERVICE_TYPES.EMBED,
|
|
49
|
+
'text_text_stream',
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// =========================================================================
|
|
54
|
+
// LLMProvider interface — identity & introspection
|
|
55
|
+
// =========================================================================
|
|
56
|
+
get_name() {
|
|
57
|
+
return this.name;
|
|
58
|
+
}
|
|
59
|
+
get_capabilities() {
|
|
60
|
+
return new Set(this.capabilities);
|
|
61
|
+
}
|
|
62
|
+
get_model_for_service(service_type) {
|
|
63
|
+
switch (service_type) {
|
|
64
|
+
case SERVICE_TYPES.TEXT_TEXT:
|
|
65
|
+
return this.model_text_text;
|
|
66
|
+
case SERVICE_TYPES.IMAGE_TEXT:
|
|
67
|
+
return this.model_image_text;
|
|
68
|
+
case SERVICE_TYPES.TEXT_IMAGE:
|
|
69
|
+
return this.model_text_image;
|
|
70
|
+
case SERVICE_TYPES.EMBED:
|
|
71
|
+
return this.model_embed;
|
|
72
|
+
default:
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// =========================================================================
|
|
77
|
+
// text_text — Text input → Text output
|
|
78
|
+
// =========================================================================
|
|
79
|
+
async text_text(params, _logger) {
|
|
80
|
+
const model = this.model_text_text;
|
|
81
|
+
const messages = [
|
|
82
|
+
{ role: 'user', content: params.prompt ?? '' },
|
|
83
|
+
];
|
|
84
|
+
const start_time = Date.now();
|
|
85
|
+
let raw;
|
|
86
|
+
let status;
|
|
87
|
+
try {
|
|
88
|
+
({ raw, status } = await call_openai_api({
|
|
89
|
+
api_key: this.api_key,
|
|
90
|
+
api_url: this.api_url,
|
|
91
|
+
model,
|
|
92
|
+
messages,
|
|
93
|
+
generation_config: this.generation_config,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
98
|
+
return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
|
|
99
|
+
}
|
|
100
|
+
const latency_ms = Date.now() - start_time;
|
|
101
|
+
if (status >= 400) {
|
|
102
|
+
const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
|
|
103
|
+
return {
|
|
104
|
+
success: false,
|
|
105
|
+
error: `OpenAI API error: ${status}`,
|
|
106
|
+
error_code,
|
|
107
|
+
retryable: error_code === 'RATE_LIMITED',
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
const choices = raw.choices;
|
|
111
|
+
const message = choices?.[0]?.message;
|
|
112
|
+
const data = message?.content;
|
|
113
|
+
const usage = openai_response_to_usage({ raw, model_fallback: model, latency_ms });
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
data,
|
|
117
|
+
text: data,
|
|
118
|
+
raw_response: raw,
|
|
119
|
+
usage,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
// =========================================================================
|
|
123
|
+
// image_text — Image input → Text output
|
|
124
|
+
// =========================================================================
|
|
125
|
+
async image_text(params, _logger) {
|
|
126
|
+
const model = this.model_image_text;
|
|
127
|
+
const url = `data:${params.image_mime_type};base64,${params.image_b64}`;
|
|
128
|
+
const messages = [
|
|
129
|
+
{
|
|
130
|
+
role: 'user',
|
|
131
|
+
content: [
|
|
132
|
+
{ type: 'image_url', image_url: { url } },
|
|
133
|
+
{ type: 'text', text: params.prompt },
|
|
134
|
+
],
|
|
135
|
+
},
|
|
136
|
+
];
|
|
137
|
+
const start_time = Date.now();
|
|
138
|
+
let raw;
|
|
139
|
+
let status;
|
|
140
|
+
try {
|
|
141
|
+
({ raw, status } = await call_openai_api({
|
|
142
|
+
api_key: this.api_key,
|
|
143
|
+
api_url: this.api_url,
|
|
144
|
+
model,
|
|
145
|
+
messages,
|
|
146
|
+
generation_config: this.generation_config,
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
151
|
+
return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
|
|
152
|
+
}
|
|
153
|
+
const latency_ms = Date.now() - start_time;
|
|
154
|
+
if (status >= 400) {
|
|
155
|
+
const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
|
|
156
|
+
return {
|
|
157
|
+
success: false,
|
|
158
|
+
error: `OpenAI API error: ${status}`,
|
|
159
|
+
error_code,
|
|
160
|
+
retryable: error_code === 'RATE_LIMITED',
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const choices = raw.choices;
|
|
164
|
+
const message = choices?.[0]?.message;
|
|
165
|
+
const data = message?.content;
|
|
166
|
+
const usage = openai_response_to_usage({ raw, model_fallback: model, latency_ms });
|
|
167
|
+
return {
|
|
168
|
+
success: true,
|
|
169
|
+
data,
|
|
170
|
+
text: data,
|
|
171
|
+
raw_response: raw,
|
|
172
|
+
usage,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
// =========================================================================
|
|
176
|
+
// text_image — Text input → Image output
|
|
177
|
+
// =========================================================================
|
|
178
|
+
async text_image(params, _logger) {
|
|
179
|
+
const model = this.model_text_image;
|
|
180
|
+
const start_time = Date.now();
|
|
181
|
+
let raw;
|
|
182
|
+
let status;
|
|
183
|
+
try {
|
|
184
|
+
({ raw, status } = await call_openai_image_api({
|
|
185
|
+
api_key: this.api_key,
|
|
186
|
+
api_url_image: this.api_url_image,
|
|
187
|
+
model,
|
|
188
|
+
prompt: params.prompt,
|
|
189
|
+
}));
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
193
|
+
return { success: false, error, error_code: 'NETWORK_ERROR', retryable: true };
|
|
194
|
+
}
|
|
195
|
+
const latency_ms = Date.now() - start_time;
|
|
196
|
+
if (status >= 400) {
|
|
197
|
+
const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: `OpenAI API error: ${status}`,
|
|
201
|
+
error_code,
|
|
202
|
+
retryable: error_code === 'RATE_LIMITED',
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
const image_data_arr = raw.data;
|
|
206
|
+
const data = image_data_arr?.[0]?.b64_json;
|
|
207
|
+
return {
|
|
208
|
+
success: true,
|
|
209
|
+
data,
|
|
210
|
+
image_b64: data,
|
|
211
|
+
image_mime_type: 'image/png',
|
|
212
|
+
raw_response: raw,
|
|
213
|
+
usage: {
|
|
214
|
+
provider: 'openai',
|
|
215
|
+
model,
|
|
216
|
+
tokens: { input: 0, output: 0, total: 0 },
|
|
217
|
+
latency_ms,
|
|
218
|
+
},
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
// =========================================================================
|
|
222
|
+
// text_text_stream — Text input → streaming Text output
|
|
223
|
+
// =========================================================================
|
|
224
|
+
async text_text_stream(params, _logger) {
|
|
225
|
+
const model = this.model_text_text;
|
|
226
|
+
const messages = [
|
|
227
|
+
{ role: 'user', content: params.prompt ?? '' },
|
|
228
|
+
];
|
|
229
|
+
return call_openai_api_stream({
|
|
230
|
+
api_key: this.api_key,
|
|
231
|
+
api_url: this.api_url,
|
|
232
|
+
model,
|
|
233
|
+
messages,
|
|
234
|
+
generation_config: this.generation_config,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
// =========================================================================
|
|
238
|
+
// embed — Text input → Vector embeddings output
|
|
239
|
+
// =========================================================================
|
|
240
|
+
async embed(params, _logger) {
|
|
241
|
+
const api_url_embed = this.api_url_embed;
|
|
242
|
+
const model = params.model ?? this.model_embed;
|
|
243
|
+
const start_time = Date.now();
|
|
244
|
+
const { raw, status } = await call_openai_embed_api({
|
|
245
|
+
api_key: this.api_key,
|
|
246
|
+
api_url_embed,
|
|
247
|
+
model,
|
|
248
|
+
input: params.text,
|
|
249
|
+
});
|
|
250
|
+
const latency_ms = Date.now() - start_time;
|
|
251
|
+
if (status >= 400) {
|
|
252
|
+
const error_code = status === 429 ? 'RATE_LIMITED' : 'API_ERROR';
|
|
253
|
+
return {
|
|
254
|
+
success: false,
|
|
255
|
+
error: `OpenAI Embeddings API error: ${status}`,
|
|
256
|
+
error_code,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
// Sort data by index (OpenAI guarantees order but let's be safe)
|
|
260
|
+
const data = raw.data
|
|
261
|
+
.sort((a, b) => a.index - b.index);
|
|
262
|
+
const vectors = data.map(d => d.embedding);
|
|
263
|
+
const dimensions = vectors[0]?.length;
|
|
264
|
+
const usage_raw = raw.usage;
|
|
265
|
+
const input_tokens = usage_raw?.prompt_tokens ?? 0;
|
|
266
|
+
const total_tokens = usage_raw?.total_tokens ?? 0;
|
|
267
|
+
const response_model = typeof raw.model === 'string' ? raw.model : model;
|
|
268
|
+
return {
|
|
269
|
+
success: true,
|
|
270
|
+
vectors,
|
|
271
|
+
dimensions,
|
|
272
|
+
model: response_model,
|
|
273
|
+
usage: {
|
|
274
|
+
provider: 'openai',
|
|
275
|
+
model: response_model,
|
|
276
|
+
tokens: { input: input_tokens, output: 0, total: total_tokens },
|
|
277
|
+
latency_ms,
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
// =========================================================================
|
|
282
|
+
// Unsupported methods (satisfy LLMProvider interface completeness)
|
|
283
|
+
// =========================================================================
|
|
284
|
+
async image_image(_params, _logger) {
|
|
285
|
+
return {
|
|
286
|
+
success: false,
|
|
287
|
+
error: 'OpenAI provider does not support image_image via this implementation',
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
async document_text(_params, _logger) {
|
|
291
|
+
return {
|
|
292
|
+
success: false,
|
|
293
|
+
error: 'OpenAI provider does not support document_text via this implementation',
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
//# sourceMappingURL=openai_provider.js.map
|