feat: jigsawstack bundle integration (#8832)
* fix: formatting errors. * fix: formmating errors for jigsawstack components. * fix: bugs identified by coderabbitai. * fix: formatting issues on JigsawStack icon gradient. * fix: project starters. * fix: value errors. * fix: app startup * fix: resolve merge conflicts, accept incoming changes. * fix: follow lexicographical order for bundle names. Co-authored-by: Edwin Jose <edwinjose900@gmail.com> * feat: add JigsawStack bundle to the sidebar, following lexographical order. * fix: remove duplicate changes, by rebasing to main/src/.../styleUtils.ts * fix: apply suggested fixes for potential issues identified from coderabbitai. --------- Co-authored-by: Edwin Jose <edwinjose900@gmail.com>
This commit is contained in:
parent
ba9740f32a
commit
8c72ea087c
20 changed files with 1356 additions and 0 deletions
23
src/backend/base/langflow/components/jigsawstack/__init__.py
Normal file
23
src/backend/base/langflow/components/jigsawstack/__init__.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
from .ai_scrape import JigsawStackAIScraperComponent
|
||||
from .ai_web_search import JigsawStackAIWebSearchComponent
|
||||
from .file_read import JigsawStackFileReadComponent
|
||||
from .file_upload import JigsawStackFileUploadComponent
|
||||
from .image_generation import JigsawStackImageGenerationComponent
|
||||
from .nsfw import JigsawStackNSFWComponent
|
||||
from .object_detection import JigsawStackObjectDetectionComponent
|
||||
from .sentiment import JigsawStackSentimentComponent
|
||||
from .text_to_sql import JigsawStackTextToSQLComponent
|
||||
from .vocr import JigsawStackVOCRComponent
|
||||
|
||||
__all__ = [
|
||||
"JigsawStackAIScraperComponent",
|
||||
"JigsawStackAIWebSearchComponent",
|
||||
"JigsawStackFileReadComponent",
|
||||
"JigsawStackFileUploadComponent",
|
||||
"JigsawStackImageGenerationComponent",
|
||||
"JigsawStackNSFWComponent",
|
||||
"JigsawStackObjectDetectionComponent",
|
||||
"JigsawStackSentimentComponent",
|
||||
"JigsawStackTextToSQLComponent",
|
||||
"JigsawStackVOCRComponent",
|
||||
]
|
||||
126
src/backend/base/langflow/components/jigsawstack/ai_scrape.py
Normal file
126
src/backend/base/langflow/components/jigsawstack/ai_scrape.py
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageTextInput, Output, SecretStrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
MAX_ELEMENT_PROMPTS = 5
|
||||
|
||||
|
||||
class JigsawStackAIScraperComponent(Component):
|
||||
display_name = "AI Scraper"
|
||||
description = "Scrape any website instantly and get consistent structured data \
|
||||
in seconds without writing any css selector code"
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/scrape"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackAIScraper"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="url",
|
||||
display_name="URL",
|
||||
info="URL of the page to scrape. Either url or html is required, but not both.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="html",
|
||||
display_name="HTML",
|
||||
info="HTML content to scrape. Either url or html is required, but not both.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="element_prompts",
|
||||
display_name="Element Prompts",
|
||||
info="Items on the page to be scraped (maximum 5). E.g. 'Plan price', 'Plan title'",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="root_element_selector",
|
||||
display_name="Root Element Selector",
|
||||
info="CSS selector to limit the scope of scraping to a specific element and its children",
|
||||
required=False,
|
||||
value="main",
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="AI Scraper Results", name="scrape_results", method="scrape"),
|
||||
]
|
||||
|
||||
def scrape(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# Build request object
|
||||
scrape_params: dict = {}
|
||||
if self.url:
|
||||
scrape_params["url"] = self.url
|
||||
if self.html:
|
||||
scrape_params["html"] = self.html
|
||||
|
||||
url_value = scrape_params.get("url", "")
|
||||
html_value = scrape_params.get("html", "")
|
||||
if (not url_value or not url_value.strip()) and (not html_value or not html_value.strip()):
|
||||
url_or_html_error = "Either 'url' or 'html' must be provided for scraping"
|
||||
raise ValueError(url_or_html_error)
|
||||
|
||||
# Process element_prompts with proper type handling
|
||||
element_prompts_list: list[str] = []
|
||||
if self.element_prompts:
|
||||
element_prompts_value: str | list[str] = self.element_prompts
|
||||
|
||||
if isinstance(element_prompts_value, str):
|
||||
if "," not in element_prompts_value:
|
||||
element_prompts_list = [element_prompts_value]
|
||||
else:
|
||||
element_prompts_list = element_prompts_value.split(",")
|
||||
elif isinstance(element_prompts_value, list):
|
||||
element_prompts_list = element_prompts_value
|
||||
else:
|
||||
# Fallback for other types
|
||||
element_prompts_list = str(element_prompts_value).split(",")
|
||||
|
||||
if len(element_prompts_list) > MAX_ELEMENT_PROMPTS:
|
||||
max_elements_error = "Maximum of 5 element prompts allowed"
|
||||
raise ValueError(max_elements_error)
|
||||
if len(element_prompts_list) == 0:
|
||||
invalid_elements_error = "Element prompts cannot be empty"
|
||||
raise ValueError(invalid_elements_error)
|
||||
|
||||
scrape_params["element_prompts"] = element_prompts_list
|
||||
|
||||
if self.root_element_selector:
|
||||
scrape_params["root_element_selector"] = self.root_element_selector
|
||||
|
||||
# Call web scraping
|
||||
response = client.web.ai_scrape(scrape_params)
|
||||
|
||||
if not response.get("success", False):
|
||||
fail_error = "JigsawStack API request failed."
|
||||
raise ValueError(fail_error)
|
||||
|
||||
result_data = response
|
||||
|
||||
self.status = "AI scrape process is now complete."
|
||||
|
||||
return Data(data=result_data)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, DropdownInput, Output, QueryInput, SecretStrInput
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
||||
class JigsawStackAIWebSearchComponent(Component):
|
||||
display_name = "AI Web Search"
|
||||
description = "Effortlessly search the Web and get access to high-quality results powered with AI."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/web/ai-search"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackAISearch"
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
QueryInput(
|
||||
name="query",
|
||||
display_name="Query",
|
||||
info="The search value. The maximum query character length is 400",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
BoolInput(
|
||||
name="ai_overview",
|
||||
display_name="AI Overview",
|
||||
info="Include AI powered overview in the search results",
|
||||
required=False,
|
||||
value=True,
|
||||
),
|
||||
DropdownInput(
|
||||
name="safe_search",
|
||||
display_name="Safe Search",
|
||||
info="Enable safe search to filter out adult content",
|
||||
required=False,
|
||||
options=["moderate", "strict", "off"],
|
||||
value="off",
|
||||
),
|
||||
BoolInput(
|
||||
name="spell_check",
|
||||
display_name="Spell Check",
|
||||
info="Spell check the search query",
|
||||
required=False,
|
||||
value=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="AI Search Results", name="search_results", method="search"),
|
||||
Output(display_name="Content Text", name="content_text", method="get_content_text"),
|
||||
]
|
||||
|
||||
def search(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# build request object
|
||||
search_params = {}
|
||||
if self.query:
|
||||
search_params["query"] = self.query
|
||||
if self.ai_overview is not None:
|
||||
search_params["ai_overview"] = self.ai_overview
|
||||
if self.safe_search:
|
||||
search_params["safe_search"] = self.safe_search
|
||||
if self.spell_check is not None:
|
||||
search_params["spell_check"] = self.spell_check
|
||||
|
||||
# Call web scraping
|
||||
response = client.web.search(search_params)
|
||||
|
||||
api_error_msg = "JigsawStack API returned unsuccessful response"
|
||||
if not response.get("success", False):
|
||||
raise ValueError(api_error_msg)
|
||||
|
||||
# Create comprehensive data object
|
||||
result_data = {
|
||||
"query": self.query,
|
||||
"ai_overview": response.get("ai_overview", ""),
|
||||
"spell_fixed": response.get("spell_fixed", False),
|
||||
"is_safe": response.get("is_safe", True),
|
||||
"results": response.get("results", []),
|
||||
"success": True,
|
||||
}
|
||||
|
||||
self.status = f"Search complete for: {response.get('query', '')}"
|
||||
|
||||
return Data(data=result_data)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
||||
def get_content_text(self) -> Message:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError:
|
||||
return Message(text="Error: JigsawStack package not found.")
|
||||
|
||||
try:
|
||||
# Initialize JigsawStack client
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
search_params = {}
|
||||
if self.query:
|
||||
search_params["query"] = self.query
|
||||
if self.ai_overview is not None:
|
||||
search_params["ai_overview"] = self.ai_overview
|
||||
if self.safe_search:
|
||||
search_params["safe_search"] = self.safe_search
|
||||
if self.spell_check is not None:
|
||||
search_params["spell_check"] = self.spell_check
|
||||
|
||||
# Call web scraping
|
||||
response = client.web.search(search_params)
|
||||
|
||||
request_failed_msg = "Request Failed"
|
||||
if not response.get("success", False):
|
||||
raise JigsawStackError(request_failed_msg)
|
||||
|
||||
# Return the content as text
|
||||
content = response.get("ai_overview", "")
|
||||
return Message(text=content)
|
||||
|
||||
except JigsawStackError as e:
|
||||
return Message(text=f"Error while using AI Search: {e!s}")
|
||||
115
src/backend/base/langflow/components/jigsawstack/file_read.py
Normal file
115
src/backend/base/langflow/components/jigsawstack/file_read.py
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
import tempfile
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import Output, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackFileReadComponent(Component):
|
||||
display_name = "File Read"
|
||||
description = "Read any previously uploaded file seamlessly from \
|
||||
JigsawStack File Storage and use it in your AI applications."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/store/file/get"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackFileRead"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
StrInput(
|
||||
name="key",
|
||||
display_name="Key",
|
||||
info="The key used to retrieve the file from JigsawStack File Storage.",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="File Path", name="file_path", method="read_and_save_file"),
|
||||
]
|
||||
|
||||
def read_and_save_file(self) -> Data:
|
||||
"""Read file from JigsawStack and save to temp file, return file path."""
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
if not self.key or self.key.strip() == "":
|
||||
invalid_key_error = "Key is required to read a file from JigsawStack File Storage."
|
||||
raise ValueError(invalid_key_error)
|
||||
|
||||
# Download file content
|
||||
response = client.store.get(self.key)
|
||||
|
||||
# Determine file extension
|
||||
file_extension = self._detect_file_extension(response)
|
||||
|
||||
# Create temporary file
|
||||
with tempfile.NamedTemporaryFile(
|
||||
delete=False, suffix=file_extension, prefix=f"jigsawstack_{self.key}_"
|
||||
) as temp_file:
|
||||
if isinstance(response, bytes):
|
||||
temp_file.write(response)
|
||||
else:
|
||||
# Handle string content
|
||||
temp_file.write(response.encode("utf-8"))
|
||||
|
||||
temp_path = temp_file.name
|
||||
|
||||
return Data(
|
||||
data={
|
||||
"file_path": temp_path,
|
||||
"key": self.key,
|
||||
"file_extension": file_extension,
|
||||
"size": len(response) if isinstance(response, bytes) else len(str(response)),
|
||||
"success": True,
|
||||
}
|
||||
)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
||||
def _detect_file_extension(self, content) -> str:
|
||||
"""Detect file extension based on content headers."""
|
||||
if isinstance(content, bytes):
|
||||
# Check magic numbers for common file types
|
||||
if content.startswith(b"\xff\xd8\xff"):
|
||||
return ".jpg"
|
||||
if content.startswith(b"\x89PNG\r\n\x1a\n"):
|
||||
return ".png"
|
||||
if content.startswith((b"GIF87a", b"GIF89a")):
|
||||
return ".gif"
|
||||
if content.startswith(b"%PDF"):
|
||||
return ".pdf"
|
||||
if content.startswith(b"PK\x03\x04"): # ZIP/DOCX/XLSX
|
||||
return ".zip"
|
||||
if content.startswith(b"\x00\x00\x01\x00"): # ICO
|
||||
return ".ico"
|
||||
if content.startswith(b"RIFF") and b"WEBP" in content[:12]:
|
||||
return ".webp"
|
||||
if content.startswith((b"\xff\xfb", b"\xff\xf3", b"\xff\xf2")):
|
||||
return ".mp3"
|
||||
if content.startswith((b"ftypmp4", b"\x00\x00\x00\x20ftypmp4")):
|
||||
return ".mp4"
|
||||
# Try to decode as text
|
||||
try:
|
||||
content.decode("utf-8")
|
||||
return ".txt" # noqa: TRY300
|
||||
except UnicodeDecodeError:
|
||||
return ".bin" # Binary file
|
||||
else:
|
||||
# String content
|
||||
return ".txt"
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
from pathlib import Path
|
||||
|
||||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, FileInput, Output, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackFileUploadComponent(Component):
|
||||
display_name = "File Upload"
|
||||
description = "Store any file seamlessly on JigsawStack File Storage and use it in your AI applications. \
|
||||
Supports various file types including images, documents, and more."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/store/file/add"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackFileUpload"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
FileInput(
|
||||
name="file",
|
||||
display_name="File",
|
||||
info="Upload file to be stored on JigsawStack File Storage.",
|
||||
required=True,
|
||||
file_types=["pdf", "png", "jpg", "jpeg", "mp4", "mp3", "txt", "docx", "xlsx"],
|
||||
),
|
||||
StrInput(
|
||||
name="key",
|
||||
display_name="Key",
|
||||
info="The key used to store the file on JigsawStack File Storage. \
|
||||
If not provided, a unique key will be generated.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
BoolInput(
|
||||
name="overwrite",
|
||||
display_name="Overwrite Existing File",
|
||||
info="If true, will overwrite the existing file with the same key. \
|
||||
If false, will return an error if the file already exists.",
|
||||
required=False,
|
||||
value=True,
|
||||
),
|
||||
BoolInput(
|
||||
name="temp_public_url",
|
||||
display_name="Return Temporary Public URL",
|
||||
info="If true, will return a temporary public URL which lasts for a limited time. \
|
||||
If false, will return the file store key which can only be accessed by the owner.",
|
||||
required=False,
|
||||
value=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="File Store Result", name="file_upload_result", method="upload_file"),
|
||||
]
|
||||
|
||||
def upload_file(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
file_path = Path(self.file)
|
||||
with Path.open(file_path, "rb") as f:
|
||||
file_content = f.read()
|
||||
params = {}
|
||||
|
||||
if self.key:
|
||||
# if key is provided, use it as the file store key
|
||||
params["key"] = self.key
|
||||
if self.overwrite is not None:
|
||||
# if overwrite is provided, use it to determine if the file should be overwritten
|
||||
params["overwrite"] = self.overwrite
|
||||
if self.temp_public_url is not None:
|
||||
# if temp_public_url is provided, use it to determine if a temporary public URL should
|
||||
params["temp_public_url"] = self.temp_public_url
|
||||
|
||||
response = client.store.upload(file_content, params)
|
||||
return Data(data=response)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
|
@ -0,0 +1,205 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import DropdownInput, IntInput, MessageTextInput, Output, SecretStrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackImageGenerationComponent(Component):
|
||||
display_name = "Image Generation"
|
||||
description = "Generate an image based on the given text by employing AI models like Flux, \
|
||||
Stable Diffusion, and other top models."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/image-generation"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackImageGeneration"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="prompt",
|
||||
display_name="Prompt",
|
||||
info="The text prompt to generate the image from. Must be between 1-5000 characters.",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="aspect_ratio",
|
||||
display_name="Aspect Ratio",
|
||||
info="The aspect ratio of the generated image. Must be one of the following:\
|
||||
'1:1', '16:9', '21:9', '3:2', '2:3', '4:5', '5:4', '3:4', '4:3', '9:16', '9:21' \
|
||||
Default is 1:1.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="url",
|
||||
display_name="URL",
|
||||
info="A valid URL where the generated image will be sent.",
|
||||
required=False,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="file_store_key",
|
||||
display_name="File Store Key",
|
||||
info="The key used to store the image on Jigsawstack File Storage. Not required if url is specified.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
IntInput(
|
||||
name="width",
|
||||
display_name="Width",
|
||||
info="The width of the image. Must be between 256-1920 pixels.",
|
||||
required=False,
|
||||
),
|
||||
IntInput(
|
||||
name="height",
|
||||
display_name="Height",
|
||||
info="The height of the image. Must be between 256-1920 pixels.",
|
||||
required=False,
|
||||
),
|
||||
IntInput(
|
||||
name="steps",
|
||||
display_name="Steps",
|
||||
info="The number of denoising steps. Must be between 1-90. \
|
||||
Higher values produce better quality images but take more time to generate.",
|
||||
required=False,
|
||||
),
|
||||
DropdownInput(
|
||||
name="output_format",
|
||||
display_name="Output Format",
|
||||
info="The output format of the generated image. Must be one of the following values:\
|
||||
png or svg",
|
||||
required=False,
|
||||
options=["png", "svg"],
|
||||
value="png",
|
||||
),
|
||||
MessageTextInput(
|
||||
name="negative_prompt",
|
||||
display_name="Negative Prompt",
|
||||
info="The text prompt to avoid in the generated image. \
|
||||
Must be between 1-5000 characters.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
advanced=True,
|
||||
),
|
||||
IntInput(
|
||||
name="seed",
|
||||
display_name="Seed",
|
||||
info="Makes generation deterministic.\
|
||||
Using the same seed and set of parameters will produce identical image each time.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
advanced=True,
|
||||
),
|
||||
IntInput(
|
||||
name="guidance",
|
||||
display_name="Guidance Scale",
|
||||
info="Higher guidance forces the model to better follow the prompt, \
|
||||
but may result in lower quality output. Must be between 1-28.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
advanced=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="Image Generation Results", name="image_generation_results", method="generate_image"),
|
||||
]
|
||||
|
||||
def generate_image(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
min_character_length = 1
|
||||
max_character_length = 5000
|
||||
min_width = 256
|
||||
max_width = 1920
|
||||
min_height = 256
|
||||
max_height = 1920
|
||||
min_steps = 1
|
||||
max_steps = 90
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
if not self.prompt or len(self.prompt) < min_character_length or len(self.prompt) > max_character_length:
|
||||
invalid_prompt_error = f"Prompts must be between \
|
||||
{min_character_length}-{max_character_length} characters."
|
||||
raise ValueError(invalid_prompt_error)
|
||||
|
||||
if self.aspect_ratio and self.aspect_ratio not in [
|
||||
"1:1",
|
||||
"16:9",
|
||||
"21:9",
|
||||
"3:2",
|
||||
"2:3",
|
||||
"4:5",
|
||||
"5:4",
|
||||
"3:4",
|
||||
"4:3",
|
||||
"9:16",
|
||||
"9:21",
|
||||
]:
|
||||
invalid_aspect_ratio_error = (
|
||||
"Aspect ratio must be one of the following: '1:1', '16:9', '21:9', '3:2', '2:3', "
|
||||
"'4:5', '5:4', '3:4', '4:3', '9:16', '9:21'."
|
||||
)
|
||||
raise ValueError(invalid_aspect_ratio_error)
|
||||
if self.width and (self.width < min_width or self.width > max_width):
|
||||
invalid_width_error = f"Width must be between {min_width}-{max_width} pixels."
|
||||
raise ValueError(invalid_width_error)
|
||||
if self.height and (self.height < min_height or self.height > max_height):
|
||||
invalid_height_error = f"Height must be between {min_height}-{max_height} pixels."
|
||||
raise ValueError(invalid_height_error)
|
||||
if self.steps and (self.steps < min_steps or self.steps > max_steps):
|
||||
invalid_steps_error = f"Steps must be between {min_steps}-{max_steps}."
|
||||
raise ValueError(invalid_steps_error)
|
||||
|
||||
params = {}
|
||||
if self.prompt:
|
||||
params["prompt"] = self.prompt.strip()
|
||||
if self.aspect_ratio:
|
||||
params["aspect_ratio"] = self.aspect_ratio.strip()
|
||||
if self.url:
|
||||
params["url"] = self.url.strip()
|
||||
if self.file_store_key:
|
||||
params["file_store_key"] = self.file_store_key.strip()
|
||||
if self.width:
|
||||
params["width"] = self.width
|
||||
if self.height:
|
||||
params["height"] = self.height
|
||||
params["return_type"] = "url"
|
||||
if self.output_format:
|
||||
params["output_format"] = self.output_format.strip()
|
||||
if self.steps:
|
||||
params["steps"] = self.steps
|
||||
|
||||
# Initialize advance_config if any advanced parameters are provided
|
||||
if self.negative_prompt or self.seed or self.guidance:
|
||||
params["advance_config"] = {}
|
||||
if self.negative_prompt:
|
||||
params["advance_config"]["negative_prompt"] = self.negative_prompt
|
||||
if self.seed:
|
||||
params["advance_config"]["seed"] = self.seed
|
||||
if self.guidance:
|
||||
params["advance_config"]["guidance"] = self.guidance
|
||||
|
||||
# Call image generation
|
||||
response = client.image_generation(params)
|
||||
|
||||
if response.get("url", None) is None or response.get("url", None).strip() == "":
|
||||
failed_response_error = "JigsawStack API returned unsuccessful response"
|
||||
raise ValueError(failed_response_error)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
60
src/backend/base/langflow/components/jigsawstack/nsfw.py
Normal file
60
src/backend/base/langflow/components/jigsawstack/nsfw.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import Output, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackNSFWComponent(Component):
|
||||
display_name = "NSFW Detection"
|
||||
description = "Detect if image/video contains NSFW content"
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/nsfw"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackNSFW"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
StrInput(
|
||||
name="url",
|
||||
display_name="URL",
|
||||
info="URL of the image or video to analyze",
|
||||
required=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="NSFW Analysis", name="nsfw_result", method="detect_nsfw"),
|
||||
]
|
||||
|
||||
def detect_nsfw(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# Build request parameters
|
||||
params = {"url": self.url}
|
||||
|
||||
response = client.validate.nsfw(params)
|
||||
|
||||
api_error_msg = "JigsawStack API returned unsuccessful response"
|
||||
if not response.get("success", False):
|
||||
raise ValueError(api_error_msg)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except ValueError:
|
||||
raise
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import BoolInput, DropdownInput, MessageTextInput, Output, SecretStrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackObjectDetectionComponent(Component):
|
||||
display_name = "Object Detection"
|
||||
description = "Perform object detection on images using JigsawStack's Object Detection Model, \
|
||||
capable of image grounding, segmentation and computer use."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/object-detection"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackObjectDetection"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="prompts",
|
||||
display_name="Prompts",
|
||||
info="The prompts to ground the object detection model. \
|
||||
You can pass a list of comma-separated prompts to extract different information from the image.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="url",
|
||||
display_name="URL",
|
||||
info="The image URL. Not required if file_store_key is specified.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="file_store_key",
|
||||
display_name="File Store Key",
|
||||
info="The key used to store the image on Jigsawstack File Storage. Not required if url is specified.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
BoolInput(
|
||||
name="annotated_image",
|
||||
display_name="Return Annotated Image",
|
||||
info="If true, will return an url for annotated image with detected objects.",
|
||||
required=False,
|
||||
value=True,
|
||||
),
|
||||
DropdownInput(
|
||||
name="features",
|
||||
display_name="Features",
|
||||
info="Select the features to enable for object detection",
|
||||
required=False,
|
||||
options=["object_detection", "gui"],
|
||||
value=["object_detection", "gui"],
|
||||
),
|
||||
DropdownInput(
|
||||
name="return_type",
|
||||
display_name="Return Type",
|
||||
info="Select the return type for the object detection results such as masks or annotations.",
|
||||
required=False,
|
||||
options=["url", "base64"],
|
||||
value="url",
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="Object Detection results", name="object_detection_results", method="detect_objects"),
|
||||
]
|
||||
|
||||
def detect_objects(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# build request object
|
||||
params = {}
|
||||
if self.prompts:
|
||||
if isinstance(self.prompts, list):
|
||||
params["prompt"] = self.prompts
|
||||
elif isinstance(self.prompts, str):
|
||||
if "," in self.prompts:
|
||||
# Split by comma and strip whitespace
|
||||
params["prompt"] = [p.strip() for p in self.prompts.split(",")]
|
||||
else:
|
||||
params["prompt"] = [self.prompts.strip()]
|
||||
else:
|
||||
invalid_prompt_error = "Prompt must be a list of strings or a single string"
|
||||
raise ValueError(invalid_prompt_error)
|
||||
if self.url:
|
||||
params["url"] = self.url
|
||||
if self.file_store_key:
|
||||
params["file_store_key"] = self.file_store_key
|
||||
|
||||
# if both url and file_store_key are not provided, raise an error
|
||||
if not self.url and not self.file_store_key:
|
||||
missing_url_error = "Either URL or File Store Key must be provided to perform object detection"
|
||||
raise ValueError(missing_url_error)
|
||||
|
||||
params["annotated_image"] = self.annotated_image
|
||||
if self.features:
|
||||
params["features"] = self.features
|
||||
|
||||
# Call web scraping
|
||||
response = client.vision.object_detection(params)
|
||||
|
||||
if not response.get("success", False):
|
||||
failed_response_error = "JigsawStack API returned unsuccessful response"
|
||||
raise ValueError(failed_response_error)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
112
src/backend/base/langflow/components/jigsawstack/sentiment.py
Normal file
112
src/backend/base/langflow/components/jigsawstack/sentiment.py
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageTextInput, Output, SecretStrInput
|
||||
from langflow.schema.data import Data
|
||||
from langflow.schema.message import Message
|
||||
|
||||
|
||||
class JigsawStackSentimentComponent(Component):
|
||||
display_name = "Sentiment Analysis"
|
||||
description = "Analyze sentiment of text using JigsawStack AI"
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/sentiment"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackSentiment"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="text",
|
||||
display_name="Text",
|
||||
info="Text to analyze for sentiment",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="Sentiment Data", name="sentiment_data", method="analyze_sentiment"),
|
||||
Output(display_name="Sentiment Text", name="sentiment_text", method="get_sentiment_text"),
|
||||
]
|
||||
|
||||
def analyze_sentiment(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
response = client.sentiment({"text": self.text})
|
||||
|
||||
api_error_msg = "JigsawStack API returned unsuccessful response"
|
||||
if not response.get("success", False):
|
||||
raise ValueError(api_error_msg)
|
||||
|
||||
sentiment_data = response.get("sentiment", {})
|
||||
|
||||
result_data = {
|
||||
"text_analyzed": self.text,
|
||||
"sentiment": sentiment_data.get("sentiment", "Unknown"),
|
||||
"emotion": sentiment_data.get("emotion", "Unknown"),
|
||||
"score": sentiment_data.get("score", 0.0),
|
||||
"sentences": response.get("sentences", []),
|
||||
"success": True,
|
||||
}
|
||||
|
||||
self.status = (
|
||||
f"Sentiment: {sentiment_data.get('sentiment', 'Unknown')} | "
|
||||
f"Emotion: {sentiment_data.get('emotion', 'Unknown')} | "
|
||||
f"Score: {sentiment_data.get('score', 0.0):.3f}"
|
||||
)
|
||||
|
||||
return Data(data=result_data)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "text_analyzed": self.text, "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
||||
def get_sentiment_text(self) -> Message:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError:
|
||||
return Message(text="Error: JigsawStack package not found. Please install it with: pip install jigsawstack")
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
response = client.sentiment({"text": self.text})
|
||||
|
||||
sentiment_data = response.get("sentiment", {})
|
||||
sentences = response.get("sentences", [])
|
||||
|
||||
# Format the output
|
||||
formatted_output = f"""Sentiment Analysis Results:
|
||||
|
||||
Text: {self.text}
|
||||
|
||||
Overall Sentiment: {sentiment_data.get("sentiment", "Unknown")}
|
||||
Emotion: {sentiment_data.get("emotion", "Unknown")}
|
||||
Score: {sentiment_data.get("score", 0.0):.3f}
|
||||
|
||||
Sentence-by-sentence Analysis:
|
||||
"""
|
||||
|
||||
for i, sentence in enumerate(sentences, 1):
|
||||
formatted_output += (
|
||||
f"{i}. {sentence.get('text', '')}\n"
|
||||
f" Sentiment: {sentence.get('sentiment', 'Unknown')} | "
|
||||
f"Emotion: {sentence.get('emotion', 'Unknown')} | "
|
||||
f"Score: {sentence.get('score', 0.0):.3f}\n"
|
||||
)
|
||||
|
||||
return Message(text=formatted_output)
|
||||
|
||||
except JigsawStackError as e:
|
||||
return Message(text=f"Error analyzing sentiment: {e!s}")
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageTextInput, Output, QueryInput, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackTextToSQLComponent(Component):
|
||||
display_name = "Text to SQL"
|
||||
description = "Convert natural language to SQL queries using JigsawStack AI"
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/text-to-sql"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackTextToSQL"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
QueryInput(
|
||||
name="prompt",
|
||||
display_name="Prompt",
|
||||
info="Natural language description of the SQL query you want to generate",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="sql_schema",
|
||||
display_name="SQL Schema",
|
||||
info=(
|
||||
"The database schema information. Can be a CREATE TABLE statement or schema description. "
|
||||
"Specifying this parameter improves SQL generation accuracy by applying "
|
||||
"database-specific syntax and optimizations."
|
||||
),
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
StrInput(
|
||||
name="file_store_key",
|
||||
display_name="File Store Key",
|
||||
info=(
|
||||
"The key used to store the database schema on Jigsawstack file Storage. "
|
||||
"Not required if sql_schema is specified."
|
||||
),
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="SQL Query", name="sql_query", method="generate_sql"),
|
||||
]
|
||||
|
||||
def generate_sql(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
schema_error = "Either 'sql_schema' or 'file_store_key' must be provided"
|
||||
if not self.sql_schema and not self.file_store_key:
|
||||
raise ValueError(schema_error)
|
||||
|
||||
# build request object
|
||||
params = {"prompt": self.prompt}
|
||||
|
||||
if self.sql_schema:
|
||||
params["sql_schema"] = self.sql_schema
|
||||
if self.file_store_key:
|
||||
params["file_store_key"] = self.file_store_key
|
||||
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
response = client.text_to_sql(params)
|
||||
|
||||
api_error_msg = "JigsawStack API returned unsuccessful response"
|
||||
if not response.get("success", False):
|
||||
raise ValueError(api_error_msg)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except ValueError:
|
||||
raise
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import MessageTextInput, Output, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackTextTranslateComponent(Component):
|
||||
display_name = "Text Translate"
|
||||
description = "Translate text from one language to another with support for multiple text formats."
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/translate"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackTextTranslate"
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
StrInput(
|
||||
name="target_language",
|
||||
display_name="Target Language",
|
||||
info="The language code of the target language to translate to. \
|
||||
Language code is identified by a unique ISO 639-1 two-letter code",
|
||||
required=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="text",
|
||||
display_name="Text",
|
||||
info="The text to translate. This can be a single string or a list of strings. \
|
||||
If a list is provided, each string will be translated separately.",
|
||||
required=True,
|
||||
is_list=True,
|
||||
tool_mode=True,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="Translation Results", name="translation_results", method="translation"),
|
||||
]
|
||||
|
||||
def translation(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# build request object
|
||||
params = {}
|
||||
if self.target_language:
|
||||
params["target_language"] = self.target_language
|
||||
|
||||
if self.text:
|
||||
if isinstance(self.text, list):
|
||||
params["text"] = self.text
|
||||
else:
|
||||
params["text"] = [self.text]
|
||||
|
||||
# Call web scraping
|
||||
response = client.translate.text(params)
|
||||
|
||||
if not response.get("success", False):
|
||||
failed_response_error = "JigsawStack API returned unsuccessful response"
|
||||
raise ValueError(failed_response_error)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
107
src/backend/base/langflow/components/jigsawstack/vocr.py
Normal file
107
src/backend/base/langflow/components/jigsawstack/vocr.py
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
from langflow.custom.custom_component.component import Component
|
||||
from langflow.io import IntInput, MessageTextInput, Output, SecretStrInput, StrInput
|
||||
from langflow.schema.data import Data
|
||||
|
||||
|
||||
class JigsawStackVOCRComponent(Component):
|
||||
display_name = "VOCR"
|
||||
description = "Extract data from any document type in a consistent structure with fine-tuned \
|
||||
vLLMs for the highest accuracy"
|
||||
documentation = "https://jigsawstack.com/docs/api-reference/ai/vocr"
|
||||
icon = "JigsawStack"
|
||||
name = "JigsawStackVOCR"
|
||||
|
||||
inputs = [
|
||||
SecretStrInput(
|
||||
name="api_key",
|
||||
display_name="JigsawStack API Key",
|
||||
info="Your JigsawStack API key for authentication",
|
||||
required=True,
|
||||
),
|
||||
MessageTextInput(
|
||||
name="prompts",
|
||||
display_name="Prompts",
|
||||
info="The prompts used to describe the image. Default prompt is Describe the image in detail. \
|
||||
You can pass a list of comma-separated prompts to extract different information from the image.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
StrInput(
|
||||
name="url",
|
||||
display_name="URL",
|
||||
info="The image or document url. Not required if file_store_key is specified.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
StrInput(
|
||||
name="file_store_key",
|
||||
display_name="File Store Key",
|
||||
info="The key used to store the image on Jigsawstack File Storage. Not required if url is specified.",
|
||||
required=False,
|
||||
tool_mode=True,
|
||||
),
|
||||
IntInput(
|
||||
name="page_range_start",
|
||||
display_name="Page Range",
|
||||
info="Page range start limit for the document. If not specified, all pages will be processed.",
|
||||
required=False,
|
||||
),
|
||||
IntInput(
|
||||
name="page_range_end",
|
||||
display_name="Page Range End",
|
||||
info="Page range end limit for the document. If not specified, all pages will be processed.",
|
||||
required=False,
|
||||
),
|
||||
]
|
||||
|
||||
outputs = [
|
||||
Output(display_name="VOCR results", name="vocr_results", method="vocr"),
|
||||
]
|
||||
|
||||
def vocr(self) -> Data:
|
||||
try:
|
||||
from jigsawstack import JigsawStack, JigsawStackError
|
||||
except ImportError as e:
|
||||
jigsawstack_import_error = (
|
||||
"JigsawStack package not found. Please install it using: pip install jigsawstack>=0.2.7"
|
||||
)
|
||||
raise ImportError(jigsawstack_import_error) from e
|
||||
|
||||
try:
|
||||
client = JigsawStack(api_key=self.api_key)
|
||||
|
||||
# build request object
|
||||
params = {}
|
||||
if self.prompts:
|
||||
if isinstance(self.prompts, list):
|
||||
params["prompt"] = self.prompts
|
||||
elif isinstance(self.prompts, str):
|
||||
if "," in self.prompts:
|
||||
# Split by comma and strip whitespace
|
||||
params["prompt"] = [p.strip() for p in self.prompts.split(",")]
|
||||
else:
|
||||
params["prompt"] = [self.prompts.strip()]
|
||||
else:
|
||||
invalid_prompt_error = "Prompt must be a list of strings or a single string"
|
||||
raise ValueError(invalid_prompt_error)
|
||||
if self.url:
|
||||
params["url"] = self.url
|
||||
if self.file_store_key:
|
||||
params["file_store_key"] = self.file_store_key
|
||||
|
||||
if self.page_range_start and self.page_range_end:
|
||||
params["page_range"] = [self.page_range_start, self.page_range_end]
|
||||
|
||||
# Call VOCR
|
||||
response = client.vision.vocr(params)
|
||||
|
||||
if not response.get("success", False):
|
||||
failed_response_error = "JigsawStack API returned unsuccessful response"
|
||||
raise ValueError(failed_response_error)
|
||||
|
||||
return Data(data=response)
|
||||
|
||||
except JigsawStackError as e:
|
||||
error_data = {"error": str(e), "success": False}
|
||||
self.status = f"Error: {e!s}"
|
||||
return Data(data=error_data)
|
||||
Loading…
Add table
Add a link
Reference in a new issue