langfun 0.0.2.dev20240330__py3-none-any.whl → 0.1.2.dev202501140804__py3-none-any.whl
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.
- langfun/__init__.py +22 -2
- langfun/core/__init__.py +17 -5
- langfun/core/agentic/__init__.py +30 -0
- langfun/core/agentic/action.py +854 -0
- langfun/core/agentic/action_eval.py +150 -0
- langfun/core/agentic/action_eval_test.py +109 -0
- langfun/core/agentic/action_test.py +136 -0
- langfun/core/coding/python/__init__.py +5 -11
- langfun/core/coding/python/correction.py +37 -28
- langfun/core/coding/python/correction_test.py +29 -3
- langfun/core/coding/python/execution.py +40 -216
- langfun/core/coding/python/execution_test.py +29 -89
- langfun/core/coding/python/generation.py +21 -11
- langfun/core/coding/python/generation_test.py +2 -2
- langfun/core/coding/python/parsing.py +108 -193
- langfun/core/coding/python/parsing_test.py +2 -105
- langfun/core/component.py +69 -2
- langfun/core/component_test.py +54 -0
- langfun/core/concurrent.py +414 -117
- langfun/core/concurrent_test.py +111 -24
- langfun/core/console.py +18 -5
- langfun/core/console_test.py +17 -0
- langfun/core/eval/__init__.py +17 -0
- langfun/core/eval/base.py +767 -140
- langfun/core/eval/base_test.py +238 -53
- langfun/core/eval/matching.py +80 -76
- langfun/core/eval/matching_test.py +19 -9
- langfun/core/eval/patching.py +130 -0
- langfun/core/eval/patching_test.py +170 -0
- langfun/core/eval/scoring.py +37 -28
- langfun/core/eval/scoring_test.py +21 -3
- langfun/core/eval/v2/__init__.py +42 -0
- langfun/core/eval/v2/checkpointing.py +380 -0
- langfun/core/eval/v2/checkpointing_test.py +228 -0
- langfun/core/eval/v2/eval_test_helper.py +136 -0
- langfun/core/eval/v2/evaluation.py +725 -0
- langfun/core/eval/v2/evaluation_test.py +180 -0
- langfun/core/eval/v2/example.py +305 -0
- langfun/core/eval/v2/example_test.py +128 -0
- langfun/core/eval/v2/experiment.py +1048 -0
- langfun/core/eval/v2/experiment_test.py +433 -0
- langfun/core/eval/v2/metric_values.py +156 -0
- langfun/core/eval/v2/metric_values_test.py +80 -0
- langfun/core/eval/v2/metrics.py +357 -0
- langfun/core/eval/v2/metrics_test.py +203 -0
- langfun/core/eval/v2/progress.py +348 -0
- langfun/core/eval/v2/progress_test.py +82 -0
- langfun/core/eval/v2/progress_tracking.py +210 -0
- langfun/core/eval/v2/progress_tracking_test.py +66 -0
- langfun/core/eval/v2/reporting.py +270 -0
- langfun/core/eval/v2/reporting_test.py +158 -0
- langfun/core/eval/v2/runners.py +488 -0
- langfun/core/eval/v2/runners_test.py +334 -0
- langfun/core/langfunc.py +3 -21
- langfun/core/langfunc_test.py +26 -8
- langfun/core/language_model.py +686 -48
- langfun/core/language_model_test.py +681 -44
- langfun/core/llms/__init__.py +100 -12
- langfun/core/llms/anthropic.py +488 -0
- langfun/core/llms/anthropic_test.py +235 -0
- langfun/core/llms/cache/base.py +21 -2
- langfun/core/llms/cache/in_memory.py +13 -0
- langfun/core/llms/cache/in_memory_test.py +88 -28
- langfun/core/llms/compositional.py +101 -0
- langfun/core/llms/compositional_test.py +73 -0
- langfun/core/llms/deepseek.py +117 -0
- langfun/core/llms/deepseek_test.py +61 -0
- langfun/core/llms/fake.py +39 -26
- langfun/core/llms/fake_test.py +136 -11
- langfun/core/llms/gemini.py +507 -0
- langfun/core/llms/gemini_test.py +195 -0
- langfun/core/llms/google_genai.py +62 -218
- langfun/core/llms/google_genai_test.py +9 -197
- langfun/core/llms/groq.py +276 -0
- langfun/core/llms/groq_test.py +64 -0
- langfun/core/llms/llama_cpp.py +15 -40
- langfun/core/llms/llama_cpp_test.py +4 -30
- langfun/core/llms/openai.py +436 -226
- langfun/core/llms/openai_compatible.py +179 -0
- langfun/core/llms/openai_compatible_test.py +495 -0
- langfun/core/llms/openai_test.py +35 -174
- langfun/core/llms/rest.py +113 -0
- langfun/core/llms/rest_test.py +111 -0
- langfun/core/llms/vertexai.py +192 -0
- langfun/core/llms/vertexai_test.py +52 -0
- langfun/core/logging.py +284 -0
- langfun/core/logging_test.py +125 -0
- langfun/core/message.py +319 -9
- langfun/core/message_test.py +190 -13
- langfun/core/modalities/__init__.py +6 -2
- langfun/core/modalities/audio.py +30 -0
- langfun/core/modalities/audio_test.py +63 -0
- langfun/core/modalities/image.py +39 -20
- langfun/core/modalities/image_test.py +52 -9
- langfun/core/modalities/mime.py +206 -29
- langfun/core/modalities/mime_test.py +90 -9
- langfun/core/modalities/ms_office.py +117 -0
- langfun/core/modalities/ms_office_test.py +389 -0
- langfun/core/modalities/pdf.py +22 -0
- langfun/core/modalities/pdf_test.py +57 -0
- langfun/core/modalities/video.py +9 -23
- langfun/core/modalities/video_test.py +3 -3
- langfun/core/modality.py +26 -3
- langfun/core/modality_test.py +2 -2
- langfun/core/sampling.py +11 -11
- langfun/core/structured/__init__.py +15 -16
- langfun/core/structured/completion.py +32 -5
- langfun/core/structured/completion_test.py +9 -8
- langfun/core/structured/description.py +2 -2
- langfun/core/structured/description_test.py +3 -3
- langfun/core/structured/function_generation.py +278 -0
- langfun/core/structured/function_generation_test.py +399 -0
- langfun/core/structured/mapping.py +150 -46
- langfun/core/structured/mapping_test.py +105 -0
- langfun/core/structured/parsing.py +33 -21
- langfun/core/structured/parsing_test.py +71 -22
- langfun/core/structured/querying.py +746 -0
- langfun/core/structured/{prompting_test.py → querying_test.py} +545 -60
- langfun/core/structured/schema.py +208 -99
- langfun/core/structured/schema_generation.py +1 -1
- langfun/core/structured/schema_generation_test.py +2 -2
- langfun/core/structured/schema_test.py +133 -34
- langfun/core/structured/scoring.py +125 -19
- langfun/core/structured/scoring_test.py +30 -0
- langfun/core/structured/tokenization.py +64 -0
- langfun/core/structured/tokenization_test.py +48 -0
- langfun/core/template.py +240 -11
- langfun/core/template_test.py +146 -1
- langfun/core/templates/conversation.py +9 -0
- langfun/core/templates/conversation_test.py +4 -3
- langfun/core/templates/selfplay_test.py +14 -2
- langfun-0.1.2.dev202501140804.dist-info/METADATA +225 -0
- langfun-0.1.2.dev202501140804.dist-info/RECORD +153 -0
- {langfun-0.0.2.dev20240330.dist-info → langfun-0.1.2.dev202501140804.dist-info}/WHEEL +1 -1
- langfun/core/coding/python/errors.py +0 -108
- langfun/core/coding/python/errors_test.py +0 -99
- langfun/core/coding/python/permissions.py +0 -90
- langfun/core/coding/python/permissions_test.py +0 -86
- langfun/core/structured/prompting.py +0 -217
- langfun/core/text_formatting.py +0 -162
- langfun/core/text_formatting_test.py +0 -47
- langfun-0.0.2.dev20240330.dist-info/METADATA +0 -99
- langfun-0.0.2.dev20240330.dist-info/RECORD +0 -102
- {langfun-0.0.2.dev20240330.dist-info → langfun-0.1.2.dev202501140804.dist-info}/LICENSE +0 -0
- {langfun-0.0.2.dev20240330.dist-info → langfun-0.1.2.dev202501140804.dist-info}/top_level.txt +0 -0
langfun/core/llms/__init__.py
CHANGED
@@ -24,31 +24,88 @@ from langfun.core.llms.fake import StaticMapping
|
|
24
24
|
from langfun.core.llms.fake import StaticResponse
|
25
25
|
from langfun.core.llms.fake import StaticSequence
|
26
26
|
|
27
|
+
# Compositional models.
|
28
|
+
from langfun.core.llms.compositional import RandomChoice
|
29
|
+
|
30
|
+
# REST-based models.
|
31
|
+
from langfun.core.llms.rest import REST
|
32
|
+
|
27
33
|
# Gemini models.
|
28
34
|
from langfun.core.llms.google_genai import GenAI
|
29
|
-
from langfun.core.llms.google_genai import
|
30
|
-
from langfun.core.llms.google_genai import
|
31
|
-
from langfun.core.llms.google_genai import
|
32
|
-
from langfun.core.llms.google_genai import
|
35
|
+
from langfun.core.llms.google_genai import GeminiFlash2_0ThinkingExp_20241219
|
36
|
+
from langfun.core.llms.google_genai import GeminiFlash2_0Exp
|
37
|
+
from langfun.core.llms.google_genai import GeminiExp_20241206
|
38
|
+
from langfun.core.llms.google_genai import GeminiExp_20241114
|
39
|
+
from langfun.core.llms.google_genai import GeminiPro1_5
|
40
|
+
from langfun.core.llms.google_genai import GeminiPro1_5_002
|
41
|
+
from langfun.core.llms.google_genai import GeminiPro1_5_001
|
42
|
+
from langfun.core.llms.google_genai import GeminiFlash1_5
|
43
|
+
from langfun.core.llms.google_genai import GeminiFlash1_5_002
|
44
|
+
from langfun.core.llms.google_genai import GeminiFlash1_5_001
|
45
|
+
from langfun.core.llms.google_genai import GeminiPro1
|
46
|
+
|
47
|
+
from langfun.core.llms.vertexai import VertexAI
|
48
|
+
from langfun.core.llms.vertexai import VertexAIGeminiFlash2_0ThinkingExp_20241219
|
49
|
+
from langfun.core.llms.vertexai import VertexAIGeminiFlash2_0Exp
|
50
|
+
from langfun.core.llms.vertexai import VertexAIGeminiExp_20241206
|
51
|
+
from langfun.core.llms.vertexai import VertexAIGeminiExp_20241114
|
52
|
+
from langfun.core.llms.vertexai import VertexAIGeminiPro1_5
|
53
|
+
from langfun.core.llms.vertexai import VertexAIGeminiPro1_5_002
|
54
|
+
from langfun.core.llms.vertexai import VertexAIGeminiPro1_5_001
|
55
|
+
from langfun.core.llms.vertexai import VertexAIGeminiFlash1_5
|
56
|
+
from langfun.core.llms.vertexai import VertexAIGeminiFlash1_5_002
|
57
|
+
from langfun.core.llms.vertexai import VertexAIGeminiFlash1_5_001
|
58
|
+
from langfun.core.llms.vertexai import VertexAIGeminiPro1
|
59
|
+
|
60
|
+
# Base for OpenAI-compatible models.
|
61
|
+
from langfun.core.llms.openai_compatible import OpenAICompatible
|
33
62
|
|
34
63
|
# OpenAI models.
|
35
64
|
from langfun.core.llms.openai import OpenAI
|
36
65
|
|
66
|
+
from langfun.core.llms.openai import GptO1
|
67
|
+
from langfun.core.llms.openai import GptO1Preview
|
68
|
+
from langfun.core.llms.openai import GptO1Preview_20240912
|
69
|
+
from langfun.core.llms.openai import GptO1Mini
|
70
|
+
from langfun.core.llms.openai import GptO1Mini_20240912
|
71
|
+
|
72
|
+
from langfun.core.llms.openai import Gpt4oMini
|
73
|
+
from langfun.core.llms.openai import Gpt4oMini_20240718
|
74
|
+
from langfun.core.llms.openai import Gpt4o
|
75
|
+
from langfun.core.llms.openai import Gpt4o_20241120
|
76
|
+
from langfun.core.llms.openai import Gpt4o_20240806
|
77
|
+
from langfun.core.llms.openai import Gpt4o_20240513
|
78
|
+
|
37
79
|
from langfun.core.llms.openai import Gpt4Turbo
|
38
|
-
from langfun.core.llms.openai import
|
39
|
-
from langfun.core.llms.openai import
|
80
|
+
from langfun.core.llms.openai import Gpt4Turbo_20240409
|
81
|
+
from langfun.core.llms.openai import Gpt4TurboPreview
|
82
|
+
from langfun.core.llms.openai import Gpt4TurboPreview_20240125
|
83
|
+
from langfun.core.llms.openai import Gpt4TurboPreview_20231106
|
84
|
+
from langfun.core.llms.openai import Gpt4VisionPreview
|
85
|
+
from langfun.core.llms.openai import Gpt4VisionPreview_20231106
|
40
86
|
from langfun.core.llms.openai import Gpt4
|
41
|
-
from langfun.core.llms.openai import
|
87
|
+
from langfun.core.llms.openai import Gpt4_20230613
|
88
|
+
|
42
89
|
from langfun.core.llms.openai import Gpt4_32K
|
43
|
-
from langfun.core.llms.openai import
|
90
|
+
from langfun.core.llms.openai import Gpt4_32K_20230613
|
44
91
|
|
45
92
|
from langfun.core.llms.openai import Gpt35Turbo
|
46
|
-
from langfun.core.llms.openai import
|
47
|
-
from langfun.core.llms.openai import
|
48
|
-
from langfun.core.llms.openai import
|
93
|
+
from langfun.core.llms.openai import Gpt35Turbo_20240125
|
94
|
+
from langfun.core.llms.openai import Gpt35Turbo_20231106
|
95
|
+
from langfun.core.llms.openai import Gpt35Turbo_20230613
|
49
96
|
from langfun.core.llms.openai import Gpt35Turbo16K
|
50
|
-
from langfun.core.llms.openai import
|
97
|
+
from langfun.core.llms.openai import Gpt35Turbo16K_20230613
|
51
98
|
|
99
|
+
# For backward compatibility.
|
100
|
+
Gpt4TurboPreview_0125 = Gpt4TurboPreview_20240125
|
101
|
+
Gpt4TurboPreview_1106 = Gpt4TurboPreview_20231106
|
102
|
+
Gpt4VisionPreview_1106 = Gpt4VisionPreview_20231106
|
103
|
+
Gpt4_0613 = Gpt4_20230613
|
104
|
+
Gpt4_32K_0613 = Gpt4_32K_20230613
|
105
|
+
Gpt35Turbo_0125 = Gpt35Turbo_20240125
|
106
|
+
Gpt35Turbo_1106 = Gpt35Turbo_20231106
|
107
|
+
Gpt35Turbo_0613 = Gpt35Turbo_20230613
|
108
|
+
Gpt35Turbo16K_0613 = Gpt35Turbo16K_20230613
|
52
109
|
|
53
110
|
from langfun.core.llms.openai import Gpt35
|
54
111
|
|
@@ -57,9 +114,40 @@ from langfun.core.llms.openai import Gpt3Curie
|
|
57
114
|
from langfun.core.llms.openai import Gpt3Babbage
|
58
115
|
from langfun.core.llms.openai import Gpt3Ada
|
59
116
|
|
117
|
+
from langfun.core.llms.anthropic import Anthropic
|
118
|
+
from langfun.core.llms.anthropic import Claude35Sonnet
|
119
|
+
from langfun.core.llms.anthropic import Claude35Sonnet20241022
|
120
|
+
from langfun.core.llms.anthropic import Claude35Sonnet20240620
|
121
|
+
from langfun.core.llms.anthropic import Claude3Opus
|
122
|
+
from langfun.core.llms.anthropic import Claude3Sonnet
|
123
|
+
from langfun.core.llms.anthropic import Claude3Haiku
|
124
|
+
from langfun.core.llms.anthropic import VertexAIAnthropic
|
125
|
+
from langfun.core.llms.anthropic import VertexAIClaude3_5_Sonnet_20241022
|
126
|
+
from langfun.core.llms.anthropic import VertexAIClaude3_5_Sonnet_20240620
|
127
|
+
from langfun.core.llms.anthropic import VertexAIClaude3_5_Haiku_20241022
|
128
|
+
from langfun.core.llms.anthropic import VertexAIClaude3_Opus_20240229
|
129
|
+
|
130
|
+
from langfun.core.llms.groq import Groq
|
131
|
+
from langfun.core.llms.groq import GroqLlama3_2_3B
|
132
|
+
from langfun.core.llms.groq import GroqLlama3_2_1B
|
133
|
+
from langfun.core.llms.groq import GroqLlama3_1_70B
|
134
|
+
from langfun.core.llms.groq import GroqLlama3_1_8B
|
135
|
+
from langfun.core.llms.groq import GroqLlama3_70B
|
136
|
+
from langfun.core.llms.groq import GroqLlama3_8B
|
137
|
+
from langfun.core.llms.groq import GroqLlama2_70B
|
138
|
+
from langfun.core.llms.groq import GroqMistral_8x7B
|
139
|
+
from langfun.core.llms.groq import GroqGemma2_9B_IT
|
140
|
+
from langfun.core.llms.groq import GroqGemma_7B_IT
|
141
|
+
from langfun.core.llms.groq import GroqWhisper_Large_v3
|
142
|
+
from langfun.core.llms.groq import GroqWhisper_Large_v3Turbo
|
143
|
+
|
60
144
|
# LLaMA C++ models.
|
61
145
|
from langfun.core.llms.llama_cpp import LlamaCppRemote
|
62
146
|
|
147
|
+
# DeepSeek models.
|
148
|
+
from langfun.core.llms.deepseek import DeepSeek
|
149
|
+
from langfun.core.llms.deepseek import DeepSeekChat
|
150
|
+
|
63
151
|
# Placeholder for Google-internal imports.
|
64
152
|
|
65
153
|
# Include cache as sub-module.
|
@@ -0,0 +1,488 @@
|
|
1
|
+
# Copyright 2023 The Langfun Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
"""Language models from Anthropic."""
|
15
|
+
|
16
|
+
import base64
|
17
|
+
import functools
|
18
|
+
import os
|
19
|
+
from typing import Annotated, Any, Literal
|
20
|
+
|
21
|
+
import langfun.core as lf
|
22
|
+
from langfun.core import modalities as lf_modalities
|
23
|
+
from langfun.core.llms import rest
|
24
|
+
import pyglove as pg
|
25
|
+
|
26
|
+
|
27
|
+
try:
|
28
|
+
# pylint: disable=g-import-not-at-top
|
29
|
+
from google import auth as google_auth
|
30
|
+
from google.auth import credentials as credentials_lib
|
31
|
+
from google.auth.transport import requests as auth_requests
|
32
|
+
Credentials = credentials_lib.Credentials
|
33
|
+
# pylint: enable=g-import-not-at-top
|
34
|
+
except ImportError:
|
35
|
+
google_auth = None
|
36
|
+
auth_requests = None
|
37
|
+
credentials_lib = None
|
38
|
+
Credentials = Any # pylint: disable=invalid-name
|
39
|
+
|
40
|
+
|
41
|
+
SUPPORTED_MODELS_AND_SETTINGS = {
|
42
|
+
# See https://docs.anthropic.com/claude/docs/models-overview
|
43
|
+
# Rate limits from https://docs.anthropic.com/claude/reference/rate-limits
|
44
|
+
# RPM/TPM for Claude-2.1, Claude-2.0, and Claude-Instant-1.2 estimated
|
45
|
+
# as RPM/TPM of the largest-available model (Claude-3-Opus).
|
46
|
+
# Price in US dollars at https://www.anthropic.com/pricing
|
47
|
+
# as of 2024-10-10.
|
48
|
+
# Anthropic models hosted on VertexAI.
|
49
|
+
'claude-3-5-sonnet-v2@20241022': pg.Dict(
|
50
|
+
max_tokens=8192,
|
51
|
+
rpm=1000,
|
52
|
+
tpm=100000,
|
53
|
+
cost_per_1k_input_tokens=0.003,
|
54
|
+
cost_per_1k_output_tokens=0.015,
|
55
|
+
),
|
56
|
+
'claude-3-5-sonnet@20240620': pg.Dict(
|
57
|
+
max_tokens=8192,
|
58
|
+
rpm=1000,
|
59
|
+
tpm=100000,
|
60
|
+
cost_per_1k_input_tokens=0.003,
|
61
|
+
cost_per_1k_output_tokens=0.015,
|
62
|
+
),
|
63
|
+
'claude-3-5-haiku@20241022': pg.Dict(
|
64
|
+
max_tokens=8192,
|
65
|
+
rpm=1000,
|
66
|
+
tpm=100000,
|
67
|
+
cost_per_1k_input_tokens=0.001,
|
68
|
+
cost_per_1k_output_tokens=0.005,
|
69
|
+
),
|
70
|
+
'claude-3-opus@20240229': pg.Dict(
|
71
|
+
max_tokens=4096,
|
72
|
+
rpm=4000,
|
73
|
+
tpm=400000,
|
74
|
+
cost_per_1k_input_tokens=0.015,
|
75
|
+
cost_per_1k_output_tokens=0.075,
|
76
|
+
),
|
77
|
+
# Anthropic hosted models.
|
78
|
+
'claude-3-5-sonnet-20241022': pg.Dict(
|
79
|
+
max_tokens=8192,
|
80
|
+
rpm=4000,
|
81
|
+
tpm=400000,
|
82
|
+
cost_per_1k_input_tokens=0.003,
|
83
|
+
cost_per_1k_output_tokens=0.015,
|
84
|
+
),
|
85
|
+
'claude-3-5-sonnet-20240620': pg.Dict(
|
86
|
+
max_tokens=8192,
|
87
|
+
rpm=4000,
|
88
|
+
tpm=400000,
|
89
|
+
cost_per_1k_input_tokens=0.003,
|
90
|
+
cost_per_1k_output_tokens=0.015,
|
91
|
+
),
|
92
|
+
'claude-3-5-haiku-20241022': pg.Dict(
|
93
|
+
max_tokens=8192,
|
94
|
+
rpm=4000,
|
95
|
+
tpm=400000,
|
96
|
+
cost_per_1k_input_tokens=0.001,
|
97
|
+
cost_per_1k_output_tokens=0.005,
|
98
|
+
),
|
99
|
+
'claude-3-opus-20240229': pg.Dict(
|
100
|
+
max_tokens=4096,
|
101
|
+
rpm=4000,
|
102
|
+
tpm=400000,
|
103
|
+
cost_per_1k_input_tokens=0.015,
|
104
|
+
cost_per_1k_output_tokens=0.075,
|
105
|
+
),
|
106
|
+
'claude-3-sonnet-20240229': pg.Dict(
|
107
|
+
max_tokens=4096,
|
108
|
+
rpm=4000,
|
109
|
+
tpm=400000,
|
110
|
+
cost_per_1k_input_tokens=0.003,
|
111
|
+
cost_per_1k_output_tokens=0.015,
|
112
|
+
),
|
113
|
+
'claude-3-haiku-20240307': pg.Dict(
|
114
|
+
max_tokens=4096,
|
115
|
+
rpm=4000,
|
116
|
+
tpm=400000,
|
117
|
+
cost_per_1k_input_tokens=0.00025,
|
118
|
+
cost_per_1k_output_tokens=0.00125,
|
119
|
+
),
|
120
|
+
'claude-2.1': pg.Dict(
|
121
|
+
max_tokens=4096,
|
122
|
+
rpm=4000,
|
123
|
+
tpm=400000,
|
124
|
+
cost_per_1k_input_tokens=0.008,
|
125
|
+
cost_per_1k_output_tokens=0.024,
|
126
|
+
),
|
127
|
+
'claude-2.0': pg.Dict(
|
128
|
+
max_tokens=4096,
|
129
|
+
rpm=4000,
|
130
|
+
tpm=400000,
|
131
|
+
cost_per_1k_input_tokens=0.008,
|
132
|
+
cost_per_1k_output_tokens=0.024,
|
133
|
+
),
|
134
|
+
'claude-instant-1.2': pg.Dict(
|
135
|
+
max_tokens=4096,
|
136
|
+
rpm=4000,
|
137
|
+
tpm=400000,
|
138
|
+
cost_per_1k_input_tokens=0.0008,
|
139
|
+
cost_per_1k_output_tokens=0.0024,
|
140
|
+
),
|
141
|
+
}
|
142
|
+
|
143
|
+
|
144
|
+
@lf.use_init_args(['model'])
|
145
|
+
class Anthropic(rest.REST):
|
146
|
+
"""Anthropic LLMs (Claude) through REST APIs.
|
147
|
+
|
148
|
+
See https://docs.anthropic.com/claude/reference/messages_post
|
149
|
+
"""
|
150
|
+
|
151
|
+
model: pg.typing.Annotated[
|
152
|
+
pg.typing.Enum(
|
153
|
+
pg.MISSING_VALUE, list(SUPPORTED_MODELS_AND_SETTINGS.keys())
|
154
|
+
),
|
155
|
+
'The name of the model to use.',
|
156
|
+
]
|
157
|
+
|
158
|
+
multimodal: Annotated[bool, 'Whether this model has multimodal support.'] = (
|
159
|
+
True
|
160
|
+
)
|
161
|
+
|
162
|
+
api_key: Annotated[
|
163
|
+
str | None,
|
164
|
+
(
|
165
|
+
'API key. If None, the key will be read from environment variable '
|
166
|
+
"'ANTHROPIC_API_KEY'."
|
167
|
+
),
|
168
|
+
] = None
|
169
|
+
|
170
|
+
api_endpoint: str = 'https://api.anthropic.com/v1/messages'
|
171
|
+
|
172
|
+
api_version: Annotated[
|
173
|
+
str,
|
174
|
+
'Anthropic API version.'
|
175
|
+
] = '2023-06-01'
|
176
|
+
|
177
|
+
def _on_bound(self):
|
178
|
+
super()._on_bound()
|
179
|
+
self._api_key = None
|
180
|
+
|
181
|
+
def _initialize(self):
|
182
|
+
api_key = self.api_key or os.environ.get('ANTHROPIC_API_KEY', None)
|
183
|
+
if not api_key:
|
184
|
+
raise ValueError(
|
185
|
+
'Please specify `api_key` during `__init__` or set environment '
|
186
|
+
'variable `ANTHROPIC_API_KEY` with your Anthropic API key.'
|
187
|
+
)
|
188
|
+
self._api_key = api_key
|
189
|
+
|
190
|
+
@property
|
191
|
+
def headers(self) -> dict[str, Any]:
|
192
|
+
return {
|
193
|
+
'x-api-key': self._api_key,
|
194
|
+
'anthropic-version': self.api_version,
|
195
|
+
'content-type': 'application/json',
|
196
|
+
# TODO(yifenglu): Remove beta flag once the feature is fully supported.
|
197
|
+
'anthropic-beta': 'pdfs-2024-09-25',
|
198
|
+
}
|
199
|
+
|
200
|
+
@property
|
201
|
+
def model_id(self) -> str:
|
202
|
+
"""Returns a string to identify the model."""
|
203
|
+
return self.model
|
204
|
+
|
205
|
+
@property
|
206
|
+
def max_concurrency(self) -> int:
|
207
|
+
rpm = SUPPORTED_MODELS_AND_SETTINGS[self.model].get('rpm', 0)
|
208
|
+
tpm = SUPPORTED_MODELS_AND_SETTINGS[self.model].get('tpm', 0)
|
209
|
+
return self.rate_to_max_concurrency(
|
210
|
+
requests_per_min=rpm, tokens_per_min=tpm
|
211
|
+
)
|
212
|
+
|
213
|
+
def estimate_cost(
|
214
|
+
self,
|
215
|
+
num_input_tokens: int,
|
216
|
+
num_output_tokens: int
|
217
|
+
) -> float | None:
|
218
|
+
"""Estimate the cost based on usage."""
|
219
|
+
cost_per_1k_input_tokens = SUPPORTED_MODELS_AND_SETTINGS[self.model].get(
|
220
|
+
'cost_per_1k_input_tokens', None
|
221
|
+
)
|
222
|
+
cost_per_1k_output_tokens = SUPPORTED_MODELS_AND_SETTINGS[self.model].get(
|
223
|
+
'cost_per_1k_output_tokens', None
|
224
|
+
)
|
225
|
+
if cost_per_1k_output_tokens is None or cost_per_1k_input_tokens is None:
|
226
|
+
return None
|
227
|
+
return (
|
228
|
+
cost_per_1k_input_tokens * num_input_tokens
|
229
|
+
+ cost_per_1k_output_tokens * num_output_tokens
|
230
|
+
) / 1000
|
231
|
+
|
232
|
+
def request(
|
233
|
+
self,
|
234
|
+
prompt: lf.Message,
|
235
|
+
sampling_options: lf.LMSamplingOptions
|
236
|
+
) -> dict[str, Any]:
|
237
|
+
"""Returns the JSON input for a message."""
|
238
|
+
request = dict()
|
239
|
+
request.update(self._request_args(sampling_options))
|
240
|
+
request.update(
|
241
|
+
dict(
|
242
|
+
messages=[
|
243
|
+
dict(role='user', content=self._content_from_message(prompt))
|
244
|
+
]
|
245
|
+
)
|
246
|
+
)
|
247
|
+
return request
|
248
|
+
|
249
|
+
def _request_args(self, options: lf.LMSamplingOptions) -> dict[str, Any]:
|
250
|
+
"""Returns a dict as request arguments."""
|
251
|
+
# Authropic requires `max_tokens` to be specified.
|
252
|
+
max_tokens = (
|
253
|
+
options.max_tokens
|
254
|
+
or SUPPORTED_MODELS_AND_SETTINGS[self.model].max_tokens
|
255
|
+
)
|
256
|
+
args = dict(
|
257
|
+
model=self.model,
|
258
|
+
max_tokens=max_tokens,
|
259
|
+
stream=False,
|
260
|
+
)
|
261
|
+
if options.stop:
|
262
|
+
args['stop_sequences'] = options.stop
|
263
|
+
if options.temperature is not None:
|
264
|
+
args['temperature'] = options.temperature
|
265
|
+
if options.top_k is not None:
|
266
|
+
args['top_k'] = options.top_k
|
267
|
+
if options.top_p is not None:
|
268
|
+
args['top_p'] = options.top_p
|
269
|
+
return args
|
270
|
+
|
271
|
+
def _content_from_message(self, prompt: lf.Message) -> list[dict[str, Any]]:
|
272
|
+
"""Converts an message to Anthropic's content protocol (list of dicts)."""
|
273
|
+
# Refer: https://docs.anthropic.com/claude/reference/messages-examples
|
274
|
+
if self.multimodal:
|
275
|
+
content = []
|
276
|
+
for chunk in prompt.chunk():
|
277
|
+
if isinstance(chunk, str):
|
278
|
+
item = dict(type='text', text=chunk)
|
279
|
+
elif isinstance(chunk, lf_modalities.Image):
|
280
|
+
item = dict(
|
281
|
+
type='image',
|
282
|
+
source=dict(
|
283
|
+
type='base64',
|
284
|
+
media_type=chunk.mime_type,
|
285
|
+
data=base64.b64encode(chunk.to_bytes()).decode(),
|
286
|
+
),
|
287
|
+
)
|
288
|
+
elif isinstance(chunk, lf_modalities.PDF):
|
289
|
+
item = dict(
|
290
|
+
type='document',
|
291
|
+
source=dict(
|
292
|
+
type='base64',
|
293
|
+
media_type=chunk.mime_type,
|
294
|
+
data=base64.b64encode(chunk.to_bytes()).decode(),
|
295
|
+
),
|
296
|
+
)
|
297
|
+
else:
|
298
|
+
raise ValueError(f'Unsupported modality object: {chunk!r}.')
|
299
|
+
content.append(item)
|
300
|
+
return content
|
301
|
+
else:
|
302
|
+
return [dict(type='text', text=prompt.text)]
|
303
|
+
|
304
|
+
def result(self, json: dict[str, Any]) -> lf.LMSamplingResult:
|
305
|
+
message = self._message_from_content(json['content'])
|
306
|
+
input_tokens = json['usage']['input_tokens']
|
307
|
+
output_tokens = json['usage']['output_tokens']
|
308
|
+
return lf.LMSamplingResult(
|
309
|
+
[lf.LMSample(message)],
|
310
|
+
usage=lf.LMSamplingUsage(
|
311
|
+
prompt_tokens=input_tokens,
|
312
|
+
completion_tokens=output_tokens,
|
313
|
+
total_tokens=input_tokens + output_tokens,
|
314
|
+
estimated_cost=self.estimate_cost(
|
315
|
+
num_input_tokens=input_tokens,
|
316
|
+
num_output_tokens=output_tokens,
|
317
|
+
),
|
318
|
+
),
|
319
|
+
)
|
320
|
+
|
321
|
+
def _message_from_content(self, content: list[dict[str, Any]]) -> lf.Message:
|
322
|
+
"""Converts Anthropic's content protocol to message."""
|
323
|
+
# Refer: https://docs.anthropic.com/claude/reference/messages-examples
|
324
|
+
return lf.AIMessage.from_chunks(
|
325
|
+
[x['text'] for x in content if x['type'] == 'text']
|
326
|
+
)
|
327
|
+
|
328
|
+
|
329
|
+
class Claude3(Anthropic):
|
330
|
+
"""Base class for Claude 3 models. 200K input tokens and 4K output tokens."""
|
331
|
+
multimodal = True
|
332
|
+
|
333
|
+
|
334
|
+
class Claude35Sonnet(Claude3):
|
335
|
+
"""A balance between between Opus and Haiku."""
|
336
|
+
model = 'claude-3-5-sonnet-20241022'
|
337
|
+
|
338
|
+
|
339
|
+
class Claude35Sonnet20241022(Claude3):
|
340
|
+
"""A balance between between Opus and Haiku."""
|
341
|
+
|
342
|
+
model = 'claude-3-5-sonnet-20241022'
|
343
|
+
|
344
|
+
|
345
|
+
class Claude35Sonnet20240620(Claude3):
|
346
|
+
"""A balance between between Opus and Haiku."""
|
347
|
+
|
348
|
+
model = 'claude-3-5-sonnet-20240620'
|
349
|
+
|
350
|
+
|
351
|
+
class Claude3Opus(Claude3):
|
352
|
+
"""Anthropic's most powerful model."""
|
353
|
+
|
354
|
+
model = 'claude-3-opus-20240229'
|
355
|
+
|
356
|
+
|
357
|
+
class Claude3Sonnet(Claude3):
|
358
|
+
"""A balance between between Opus and Haiku."""
|
359
|
+
|
360
|
+
model = 'claude-3-sonnet-20240229'
|
361
|
+
|
362
|
+
|
363
|
+
class Claude3Haiku(Claude3):
|
364
|
+
"""Anthropic's most compact model."""
|
365
|
+
|
366
|
+
model = 'claude-3-haiku-20240307'
|
367
|
+
|
368
|
+
|
369
|
+
class Claude2(Anthropic):
|
370
|
+
"""Predecessor to Claude 3 with 100K context window.."""
|
371
|
+
model = 'claude-2.0'
|
372
|
+
|
373
|
+
|
374
|
+
class Claude21(Anthropic):
|
375
|
+
"""Updated Claude 2 model with improved accuracy and 200K context window."""
|
376
|
+
model = 'claude-2.1'
|
377
|
+
|
378
|
+
|
379
|
+
class ClaudeInstant(Anthropic):
|
380
|
+
"""Cheapest small and fast model, 100K context window."""
|
381
|
+
model = 'claude-instant-1.2'
|
382
|
+
|
383
|
+
|
384
|
+
#
|
385
|
+
# Authropic models on VertexAI.
|
386
|
+
#
|
387
|
+
|
388
|
+
|
389
|
+
class VertexAIAnthropic(Anthropic):
|
390
|
+
"""Anthropic models on VertexAI."""
|
391
|
+
|
392
|
+
project: Annotated[
|
393
|
+
str | None,
|
394
|
+
'Google Cloud project ID.',
|
395
|
+
] = None
|
396
|
+
|
397
|
+
location: Annotated[
|
398
|
+
Literal['us-east5', 'europe-west1'],
|
399
|
+
'GCP location with Anthropic models hosted.'
|
400
|
+
] = 'us-east5'
|
401
|
+
|
402
|
+
credentials: Annotated[
|
403
|
+
Credentials | None, # pytype: disable=invalid-annotation
|
404
|
+
(
|
405
|
+
'Credentials to use. If None, the default credentials '
|
406
|
+
'to the environment will be used.'
|
407
|
+
),
|
408
|
+
] = None
|
409
|
+
|
410
|
+
api_version = 'vertex-2023-10-16'
|
411
|
+
|
412
|
+
def _on_bound(self):
|
413
|
+
super()._on_bound()
|
414
|
+
if google_auth is None:
|
415
|
+
raise ValueError(
|
416
|
+
'Please install "langfun[llm-google-vertex]" to use Vertex AI models.'
|
417
|
+
)
|
418
|
+
self._project = None
|
419
|
+
self._credentials = None
|
420
|
+
|
421
|
+
def _initialize(self):
|
422
|
+
project = self.project or os.environ.get('VERTEXAI_PROJECT', None)
|
423
|
+
if not project:
|
424
|
+
raise ValueError(
|
425
|
+
'Please specify `project` during `__init__` or set environment '
|
426
|
+
'variable `VERTEXAI_PROJECT` with your Vertex AI project ID.'
|
427
|
+
)
|
428
|
+
self._project = project
|
429
|
+
credentials = self.credentials
|
430
|
+
if credentials is None:
|
431
|
+
# Use default credentials.
|
432
|
+
credentials = google_auth.default(
|
433
|
+
scopes=['https://www.googleapis.com/auth/cloud-platform']
|
434
|
+
)
|
435
|
+
self._credentials = credentials
|
436
|
+
|
437
|
+
@functools.cached_property
|
438
|
+
def _session(self):
|
439
|
+
assert self._api_initialized
|
440
|
+
assert self._credentials is not None
|
441
|
+
assert auth_requests is not None
|
442
|
+
s = auth_requests.AuthorizedSession(self._credentials)
|
443
|
+
s.headers.update(self.headers or {})
|
444
|
+
return s
|
445
|
+
|
446
|
+
@property
|
447
|
+
def headers(self):
|
448
|
+
return {
|
449
|
+
'Content-Type': 'application/json; charset=utf-8',
|
450
|
+
}
|
451
|
+
|
452
|
+
@property
|
453
|
+
def api_endpoint(self) -> str:
|
454
|
+
return (
|
455
|
+
f'https://{self.location}-aiplatform.googleapis.com/v1/projects/'
|
456
|
+
f'{self._project}/locations/{self.location}/publishers/anthropic/'
|
457
|
+
f'models/{self.model}:streamRawPredict'
|
458
|
+
)
|
459
|
+
|
460
|
+
def request(
|
461
|
+
self,
|
462
|
+
prompt: lf.Message,
|
463
|
+
sampling_options: lf.LMSamplingOptions
|
464
|
+
):
|
465
|
+
request = super().request(prompt, sampling_options)
|
466
|
+
request['anthropic_version'] = self.api_version
|
467
|
+
del request['model']
|
468
|
+
return request
|
469
|
+
|
470
|
+
|
471
|
+
class VertexAIClaude3_Opus_20240229(VertexAIAnthropic): # pylint: disable=invalid-name
|
472
|
+
"""Anthropic's Claude 3 Opus model on VertexAI."""
|
473
|
+
model = 'claude-3-opus@20240229'
|
474
|
+
|
475
|
+
|
476
|
+
class VertexAIClaude3_5_Sonnet_20241022(VertexAIAnthropic): # pylint: disable=invalid-name
|
477
|
+
"""Anthropic's Claude 3.5 Sonnet model on VertexAI."""
|
478
|
+
model = 'claude-3-5-sonnet-v2@20241022'
|
479
|
+
|
480
|
+
|
481
|
+
class VertexAIClaude3_5_Sonnet_20240620(VertexAIAnthropic): # pylint: disable=invalid-name
|
482
|
+
"""Anthropic's Claude 3.5 Sonnet model on VertexAI."""
|
483
|
+
model = 'claude-3-5-sonnet@20240620'
|
484
|
+
|
485
|
+
|
486
|
+
class VertexAIClaude3_5_Haiku_20241022(VertexAIAnthropic): # pylint: disable=invalid-name
|
487
|
+
"""Anthropic's Claude 3.5 Haiku model on VertexAI."""
|
488
|
+
model = 'claude-3-5-haiku@20241022'
|