mirror of
https://github.com/run-llama/LlamaIndexTS.git
synced 2026-07-15 06:52:45 -04:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c08302f876 | |||
| 345300f110 | |||
| f322c5d202 | |||
| 376d29a78f | |||
| 224d507ab5 | |||
| 1f680d731d |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"llamaindex": patch
|
||||
---
|
||||
|
||||
feat: add splitByPage mode to LlamaParseReader
|
||||
@@ -1,5 +1,12 @@
|
||||
# docs
|
||||
|
||||
## 0.0.52
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 376d29a: feat: added tool calling and agent support for llama3.1 504B
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.51
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -15,6 +15,7 @@ LlamaIndex.TS comes with a few built-in agents, but you can also create your own
|
||||
- Anthropic Agent both via Anthropic and Bedrock (in `@llamaIndex/community`)
|
||||
- Gemini Agent
|
||||
- ReACT Agent
|
||||
- Meta3.1 504B via Bedrock (in `@llamaIndex/community`)
|
||||
|
||||
## Examples
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ They can be divided into two groups.
|
||||
- `gpt4oApiKey?` Deprecated. Use vendorMultimodal params. Optional. Set the GPT-4o API key. Lowers the cost of parsing by using your own API key. Your OpenAI account will be charged. Can also be set in the environment variable `LLAMA_CLOUD_GPT4O_API_KEY`.
|
||||
- `boundingBox?` Optional. Specify an area of the document to parse. Expects the bounding box margins as a string in clockwise order, e.g. `boundingBox = "0.1,0,0,0"` to not parse the top 10% of the document.
|
||||
- `targetPages?` Optional. Specify which pages to parse by specifying them as a comma-separated list. First page is `0`.
|
||||
- `splitByPage` Wether to split the results, creating one document per page. Uses the set `pageSeparator` or `\n---\n` as fallback. Default is true.
|
||||
- `useVendorMultimodalModel` set to true to use a multimodal model. Default is `false`.
|
||||
- `vendorMultimodalModel?` Optional. Specify which multimodal model to use. Default is GPT4o. See [here](https://docs.cloud.llamaindex.ai/llamaparse/features/multimodal) for a list of available models and cost.
|
||||
- `vendorMultimodalApiKey?` Optional. Set the multimodal model API key. Can also be set in the environment variable `LLAMA_CLOUD_VENDOR_MULTIMODAL_API_KEY`.
|
||||
|
||||
@@ -31,7 +31,7 @@ META_LLAMA3_8B_INSTRUCT = "meta.llama3-8b-instruct-v1:0";
|
||||
META_LLAMA3_70B_INSTRUCT = "meta.llama3-70b-instruct-v1:0";
|
||||
META_LLAMA3_1_8B_INSTRUCT = "meta.llama3-1-8b-instruct-v1:0"; // available on us-west-2
|
||||
META_LLAMA3_1_70B_INSTRUCT = "meta.llama3-1-70b-instruct-v1:0"; // available on us-west-2
|
||||
META_LLAMA3_1_405B_INSTRUCT = "meta.llama3-1-405b-instruct-v1:0"; // preview only, available on us-west-2
|
||||
META_LLAMA3_1_405B_INSTRUCT = "meta.llama3-1-405b-instruct-v1:0"; // preview only, available on us-west-2, tool calling supported
|
||||
```
|
||||
|
||||
Sonnet, Haiku and Opus are multimodal, image_url only supports base64 data url format, e.g. `data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==`
|
||||
@@ -67,3 +67,72 @@ async function main() {
|
||||
console.log(response.response);
|
||||
}
|
||||
```
|
||||
|
||||
## Agent Example
|
||||
|
||||
```ts
|
||||
import { BEDROCK_MODELS, Bedrock } from "@llamaindex/community";
|
||||
import { FunctionTool, LLMAgent } from "llamaindex";
|
||||
|
||||
const sumNumbers = FunctionTool.from(
|
||||
({ a, b }: { a: number; b: number }) => `${a + b}`,
|
||||
{
|
||||
name: "sumNumbers",
|
||||
description: "Use this function to sum two numbers",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The first number",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The second number",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const divideNumbers = FunctionTool.from(
|
||||
({ a, b }: { a: number; b: number }) => `${a / b}`,
|
||||
{
|
||||
name: "divideNumbers",
|
||||
description: "Use this function to divide two numbers",
|
||||
parameters: {
|
||||
type: "object",
|
||||
properties: {
|
||||
a: {
|
||||
type: "number",
|
||||
description: "The dividend a to divide",
|
||||
},
|
||||
b: {
|
||||
type: "number",
|
||||
description: "The divisor b to divide by",
|
||||
},
|
||||
},
|
||||
required: ["a", "b"],
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
const bedrock = new Bedrock({
|
||||
model: BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT,
|
||||
...
|
||||
});
|
||||
|
||||
async function main() {
|
||||
const agent = new LLMAgent({
|
||||
llm: bedrock,
|
||||
tools: [sumNumbers, divideNumbers],
|
||||
});
|
||||
|
||||
const response = await agent.chat({
|
||||
message: "How much is 5 + 5? then divide by 2",
|
||||
});
|
||||
|
||||
console.log(response.message);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "docs",
|
||||
"version": "0.0.51",
|
||||
"version": "0.0.52",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"docusaurus": "docusaurus",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @llamaindex/autotool-02-next-example
|
||||
|
||||
## 0.1.36
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
- @llamaindex/autotool@2.0.0
|
||||
|
||||
## 0.1.35
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/autotool-02-next-example",
|
||||
"private": true,
|
||||
"version": "0.1.35",
|
||||
"version": "0.1.36",
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
"unplugin": "^1.10.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"llamaindex": "^0.5.10",
|
||||
"llamaindex": "^0.5.11",
|
||||
"openai": "^4",
|
||||
"typescript": "^4"
|
||||
},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/cloud
|
||||
|
||||
## 0.2.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 1f680d7: chore: bump llamacloud api
|
||||
|
||||
## 0.2.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
+835
-117
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "@llamaindex/cloud",
|
||||
"version": "0.2.0",
|
||||
"version": "0.2.1",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"generate": "pnpm dlx @hey-api/openapi-ts",
|
||||
"generate": "pnpm dlx @hey-api/openapi-ts --client fetch",
|
||||
"build": "pnpm run generate && bunchee"
|
||||
},
|
||||
"files": [
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# @llamaindex/community
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- 224d507: fix: prevent tool calling getting mixed with conversation
|
||||
- 376d29a: feat: added tool calling and agent support for llama3.1 504B
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
- Bedrock support for the Anthropic Claude Models [usage](https://ts.llamaindex.ai/modules/llms/available_llms/bedrock)
|
||||
- Bedrock support for the Meta LLama 2, 3 and 3.1 Models [usage](https://ts.llamaindex.ai/modules/llms/available_llms/bedrock)
|
||||
- Meta LLama3.1 405b tool call support
|
||||
|
||||
## LICENSE
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/community",
|
||||
"description": "Community package for LlamaIndexTS",
|
||||
"version": "0.0.25",
|
||||
"version": "0.0.26",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
@@ -19,11 +19,11 @@
|
||||
"./llm/bedrock": {
|
||||
"import": {
|
||||
"types": "./dist/type/llm/bedrock.d.ts",
|
||||
"default": "./dist/llm/bedrock/base.js"
|
||||
"default": "./dist/llm/bedrock/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./dist/type/llm/bedrock.d.ts",
|
||||
"default": "./dist/llm/bedrock/base.cjs"
|
||||
"default": "./dist/llm/bedrock/index.cjs"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -47,6 +47,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-bedrock-runtime": "^3.613.0",
|
||||
"@llamaindex/core": "workspace:*"
|
||||
"@llamaindex/core": "workspace:*",
|
||||
"@llamaindex/env": "workspace:*"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@ export {
|
||||
BEDROCK_MODELS,
|
||||
BEDROCK_MODEL_MAX_TOKENS,
|
||||
Bedrock,
|
||||
} from "./llm/bedrock/base.js";
|
||||
} from "./llm/bedrock/index.js";
|
||||
|
||||
+6
-5
@@ -16,17 +16,18 @@ import {
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "../provider";
|
||||
import { toUtf8 } from "../utils";
|
||||
import type {
|
||||
AnthropicNoneStreamingResponse,
|
||||
AnthropicStreamEvent,
|
||||
AnthropicTextContent,
|
||||
ToolBlock,
|
||||
} from "../types";
|
||||
} from "./types";
|
||||
|
||||
import {
|
||||
mapBaseToolsToAnthropicTools,
|
||||
mapChatMessagesToAnthropicMessages,
|
||||
toUtf8,
|
||||
} from "../utils";
|
||||
} from "./utils";
|
||||
|
||||
export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
getResultFromResponse(
|
||||
@@ -69,6 +70,7 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
let tool: ToolBlock | undefined = undefined;
|
||||
// #TODO this should be broken down into a separate consumer
|
||||
for await (const response of stream) {
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (
|
||||
event?.type === "content_block_start" &&
|
||||
@@ -114,11 +116,10 @@ export class AnthropicProvider extends Provider<AnthropicStreamEvent> {
|
||||
};
|
||||
}
|
||||
}
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta,
|
||||
delta: options ? "" : delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
@@ -0,0 +1,142 @@
|
||||
import type { ToolMetadata } from "@llamaindex/core/llms";
|
||||
import type { InvocationMetrics } from "../types";
|
||||
|
||||
type Usage = {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
};
|
||||
|
||||
type Message = {
|
||||
id: string;
|
||||
type: string;
|
||||
role: string;
|
||||
content: string[];
|
||||
model: string;
|
||||
stop_reason: string | null;
|
||||
stop_sequence: string | null;
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type ToolBlock = {
|
||||
id: string;
|
||||
input: unknown;
|
||||
name: string;
|
||||
type: "tool_use";
|
||||
};
|
||||
|
||||
export type TextBlock = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
type ContentBlockStart = {
|
||||
type: "content_block_start";
|
||||
index: number;
|
||||
content_block: ToolBlock | TextBlock;
|
||||
};
|
||||
|
||||
type Delta =
|
||||
| {
|
||||
type: "text_delta";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type: "input_json_delta";
|
||||
partial_json: string;
|
||||
};
|
||||
|
||||
type ContentBlockDelta = {
|
||||
type: "content_block_delta";
|
||||
index: number;
|
||||
delta: Delta;
|
||||
};
|
||||
|
||||
type ContentBlockStop = {
|
||||
type: "content_block_stop";
|
||||
index: number;
|
||||
};
|
||||
|
||||
type MessageDelta = {
|
||||
type: "message_delta";
|
||||
delta: {
|
||||
stop_reason: string;
|
||||
stop_sequence: string | null;
|
||||
};
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type MessageStop = {
|
||||
type: "message_stop";
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type AnthropicStreamEvent =
|
||||
| { type: "message_start"; message: Message }
|
||||
| ContentBlockStart
|
||||
| ContentBlockDelta
|
||||
| ContentBlockStop
|
||||
| MessageDelta
|
||||
| MessageStop;
|
||||
|
||||
export type AnthropicContent =
|
||||
| AnthropicTextContent
|
||||
| AnthropicImageContent
|
||||
| AnthropicToolContent
|
||||
| AnthropicToolResultContent;
|
||||
|
||||
export type AnthropicTextContent = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type AnthropicToolContent = {
|
||||
type: "tool_use";
|
||||
id: string;
|
||||
name: string;
|
||||
input: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type AnthropicToolResultContent = {
|
||||
type: "tool_result";
|
||||
tool_use_id: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AnthropicMediaTypes =
|
||||
| "image/jpeg"
|
||||
| "image/png"
|
||||
| "image/webp"
|
||||
| "image/gif";
|
||||
|
||||
export type AnthropicImageSource = {
|
||||
type: "base64";
|
||||
media_type: AnthropicMediaTypes;
|
||||
data: string; // base64 encoded image bytes
|
||||
};
|
||||
|
||||
export type AnthropicImageContent = {
|
||||
type: "image";
|
||||
source: AnthropicImageSource;
|
||||
};
|
||||
|
||||
export type AnthropicMessage = {
|
||||
role: "user" | "assistant";
|
||||
content: AnthropicContent[];
|
||||
};
|
||||
|
||||
export type AnthropicNoneStreamingResponse = {
|
||||
id: string;
|
||||
type: "message";
|
||||
role: "assistant";
|
||||
content: AnthropicContent[];
|
||||
model: string;
|
||||
stop_reason: "end_turn" | "max_tokens" | "stop_sequence";
|
||||
stop_sequence?: string;
|
||||
usage: { input_tokens: number; output_tokens: number };
|
||||
};
|
||||
|
||||
export type AnthropicTool = {
|
||||
name: string;
|
||||
description: string;
|
||||
input_schema: ToolMetadata["parameters"];
|
||||
};
|
||||
@@ -0,0 +1,186 @@
|
||||
import type { JSONObject } from "@llamaindex/core/global";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContent,
|
||||
MessageContentDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { mapMessageContentToMessageContentDetails } from "../utils";
|
||||
import type {
|
||||
AnthropicContent,
|
||||
AnthropicImageContent,
|
||||
AnthropicMediaTypes,
|
||||
AnthropicMessage,
|
||||
AnthropicTextContent,
|
||||
AnthropicTool,
|
||||
} from "./types.js";
|
||||
|
||||
const ACCEPTED_IMAGE_MIME_TYPES = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/webp",
|
||||
"image/gif",
|
||||
];
|
||||
|
||||
export const mergeNeighboringSameRoleMessages = (
|
||||
messages: AnthropicMessage[],
|
||||
): AnthropicMessage[] => {
|
||||
return messages.reduce(
|
||||
(result: AnthropicMessage[], current: AnthropicMessage, index: number) => {
|
||||
if (index > 0 && messages[index - 1].role === current.role) {
|
||||
result[result.length - 1].content = [
|
||||
...result[result.length - 1].content,
|
||||
...current.content,
|
||||
];
|
||||
} else {
|
||||
result.push(current);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
export const mapMessageContentDetailToAnthropicContent = <
|
||||
T extends MessageContentDetail,
|
||||
>(
|
||||
detail: T,
|
||||
): AnthropicContent => {
|
||||
let content: AnthropicContent;
|
||||
|
||||
if (detail.type === "text") {
|
||||
content = mapTextContent(detail.text);
|
||||
} else if (detail.type === "image_url") {
|
||||
content = mapImageContent(detail.image_url.url);
|
||||
} else {
|
||||
throw new Error("Unsupported content detail type");
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
export const mapMessageContentToAnthropicContent = <T extends MessageContent>(
|
||||
content: T,
|
||||
): AnthropicContent[] => {
|
||||
return mapMessageContentToMessageContentDetails(content).map(
|
||||
mapMessageContentDetailToAnthropicContent,
|
||||
);
|
||||
};
|
||||
|
||||
export const mapBaseToolsToAnthropicTools = (
|
||||
tools?: BaseTool[],
|
||||
): AnthropicTool[] => {
|
||||
if (!tools) return [];
|
||||
return tools.map((tool: BaseTool) => {
|
||||
const {
|
||||
metadata: { parameters, ...options },
|
||||
} = tool;
|
||||
return {
|
||||
...options,
|
||||
input_schema: parameters,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const mapChatMessagesToAnthropicMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): AnthropicMessage[] => {
|
||||
const mapped = messages
|
||||
.flatMap((msg: T): AnthropicMessage[] => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "assistant",
|
||||
content: msg.options.toolCall.map((call) => ({
|
||||
type: "tool_use",
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
input: call.input as JSONObject,
|
||||
})),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "tool_result",
|
||||
tool_use_id: msg.options.toolResult.id,
|
||||
content: msg.options.toolResult.result,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
return mapMessageContentToMessageContentDetails(msg.content).map(
|
||||
(detail: MessageContentDetail): AnthropicMessage => {
|
||||
const content = mapMessageContentDetailToAnthropicContent(detail);
|
||||
|
||||
return {
|
||||
role: msg.role === "assistant" ? "assistant" : "user",
|
||||
content: [content],
|
||||
};
|
||||
},
|
||||
);
|
||||
})
|
||||
.filter((message: AnthropicMessage) => {
|
||||
const content = message.content[0];
|
||||
if (content.type === "text" && !content.text) return false;
|
||||
if (content.type === "image" && !content.source.data) return false;
|
||||
if (content.type === "image" && message.role === "assistant")
|
||||
return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return mergeNeighboringSameRoleMessages(mapped);
|
||||
};
|
||||
|
||||
export const mapTextContent = (text: string): AnthropicTextContent => {
|
||||
return { type: "text", text };
|
||||
};
|
||||
|
||||
export const extractDataUrlComponents = (
|
||||
dataUrl: string,
|
||||
): {
|
||||
mimeType: string;
|
||||
base64: string;
|
||||
} => {
|
||||
const parts = dataUrl.split(";base64,");
|
||||
|
||||
if (parts.length !== 2 || !parts[0].startsWith("data:")) {
|
||||
throw new Error("Invalid data URL");
|
||||
}
|
||||
|
||||
const mimeType = parts[0].slice(5);
|
||||
const base64 = parts[1];
|
||||
|
||||
return {
|
||||
mimeType,
|
||||
base64,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapImageContent = (imageUrl: string): AnthropicImageContent => {
|
||||
if (!imageUrl.startsWith("data:"))
|
||||
throw new Error(
|
||||
"For Anthropic please only use base64 data url, e.g.: data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==",
|
||||
);
|
||||
const { mimeType, base64: data } = extractDataUrlComponents(imageUrl);
|
||||
if (!ACCEPTED_IMAGE_MIME_TYPES.includes(mimeType))
|
||||
throw new Error(
|
||||
`Anthropic only accepts the following mimeTypes: ${ACCEPTED_IMAGE_MIME_TYPES.join("\n")}`,
|
||||
);
|
||||
|
||||
return {
|
||||
type: "image",
|
||||
source: {
|
||||
type: "base64",
|
||||
media_type: mimeType as AnthropicMediaTypes,
|
||||
data,
|
||||
},
|
||||
};
|
||||
};
|
||||
+11
-2
@@ -22,8 +22,16 @@ import {
|
||||
type BedrockChatStreamResponse,
|
||||
Provider,
|
||||
} from "./provider";
|
||||
import { PROVIDERS } from "./providers";
|
||||
import { mapMessageContentToMessageContentDetails } from "./utils.js";
|
||||
import { mapMessageContentToMessageContentDetails } from "./utils";
|
||||
|
||||
import { AnthropicProvider } from "./anthropic/provider";
|
||||
import { MetaProvider } from "./meta/provider";
|
||||
|
||||
// Other providers should go here
|
||||
export const PROVIDERS: { [key: string]: Provider } = {
|
||||
anthropic: new AnthropicProvider(),
|
||||
meta: new MetaProvider(),
|
||||
};
|
||||
|
||||
export type BedrockChatParamsStreaming = LLMChatParamsStreaming<
|
||||
BedrockAdditionalChatOptions,
|
||||
@@ -140,6 +148,7 @@ export const TOOL_CALL_MODELS = [
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_HAIKU,
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_OPUS,
|
||||
BEDROCK_MODELS.ANTHROPIC_CLAUDE_3_5_SONNET,
|
||||
BEDROCK_MODELS.META_LLAMA3_1_405B_INSTRUCT,
|
||||
];
|
||||
|
||||
const getProvider = (model: string): Provider => {
|
||||
@@ -0,0 +1,3 @@
|
||||
export const TOKENS = {
|
||||
TOOL_CALL: "<|python_tag|>",
|
||||
};
|
||||
@@ -0,0 +1,136 @@
|
||||
import type {
|
||||
InvokeModelCommandInput,
|
||||
InvokeModelWithResponseStreamCommandInput,
|
||||
ResponseStream,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
LLMMetadata,
|
||||
ToolCall,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import { toUtf8 } from "../utils";
|
||||
import type { MetaNoneStreamingResponse, MetaStreamEvent } from "./types";
|
||||
|
||||
import { randomUUID } from "@llamaindex/env";
|
||||
import { Provider, type BedrockChatStreamResponse } from "../provider";
|
||||
import { TOKENS } from "./constants";
|
||||
import {
|
||||
mapChatMessagesToMetaLlama2Messages,
|
||||
mapChatMessagesToMetaLlama3Messages,
|
||||
} from "./utils";
|
||||
|
||||
export class MetaProvider extends Provider<MetaStreamEvent> {
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): MetaNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse<ToolContent>(
|
||||
response: Record<string, any>,
|
||||
): ToolContent[] {
|
||||
const result = this.getResultFromResponse(response);
|
||||
if (!result.generation.trim().startsWith(TOKENS.TOOL_CALL)) return [];
|
||||
const tool = JSON.parse(
|
||||
result.generation.trim().split(TOKENS.TOOL_CALL)[1],
|
||||
);
|
||||
return [
|
||||
{
|
||||
id: randomUUID(),
|
||||
name: tool.name,
|
||||
input: tool.parameters,
|
||||
} as ToolContent,
|
||||
];
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
if (result.generation.trim().startsWith(TOKENS.TOOL_CALL)) return "";
|
||||
return result.generation;
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.generation) {
|
||||
return event.generation;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
async *reduceStream(
|
||||
stream: AsyncIterable<ResponseStream>,
|
||||
): BedrockChatStreamResponse {
|
||||
const collecting: string[] = [];
|
||||
let toolId: string | undefined = undefined;
|
||||
for await (const response of stream) {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
const delta = this.getTextFromStreamResponse(response);
|
||||
// odd quirk of llama3.1, start token is \n\n
|
||||
if (
|
||||
!event?.generation.trim() &&
|
||||
event?.generation_token_count === 1 &&
|
||||
event.prompt_token_count !== null
|
||||
)
|
||||
continue;
|
||||
|
||||
if (delta === TOKENS.TOOL_CALL) {
|
||||
toolId = randomUUID();
|
||||
continue;
|
||||
}
|
||||
|
||||
let options: undefined | ToolCallLLMMessageOptions = undefined;
|
||||
if (toolId && event?.stop_reason === "stop") {
|
||||
const tool = JSON.parse(collecting.join(""));
|
||||
options = {
|
||||
toolCall: [
|
||||
{
|
||||
id: toolId,
|
||||
name: tool.name,
|
||||
input: tool.parameters,
|
||||
} as ToolCall,
|
||||
],
|
||||
};
|
||||
} else if (toolId && !event?.stop_reason) {
|
||||
collecting.push(delta);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!delta && !options) continue;
|
||||
|
||||
yield {
|
||||
delta: options ? "" : delta,
|
||||
options,
|
||||
raw: response,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
let prompt: string = "";
|
||||
if (metadata.model.startsWith("meta.llama3")) {
|
||||
prompt = mapChatMessagesToMetaLlama3Messages(messages, tools);
|
||||
} else if (metadata.model.startsWith("meta.llama2")) {
|
||||
prompt = mapChatMessagesToMetaLlama2Messages(messages);
|
||||
} else {
|
||||
throw new Error(`Meta model ${metadata.model} is not supported`);
|
||||
}
|
||||
|
||||
return {
|
||||
modelId: metadata.model,
|
||||
contentType: "application/json",
|
||||
accept: "application/json",
|
||||
body: JSON.stringify({
|
||||
prompt,
|
||||
max_gen_len: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import type { InvocationMetrics } from "../types";
|
||||
|
||||
export type MetaTextContent = string;
|
||||
|
||||
export type MetaMessage = {
|
||||
role: "user" | "assistant" | "system" | "ipython";
|
||||
content: MetaTextContent;
|
||||
};
|
||||
|
||||
type MetaResponse = {
|
||||
generation: string;
|
||||
prompt_token_count: number;
|
||||
generation_token_count: number;
|
||||
stop_reason: "stop" | "length";
|
||||
};
|
||||
|
||||
export type MetaStreamEvent = MetaResponse & {
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type MetaNoneStreamingResponse = MetaResponse;
|
||||
@@ -0,0 +1,198 @@
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContentTextDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
} from "@llamaindex/core/llms";
|
||||
import type { MetaMessage } from "./types";
|
||||
|
||||
const getToolCallInstructionString = (tool: BaseTool): string => {
|
||||
return `Use the function '${tool.metadata.name}' to '${tool.metadata.description}'`;
|
||||
};
|
||||
|
||||
const getToolCallParametersString = (tool: BaseTool): string => {
|
||||
return JSON.stringify({
|
||||
name: tool.metadata.name,
|
||||
description: tool.metadata.description,
|
||||
parameters: tool.metadata.parameters
|
||||
? Object.entries(tool.metadata.parameters.properties).map(
|
||||
([name, definition]) => ({ [name]: definition }),
|
||||
)
|
||||
: {},
|
||||
});
|
||||
};
|
||||
|
||||
// ported from https://github.com/meta-llama/llama-agentic-system/blob/main/llama_agentic_system/system_prompt.py
|
||||
// NOTE: using json instead of the above xml style tool calling works more reliability
|
||||
export const getToolsPrompt = (tools?: BaseTool[]) => {
|
||||
if (!tools?.length) return "";
|
||||
|
||||
const customToolParams = tools.map((tool) => {
|
||||
return [
|
||||
getToolCallInstructionString(tool),
|
||||
getToolCallParametersString(tool),
|
||||
].join("\n\n");
|
||||
});
|
||||
|
||||
return `
|
||||
Environment: node
|
||||
|
||||
# Tool Instructions
|
||||
- Never use ipython, always use javascript in node
|
||||
|
||||
Cutting Knowledge Date: December 2023
|
||||
Today Date: ${new Date().toLocaleString("en-US", { year: "numeric", month: "long" })}
|
||||
|
||||
You have access to the following functions:
|
||||
|
||||
${customToolParams}
|
||||
|
||||
Think very carefully before calling functions.
|
||||
|
||||
If a you choose to call a function ONLY reply in the following json format:
|
||||
{
|
||||
"name": function_name,
|
||||
"parameters": parameters,
|
||||
}
|
||||
where
|
||||
|
||||
{
|
||||
"name": function_name,
|
||||
"parameters": parameters, => a JSON dict with the function argument name as key and function argument value as value.
|
||||
}
|
||||
|
||||
Here is an example,
|
||||
|
||||
{
|
||||
"name": "example_function_name",
|
||||
"parameters": {"example_name": "example_value"}
|
||||
}
|
||||
|
||||
Reminder:
|
||||
- Function calls MUST follow the specified format
|
||||
- Required parameters MUST be specified
|
||||
- Only call one function at a time
|
||||
- Put the entire function call reply on one line
|
||||
- Always add your sources when using search results to answer the user query
|
||||
`;
|
||||
};
|
||||
|
||||
export const mapChatRoleToMetaRole = (
|
||||
role: ChatMessage["role"],
|
||||
): MetaMessage["role"] => {
|
||||
if (role === "assistant") return "assistant";
|
||||
if (role === "user") return "user";
|
||||
return "system";
|
||||
};
|
||||
|
||||
export const mapChatMessagesToMetaMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): MetaMessage[] => {
|
||||
return messages.flatMap((msg) => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return msg.options.toolCall.map((call) => ({
|
||||
role: "assistant",
|
||||
content: JSON.stringify({
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
parameters: call.input,
|
||||
}),
|
||||
}));
|
||||
}
|
||||
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return {
|
||||
role: "ipython",
|
||||
content: JSON.stringify(msg.options.toolResult),
|
||||
};
|
||||
}
|
||||
|
||||
let content: string = "";
|
||||
if (typeof msg.content === "string") {
|
||||
content = msg.content;
|
||||
} else if (msg.content.length) {
|
||||
content = (msg.content[0] as MessageContentTextDetail).text;
|
||||
}
|
||||
return {
|
||||
role: mapChatRoleToMetaRole(msg.role),
|
||||
content,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-3
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama3Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
tools?: BaseTool[],
|
||||
): string => {
|
||||
const parts: string[] = [];
|
||||
if (tools?.length) {
|
||||
parts.push(
|
||||
"<|begin_of_text|>",
|
||||
"<|start_header_id|>system<|end_header_id|>",
|
||||
getToolsPrompt(tools),
|
||||
"<|eot_id|>",
|
||||
);
|
||||
}
|
||||
|
||||
const mapped = mapChatMessagesToMetaMessages(messages).map((message) => {
|
||||
return [
|
||||
"<|start_header_id|>",
|
||||
message.role,
|
||||
"<|end_header_id|>",
|
||||
message.content,
|
||||
"<|eot_id|>",
|
||||
].join("\n");
|
||||
});
|
||||
|
||||
parts.push(
|
||||
"<|begin_of_text|>",
|
||||
...mapped,
|
||||
"<|start_header_id|>assistant<|end_header_id|>",
|
||||
);
|
||||
return parts.join("\n");
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-2
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama2Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): string => {
|
||||
const mapped = mapChatMessagesToMetaMessages(messages);
|
||||
let output = "<s>";
|
||||
let insideInst = false;
|
||||
let needsStartAgain = false;
|
||||
for (const message of mapped) {
|
||||
if (needsStartAgain) {
|
||||
output += "<s>";
|
||||
needsStartAgain = false;
|
||||
}
|
||||
const text = message.content;
|
||||
if (message.role === "system") {
|
||||
if (!insideInst) {
|
||||
output += "[INST] ";
|
||||
insideInst = true;
|
||||
}
|
||||
output += `<<SYS>>\n${text}\n<</SYS>>\n`;
|
||||
} else if (message.role === "user") {
|
||||
output += text;
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
} else if (message.role === "assistant") {
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
output += ` ${text} </s>\n`;
|
||||
needsStartAgain = true;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
@@ -23,6 +23,7 @@ export type BedrockChatStreamResponse = AsyncIterable<
|
||||
export abstract class Provider<ProviderStreamEvent extends {} = {}> {
|
||||
abstract getTextFromResponse(response: Record<string, any>): string;
|
||||
|
||||
// Return tool calls from none streaming calls
|
||||
abstract getToolsFromResponse<T extends {} = {}>(
|
||||
response: Record<string, any>,
|
||||
): T[];
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
import { Provider } from "../provider";
|
||||
import { AnthropicProvider } from "./anthropic";
|
||||
import { MetaProvider } from "./meta";
|
||||
|
||||
// Other providers should go here
|
||||
export const PROVIDERS: { [key: string]: Provider } = {
|
||||
anthropic: new AnthropicProvider(),
|
||||
meta: new MetaProvider(),
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
import type {
|
||||
InvokeModelCommandInput,
|
||||
InvokeModelWithResponseStreamCommandInput,
|
||||
} from "@aws-sdk/client-bedrock-runtime";
|
||||
import type { ChatMessage, LLMMetadata } from "@llamaindex/core/llms";
|
||||
import type { MetaNoneStreamingResponse, MetaStreamEvent } from "../types";
|
||||
import {
|
||||
mapChatMessagesToMetaLlama2Messages,
|
||||
mapChatMessagesToMetaLlama3Messages,
|
||||
toUtf8,
|
||||
} from "../utils";
|
||||
|
||||
import { Provider } from "../provider";
|
||||
|
||||
export class MetaProvider extends Provider<MetaStreamEvent> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
getResultFromResponse(
|
||||
response: Record<string, any>,
|
||||
): MetaNoneStreamingResponse {
|
||||
return JSON.parse(toUtf8(response.body));
|
||||
}
|
||||
|
||||
getToolsFromResponse(_response: Record<string, any>): never {
|
||||
throw new Error("Not supported by this provider.");
|
||||
}
|
||||
|
||||
getTextFromResponse(response: Record<string, any>): string {
|
||||
const result = this.getResultFromResponse(response);
|
||||
return result.generation;
|
||||
}
|
||||
|
||||
getTextFromStreamResponse(response: Record<string, any>): string {
|
||||
const event = this.getStreamingEventResponse(response);
|
||||
if (event?.generation) {
|
||||
return event.generation;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
getRequestBody<T extends ChatMessage>(
|
||||
metadata: LLMMetadata,
|
||||
messages: T[],
|
||||
): InvokeModelCommandInput | InvokeModelWithResponseStreamCommandInput {
|
||||
let promptFunction: (messages: ChatMessage[]) => string;
|
||||
|
||||
if (metadata.model.startsWith("meta.llama3")) {
|
||||
promptFunction = mapChatMessagesToMetaLlama3Messages;
|
||||
} else if (metadata.model.startsWith("meta.llama2")) {
|
||||
promptFunction = mapChatMessagesToMetaLlama2Messages;
|
||||
} else {
|
||||
throw new Error(`Meta model ${metadata.model} is not supported`);
|
||||
}
|
||||
|
||||
return {
|
||||
modelId: metadata.model,
|
||||
contentType: "application/json",
|
||||
accept: "application/json",
|
||||
body: JSON.stringify({
|
||||
prompt: promptFunction(messages),
|
||||
max_gen_len: metadata.maxTokens,
|
||||
temperature: metadata.temperature,
|
||||
top_p: metadata.topP,
|
||||
}),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,165 +1,11 @@
|
||||
type Usage = {
|
||||
input_tokens: number;
|
||||
output_tokens: number;
|
||||
};
|
||||
|
||||
type Message = {
|
||||
id: string;
|
||||
type: string;
|
||||
role: string;
|
||||
content: string[];
|
||||
model: string;
|
||||
stop_reason: string | null;
|
||||
stop_sequence: string | null;
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
export type ToolBlock = {
|
||||
id: string;
|
||||
input: unknown;
|
||||
name: string;
|
||||
type: "tool_use";
|
||||
};
|
||||
|
||||
export type TextBlock = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
type ContentBlockStart = {
|
||||
type: "content_block_start";
|
||||
index: number;
|
||||
content_block: ToolBlock | TextBlock;
|
||||
};
|
||||
|
||||
type Delta =
|
||||
| {
|
||||
type: "text_delta";
|
||||
text: string;
|
||||
}
|
||||
| {
|
||||
type: "input_json_delta";
|
||||
partial_json: string;
|
||||
};
|
||||
|
||||
type ContentBlockDelta = {
|
||||
type: "content_block_delta";
|
||||
index: number;
|
||||
delta: Delta;
|
||||
};
|
||||
|
||||
type ContentBlockStop = {
|
||||
type: "content_block_stop";
|
||||
index: number;
|
||||
};
|
||||
|
||||
type MessageDelta = {
|
||||
type: "message_delta";
|
||||
delta: {
|
||||
stop_reason: string;
|
||||
stop_sequence: string | null;
|
||||
};
|
||||
usage: Usage;
|
||||
};
|
||||
|
||||
type InvocationMetrics = {
|
||||
export type InvocationMetrics = {
|
||||
inputTokenCount: number;
|
||||
outputTokenCount: number;
|
||||
invocationLatency: number;
|
||||
firstByteLatency: number;
|
||||
};
|
||||
|
||||
type MessageStop = {
|
||||
type: "message_stop";
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type ToolChoice =
|
||||
| { type: "any" }
|
||||
| { type: "auto" }
|
||||
| { type: "tool"; name: string };
|
||||
|
||||
export type AnthropicStreamEvent =
|
||||
| { type: "message_start"; message: Message }
|
||||
| ContentBlockStart
|
||||
| ContentBlockDelta
|
||||
| ContentBlockStop
|
||||
| MessageDelta
|
||||
| MessageStop;
|
||||
|
||||
export type AnthropicContent =
|
||||
| AnthropicTextContent
|
||||
| AnthropicImageContent
|
||||
| AnthropicToolContent
|
||||
| AnthropicToolResultContent;
|
||||
|
||||
export type MetaTextContent = string;
|
||||
|
||||
export type AnthropicTextContent = {
|
||||
type: "text";
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type AnthropicToolContent = {
|
||||
type: "tool_use";
|
||||
id: string;
|
||||
name: string;
|
||||
input: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type AnthropicToolResultContent = {
|
||||
type: "tool_result";
|
||||
tool_use_id: string;
|
||||
content: string;
|
||||
};
|
||||
|
||||
export type AnthropicMediaTypes =
|
||||
| "image/jpeg"
|
||||
| "image/png"
|
||||
| "image/webp"
|
||||
| "image/gif";
|
||||
|
||||
export type AnthropicImageSource = {
|
||||
type: "base64";
|
||||
media_type: AnthropicMediaTypes;
|
||||
data: string; // base64 encoded image bytes
|
||||
};
|
||||
|
||||
export type AnthropicImageContent = {
|
||||
type: "image";
|
||||
source: AnthropicImageSource;
|
||||
};
|
||||
|
||||
export type AnthropicMessage = {
|
||||
role: "user" | "assistant";
|
||||
content: AnthropicContent[];
|
||||
};
|
||||
|
||||
export type MetaMessage = {
|
||||
role: "user" | "assistant" | "system";
|
||||
content: MetaTextContent;
|
||||
};
|
||||
|
||||
export type AnthropicNoneStreamingResponse = {
|
||||
id: string;
|
||||
type: "message";
|
||||
role: "assistant";
|
||||
content: AnthropicContent[];
|
||||
model: string;
|
||||
stop_reason: "end_turn" | "max_tokens" | "stop_sequence";
|
||||
stop_sequence?: string;
|
||||
usage: { input_tokens: number; output_tokens: number };
|
||||
};
|
||||
|
||||
type MetaResponse = {
|
||||
generation: string;
|
||||
prompt_token_count: number;
|
||||
generation_token_count: number;
|
||||
stop_reason: "stop" | "length";
|
||||
};
|
||||
|
||||
export type MetaStreamEvent = MetaResponse & {
|
||||
"amazon-bedrock-invocationMetrics": InvocationMetrics;
|
||||
};
|
||||
|
||||
export type MetaNoneStreamingResponse = MetaResponse;
|
||||
|
||||
@@ -1,28 +1,7 @@
|
||||
import type { JSONObject } from "@llamaindex/core/global";
|
||||
import type {
|
||||
BaseTool,
|
||||
ChatMessage,
|
||||
MessageContent,
|
||||
MessageContentDetail,
|
||||
MessageContentTextDetail,
|
||||
ToolCallLLMMessageOptions,
|
||||
ToolMetadata,
|
||||
} from "@llamaindex/core/llms";
|
||||
import type {
|
||||
AnthropicContent,
|
||||
AnthropicImageContent,
|
||||
AnthropicMediaTypes,
|
||||
AnthropicMessage,
|
||||
AnthropicTextContent,
|
||||
MetaMessage,
|
||||
} from "./types.js";
|
||||
|
||||
const ACCEPTED_IMAGE_MIME_TYPES = [
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/webp",
|
||||
"image/gif",
|
||||
];
|
||||
|
||||
export const mapMessageContentToMessageContentDetails = (
|
||||
content: MessageContent,
|
||||
@@ -30,250 +9,5 @@ export const mapMessageContentToMessageContentDetails = (
|
||||
return Array.isArray(content) ? content : [{ type: "text", text: content }];
|
||||
};
|
||||
|
||||
export const mergeNeighboringSameRoleMessages = (
|
||||
messages: AnthropicMessage[],
|
||||
): AnthropicMessage[] => {
|
||||
return messages.reduce(
|
||||
(result: AnthropicMessage[], current: AnthropicMessage, index: number) => {
|
||||
if (index > 0 && messages[index - 1].role === current.role) {
|
||||
result[result.length - 1].content = [
|
||||
...result[result.length - 1].content,
|
||||
...current.content,
|
||||
];
|
||||
} else {
|
||||
result.push(current);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
[],
|
||||
);
|
||||
};
|
||||
|
||||
export const mapMessageContentDetailToAnthropicContent = <
|
||||
T extends MessageContentDetail,
|
||||
>(
|
||||
detail: T,
|
||||
): AnthropicContent => {
|
||||
let content: AnthropicContent;
|
||||
|
||||
if (detail.type === "text") {
|
||||
content = mapTextContent(detail.text);
|
||||
} else if (detail.type === "image_url") {
|
||||
content = mapImageContent(detail.image_url.url);
|
||||
} else {
|
||||
throw new Error("Unsupported content detail type");
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
export const mapMessageContentToAnthropicContent = <T extends MessageContent>(
|
||||
content: T,
|
||||
): AnthropicContent[] => {
|
||||
return mapMessageContentToMessageContentDetails(content).map(
|
||||
mapMessageContentDetailToAnthropicContent,
|
||||
);
|
||||
};
|
||||
|
||||
type AnthropicTool = {
|
||||
name: string;
|
||||
description: string;
|
||||
input_schema: ToolMetadata["parameters"];
|
||||
};
|
||||
|
||||
export const mapBaseToolsToAnthropicTools = (
|
||||
tools?: BaseTool[],
|
||||
): AnthropicTool[] => {
|
||||
if (!tools) return [];
|
||||
return tools.map((tool: BaseTool) => {
|
||||
const {
|
||||
metadata: { parameters, ...options },
|
||||
} = tool;
|
||||
return {
|
||||
...options,
|
||||
input_schema: parameters,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const mapChatMessagesToAnthropicMessages = <
|
||||
T extends ChatMessage<ToolCallLLMMessageOptions>,
|
||||
>(
|
||||
messages: T[],
|
||||
): AnthropicMessage[] => {
|
||||
const mapped = messages
|
||||
.flatMap((msg: T): AnthropicMessage[] => {
|
||||
if (msg.options && "toolCall" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "assistant",
|
||||
content: msg.options.toolCall.map((call) => ({
|
||||
type: "tool_use",
|
||||
id: call.id,
|
||||
name: call.name,
|
||||
input: call.input as JSONObject,
|
||||
})),
|
||||
},
|
||||
];
|
||||
}
|
||||
if (msg.options && "toolResult" in msg.options) {
|
||||
return [
|
||||
{
|
||||
role: "user",
|
||||
content: [
|
||||
{
|
||||
type: "tool_result",
|
||||
tool_use_id: msg.options.toolResult.id,
|
||||
content: msg.options.toolResult.result,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
return mapMessageContentToMessageContentDetails(msg.content).map(
|
||||
(detail: MessageContentDetail): AnthropicMessage => {
|
||||
const content = mapMessageContentDetailToAnthropicContent(detail);
|
||||
|
||||
return {
|
||||
role: msg.role === "assistant" ? "assistant" : "user",
|
||||
content: [content],
|
||||
};
|
||||
},
|
||||
);
|
||||
})
|
||||
.filter((message: AnthropicMessage) => {
|
||||
const content = message.content[0];
|
||||
if (content.type === "text" && !content.text) return false;
|
||||
if (content.type === "image" && !content.source.data) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
return mergeNeighboringSameRoleMessages(mapped);
|
||||
};
|
||||
|
||||
export const mapChatMessagesToMetaMessages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): MetaMessage[] => {
|
||||
return messages.map((msg) => {
|
||||
let content: string = "";
|
||||
if (typeof msg.content === "string") {
|
||||
content = msg.content;
|
||||
} else if (msg.content.length) {
|
||||
content = (msg.content[0] as MessageContentTextDetail).text;
|
||||
}
|
||||
return {
|
||||
role:
|
||||
msg.role === "assistant"
|
||||
? "assistant"
|
||||
: msg.role === "user"
|
||||
? "user"
|
||||
: "system",
|
||||
content,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-3
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama3Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): string => {
|
||||
const mapped = mapChatMessagesToMetaMessages(messages).map((message) => {
|
||||
const text = message.content;
|
||||
return `<|start_header_id|>${message.role}<|end_header_id|>\n${text}\n<|eot_id|>\n`;
|
||||
});
|
||||
return (
|
||||
"<|begin_of_text|>" +
|
||||
mapped.join("\n") +
|
||||
"\n<|start_header_id|>assistant<|end_header_id|>\n"
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Documentation at https://llama.meta.com/docs/model-cards-and-prompt-formats/meta-llama-2
|
||||
*/
|
||||
export const mapChatMessagesToMetaLlama2Messages = <T extends ChatMessage>(
|
||||
messages: T[],
|
||||
): string => {
|
||||
const mapped = mapChatMessagesToMetaMessages(messages);
|
||||
let output = "<s>";
|
||||
let insideInst = false;
|
||||
let needsStartAgain = false;
|
||||
for (const message of mapped) {
|
||||
if (needsStartAgain) {
|
||||
output += "<s>";
|
||||
needsStartAgain = false;
|
||||
}
|
||||
const text = message.content;
|
||||
if (message.role === "system") {
|
||||
if (!insideInst) {
|
||||
output += "[INST] ";
|
||||
insideInst = true;
|
||||
}
|
||||
output += `<<SYS>>\n${text}\n<</SYS>>\n`;
|
||||
} else if (message.role === "user") {
|
||||
output += text;
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
} else if (message.role === "assistant") {
|
||||
if (insideInst) {
|
||||
output += " [/INST]";
|
||||
insideInst = false;
|
||||
}
|
||||
output += ` ${text} </s>\n`;
|
||||
needsStartAgain = true;
|
||||
}
|
||||
}
|
||||
return output;
|
||||
};
|
||||
|
||||
export const mapTextContent = (text: string): AnthropicTextContent => {
|
||||
return { type: "text", text };
|
||||
};
|
||||
|
||||
export const extractDataUrlComponents = (
|
||||
dataUrl: string,
|
||||
): {
|
||||
mimeType: string;
|
||||
base64: string;
|
||||
} => {
|
||||
const parts = dataUrl.split(";base64,");
|
||||
|
||||
if (parts.length !== 2 || !parts[0].startsWith("data:")) {
|
||||
throw new Error("Invalid data URL");
|
||||
}
|
||||
|
||||
const mimeType = parts[0].slice(5);
|
||||
const base64 = parts[1];
|
||||
|
||||
return {
|
||||
mimeType,
|
||||
base64,
|
||||
};
|
||||
};
|
||||
|
||||
export const mapImageContent = (imageUrl: string): AnthropicImageContent => {
|
||||
if (!imageUrl.startsWith("data:"))
|
||||
throw new Error(
|
||||
"For Anthropic please only use base64 data url, e.g.: data:image/jpeg;base64,SGVsbG8sIFdvcmxkIQ==",
|
||||
);
|
||||
const { mimeType, base64: data } = extractDataUrlComponents(imageUrl);
|
||||
if (!ACCEPTED_IMAGE_MIME_TYPES.includes(mimeType))
|
||||
throw new Error(
|
||||
`Anthropic only accepts the following mimeTypes: ${ACCEPTED_IMAGE_MIME_TYPES.join("\n")}`,
|
||||
);
|
||||
|
||||
return {
|
||||
type: "image",
|
||||
source: {
|
||||
type: "base64",
|
||||
media_type: mimeType as AnthropicMediaTypes,
|
||||
data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const toUtf8 = (input: Uint8Array): string =>
|
||||
new TextDecoder("utf-8").decode(input);
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/experimental
|
||||
|
||||
## 0.0.61
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.60
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@llamaindex/experimental",
|
||||
"description": "Experimental package for LlamaIndexTS",
|
||||
"version": "0.0.60",
|
||||
"version": "0.0.61",
|
||||
"type": "module",
|
||||
"types": "dist/type/index.d.ts",
|
||||
"main": "dist/cjs/index.js",
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
# llamaindex
|
||||
|
||||
## 0.5.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [1f680d7]
|
||||
- @llamaindex/cloud@0.2.1
|
||||
|
||||
## 0.5.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/cloudflare-worker-agent-test
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/cloudflare-worker-agent-test",
|
||||
"version": "0.0.44",
|
||||
"version": "0.0.45",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/next-agent-test
|
||||
|
||||
## 0.1.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/next-agent-test",
|
||||
"version": "0.1.44",
|
||||
"version": "0.1.45",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# test-edge-runtime
|
||||
|
||||
## 0.1.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.1.43
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/nextjs-edge-runtime-test",
|
||||
"version": "0.1.43",
|
||||
"version": "0.1.44",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/next-node-runtime
|
||||
|
||||
## 0.0.26
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.25
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/next-node-runtime-test",
|
||||
"version": "0.0.25",
|
||||
"version": "0.0.26",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# @llamaindex/waku-query-engine-test
|
||||
|
||||
## 0.0.45
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- llamaindex@0.5.11
|
||||
|
||||
## 0.0.44
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@llamaindex/waku-query-engine-test",
|
||||
"version": "0.0.44",
|
||||
"version": "0.0.45",
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "llamaindex",
|
||||
"version": "0.5.10",
|
||||
"version": "0.5.11",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"keywords": [
|
||||
|
||||
@@ -143,6 +143,8 @@ export class LlamaParseReader extends FileReader {
|
||||
targetPages?: string;
|
||||
// Whether or not to ignore and skip errors raised during parsing.
|
||||
ignoreErrors: boolean = true;
|
||||
// Whether to split by page using the pageSeparator or '\n---\n' as default.
|
||||
splitByPage: boolean = true;
|
||||
// Whether to use the vendor multimodal API.
|
||||
useVendorMultimodalModel: boolean = false;
|
||||
// The model name for the vendor multimodal API
|
||||
@@ -326,10 +328,17 @@ export class LlamaParseReader extends FileReader {
|
||||
}
|
||||
|
||||
// Return results as Document objects
|
||||
const resultJson = await this.getJobResult(jobId, this.resultType);
|
||||
const jobResults = await this.getJobResult(jobId, this.resultType);
|
||||
const resultText = jobResults[this.resultType];
|
||||
|
||||
// Split the text by separator if splitByPage is true
|
||||
if (this.splitByPage) {
|
||||
return this.splitTextBySeparator(resultText);
|
||||
}
|
||||
|
||||
return [
|
||||
new Document({
|
||||
text: resultJson[this.resultType],
|
||||
text: resultText,
|
||||
}),
|
||||
];
|
||||
} catch (e) {
|
||||
@@ -485,6 +494,17 @@ export class LlamaParseReader extends FileReader {
|
||||
return filteredParams;
|
||||
}
|
||||
|
||||
private splitTextBySeparator(text: string): Document[] {
|
||||
const separator = this.pageSeparator ?? "\n---\n";
|
||||
const textChunks = text.split(separator);
|
||||
return textChunks.map(
|
||||
(docChunk: string) =>
|
||||
new Document({
|
||||
text: docChunk,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
static async getMimeType(
|
||||
data: Uint8Array,
|
||||
): Promise<{ mime: string; extension: string }> {
|
||||
|
||||
Generated
+3
@@ -352,6 +352,9 @@ importers:
|
||||
'@llamaindex/core':
|
||||
specifier: workspace:*
|
||||
version: link:../core
|
||||
'@llamaindex/env':
|
||||
specifier: workspace:*
|
||||
version: link:../env
|
||||
devDependencies:
|
||||
'@types/node':
|
||||
specifier: ^20.14.2
|
||||
|
||||
Reference in New Issue
Block a user