feat: Needle Search Tool With Template (#6648)
* feat: Needle Search Tool With Templte * lint * lint * lint * lint * refactor: Use Langflow Agent instead of CrewAI Agent * techdebt: adjust Needle component to use tool mode and remove tool component * lint * lint * Update Invoice Summarizer.json * Update Invoice Summarizer.json * update to the component * refactor: Use Needle icon svg * make format * component updates * update with latest agent component * updated a missing connection when updating the agent component * update template --------- Co-authored-by: Edwin Jose <edwin.jose@datastax.com>
This commit is contained in:
parent
1249ea138c
commit
94bc8dbc7d
17 changed files with 2122 additions and 99 deletions
|
|
@ -1,18 +0,0 @@
|
|||
const SvgNeedleIcon = (props) => (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="1em"
|
||||
height="1em"
|
||||
viewBox="0 0 32 32"
|
||||
{...props}
|
||||
>
|
||||
<circle cx="16" cy="16" r="15" stroke="currentColor" strokeWidth="2" />
|
||||
<path
|
||||
fill="currentColor"
|
||||
d="M6.06661 23.4341L19.2183 4.1263C19.5277 3.67209 20.3458 3.99976 20.3225 4.54884C20.1123 9.51475 23.0448 12.1637 28.0237 12.3643C28.5874 12.387 28.8315 13.2879 28.3252 13.5368L6.70039 24.1643C6.23948 24.3909 5.7775 23.8586 6.06661 23.4341Z"
|
||||
/>
|
||||
<circle cx="24.5" cy="8.5" r="1.5" fill="currentColor" />
|
||||
</svg>
|
||||
);
|
||||
|
||||
export default SvgNeedleIcon;
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import SvgNeedleIcon from "./NeedleIcon";
|
||||
import NeedleSvg from "./needle-icon.svg?react";
|
||||
|
||||
export const NeedleIcon = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
>((props, ref) => {
|
||||
return <SvgNeedleIcon ref={ref} {...props} />;
|
||||
return <NeedleSvg ref={ref} {...props} />;
|
||||
});
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
Before Width: | Height: | Size: 503 B After Width: | Height: | Size: 45 KiB |
102
src/frontend/tests/core/integrations/Invoice Summarizer.spec.ts
Normal file
102
src/frontend/tests/core/integrations/Invoice Summarizer.spec.ts
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import { expect, test } from "@playwright/test";
|
||||
import * as dotenv from "dotenv";
|
||||
import path from "path";
|
||||
import { awaitBootstrapTest } from "../../utils/await-bootstrap-test";
|
||||
import { initialGPTsetup } from "../../utils/initialGPTsetup";
|
||||
|
||||
test(
|
||||
"Invoice Summarizer",
|
||||
{ tag: ["@release", "@starter-projects"] },
|
||||
async ({ page }) => {
|
||||
test.skip(
|
||||
!process?.env?.OPENAI_API_KEY ||
|
||||
!process?.env?.NEEDLE_API_KEY ||
|
||||
!process?.env?.NEEDLE_COLLECTION_ID,
|
||||
"OPENAI_API_KEY, NEEDLE_API_KEY, and NEEDLE_COLLECTION_ID 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: "Invoice Summarizer" }).click();
|
||||
|
||||
await initialGPTsetup(page);
|
||||
|
||||
// Configure Needle Search Knowledge Base
|
||||
await page
|
||||
.getByTestId("input_str_needle_api_key")
|
||||
.fill(process.env.NEEDLE_API_KEY || "");
|
||||
await page
|
||||
.getByTestId("input_str_collection_id")
|
||||
.fill(process.env.NEEDLE_COLLECTION_ID || "");
|
||||
|
||||
// Run the flow
|
||||
await page.getByTestId("button_run_chat output").click();
|
||||
|
||||
// Wait for the flow to build successfully
|
||||
await page.waitForSelector("text=built successfully", { timeout: 30000 });
|
||||
await page.getByText("built successfully").last().click({
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Switch to Playground
|
||||
await page.getByText("Playground", { exact: true }).last().click();
|
||||
|
||||
// Wait for the playground to be ready
|
||||
const inputPlaceholder = page
|
||||
.getByPlaceholder(
|
||||
"No chat input variables found. Click to run your flow.",
|
||||
{ exact: true },
|
||||
)
|
||||
.last();
|
||||
|
||||
await expect(inputPlaceholder).toBeVisible({ timeout: 10000 });
|
||||
|
||||
// Verify initial response is displayed
|
||||
await expect(page.getByText("Search Results Summary")).toBeVisible({
|
||||
timeout: 15000,
|
||||
});
|
||||
|
||||
// Verify that specific invoice-related data appears in the results
|
||||
const keyTerms = ["expenses", "invoice", "vendor"];
|
||||
for (const term of keyTerms) {
|
||||
await expect(page.getByText(term, { exact: false })).toBeVisible({
|
||||
timeout: 5000,
|
||||
});
|
||||
}
|
||||
|
||||
// Test interaction with the flow by adding a specific query
|
||||
// Click the input field and type a query
|
||||
await inputPlaceholder.click();
|
||||
await page.keyboard.type("Summarize the total expenses from last month");
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
// Wait for response to the specific query
|
||||
await expect(page.getByText("Search Results Summary")).toBeVisible({
|
||||
timeout: 20000,
|
||||
});
|
||||
|
||||
// Verify that expense summary information appears in the response
|
||||
await expect(page.getByText("expenses", { exact: false })).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// Test error handling - invalid query
|
||||
await page.keyboard.type("xyz123$%^NonSensicalQuery");
|
||||
await page.keyboard.press("Enter");
|
||||
|
||||
// Wait for the response, which should still show search results or appropriate message
|
||||
await expect(
|
||||
page
|
||||
.getByText("Search Results", { exact: false })
|
||||
.or(page.getByText("no relevant", { exact: false })),
|
||||
).toBeVisible({ timeout: 20000 });
|
||||
|
||||
// Cleanup - Reset the session
|
||||
await page.getByTestId("side_nav_options_all-templates").click();
|
||||
},
|
||||
);
|
||||
Loading…
Add table
Add a link
Reference in a new issue