feat: Add image upload support with file path handling (#8830)
* ✨ (data.py): introduce a new function get_file_paths to resolve file paths before creating image URLs in HumanMessage contents * ✨ (general-bugs-agent-images-playground.spec.ts): add test case for user to send images in the playground with the agent component * 📝 (general-bugs-agent-images-playground.spec.ts): update file path to image file to fix test failure due to incorrect file path * [autofix.ci] apply automated fixes * fix: autofix.ci / Update Starter Projects (pull_request) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: italojohnny <italojohnnydosanjos@gmail.com>
This commit is contained in:
parent
6d99faa7d0
commit
557f7b31aa
31 changed files with 216 additions and 121 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -169,8 +169,11 @@ class Data(BaseModel):
|
|||
files = self.data.get("files", [])
|
||||
if sender == MESSAGE_SENDER_USER:
|
||||
if files:
|
||||
from langflow.schema.image import get_file_paths
|
||||
|
||||
contents = [{"type": "text", "text": text}]
|
||||
for file_path in files:
|
||||
resolved_file_paths = get_file_paths(files)
|
||||
for file_path in resolved_file_paths:
|
||||
image_url = create_data_url(file_path)
|
||||
contents.append({"type": "image_url", "image_url": {"url": image_url}})
|
||||
human_message = HumanMessage(content=contents)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import dotenv from "dotenv";
|
||||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
|
||||
test(
|
||||
"user must be able to send images in the playground with the agent component",
|
||||
{ tag: ["@release", "@components"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.ANTHROPIC_API_KEY,
|
||||
"ANTHROPIC_API_KEY required to run this test",
|
||||
);
|
||||
|
||||
if (!process.env.CI) {
|
||||
dotenv.config({ path: path.resolve(__dirname, "../../.env") });
|
||||
}
|
||||
await awaitBootstrapTest(page);
|
||||
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
await page.getByRole("heading", { name: "Simple Agent" }).first().click();
|
||||
|
||||
await page.getByTestId("value-dropdown-dropdown_str_agent_llm").click();
|
||||
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
await page.getByText("Anthropic").last().click();
|
||||
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-api_key")
|
||||
.fill(process.env.ANTHROPIC_API_KEY || "");
|
||||
|
||||
await page.getByTestId("playground-btn-flow-io").click();
|
||||
|
||||
// Read the image file as a binary string
|
||||
const filePath = "tests/assets/chain.png";
|
||||
const fileContent = readFileSync(filePath, "base64");
|
||||
|
||||
// Create the DataTransfer and File objects within the browser context
|
||||
const dataTransfer = await page.evaluateHandle(
|
||||
({ fileContent }) => {
|
||||
const dt = new DataTransfer();
|
||||
const byteCharacters = atob(fileContent);
|
||||
const byteNumbers = new Array(byteCharacters.length);
|
||||
for (let i = 0; i < byteCharacters.length; i++) {
|
||||
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
||||
}
|
||||
const byteArray = new Uint8Array(byteNumbers);
|
||||
const file = new File([byteArray], "chain.png", { type: "image/png" });
|
||||
dt.items.add(file);
|
||||
return dt;
|
||||
},
|
||||
{ fileContent },
|
||||
);
|
||||
|
||||
await page.waitForSelector('[data-testid="input-chat-playground"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
// Locate the target element
|
||||
const element = await page.getByTestId("input-chat-playground");
|
||||
|
||||
// Dispatch the drop event on the target element
|
||||
await element.dispatchEvent("drop", { dataTransfer });
|
||||
|
||||
await page
|
||||
.getByTestId("input-chat-playground")
|
||||
.fill("tell me a small history about the image");
|
||||
|
||||
await page.waitForSelector('[data-testid="button-send"]', {
|
||||
timeout: 100000,
|
||||
});
|
||||
|
||||
await page.getByTestId("button-send").click();
|
||||
|
||||
await page.waitForSelector("text=chain.png", { timeout: 30000 });
|
||||
|
||||
await page.getByText("chain.png").isVisible();
|
||||
|
||||
await page.waitForTimeout(5000);
|
||||
|
||||
const textFromLlm = await page
|
||||
.locator(".markdown.prose")
|
||||
.last()
|
||||
.textContent();
|
||||
|
||||
expect(textFromLlm?.toLowerCase()).toContain("chain");
|
||||
const lengthOfTextFromLlm = textFromLlm?.length;
|
||||
expect(lengthOfTextFromLlm).toBeGreaterThan(100);
|
||||
},
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue