@l10nmonster/helpers-anthropic 3.0.0-alpha.1
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 +106 -0
- package/anthropicAgent.js +183 -0
- package/example.js +65 -0
- package/index.js +1 -0
- package/package.json +22 -0
package/README.md
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# L10nMonster Anthropic Helper
|
|
2
|
+
|
|
3
|
+
This package provides integration between L10nMonster and Anthropic's Claude models via both direct API and Google Vertex AI.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @l10nmonster/helpers-anthropic
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Direct API Configuration
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import { AnthropicAgent } from '@l10nmonster/helpers-anthropic';
|
|
17
|
+
|
|
18
|
+
const agent = new AnthropicAgent({
|
|
19
|
+
id: 'claude-translator',
|
|
20
|
+
model: 'claude-3-5-sonnet-latest',
|
|
21
|
+
quality: 80,
|
|
22
|
+
temperature: 0.1,
|
|
23
|
+
maxTokens: 4096,
|
|
24
|
+
apiKey: 'your-anthropic-api-key' // Direct API access
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Vertex AI Configuration
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
import { AnthropicAgent } from '@l10nmonster/helpers-anthropic';
|
|
32
|
+
|
|
33
|
+
const agent = new AnthropicAgent({
|
|
34
|
+
id: 'claude-translator',
|
|
35
|
+
model: 'claude-3-5-sonnet@20241022',
|
|
36
|
+
quality: 80,
|
|
37
|
+
temperature: 0.1,
|
|
38
|
+
maxTokens: 4096,
|
|
39
|
+
vertexProject: 'your-gcp-project-id',
|
|
40
|
+
vertexLocation: 'us-central1'
|
|
41
|
+
});
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Authentication
|
|
45
|
+
|
|
46
|
+
The AnthropicAgent supports two authentication methods:
|
|
47
|
+
|
|
48
|
+
#### Direct API
|
|
49
|
+
1. **API Key**: Obtain an API key from [Anthropic Console](https://console.anthropic.com/)
|
|
50
|
+
2. **Set apiKey**: Pass your API key in the configuration
|
|
51
|
+
|
|
52
|
+
#### Vertex AI
|
|
53
|
+
1. **Service Account**: Set up a service account with Vertex AI permissions
|
|
54
|
+
2. **gcloud CLI**: Run `gcloud auth login` and `gcloud config set project YOUR_PROJECT_ID`
|
|
55
|
+
3. **Environment Variables**: Set `GOOGLE_APPLICATION_CREDENTIALS` to point to your service account key file
|
|
56
|
+
|
|
57
|
+
### Retry Behavior
|
|
58
|
+
|
|
59
|
+
The AnthropicAgent uses the native retry mechanism built into both the Anthropic SDK and Anthropic Vertex SDK:
|
|
60
|
+
|
|
61
|
+
- **Automatic Retries**: Both SDKs automatically handle retries with exponential backoff
|
|
62
|
+
- **Configurable**: Set `maxRetries` in the constructor to control retry attempts (passed directly to both SDKs)
|
|
63
|
+
- **Smart Error Handling**: Automatically retries on network errors, rate limits, and temporary service issues
|
|
64
|
+
- **No Manual Implementation**: Unlike other providers, this uses the SDK's native retry logic for better reliability
|
|
65
|
+
- **Consistent Behavior**: The same `maxRetries` value is used whether you're using direct API or Vertex AI
|
|
66
|
+
|
|
67
|
+
### Configuration Options
|
|
68
|
+
|
|
69
|
+
- `model` (required): The Claude model to use
|
|
70
|
+
- `quality` (required): Quality score for translations (0-100)
|
|
71
|
+
- `apiKey`: Your Anthropic API key (for direct API access)
|
|
72
|
+
- `temperature`: Controls randomness (0.0-1.0, default: 0.1)
|
|
73
|
+
- `maxTokens`: Maximum output tokens (default: 4096)
|
|
74
|
+
- `maxRetries`: Maximum number of retries (passed to Anthropic SDK)
|
|
75
|
+
- `vertexProject`: GCP project ID (for Vertex AI, auto-detected if not provided)
|
|
76
|
+
- `vertexLocation`: GCP region (for Vertex AI, default: 'global')
|
|
77
|
+
- `persona`: Custom translator persona (optional)
|
|
78
|
+
- `customSchema`: Custom response schema (optional)
|
|
79
|
+
|
|
80
|
+
## Testing
|
|
81
|
+
|
|
82
|
+
Run the test suite using Node.js built-in testing:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
# From the package directory
|
|
86
|
+
npm test
|
|
87
|
+
|
|
88
|
+
# From the workspace root
|
|
89
|
+
npm test --workspace=helpers-anthropic
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
The test suite includes:
|
|
93
|
+
- Unit tests for all major functionality
|
|
94
|
+
- Integration tests with the LLMTranslationProvider inheritance
|
|
95
|
+
- Error handling and edge case scenarios
|
|
96
|
+
- Mock testing without external API calls
|
|
97
|
+
|
|
98
|
+
## Requirements
|
|
99
|
+
|
|
100
|
+
- Node.js >= 18.0.0
|
|
101
|
+
- Google Cloud Project with Vertex AI API enabled
|
|
102
|
+
- Proper authentication setup for Google Cloud
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
MIT
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import { AnthropicVertex } from '@anthropic-ai/vertex-sdk';
|
|
2
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
3
|
+
import { GoogleAuth } from 'google-auth-library';
|
|
4
|
+
|
|
5
|
+
import { logInfo, logVerbose, logWarn, providers, styleString } from '../core/index.js';
|
|
6
|
+
|
|
7
|
+
const TRANSLATION_TOOL = {
|
|
8
|
+
name: 'provide_translations',
|
|
9
|
+
description: 'Provide translations for the given strings',
|
|
10
|
+
input_schema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
translations: {
|
|
14
|
+
type: 'array',
|
|
15
|
+
items: {
|
|
16
|
+
type: 'object',
|
|
17
|
+
properties: {
|
|
18
|
+
translation: { type: 'string', description: 'the translated string' },
|
|
19
|
+
confidence: { type: 'number', description: 'a confidence score between 0 and 100' },
|
|
20
|
+
notes: { type: 'string', description: 'any additional notes about the translation' }
|
|
21
|
+
},
|
|
22
|
+
required: ['translation', 'confidence', 'notes']
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
required: ['translations']
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {object} AnthropicAgentOptions
|
|
32
|
+
* @extends LLMTranslationProviderOptions
|
|
33
|
+
* @property {string} [apiKey] - The Anthropic API key (if using direct API).
|
|
34
|
+
* @property {string} [vertexProject] - The VertexAI project ID.
|
|
35
|
+
* @property {string} [vertexLocation] - The VertexAI datacenter location.
|
|
36
|
+
* @property {number} [maxTokens] - Maximum number of output tokens (32000 by default)
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Provider for Anthropic Claude LLMs via Vertex AI or direct API.
|
|
41
|
+
*/
|
|
42
|
+
export class AnthropicAgent extends providers.LLMTranslationProvider {
|
|
43
|
+
#client;
|
|
44
|
+
#apiKey;
|
|
45
|
+
#vertexProject;
|
|
46
|
+
#vertexLocation;
|
|
47
|
+
#maxTokens;
|
|
48
|
+
#maxRetries;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Initializes a new instance of the AnthropicAgent class.
|
|
52
|
+
* @param {AnthropicAgentOptions} options - Configuration options for the provider.
|
|
53
|
+
*/
|
|
54
|
+
constructor({ apiKey, vertexProject, vertexLocation, maxTokens, maxRetries, ...options }) {
|
|
55
|
+
super({...options, maxRetries: 0}); // bypass our own retry logic since Anthropic SDK has built-in support
|
|
56
|
+
this.#apiKey = apiKey;
|
|
57
|
+
this.#vertexProject = vertexProject;
|
|
58
|
+
this.#vertexLocation = vertexLocation ?? 'us-east5';
|
|
59
|
+
this.#maxTokens = maxTokens ?? 32000;
|
|
60
|
+
this.#maxRetries = maxRetries ?? 2;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// we initialize on first use so that constructor is fast and doesn't fail if auth is missing
|
|
64
|
+
// also, we need this to be async so that we can await for projectId if it's not provided
|
|
65
|
+
async lazyInit() {
|
|
66
|
+
if (this.#client) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (this.#apiKey) {
|
|
70
|
+
// Direct Anthropic API
|
|
71
|
+
this.#client = new Anthropic({
|
|
72
|
+
apiKey: this.#apiKey,
|
|
73
|
+
maxRetries: this.#maxRetries,
|
|
74
|
+
timeout: 15 * 60000, // 15 minutes
|
|
75
|
+
});
|
|
76
|
+
logInfo`AnthropicAgent ${this.id} initialized with direct Anthropic API`;
|
|
77
|
+
} else {
|
|
78
|
+
if (!this.#vertexProject) {
|
|
79
|
+
try {
|
|
80
|
+
const auth = new GoogleAuth({});
|
|
81
|
+
this.#vertexProject = await auth.getProjectId();
|
|
82
|
+
} catch (e) {
|
|
83
|
+
throw new Error(`Couldn't get credentials, did you run 'gcloud auth login'?\n${e.message}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
this.#client = new AnthropicVertex({
|
|
87
|
+
projectId: this.#vertexProject,
|
|
88
|
+
region: this.#vertexLocation,
|
|
89
|
+
maxRetries: this.#maxRetries,
|
|
90
|
+
timeout: 15 * 60000, // 15 minutes
|
|
91
|
+
});
|
|
92
|
+
logInfo`AnthropicAgent ${this.id} initialized with Vertex AI platform (${this.#vertexLocation}/${this.#vertexProject})`;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
prepareTranslateChunkArgs({ sourceLang, targetLang, xmlTus, instructions }) {
|
|
97
|
+
const userPrompt = this.buildUserPrompt({ sourceLang, targetLang, xmlTus, instructions });
|
|
98
|
+
|
|
99
|
+
const messages = [
|
|
100
|
+
{
|
|
101
|
+
role: 'user',
|
|
102
|
+
content: userPrompt
|
|
103
|
+
}
|
|
104
|
+
];
|
|
105
|
+
|
|
106
|
+
const toolConfig = this.customSchema ? {
|
|
107
|
+
tools: [{
|
|
108
|
+
name: 'provide_custom_translations',
|
|
109
|
+
description: 'Provide translations using custom schema',
|
|
110
|
+
input_schema: {
|
|
111
|
+
type: 'object',
|
|
112
|
+
properties: {
|
|
113
|
+
translations: {
|
|
114
|
+
type: 'array',
|
|
115
|
+
items: this.customSchema
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
required: ['translations']
|
|
119
|
+
}
|
|
120
|
+
}],
|
|
121
|
+
tool_choice: { type: 'tool', name: 'provide_custom_translations' }
|
|
122
|
+
} : {
|
|
123
|
+
tools: [TRANSLATION_TOOL],
|
|
124
|
+
tool_choice: { type: 'tool', name: 'provide_translations' }
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
model: this.model,
|
|
129
|
+
max_tokens: this.#maxTokens,
|
|
130
|
+
temperature: this.temperature,
|
|
131
|
+
system: this.systemPrompt,
|
|
132
|
+
messages,
|
|
133
|
+
...toolConfig
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async generateContent(args) {
|
|
138
|
+
return await this.#client.messages.create(args);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
convertTranslationResponse(res) {
|
|
142
|
+
try {
|
|
143
|
+
if (res.stop_reason !== 'tool_use') {
|
|
144
|
+
throw new Error(`Unexpected stop reason: ${res.stop_reason}`);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Find the tool use content
|
|
148
|
+
const toolUse = res.content.find(content => content.type === 'tool_use');
|
|
149
|
+
if (!toolUse) {
|
|
150
|
+
throw new Error('No tool use found in response');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const translations = toolUse.input.translations;
|
|
154
|
+
if (!Array.isArray(translations)) {
|
|
155
|
+
throw new Error('Invalid translations format');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const cost = [
|
|
159
|
+
(res.usage.input_tokens ?? 0) / translations.length,
|
|
160
|
+
(res.usage.output_tokens ?? 0) / translations.length,
|
|
161
|
+
((res.usage.input_tokens ?? 0) + (res.usage.output_tokens ?? 0)) / translations.length,
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
return this.processTranslations(translations, cost);
|
|
165
|
+
} catch (e) {
|
|
166
|
+
logWarn`Unexpected convertTranslationResponse error: ${e.message}`;
|
|
167
|
+
return [];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
async info() {
|
|
172
|
+
const info = await super.info();
|
|
173
|
+
try {
|
|
174
|
+
await this.lazyInit();
|
|
175
|
+
// SDK doesn't support listing models or getting model info on Vertex AI
|
|
176
|
+
const models = ['claude-opus-4-20250514', 'claude-sonnet-4-20250514'];
|
|
177
|
+
info.description.push(styleString`Supported models: ${models.join(', ')}`);
|
|
178
|
+
} catch (e) {
|
|
179
|
+
info.description.push(styleString`Unable to connect to Anthropic server: ${e.cause?.message ?? e.message}`);
|
|
180
|
+
}
|
|
181
|
+
return info;
|
|
182
|
+
}
|
|
183
|
+
}
|
package/example.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { AnthropicAgent } from './index.js';
|
|
2
|
+
|
|
3
|
+
// Example L10nMonster configuration using AnthropicAgent
|
|
4
|
+
export const exampleConfig = {
|
|
5
|
+
translationProviders: [
|
|
6
|
+
// Direct API configuration
|
|
7
|
+
{
|
|
8
|
+
id: 'claude-direct-api',
|
|
9
|
+
provider: AnthropicAgent,
|
|
10
|
+
options: {
|
|
11
|
+
model: 'claude-3-5-sonnet-latest',
|
|
12
|
+
quality: 90,
|
|
13
|
+
temperature: 0.1,
|
|
14
|
+
maxTokens: 4096,
|
|
15
|
+
maxRetries: 3, // Passed to Anthropic SDK for native retry handling
|
|
16
|
+
apiKey: process.env.ANTHROPIC_API_KEY, // Set your API key
|
|
17
|
+
persona: 'You are a professional translator specializing in technical documentation and user interfaces.',
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
// Vertex AI configuration
|
|
21
|
+
{
|
|
22
|
+
id: 'claude-vertex-sonnet',
|
|
23
|
+
provider: AnthropicAgent,
|
|
24
|
+
options: {
|
|
25
|
+
model: 'claude-3-5-sonnet@20241022',
|
|
26
|
+
quality: 85,
|
|
27
|
+
temperature: 0.1,
|
|
28
|
+
maxTokens: 4096,
|
|
29
|
+
// vertexProject: 'your-gcp-project-id', // Optional, auto-detected
|
|
30
|
+
vertexLocation: 'us-central1',
|
|
31
|
+
persona: 'You are a professional translator specializing in technical documentation and user interfaces.',
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'claude-vertex-haiku',
|
|
36
|
+
provider: AnthropicAgent,
|
|
37
|
+
options: {
|
|
38
|
+
model: 'claude-3-5-haiku@20241022',
|
|
39
|
+
quality: 80,
|
|
40
|
+
temperature: 0.1,
|
|
41
|
+
maxTokens: 2048,
|
|
42
|
+
vertexLocation: 'us-central1',
|
|
43
|
+
persona: 'You are a fast and efficient translator focused on accuracy and consistency.',
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
],
|
|
47
|
+
|
|
48
|
+
// Example translation jobs configuration
|
|
49
|
+
jobs: [
|
|
50
|
+
{
|
|
51
|
+
id: 'ui-translation',
|
|
52
|
+
translationProvider: 'claude-direct-api',
|
|
53
|
+
instructions: 'Translate user interface strings. Keep labels concise and maintain consistent terminology.',
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'content-translation',
|
|
57
|
+
translationProvider: 'claude-vertex-haiku',
|
|
58
|
+
instructions: 'Translate general content while maintaining the original tone and style.',
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// Example usage
|
|
64
|
+
console.log('AnthropicAgent configuration example loaded');
|
|
65
|
+
console.log('Available providers:', exampleConfig.translationProviders.map(p => p.id));
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { AnthropicAgent } from './anthropicAgent.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@l10nmonster/helpers-anthropic",
|
|
3
|
+
"version": "3.0.0-alpha.1",
|
|
4
|
+
"description": "Anthropic Claude LLM provider for l10nmonster using Vertex AI",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "anthropicAgent.js",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"test": "node --test"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@anthropic-ai/vertex-sdk": "latest",
|
|
12
|
+
"@anthropic-ai/sdk": "latest",
|
|
13
|
+
"google-auth-library": "^10"
|
|
14
|
+
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@l10nmonster/core": "file:../core"
|
|
17
|
+
},
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"license": "MIT"
|
|
22
|
+
}
|