From d59757d82fd58acddefed862522a39fe7a67cca0 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Mon, 4 Mar 2024 08:46:39 -0300 Subject: [PATCH 01/10] Fix refresh http only variable (#1493) (#1494) * Fix refresh http only variable (#1493) * Fix refresh http only variable * Update version to 0.6.10 in pyproject.toml --- pyproject.toml | 2 +- src/backend/langflow/api/v1/login.py | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e7447b1e2..79dee5994 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.6.9" +version = "0.6.10" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ diff --git a/src/backend/langflow/api/v1/login.py b/src/backend/langflow/api/v1/login.py index 2055c18c2..b0946fd0a 100644 --- a/src/backend/langflow/api/v1/login.py +++ b/src/backend/langflow/api/v1/login.py @@ -1,5 +1,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request, Response, status from fastapi.security import OAuth2PasswordRequestForm +from sqlmodel import Session + from langflow.api.v1.schemas import Token from langflow.services.auth.utils import ( authenticate_user, @@ -8,7 +10,6 @@ from langflow.services.auth.utils import ( create_user_tokens, ) from langflow.services.deps import get_session, get_settings_service -from sqlmodel import Session router = APIRouter(tags=["Login"]) @@ -85,7 +86,9 @@ async def auto_login( @router.post("/refresh") -async def refresh_token(request: Request, response: Response, settings_service=Depends(get_settings_service)): +async def refresh_token( + request: Request, response: Response, settings_service=Depends(get_settings_service) +): auth_settings = settings_service.auth_settings token = request.cookies.get("refresh_token_lf") @@ -95,7 +98,7 @@ async def refresh_token(request: Request, response: Response, settings_service=D response.set_cookie( "refresh_token_lf", tokens["refresh_token"], - httponly=auth_settings.REFRESH_TOKEN_HTTPONLY, + httponly=auth_settings.REFRESH_HTTPONLY, samesite=auth_settings.REFRESH_SAME_SITE, secure=auth_settings.REFRESH_SECURE, ) From 3fbcd02bd92ffe65a8d542d0076164406791c253 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 21 Mar 2024 12:21:44 -0300 Subject: [PATCH 02/10] Refactor parse_return_statement method to handle nested returns (#1549) Fixes [Component Output] Custom component does not display output connection points in Langflow UI #1357 --- .../custom/code_parser/code_parser.py | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/interface/custom/code_parser/code_parser.py b/src/backend/langflow/interface/custom/code_parser/code_parser.py index 7a102e33f..1ab1021b7 100644 --- a/src/backend/langflow/interface/custom/code_parser/code_parser.py +++ b/src/backend/langflow/interface/custom/code_parser/code_parser.py @@ -6,6 +6,8 @@ from typing import Any, Dict, List, Type, Union from cachetools import TTLCache, cachedmethod, keys from fastapi import HTTPException + + from langflow.interface.custom.schema import CallableCodeDetails, ClassCodeDetails @@ -234,10 +236,28 @@ class CodeParser: def parse_return_statement(self, node: ast.FunctionDef) -> bool: """ - Parses the return statement of a function or method node. + Parses the return statement of a function or method node, including nested returns. """ - return any(isinstance(n, ast.Return) for n in node.body) + def has_return(node): + if isinstance(node, ast.Return): + return True + elif isinstance(node, ast.If): + return any(has_return(child) for child in node.body) or any(has_return(child) for child in node.orelse) + elif isinstance(node, ast.Try): + return ( + any(has_return(child) for child in node.body) + or any(has_return(child) for child in node.handlers) + or any(has_return(child) for child in node.finalbody) + ) + elif isinstance(node, (ast.For, ast.While)): + return any(has_return(child) for child in node.body) or any(has_return(child) for child in node.orelse) + elif isinstance(node, ast.With): + return any(has_return(child) for child in node.body) + else: + return False + + return any(has_return(child) for child in node.body) def parse_assign(self, stmt): """ From d39ace293c1cb446cd047398e9f7cd87df2eda7e Mon Sep 17 00:00:00 2001 From: chenhongsheng Date: Fri, 22 Mar 2024 00:21:50 +0800 Subject: [PATCH 03/10] fix init ChatMessagePromptTemplate error issue #1351 (#1535) fix init ChatMessagePromptTemplate error issue #1351.ChatMessagePromptTemplate init had role properties,but the params not passing through issue:https://github.com/logspace-ai/langflow/issues/1351 --- src/backend/langflow/interface/initialize/utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/backend/langflow/interface/initialize/utils.py b/src/backend/langflow/interface/initialize/utils.py index 5ecae3d70..0ef76836b 100644 --- a/src/backend/langflow/interface/initialize/utils.py +++ b/src/backend/langflow/interface/initialize/utils.py @@ -32,6 +32,8 @@ def check_tools_in_params(params: Dict): def instantiate_from_template(class_object, params: Dict): from_template_params = {"template": params.pop("prompt", params.pop("template", ""))} + + from_template_params.update(params) if not from_template_params.get("template"): raise ValueError("Prompt template is required") return class_object.from_template(**from_template_params) From 38cfd46eae5a1c3a84056e41f7e716ab5cde2e8d Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Thu, 21 Mar 2024 18:36:38 -0300 Subject: [PATCH 04/10] Refactor API key encryption and decryption methods --- src/backend/langflow/services/auth/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/langflow/services/auth/utils.py b/src/backend/langflow/services/auth/utils.py index a47604b9a..cc0120de9 100644 --- a/src/backend/langflow/services/auth/utils.py +++ b/src/backend/langflow/services/auth/utils.py @@ -9,8 +9,8 @@ from jose import JWTError, jwt from sqlmodel import Session from starlette.websockets import WebSocket -from langflow.services.database.models.api_key.model import ApiKey from langflow.services.database.models.api_key.crud import check_key +from langflow.services.database.models.api_key.model import ApiKey from langflow.services.database.models.user.crud import get_user_by_id, get_user_by_username, update_user_last_login_at from langflow.services.database.models.user.model import User from langflow.services.deps import get_session, get_settings_service @@ -333,7 +333,7 @@ def encrypt_api_key(api_key: str, settings_service=Depends(get_settings_service) fernet = get_fernet(settings_service) # Two-way encryption encrypted_key = fernet.encrypt(api_key.encode()) - return encrypted_key + return encrypted_key.decode() def decrypt_api_key(encrypted_api_key: str, settings_service=Depends(get_settings_service)): From c1d93a0855bf72bed8b7bc71fb8f533032ad0d2f Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Fri, 22 Mar 2024 08:35:43 -0300 Subject: [PATCH 05/10] Bump version to 0.6.11 in pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 79dee5994..a6d726813 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "langflow" -version = "0.6.10" +version = "0.6.11" description = "A Python package with a built-in web application" authors = ["Logspace "] maintainers = [ From 0b380afb66ba71545e94c770ea084ee45367b033 Mon Sep 17 00:00:00 2001 From: Daiki Sakai <1daiki0sakai1@gmail.com> Date: Fri, 22 Mar 2024 20:47:34 +0900 Subject: [PATCH 06/10] Migrate to langchain_anthropic and add ChatAnthropic enhancements (#1551) Migrate to langchain_anthropic and enhance ChatAnthropic functionality - Replace langchain_community with langchain_anthropic for ChatAnthropic - Add support for selecting the Claude model in ChatAnthropic - Implement top_p and top_k parameter support in ChatAnthropic --- poetry.lock | 69 +++++++++---------- pyproject.toml | 3 +- .../langflow/components/llms/ChatAnthropic.py | 33 +++++++-- 3 files changed, 61 insertions(+), 44 deletions(-) diff --git a/poetry.lock b/poetry.lock index 18eb20773..e4a40a618 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiohttp" @@ -167,13 +167,13 @@ files = [ [[package]] name = "anthropic" -version = "0.15.1" +version = "0.21.3" description = "The official Python library for the anthropic API" optional = false python-versions = ">=3.7" files = [ - {file = "anthropic-0.15.1-py3-none-any.whl", hash = "sha256:50344141ba12580dac829acc1a6921905e975393cca16c99b796a63903e997b9"}, - {file = "anthropic-0.15.1.tar.gz", hash = "sha256:f188037c09a86c993196967a7c4ca7b0c30a7f51b261a9360528b5104069c088"}, + {file = "anthropic-0.21.3-py3-none-any.whl", hash = "sha256:5869115453b543a46ded6515c9f29b8d610b6e94bbba3230ad80ac947d2b0862"}, + {file = "anthropic-0.21.3.tar.gz", hash = "sha256:02f1ab5694c497e2b2d42d30d51a4f2edcaca92d2ec86bb64fe78a9c7434a869"}, ] [package.dependencies] @@ -1279,6 +1279,17 @@ files = [ {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, ] +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + [[package]] name = "deprecated" version = "1.2.14" @@ -3474,6 +3485,22 @@ openai = ["openai (<2)", "tiktoken (>=0.3.2,<0.6.0)"] qdrant = ["qdrant-client (>=1.3.1,<2.0.0)"] text-helpers = ["chardet (>=5.1.0,<6.0.0)"] +[[package]] +name = "langchain-anthropic" +version = "0.1.4" +description = "An integration package connecting AnthropicMessages and LangChain" +optional = false +python-versions = ">=3.8.1,<4.0" +files = [ + {file = "langchain_anthropic-0.1.4-py3-none-any.whl", hash = "sha256:9b3e28c1c0f7a502495b240c6c015d7fc57d04fb381fae389ecdce8847de5777"}, + {file = "langchain_anthropic-0.1.4.tar.gz", hash = "sha256:d772f7111335953d23393cac8173a0a1ee65b5fe0dc137c6b7a6db2a06fbcac4"}, +] + +[package.dependencies] +anthropic = ">=0.17.0,<1" +defusedxml = ">=0.7.1,<0.8.0" +langchain-core = ">=0.1,<0.2" + [[package]] name = "langchain-community" version = "0.0.24" @@ -4694,6 +4721,7 @@ optional = true python-versions = ">=3" files = [ {file = "nvidia_nvjitlink_cu12-12.3.101-py3-none-manylinux1_x86_64.whl", hash = "sha256:64335a8088e2b9d196ae8665430bc6a2b7e6ef2eb877a9c735c804bd4ff6467c"}, + {file = "nvidia_nvjitlink_cu12-12.3.101-py3-none-manylinux2014_aarch64.whl", hash = "sha256:211a63e7b30a9d62f1a853e19928fbb1a750e3f17a13a3d1f98ff0ced19478dd"}, {file = "nvidia_nvjitlink_cu12-12.3.101-py3-none-win_amd64.whl", hash = "sha256:1b2e317e437433753530792f13eece58f0aec21a2b05903be7bffe58a606cbd1"}, ] @@ -8312,20 +8340,6 @@ files = [ [package.dependencies] types-urllib3 = "*" -[[package]] -name = "types-requests" -version = "2.31.0.20240218" -description = "Typing stubs for requests" -optional = false -python-versions = ">=3.8" -files = [ - {file = "types-requests-2.31.0.20240218.tar.gz", hash = "sha256:f1721dba8385958f504a5386240b92de4734e047a08a40751c1654d1ac3349c5"}, - {file = "types_requests-2.31.0.20240218-py3-none-any.whl", hash = "sha256:a82807ec6ddce8f00fe0e949da6d6bc1fbf1715420218a9640d695f70a9e5a9b"}, -] - -[package.dependencies] -urllib3 = ">=2" - [[package]] name = "types-urllib3" version = "1.26.25.14" @@ -8539,23 +8553,6 @@ brotli = ["brotli (==1.0.9)", "brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotl secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] -[[package]] -name = "urllib3" -version = "2.0.7" -description = "HTTP library with thread-safe connection pooling, file post, and more." -optional = false -python-versions = ">=3.7" -files = [ - {file = "urllib3-2.0.7-py3-none-any.whl", hash = "sha256:fdb6d215c776278489906c2f8916e6e7d4f5a9b602ccbcfdf7f016fc8da0596e"}, - {file = "urllib3-2.0.7.tar.gz", hash = "sha256:c97dfde1f7bd43a71c8d2a58e369e9b2bf692d1334ea9f9cae55add7d0dd0f84"}, -] - -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"] -secure = ["certifi", "cryptography (>=1.9)", "idna (>=2.0.0)", "pyopenssl (>=17.1.0)", "urllib3-secure-extra"] -socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] -zstd = ["zstandard (>=0.18.0)"] - [[package]] name = "uvicorn" version = "0.27.1" @@ -9211,4 +9208,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"] [metadata] lock-version = "2.0" python-versions = ">=3.9,<3.12" -content-hash = "25c6686705b9e1a5a01b48c85bfc8e04592f1cf91d69ff47d421d9d7a895e1df" +content-hash = "1c79f55577a8fa603c09b2b7c02a01a7a397960c6c9c134dcee7e2f6eeea3d9e" diff --git a/pyproject.toml b/pyproject.toml index a6d726813..a0deb2737 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,7 +60,6 @@ cohere = "^4.47.0" python-multipart = "^0.0.7" sqlmodel = "^0.0.14" faiss-cpu = "^1.7.4" -anthropic = "^0.15.0" orjson = "3.9.15" multiprocess = "^0.70.14" cachetools = "^5.3.1" @@ -105,6 +104,8 @@ elasticsearch = "^8.12.0" pytube = "^15.0.0" llama-index = "0.9.48" langchain-openai = "^0.0.6" +urllib3 = "<2" +langchain-anthropic = "^0.1.4" [tool.poetry.group.dev.dependencies] pytest-asyncio = "^0.23.1" diff --git a/src/backend/langflow/components/llms/ChatAnthropic.py b/src/backend/langflow/components/llms/ChatAnthropic.py index c0e376d16..7e44636d4 100644 --- a/src/backend/langflow/components/llms/ChatAnthropic.py +++ b/src/backend/langflow/components/llms/ChatAnthropic.py @@ -2,7 +2,9 @@ from pydantic.v1.types import SecretStr from langflow import CustomComponent from typing import Optional, Union, Callable from langflow.field_typing import BaseLanguageModel -from langchain_community.chat_models.anthropic import ChatAnthropic + +# from langchain_community.chat_models.anthropic import ChatAnthropic +from langchain_anthropic import ChatAnthropic class ChatAnthropicComponent(CustomComponent): @@ -17,31 +19,48 @@ class ChatAnthropicComponent(CustomComponent): "field_type": "str", "password": True, }, - "anthropic_api_url": { - "display_name": "Anthropic API URL", - "field_type": "str", - }, "model_kwargs": { "display_name": "Model Kwargs", "field_type": "dict", "advanced": True, }, + "model_name": { + "display_name": "Model Name", + "field_type": "str", + "advanced": False, + "required": False, + "options": ["claude-3-opus-20240229", "claude-3-sonnet-20240229", "claude-3-haiku-20240307"], + }, "temperature": { "display_name": "Temperature", "field_type": "float", }, + "max_tokens": { + "display_name": "Max Tokens", + "field_type": "int", + "advanced": False, + "required": False, + }, + "top_k": {"display_name": "Top K", "field_type": "int", "advanced": True}, + "top_p": {"display_name": "Top P", "field_type": "float", "advanced": True}, } def build( self, anthropic_api_key: str, - anthropic_api_url: Optional[str] = None, model_kwargs: dict = {}, + model_name: str = "claude-3-opus-20240229", temperature: Optional[float] = None, + max_tokens: Optional[int] = 1024, + top_k: Optional[int] = None, + top_p: Optional[float] = None, ) -> Union[BaseLanguageModel, Callable]: return ChatAnthropic( anthropic_api_key=SecretStr(anthropic_api_key), - anthropic_api_url=anthropic_api_url, model_kwargs=model_kwargs, + model_name=model_name, temperature=temperature, + max_tokens=max_tokens, + top_k=top_k, + top_p=top_p, ) From 402e706f27dd10481bfbaac632c2ccf22840d42e Mon Sep 17 00:00:00 2001 From: Daiki Sakai <1daiki0sakai1@gmail.com> Date: Fri, 22 Mar 2024 20:49:17 +0900 Subject: [PATCH 07/10] Fix unintended input submission during IME composition (#1552) Prevent input submission on Enter key press during IME composition --- src/frontend/src/modals/formModal/chatInput/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/frontend/src/modals/formModal/chatInput/index.tsx b/src/frontend/src/modals/formModal/chatInput/index.tsx index 242ce6532..0cd109e3b 100644 --- a/src/frontend/src/modals/formModal/chatInput/index.tsx +++ b/src/frontend/src/modals/formModal/chatInput/index.tsx @@ -29,7 +29,7 @@ export default function ChatInput({