Adds Google Generative AI Component and other small bugfixes (#1207)

This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-12-13 21:44:00 -03:00 committed by GitHub
commit bba6aa70e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
43 changed files with 5778 additions and 40 deletions

View file

@ -1 +1,2 @@
.venv/
.venv/
**/aws

17
.github/stale.yml vendored
View file

@ -1,17 +0,0 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 45
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

View file

@ -40,5 +40,5 @@ jobs:
run: docker compose up --exit-code-from tests tests result_backend broker celeryworker db --build
continue-on-error: true
- name: Stop services
run: docker compose down
# - name: Stop services
# run: docker compose down

View file

@ -115,7 +115,7 @@ Each option is detailed below:
- `--install-completion [bash|zsh|fish|powershell|pwsh]`: Installs completion for the specified shell.
- `--show-completion [bash|zsh|fish|powershell|pwsh]`: Shows completion for the specified shell, allowing you to copy it or customize the installation.
- `--backend-only`: This parameter, with a default value of `False`, allows running only the backend server without the frontend. It can also be set using the `LANGFLOW_BACKEND_ONLY` environment variable.
- `store`: This parameter, with a default value of `True`, enables the store features, use `--no-store` to deactivate it. It can be configured using the `LANGFLOW_STORE` environment variable.
- `--store`: This parameter, with a default value of `True`, enables the store features, use `--no-store` to deactivate it. It can be configured using the `LANGFLOW_STORE` environment variable.
These parameters are important for users who need to customize the behavior of Langflow, especially in development or specialized deployment scenarios. You may want to update the documentation to include these parameters for completeness and clarity.

20
cdk.Dockerfile Normal file
View file

@ -0,0 +1,20 @@
FROM --platform=linux/amd64 python:3.10-slim
WORKDIR /app
# Install Poetry
RUN apt-get update && apt-get install gcc g++ curl build-essential postgresql-server-dev-all -y
RUN curl -sSL https://install.python-poetry.org | python3 -
# # Add Poetry to PATH
ENV PATH="${PATH}:/root/.local/bin"
# # Copy the pyproject.toml and poetry.lock files
COPY poetry.lock pyproject.toml ./
# Copy the rest of the application codes
COPY ./ ./
# Install dependencies
RUN poetry config virtualenvs.create false && poetry install --no-interaction --no-ansi
RUN poetry add pymysql==1.0.2
CMD ["sh", "./container-cmd-cdk.sh"]

3
container-cmd-cdk.sh Normal file
View file

@ -0,0 +1,3 @@
export LANGFLOW_DATABASE_URL="mysql+pymysql://${username}:${password}@${host}:3306/${dbname}"
# echo $LANGFLOW_DATABASE_URL
uvicorn --factory src.backend.langflow.main:create_app --host 0.0.0.0 --port 7860 --reload --log-level debug

View file

@ -1,28 +1,35 @@
version: "3"
networks:
langflow:
services:
backend:
build:
context: ./
dockerfile: ./dev.Dockerfile
env_file:
- .env
ports:
- "7860:7860"
volumes:
- ./:/app
command: bash -c "uvicorn --factory src.backend.langflow.main:create_app --host 0.0.0.0 --port 7860 --reload"
networks:
- langflow
frontend:
build:
context: ./src/frontend
dockerfile: ./dev.Dockerfile
dockerfile: ./cdk.Dockerfile
args:
- BACKEND_URL=http://backend:7860
environment:
- VITE_PROXY_TARGET=http://backend:7860
ports:
- "3000:3000"
- "8080:3000"
volumes:
- ./src/frontend/public:/home/node/app/public
- ./src/frontend/src:/home/node/app/src
- ./src/frontend/package.json:/home/node/app/package.json
restart: on-failure
networks:
- langflow

65
poetry.lock generated
View file

@ -2058,6 +2058,22 @@ certifi = "*"
gevent = ">=0.13"
six = "*"
[[package]]
name = "google-ai-generativelanguage"
version = "0.4.0"
description = "Google Ai Generativelanguage API client library"
optional = false
python-versions = ">=3.7"
files = [
{file = "google-ai-generativelanguage-0.4.0.tar.gz", hash = "sha256:c8199066c08f74c4e91290778329bb9f357ba1ea5d6f82de2bc0d10552bf4f8c"},
{file = "google_ai_generativelanguage-0.4.0-py3-none-any.whl", hash = "sha256:e4c425376c1ee26c78acbc49a24f735f90ebfa81bf1a06495fae509a2433232c"},
]
[package.dependencies]
google-api-core = {version = ">=1.34.0,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]}
proto-plus = ">=1.22.3,<2.0.0dev"
protobuf = ">=3.19.5,<3.20.0 || >3.20.0,<3.20.1 || >3.20.1,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<5.0.0dev"
[[package]]
name = "google-api-core"
version = "2.15.0"
@ -2140,13 +2156,13 @@ httplib2 = ">=0.19.0"
[[package]]
name = "google-cloud-aiplatform"
version = "1.38.0"
version = "1.38.1"
description = "Vertex AI API client library"
optional = false
python-versions = ">=3.8"
files = [
{file = "google-cloud-aiplatform-1.38.0.tar.gz", hash = "sha256:dff91f79b64e279f0e61dfd63c4e067ba5fa75ef0f4614289bbdca70d086a9e2"},
{file = "google_cloud_aiplatform-1.38.0-py2.py3-none-any.whl", hash = "sha256:7eec50d9a36d43e163f019a1ade9284d4580602a5108738a0ebff8940ea47ce0"},
{file = "google-cloud-aiplatform-1.38.1.tar.gz", hash = "sha256:30439d914bb028443c0506cc0e6dd825cff5401aeb8233e13d8cfd77c3c87da1"},
{file = "google_cloud_aiplatform-1.38.1-py2.py3-none-any.whl", hash = "sha256:5e1fcd1068dd2c4f0fc89aa616e34a8b9434eaa72ea6216f5036ef26f08bd448"},
]
[package.dependencies]
@ -2179,13 +2195,13 @@ xai = ["tensorflow (>=2.3.0,<3.0.0dev)"]
[[package]]
name = "google-cloud-bigquery"
version = "3.14.0"
version = "3.14.1"
description = "Google BigQuery API client library"
optional = false
python-versions = ">=3.7"
files = [
{file = "google-cloud-bigquery-3.14.0.tar.gz", hash = "sha256:76c919f771ac82ba372f5a8d326c032229c5fdab738d03a2b6e73b412c22c9eb"},
{file = "google_cloud_bigquery-3.14.0-py2.py3-none-any.whl", hash = "sha256:3304f4742546be70e531232f31bbf5b4b257aa63a508101ab7c4582c9503b636"},
{file = "google-cloud-bigquery-3.14.1.tar.gz", hash = "sha256:aa15bd86f79ea76824c7d710f5ae532323c4b3ba01ef4abff42d4ee7a2e9b142"},
{file = "google_cloud_bigquery-3.14.1-py2.py3-none-any.whl", hash = "sha256:a8ded18455da71508db222b7c06197bc12b6dbc6ed5b0b64e7007b76d7016957"},
]
[package.dependencies]
@ -2344,6 +2360,26 @@ files = [
[package.extras]
testing = ["pytest"]
[[package]]
name = "google-generativeai"
version = "0.3.1"
description = "Google Generative AI High level API client library and tools."
optional = false
python-versions = ">=3.9"
files = [
{file = "google_generativeai-0.3.1-py3-none-any.whl", hash = "sha256:800ec6041ca537b897d7ba654f4125651c64b38506f2bfce3b464370e3333a1b"},
]
[package.dependencies]
google-ai-generativelanguage = "0.4.0"
google-api-core = "*"
google-auth = "*"
protobuf = "*"
tqdm = "*"
[package.extras]
dev = ["Pillow", "absl-py", "black", "ipython", "nose2", "pandas", "pytype", "pyyaml"]
[[package]]
name = "google-resumable-media"
version = "2.7.0"
@ -3618,6 +3654,21 @@ langchain-core = ">=0.1,<0.2"
[package.extras]
extended-testing = ["faker (>=19.3.1,<20.0.0)", "jinja2 (>=3,<4)", "presidio-analyzer (>=2.2.33,<3.0.0)", "presidio-anonymizer (>=2.2.33,<3.0.0)", "sentence-transformers (>=2,<3)", "vowpal-wabbit-next (==0.6.0)"]
[[package]]
name = "langchain-google-genai"
version = "0.0.2"
description = "An integration package connecting Google's genai package and LangChain"
optional = false
python-versions = ">=3.9,<4.0"
files = [
{file = "langchain_google_genai-0.0.2-py3-none-any.whl", hash = "sha256:d98b1bb5eb0b65e7582fe18031ec0fe35d78820deb2825bddfe6c37218008e5c"},
{file = "langchain_google_genai-0.0.2.tar.gz", hash = "sha256:6209991f8c5b07efc194514ab04baf3e8ffa4a95ae697db7d1c6ba8cd430ead8"},
]
[package.dependencies]
google-generativeai = ">=0.3.1,<0.4.0"
langchain-core = ">=0.1,<0.2"
[[package]]
name = "langdetect"
version = "1.0.9"
@ -9217,4 +9268,4 @@ local = ["ctransformers", "llama-cpp-python", "sentence-transformers"]
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.11"
content-hash = "a3b010e02c9cb3c943898847ab78644a5dcc38c8bf5108d833b06fb3378e7c96"
content-hash = "6bed78abe6228dfd01ba4cf4052a95d24bcb0746294a8da442bbaa846187071f"

View file

@ -1,6 +1,6 @@
[tool.poetry]
name = "langflow"
version = "0.6.2"
version = "0.6.3"
description = "A Python package with a built-in web application"
authors = ["Logspace <contact@logspace.ai>"]
maintainers = [
@ -102,6 +102,7 @@ numexpr = "^2.8.6"
qianfan = "0.0.5"
pgvector = "^0.2.3"
pyautogen = "^0.2.0"
langchain-google-genai = "^0.0.2"
[tool.poetry.group.dev.dependencies]
pytest-asyncio = "^0.23.1"

11
scripts/aws/.env.example Normal file
View file

@ -0,0 +1,11 @@
# Description: Example of .env file
# Usage: Copy this file to .env and change the values
# according to your needs
# Do not commit .env file to git
# Do not change .env.example file
#     You can set up a superuser's username and password
# If there is no need for user management, set LANGFLOW_AUTO_LOGIN=true and delete LANGFLOW_SUPERUSER and LANGFLOW_SUPERUSER_PASSWORD.
LANGFLOW_AUTO_LOGIN=false
LANGFLOW_SUPERUSER=admin
LANGFLOW_SUPERUSER_PASSWORD=123456

9
scripts/aws/.gitignore vendored Normal file
View file

@ -0,0 +1,9 @@
*.js
!jest.config.js
*.d.ts
node_modules
# CDK asset staging directory
.cdk.staging
cdk.out
!/lib

6
scripts/aws/.npmignore Normal file
View file

@ -0,0 +1,6 @@
*.ts
!*.d.ts
# CDK asset staging directory
.cdk.staging
cdk.out

54
scripts/aws/README.ja.md Normal file
View file

@ -0,0 +1,54 @@
# Langflow on AWS
**想定時間**: 30 分
## 説明
Langflow on AWS では、 [AWS Cloud Development Kit](https://aws.amazon.com/cdk/?nc2=type_a) (CDK) を用いて Langflow を AWS 上にデプロイする方法を学べます。
このチュートリアルは、AWS アカウントと AWS に関する基本的な知識を有していることを前提としています。
作成するアプリケーションのアーキテクチャです。
![langflow-archi](./img/langflow-archi.png)
AWS CDK によって [Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/?nc1=h_ls)、[AWS Fargate](https://aws.amazon.com/fargate/?nc2=type_a)、[Amazon Aurora](https://aws.amazon.com/rds/aurora/?nc2=type_a) を作成します。
Auroraのシークレットは [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/?nc2=type_a) によって管理されます。
Fargate のタスクはフロントエンドとバックエンドに分かれており、サービス検出によって通信します。
リソースをデプロイするだけであれば、上記の各サービスについて深い知識は必要ありません。
# 環境構築とデプロイ方法
1. [AWS CloudShell](https://us-east-1.console.aws.amazon.com/cloudshell/home?region=us-east-1)を開きます。
1. 以下のコマンドを実行します。
```shell
git clone https://github.com/aws-samples/cloud9-setup-for-prototyping
cd cloud9-setup-for-prototyping
./bin/bootstrap
```
1. `Done!` と表示されたら [AWS Cloud9](https://us-east-1.console.aws.amazon.com/cloud9control/home?region=us-east-1#/) から `cloud9-for-prototyping` を開きます。
![make-cloud9](./img/langflow-cloud9.png)
1. 以下のコマンドを実行します。
```shell
git clone -b aws-cdk https://github.com/logspace-ai/langflow.git
cd langflow/scripts/aws
cp .env.example .env # 環境設定を変える場合はこのファイル(.env)を編集してください。
npm ci
cdk bootstrap
cdk deploy
```
1. 表示される URL にアクセスします。
```shell
Outputs:
LangflowAppStack.NetworkURLXXXXXX = http://alb-XXXXXXXXXXX.elb.amazonaws.com
```
1. サインイン画面でユーザー名とパスワードを入力します。`.env`ファイルでユーザー名とパスワードを設定していない場合、ユーザー名は`admin`、パスワードは`123456`で設定されます。
![make-cloud9](./img/langflow-signin.png)
# 環境の削除
1. `Cloud9` で以下のコマンドを実行します。
```shell
bash delete-resources.sh
```
1. [AWS CloudFormation](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/getting-started)を開き、`aws-cloud9-cloud9-for-prototyping-XXXX` を選択して削除します。
![delete-cfn](./img/langflow-cfn.png)

53
scripts/aws/README.md Normal file
View file

@ -0,0 +1,53 @@
# Deploy Langflow on AWS
**Duration**: 30 minutes
## Introduction
In this tutorial, you will learn how to deploy langflow on AWS using [AWS Cloud Development Kit](https://aws.amazon.com/cdk/?nc2=type_a) (CDK).
This tutorial assumes you have an AWS account and basic knowledge of AWS.
The architecture of the application to be created:
![langflow-archi](./img/langflow-archi.png)
[Application Load Balancer](https://aws.amazon.com/elasticloadbalancing/application-load-balancer/?nc1=h_ls), [AWS Fargate](https://aws.amazon.com/fargate/?nc2=type_a) and [Amazon Aurora](https://aws.amazon.com/rds/aurora/?nc2=type_a) are created by AWS CDK.
The aurora's secrets are managed by [AWS Secrets Manager](https://aws.amazon.com/secrets-manager/?nc2=type_a).
The Fargate task is divided into a frontend and a backend, which communicate through service discovery.
If you just want to deploy resources, you do not need in-depth knowledge of each of the above services.
# How to set up your environment and deploy langflow
1. Open [AWS CloudShell](https://us-east-1.console.aws.amazon.com/cloudshell/home?region=us-east-1).
1. Run the following commands in Cloudshell:
```shell
git clone https://github.com/aws-samples/cloud9-setup-for-prototyping
cd cloud9-setup-for-prototyping
./bin/bootstrap
```
1. When you see `Done!` in Cloudshell, open `cloud9-for-prototyping` from [AWS Cloud9](https://us-east-1.console.aws.amazon.com/cloud9control/home?region=us-east-1#/).
![make-cloud9](./img/langflow-cloud9-en.png)
1. Run the following command in the Cloud9 terminal.
```shell
git clone -b aws-cdk https://github.com/logspace-ai/langflow.git
cd langflow/scripts/aws
cp .env.example .env # Edit this file if you need environment settings
npm ci
cdk bootstrap
cdk deploy
```
1. Access the URL displayed.
```shell
Outputs:
LangflowAppStack.NetworkURLXXXXXX = http://alb-XXXXXXXXXXX.elb.amazonaws.com
```
1. Enter your user name and password to sign in. If you have not set a user name and password in your `.env` file, the user name will be set to `admin` and the password to `123456`.
![signin-langflow](./img/langflow-signin.png)
# Cleanup
1. Run the following command in the Cloud9 terminal.
```shell
bash delete-resources.sh
```
1. Open [AWS CloudFormation](https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/getting-started), select `aws-cloud9-cloud9-for-prototyping-XXXX` and delete it.
![delete-cfn](./img/langflow-cfn.png)

21
scripts/aws/bin/cdk.ts Normal file
View file

@ -0,0 +1,21 @@
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { LangflowAppStack } from '../lib/cdk-stack';
const app = new cdk.App();
new LangflowAppStack(app, 'LangflowAppStack', {
/* If you don't specify 'env', this stack will be environment-agnostic.
* Account/Region-dependent features and context lookups will not work,
* but a single synthesized template can be deployed anywhere. */
/* Uncomment the next line to specialize this stack for the AWS Account
* and Region that are implied by the current CLI configuration. */
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
/* Uncomment the next line if you know exactly what Account and Region you
* want to deploy the stack to. */
// env: { account: '123456789012', region: 'us-east-1' },
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});

55
scripts/aws/cdk.json Normal file
View file

@ -0,0 +1,55 @@
{
"app": "npx ts-node --prefer-ts-exts bin/cdk.ts",
"watch": {
"include": [
"**"
],
"exclude": [
"README.md",
"cdk*.json",
"**/*.d.ts",
"**/*.js",
"tsconfig.json",
"package*.json",
"yarn.lock",
"node_modules",
"test"
]
},
"context": {
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
"@aws-cdk/core:checkSecretUsage": true,
"@aws-cdk/core:target-partitions": [
"aws",
"aws-cn"
],
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
"@aws-cdk/aws-iam:minimizePolicies": true,
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
"@aws-cdk/core:enablePartitionLiterals": true,
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
"@aws-cdk/aws-iam:standardizedServicePrincipals": true,
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
"@aws-cdk/aws-route53-patters:useCertificate": true,
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
"@aws-cdk/aws-redshift:columnId": true,
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
"@aws-cdk/aws-kms:aliasNameRef": true,
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true
}
}

View file

@ -0,0 +1,3 @@
docker stop $(docker ps -aq)
docker rm $(docker ps -aq)
docker rmi -f $(docker images -aq)

View file

@ -0,0 +1,4 @@
aws cloudformation delete-stack --stack-name LangflowAppStack
aws ecr delete-repository --repository-name langflow-backend-repository --force
aws ecr delete-repository --repository-name langflow-frontend-repository --force
# aws ecr describe-repositories --output json | jq -re ".repositories[].repositoryName"

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

View file

@ -0,0 +1,8 @@
module.exports = {
testEnvironment: 'node',
roots: ['<rootDir>/test'],
testMatch: ['**/*.test.ts'],
transform: {
'^.+\\.tsx?$': 'ts-jest'
}
};

View file

@ -0,0 +1,64 @@
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ecs from 'aws-cdk-lib/aws-ecs'
import { Network, EcrRepository, FrontEndCluster, BackEndCluster, Rds, EcsIAM } from './construct';
// import * as sqs from 'aws-cdk-lib/aws-sqs';
export class LangflowAppStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Arch
const arch = ecs.CpuArchitecture.X86_64
// VPC
const { vpc, cluster, alb, targetGroup, cloudmapNamespace, ecsFrontSG, ecsBackSG, dbSG, albSG, backendLogGroup, frontendLogGroup} = new Network(this, 'Network')
// ECR
const { ecrFrontEndRepository,ecrBackEndRepository} = new EcrRepository(this, 'Ecr', {
cloudmapNamespace:cloudmapNamespace,
arch:arch
})
// RDS
// VPCとSGのリソース情報をPropsとして引き渡す
const { rdsCluster } = new Rds(this, 'Rds', { vpc, dbSG })
// IAM
const { frontendTaskRole, frontendTaskExecutionRole, backendTaskRole, backendTaskExecutionRole } = new EcsIAM(this, 'EcsIAM',{
rdsCluster:rdsCluster
})
const backendService = new BackEndCluster(this, 'backend', {
cluster:cluster,
ecsBackSG:ecsBackSG,
ecrBackEndRepository:ecrBackEndRepository,
backendTaskRole:backendTaskRole,
backendTaskExecutionRole:backendTaskExecutionRole,
backendLogGroup:backendLogGroup,
cloudmapNamespace:cloudmapNamespace,
rdsCluster:rdsCluster,
alb:alb,
arch:arch
})
backendService.node.addDependency(rdsCluster);
const frontendService = new FrontEndCluster(this, 'frontend',{
cluster:cluster,
ecsFrontSG:ecsFrontSG,
ecrFrontEndRepository:ecrFrontEndRepository,
targetGroup: targetGroup,
backendServiceName: backendService.backendServiceName,
frontendTaskRole: frontendTaskRole,
frontendTaskExecutionRole: frontendTaskExecutionRole,
frontendLogGroup: frontendLogGroup,
cloudmapNamespace: cloudmapNamespace,
arch:arch
})
frontendService.node.addDependency(backendService);
// S3+CloudFront
// new Web(this,'Cloudfront-S3')
}
}

View file

@ -0,0 +1,105 @@
import { Duration } from 'aws-cdk-lib'
import { Construct } from 'constructs';
import {
aws_ec2 as ec2,
aws_ecs as ecs,
aws_ecr as ecr,
aws_rds as rds,
aws_servicediscovery as servicediscovery,
aws_iam as iam,
aws_logs as logs,
aws_elasticloadbalancingv2 as elb,
} from 'aws-cdk-lib';
import * as dotenv from 'dotenv';
const path = require('path');
dotenv.config({path: path.join(__dirname, "../../.env")});
interface BackEndProps {
cluster: ecs.Cluster
ecsBackSG:ec2.SecurityGroup
ecrBackEndRepository:ecr.Repository
backendTaskRole: iam.Role;
backendTaskExecutionRole: iam.Role;
backendLogGroup: logs.LogGroup;
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
rdsCluster:rds.DatabaseCluster
alb:elb.IApplicationLoadBalancer
arch:ecs.CpuArchitecture
}
export class BackEndCluster extends Construct {
readonly backendServiceName: string
constructor(scope: Construct, id: string, props:BackEndProps) {
super(scope, id)
const containerPort = 7860
// Secrets ManagerからDB認証情報を取ってくる
const secretsDB = props.rdsCluster.secret!;
// Create Backend Fargate Service
const backendTaskDefinition = new ecs.FargateTaskDefinition(
this,
'BackEndTaskDef',
{
memoryLimitMiB: 3072,
cpu: 1024,
executionRole: props.backendTaskExecutionRole,
runtimePlatform:{
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
cpuArchitecture: props.arch,
},
taskRole: props.backendTaskRole,
}
);
backendTaskDefinition.addContainer('backendContainer', {
image: ecs.ContainerImage.fromEcrRepository(props.ecrBackEndRepository, "latest"),
containerName:'langflow-back-container',
logging: ecs.LogDriver.awsLogs({
streamPrefix: 'my-stream',
logGroup: props.backendLogGroup,
}),
environment:{
// user:pass@endpoint:port/dbname
// "LANGFLOW_DATABASE_URL" : `mysql+pymysql://${username}:${password}@${host}:3306/${dbname}`,
// "LANGFLOW_DATABASE_URL" : "sqlite:///./langflow.db",
// "LANGFLOW_LANGCHAIN_CACHE" : "SQLiteCache",
// "LANGFLOW_AUTO_LOGIN" : "false",
// "LANGFLOW_SUPERUSER" : "admin",
// "LANGFLOW_SUPERUSER_PASSWORD" : "1234567"
"LANGFLOW_AUTO_LOGIN" : process.env.LANGFLOW_AUTO_LOGIN ?? 'false',
"LANGFLOW_SUPERUSER" : process.env.LANGFLOW_SUPERUSER ?? "admin",
"LANGFLOW_SUPERUSER_PASSWORD" : process.env.LANGFLOW_SUPERUSER_PASSWORD ?? "123456"
},
portMappings: [
{
containerPort: containerPort,
protocol: ecs.Protocol.TCP,
},
],
// Secretの設定
secrets: {
"dbname": ecs.Secret.fromSecretsManager(secretsDB, 'dbname'),
"username": ecs.Secret.fromSecretsManager(secretsDB, 'username'),
"host": ecs.Secret.fromSecretsManager(secretsDB, 'host'),
"password": ecs.Secret.fromSecretsManager(secretsDB, 'password'),
},
});
this.backendServiceName = 'backend'
const backendService = new ecs.FargateService(this, 'BackEndService', {
cluster: props.cluster,
serviceName: this.backendServiceName,
taskDefinition: backendTaskDefinition,
enableExecuteCommand: true,
securityGroups: [props.ecsBackSG],
cloudMapOptions: {
cloudMapNamespace: props.cloudmapNamespace,
containerPort: containerPort,
dnsRecordType: servicediscovery.DnsRecordType.A,
dnsTtl: Duration.seconds(10),
name: this.backendServiceName
},
vpcSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
});
}
}

View file

@ -0,0 +1,65 @@
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2'
import * as rds from "aws-cdk-lib/aws-rds";
import * as cdk from 'aws-cdk-lib';
interface RdsProps {
vpc: ec2.Vpc
dbSG:ec2.SecurityGroup
}
export class Rds extends Construct{
readonly rdsCluster: rds.DatabaseCluster
constructor(scope: Construct, id:string, props: RdsProps){
super(scope, id);
const {vpc, dbSG} = props
const instanceType = ec2.InstanceType.of(ec2.InstanceClass.BURSTABLE4_GRAVITON, ec2.InstanceSize.MEDIUM)
// RDSのパスワードを自動生成してSecrets Managerに格納
const rdsCredentials = rds.Credentials.fromGeneratedSecret('db_user',{
secretName: 'langflow-DbSecret',
})
// DB クラスターのパラメータグループ作成
const clusterParameterGroup = new rds.ParameterGroup(scope, 'ClusterParameterGroup',{
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_02_0
}),
description: 'for-langflow',
})
clusterParameterGroup.bindToCluster({})
// DB インスタンスのパラメタグループ作成
const instanceParameterGroup = new rds.ParameterGroup(scope, 'InstanceParameterGroup',{
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_02_0,
}),
description: 'for-langflow',
})
instanceParameterGroup.bindToInstance({})
this.rdsCluster = new rds.DatabaseCluster(scope, 'LangflowDbCluster', {
engine: rds.DatabaseClusterEngine.auroraMysql({
version: rds.AuroraMysqlEngineVersion.VER_3_02_0,
}),
storageEncrypted: true,
credentials: rdsCredentials,
instanceIdentifierBase: 'langflow-instance',
vpc:vpc,
vpcSubnets:vpc.selectSubnets({
subnetGroupName: 'langflow-Isolated',
}),
securityGroups:[dbSG],
writer: rds.ClusterInstance.provisioned("WriterInstance", {
instanceType: instanceType,
enablePerformanceInsights: true,
parameterGroup:instanceParameterGroup,
}),
// 2台目以降はreaders:で設定
parameterGroup: clusterParameterGroup,
defaultDatabaseName: 'langflow',
})
}
}

View file

@ -0,0 +1,78 @@
import { RemovalPolicy } from 'aws-cdk-lib'
import * as ecr from 'aws-cdk-lib/aws-ecr'
import * as ecrdeploy from 'cdk-ecr-deployment'
import * as ecs from 'aws-cdk-lib/aws-ecs'
import * as servicediscovery from 'aws-cdk-lib/aws-servicediscovery'
import { DockerImageAsset, Platform } from 'aws-cdk-lib/aws-ecr-assets'
import * as path from "path";
import { Construct } from 'constructs'
interface ECRProps {
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
arch:ecs.CpuArchitecture;
}
export class EcrRepository extends Construct {
readonly ecrFrontEndRepository: ecr.Repository
readonly ecrBackEndRepository: ecr.Repository
constructor(scope: Construct, id: string, props: ECRProps) {
super(scope, id)
const imagePlatform = props.arch == ecs.CpuArchitecture.ARM64 ? Platform.LINUX_ARM64 : Platform.LINUX_AMD64
const backendPath = path.join(__dirname, "../../../../../", "langflow")
const frontendPath = path.join(__dirname, "../../../../src/", "frontend")
const excludeDir = ['node_modules','.git', 'cdk.out']
const LifecycleRule = {
tagStatus: ecr.TagStatus.ANY,
description: 'Delete more than 30 image',
maxImageCount: 30,
}
// リポジトリ作成
this.ecrFrontEndRepository = new ecr.Repository(scope, 'LangflowFrontEndRepository', {
repositoryName: 'langflow-frontend-repository',
removalPolicy: RemovalPolicy.RETAIN,
imageScanOnPush: true,
})
this.ecrBackEndRepository = new ecr.Repository(scope, 'LangflowBackEndRepository', {
repositoryName: 'langflow-backend-repository',
removalPolicy: RemovalPolicy.RETAIN,
imageScanOnPush: true,
})
// LifecycleRule作成
this.ecrFrontEndRepository.addLifecycleRule(LifecycleRule)
this.ecrBackEndRepository.addLifecycleRule(LifecycleRule)
// Create Docker Image Asset
const dockerFrontEndImageAsset = new DockerImageAsset(this, "DockerFrontEndImageAsset", {
directory: frontendPath,
file:"cdk.Dockerfile",
buildArgs:{
"BACKEND_URL":`http://backend.${props.cloudmapNamespace.namespaceName}:7860`
},
exclude: excludeDir,
platform: imagePlatform,
});
const dockerBackEndImageAsset = new DockerImageAsset(this, "DockerBackEndImageAsset", {
directory: backendPath,
file:"cdk.Dockerfile",
exclude: excludeDir,
platform: imagePlatform,
});
// Deploy Docker Image to ECR Repository
new ecrdeploy.ECRDeployment(this, "DeployFrontEndImage", {
src: new ecrdeploy.DockerImageName(dockerFrontEndImageAsset.imageUri),
dest: new ecrdeploy.DockerImageName(this.ecrFrontEndRepository.repositoryUri)
});
// Deploy Docker Image to ECR Repository
new ecrdeploy.ECRDeployment(this, "DeployBackEndImage", {
src: new ecrdeploy.DockerImageName(dockerBackEndImageAsset.imageUri),
dest: new ecrdeploy.DockerImageName(this.ecrBackEndRepository.repositoryUri)
});
}
}

View file

@ -0,0 +1,117 @@
import { Duration } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import {
aws_ec2 as ec2,
aws_ecs as ecs,
aws_ecr as ecr,
aws_servicediscovery as servicediscovery,
aws_iam as iam,
aws_logs as logs,
aws_elasticloadbalancingv2 as elb,
} from 'aws-cdk-lib';
import { CpuArchitecture } from 'aws-cdk-lib/aws-ecs';
interface FrontEndProps {
cluster:ecs.Cluster
ecsFrontSG:ec2.SecurityGroup
ecrFrontEndRepository:ecr.Repository
targetGroup: elb.ApplicationTargetGroup;
backendServiceName: string;
frontendTaskRole: iam.Role;
frontendTaskExecutionRole: iam.Role;
frontendLogGroup: logs.LogGroup;
cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
arch:ecs.CpuArchitecture;
}
export class FrontEndCluster extends Construct {
constructor(scope: Construct, id: string, props:FrontEndProps) {
super(scope, id)
const containerPort = 3000
const frontendTaskDefinition = new ecs.FargateTaskDefinition(
this,
'FrontendTaskDef',
{
memoryLimitMiB: 3072,
cpu: 1024,
executionRole: props.frontendTaskExecutionRole,
runtimePlatform:{
operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
cpuArchitecture: props.arch,
},
taskRole: props.frontendTaskRole,
}
);
const frontendServiceName = 'frontend'
frontendTaskDefinition.addContainer('frontendContainer', {
image: ecs.ContainerImage.fromEcrRepository(props.ecrFrontEndRepository, "latest"),
containerName:'langflow-front-container',
environment: {
BACKEND_SERVICE_NAME: props.backendServiceName,
BACKEND_URL: `http://${props.backendServiceName}.${props.cloudmapNamespace.namespaceName}:7860/`,
VITE_PROXY_TARGET: `http://${props.backendServiceName}.${props.cloudmapNamespace.namespaceName}:7860/`,
},
logging: ecs.LogDriver.awsLogs({
streamPrefix: 'my-stream',
logGroup: props.frontendLogGroup,
}),
portMappings: [
{
name:frontendServiceName,
containerPort: containerPort,
protocol: ecs.Protocol.TCP,
appProtocol:ecs.AppProtocol.http,
},
],
});
const frontendService = new ecs.FargateService(
this,
'FrontendService',
{
serviceName: frontendServiceName,
cluster: props.cluster,
desiredCount: 1,
assignPublicIp: false,
taskDefinition: frontendTaskDefinition,
enableExecuteCommand: true,
securityGroups: [props.ecsFrontSG],
cloudMapOptions: {
cloudMapNamespace: props.cloudmapNamespace,
containerPort: containerPort,
dnsRecordType: servicediscovery.DnsRecordType.A,
dnsTtl: Duration.seconds(10),
name: frontendServiceName
},
healthCheckGracePeriod: Duration.seconds(1000),
}
);
props.targetGroup.addTarget(frontendService);
// // Create ALB and ECS Fargate Service
// const frontService = new ecs_patterns.ApplicationLoadBalancedFargateService(
// this,
// "FrontEndService",
// {
// cluster: cluster,
// serviceName: 'langflow-frontend-service',
// cpu: 256,
// memoryLimitMiB: 512,
// listenerPort: 80,
// assignPublicIp: true, // Public facing - ALB
// taskSubnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
// securityGroups:[ecsFrontSG],
// taskImageOptions: {
// family: 'langflow-taskdef',
// containerName: 'langflow-front-container',
// image: ecs.ContainerImage.fromEcrRepository(ecrFrontEndRepository, "latest"),
// containerPort: 3000, // L2なので、TargetGroupのportが3000で設定されるはず
// },
// loadBalancer:alb,
// openListener:false,
// }
// );
}
}

View file

@ -0,0 +1,101 @@
import { RemovalPolicy, Duration } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import {
aws_rds as rds,
aws_iam as iam,
} from 'aws-cdk-lib';
interface IAMProps {
rdsCluster:rds.DatabaseCluster
}
export class EcsIAM extends Construct {
readonly frontendTaskRole: iam.Role;
readonly frontendTaskExecutionRole: iam.Role;
readonly backendTaskRole: iam.Role;
readonly backendTaskExecutionRole: iam.Role;
constructor(scope: Construct, id: string, props:IAMProps) {
super(scope, id)
// Policy Statements
// ECS Policy State
const ECSExecPolicyStatement = new iam.PolicyStatement({
sid: 'allowECSExec',
resources: ['*'],
actions: [
'ecr:GetAuthorizationToken',
'ecr:BatchCheckLayerAvailability',
'ecr:GetDownloadUrlForLayer',
'ecr:BatchGetImage',
],
});
// Bedrock Policy State
const BedrockPolicyStatement = new iam.PolicyStatement({
sid: 'allowBedrockAccess',
resources: ['*'],
actions: [
'bedrock:*',
],
});
// Kendra Policy State
const KendraPolicyStatement = new iam.PolicyStatement({
sid: 'allowKendraAccess',
resources: ['*'],
actions: [
'kendra:*'
],
});
// Create Rag Policy
const RagAccessPolicy = new iam.Policy(this, 'RAGFullAccess', {
statements: [KendraPolicyStatement,BedrockPolicyStatement],
})
// Secrets ManagerからDB認証情報を取ってくるためのPolicy
const SecretsManagerPolicy = new iam.Policy(this, 'SMGetPolicy', {
statements: [new iam.PolicyStatement({
actions: ['secretsmanager:GetSecretValue'],
resources: [props.rdsCluster.secret!.secretArn],
})],
})
// FrontEnd Task Role
this.frontendTaskRole = new iam.Role(this, 'FrontendTaskRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
});
this.frontendTaskRole.addToPolicy(ECSExecPolicyStatement);
// BackEnd Task Role
this.backendTaskRole = new iam.Role(this, 'BackendTaskRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
});
// ECS Exec Policyの付与
this.backendTaskRole.addToPolicy(ECSExecPolicyStatement);
// KendraとBedrockのアクセス権付与
this.backendTaskRole.attachInlinePolicy(RagAccessPolicy);
// FrontEnd Task ExecutionRole
this.frontendTaskExecutionRole = new iam.Role(this, 'frontendTaskExecutionRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
managedPolicies: [
{
managedPolicyArn:
'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
},
],
});
// BackEnd Task ExecutionRole
this.backendTaskExecutionRole = new iam.Role(this, 'backendTaskExecutionRole', {
assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
managedPolicies: [
{
managedPolicyArn:
'arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
},
],
});
this.backendTaskExecutionRole.attachInlinePolicy(SecretsManagerPolicy);
this.backendTaskExecutionRole.attachInlinePolicy(RagAccessPolicy);
}
}

View file

@ -0,0 +1,6 @@
export * from './db';
export * from './ecr';
export * from './iam';
export * from './frontend';
export * from './backend';
export * from './network';

View file

@ -0,0 +1,143 @@
import { RemovalPolicy, Duration, CfnOutput } from 'aws-cdk-lib'
import { Construct } from 'constructs'
import {
aws_ec2 as ec2,
aws_ecs as ecs,
aws_logs as logs,
aws_servicediscovery as servicediscovery,
aws_elasticloadbalancingv2 as elb,
} from 'aws-cdk-lib';
export class Network extends Construct {
readonly vpc: ec2.Vpc;
readonly cluster: ecs.Cluster;
readonly alb: elb.IApplicationLoadBalancer;
readonly targetGroup: elb.ApplicationTargetGroup;
readonly cloudmapNamespace: servicediscovery.PrivateDnsNamespace;
readonly ecsFrontSG: ec2.SecurityGroup;
readonly ecsBackSG: ec2.SecurityGroup;
readonly dbSG: ec2.SecurityGroup;
readonly albSG: ec2.SecurityGroup;
readonly backendLogGroup: logs.LogGroup;
readonly frontendLogGroup: logs.LogGroup;
constructor(scope: Construct, id: string) {
super(scope, id)
const alb_listen_port=80
const front_service_port=3000
const back_service_port=7860
// VPC等リソースの作成
this.vpc = new ec2.Vpc(scope, 'VPC', {
vpcName: 'langflow-vpc',
ipAddresses: ec2.IpAddresses.cidr('10.0.0.0/16'),
maxAzs: 3,
subnetConfiguration: [
{
cidrMask: 24,
name: 'langflow-Isolated',
subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
},
{
cidrMask: 24,
name: 'langflow-Public',
subnetType: ec2.SubnetType.PUBLIC,
},
{
cidrMask: 24,
name: 'langflow-Private',
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS
},
],
natGateways: 1,
})
// Cluster
this.cluster = new ecs.Cluster(this, 'EcsCluster', {
clusterName: 'langflow-cluster',
vpc: this.vpc,
enableFargateCapacityProviders: true,
});
// Private DNS
this.cloudmapNamespace = new servicediscovery.PrivateDnsNamespace(
this,
'Namespace',
{
name: 'ecs-deploy.com',
vpc: this.vpc,
}
);
// ALBに設定するセキュリティグループ
this.albSG = new ec2.SecurityGroup(scope, 'ALBSecurityGroup', {
securityGroupName: 'alb-sg',
description: 'for alb',
vpc: this.vpc,
})
this.albSG.addIngressRule(ec2.Peer.anyIpv4(), ec2.Port.tcp(alb_listen_port))
this.alb = new elb.ApplicationLoadBalancer(this,'langflow-alb',{
internetFacing: true, //インターネットからのアクセスを許可するかどうか指定
loadBalancerName: 'langflow-alb',
securityGroup: this.albSG, //作成したセキュリティグループを割り当てる
vpc:this.vpc,
})
const listener = this.alb.addListener('Listener', { port: alb_listen_port });
this.targetGroup = listener.addTargets('targetGroup', {
port: front_service_port,
protocol: elb.ApplicationProtocol.HTTP,
healthCheck: {
enabled: true,
path: '/health',
healthyThresholdCount: 2,
unhealthyThresholdCount: 4,
interval: Duration.seconds(100),
timeout: Duration.seconds(30),
healthyHttpCodes: '200',
},
});
// ECS FrontEndに設定するセキュリティグループ
this.ecsFrontSG = new ec2.SecurityGroup(scope, 'ECSFrontEndSecurityGroup', {
securityGroupName: 'langflow-ecs-front-sg',
description: 'for langflow-front-ecs',
vpc: this.vpc,
})
this.ecsFrontSG.addIngressRule(this.albSG, ec2.Port.allTcp())
// ECS BackEndに設定するセキュリティグループ
this.ecsBackSG = new ec2.SecurityGroup(scope, 'ECSBackEndSecurityGroup', {
securityGroupName: 'langflow-ecs-back-sg',
description: 'for langflow-back-ecs',
vpc: this.vpc,
})
this.ecsBackSG.addIngressRule(this.ecsFrontSG, ec2.Port.tcp(back_service_port))
// RDSに設定するセキュリティグループ
this.dbSG = new ec2.SecurityGroup(scope, 'DBSecurityGroup', {
allowAllOutbound: true,
securityGroupName: 'langflow-db',
description: 'for langflow-db',
vpc: this.vpc,
})
// AppRunnerSecurityGroupからのポート3306:mysql(5432:postgres)のインバウンドを許可
this.dbSG.addIngressRule(this.ecsBackSG, ec2.Port.tcp(3306))
// Create CloudWatch Log Group
this.backendLogGroup = new logs.LogGroup(this, 'backendLogGroup', {
logGroupName: 'langflow-backend-logs',
removalPolicy: RemovalPolicy.DESTROY,
});
this.frontendLogGroup = new logs.LogGroup(this, 'frontendLogGroup', {
logGroupName: 'langflow-frontend-logs',
removalPolicy: RemovalPolicy.DESTROY,
});
new CfnOutput(this, 'URL', {
value: `http://${this.alb.loadBalancerDnsName}`,
});
}
}

4613
scripts/aws/package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

29
scripts/aws/package.json Normal file
View file

@ -0,0 +1,29 @@
{
"name": "cdk",
"version": "0.1.0",
"bin": {
"cdk": "bin/cdk.js"
},
"scripts": {
"build": "tsc",
"watch": "tsc -w",
"test": "jest",
"cdk": "cdk"
},
"devDependencies": {
"@types/jest": "^29.5.1",
"@types/node": "20.1.7",
"aws-cdk": "2.86.0",
"jest": "^29.5.0",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
"typescript": "~5.1.3"
},
"dependencies": {
"aws-cdk-lib": "^2.86.0",
"cdk-ecr-deployment": "^2.5.30",
"constructs": "^10.0.0",
"dotenv": "^16.3.1",
"source-map-support": "^0.5.21"
}
}

View file

@ -0,0 +1,17 @@
// import * as cdk from 'aws-cdk-lib';
// import { Template } from 'aws-cdk-lib/assertions';
// import * as Cdk from '../lib/cdk-stack';
// example test. To run these tests, uncomment this file along with the
// example resource in lib/cdk-stack.ts
test('SQS Queue Created', () => {
// const app = new cdk.App();
// // WHEN
// const stack = new Cdk.CdkStack(app, 'MyTestStack');
// // THEN
// const template = Template.fromStack(stack);
// template.hasResourceProperties('AWS::SQS::Queue', {
// VisibilityTimeout: 300
// });
});

View file

@ -0,0 +1,72 @@
from typing import Optional
from langchain_google_genai import ChatGoogleGenerativeAI # type: ignore
from langflow import CustomComponent
from langflow.field_typing import BaseLanguageModel, RangeSpec, TemplateField
class GoogleGenerativeAIComponent(CustomComponent):
display_name: str = "Google Generative AI"
description: str = "A component that uses Google Generative AI to generate text."
documentation: str = "http://docs.langflow.org/components/custom"
def build_config(self):
return {
"google_api_key": TemplateField(
display_name="Google API Key",
info="The Google API Key to use for the Google Generative AI.",
),
"max_output_tokens": TemplateField(
display_name="Max Output Tokens",
info="The maximum number of tokens to generate.",
),
"temperature": TemplateField(
display_name="Temperature",
info="Run inference with this temperature. Must by in the closed interval [0.0, 1.0].",
),
"top_k": TemplateField(
display_name="Top K",
info="Decode using top-k sampling: consider the set of top_k most probable tokens. Must be positive.",
range_spec=RangeSpec(min=0, max=2, step=0.1),
advanced=True,
),
"top_p": TemplateField(
display_name="Top P",
info="The maximum cumulative probability of tokens to consider when sampling.",
advanced=True,
),
"n": TemplateField(
display_name="N",
info="Number of chat completions to generate for each prompt. Note that the API may not return the full n completions if duplicates are generated.",
advanced=True,
),
"model": TemplateField(
display_name="Model",
info="The name of the model to use. Supported examples: gemini-pro",
options=["gemini-pro", "gemini-pro-vision"],
),
"code": TemplateField(
advanced=True,
),
}
def build(
self,
google_api_key: str,
model: str,
max_output_tokens: Optional[int] = None,
temperature: float = 0.1,
top_k: Optional[int] = None,
top_p: Optional[float] = None,
n: Optional[int] = 1,
) -> BaseLanguageModel:
return ChatGoogleGenerativeAI(
model=model,
max_output_tokens=max_output_tokens or None,
temperature=temperature,
top_k=top_k or None,
top_p=top_p or None,
n=n or 1,
google_api_key=google_api_key,
)

View file

@ -5,6 +5,7 @@ from typing import Any, Dict, List
import orjson
from langchain.agents import ZeroShotAgent
from langchain.schema import BaseOutputParser, Document
from langflow.services.database.models.base import orjson_dumps
@ -16,6 +17,8 @@ def handle_node_type(node_type, class_object, params: Dict):
prompt = instantiate_from_template(class_object, params)
elif node_type == "ChatPromptTemplate":
prompt = class_object.from_messages(**params)
elif hasattr(class_object, "from_template") and params.get("template"):
prompt = class_object.from_template(template=params.pop("template"))
else:
prompt = class_object(**params)
return params, prompt

View file

@ -47,7 +47,6 @@ class Settings(BaseSettings):
else:
logger.debug("No DATABASE_URL env variable, using sqlite database")
value = "sqlite:///./langflow.db"
return value
@validator("COMPONENTS_PATH", pre=True)

View file

@ -0,0 +1,26 @@
#baseline
FROM --platform=linux/amd64 node:19-bullseye-slim AS base
RUN mkdir -p /home/node/app
RUN chown -R node:node /home/node && chmod -R 770 /home/node
RUN apt-get update && apt-get install -y jq curl
WORKDIR /home/node/app
# client build
FROM base AS builder-client
ARG BACKEND_URL
ENV BACKEND_URL $BACKEND_URL
RUN echo "BACKEND_URL: $BACKEND_URL"
WORKDIR /home/node/app
COPY --chown=node:node . ./
COPY ./set_proxy.sh .
RUN chmod +x set_proxy.sh && \
cat set_proxy.sh | tr -d '\r' > set_proxy_unix.sh && \
chmod +x set_proxy_unix.sh && \
./set_proxy_unix.sh
USER node
RUN npm install --loglevel warn
CMD ["npm", "run", "dev:docker"]

View file

@ -364,10 +364,9 @@ export default function GenericNode({
<div
className={
showNode
? "overflow-hidden " +
(data.node?.description === "" && !nameEditable
? "pb-5"
: "py-5")
? data.node?.description === "" && !nameEditable
? "pb-5"
: "py-5"
: ""
}
>

View file

@ -6,11 +6,13 @@ export default function PageLayout({
description,
children,
button,
betaIcon,
}: {
title: string;
description: string;
children: React.ReactNode;
button?: React.ReactNode;
betaIcon: boolean;
}) {
return (
<div className="flex h-screen w-full flex-col">
@ -18,7 +20,10 @@ export default function PageLayout({
<div className="flex h-full w-full flex-col justify-between overflow-auto bg-background px-16">
<div className="flex w-full items-center justify-between gap-4 space-y-0.5 py-8 pb-2">
<div className="flex w-full flex-col">
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
<h2 className="text-2xl font-bold tracking-tight">
{title}
{betaIcon && <span className="store-beta-icon">BETA</span>}
</h2>
<p className="text-muted-foreground">{description}</p>
</div>
<div className="flex-shrink-0">{button && button}</div>

View file

@ -198,6 +198,7 @@ export default function FormModal({
window.location.protocol === "https:" || window.location.port === "443";
const webSocketProtocol = isSecureProtocol ? "wss" : "ws";
const host = isDevelopment ? "localhost:7860" : window.location.host;
const chatEndpoint = `/api/v1/chat/${chatId}`;
return `${

View file

@ -164,6 +164,7 @@ export default function StorePage(): JSX.Element {
return (
<PageLayout
betaIcon
title="Langflow Store"
description="Search flows and components from the community."
button={

View file

@ -311,7 +311,7 @@
@apply hover:text-accent-foreground hover:transition-all;
}
.generic-node-desc {
@apply h-full px-5 mb-4 w-full text-foreground;
@apply mb-4 h-full w-full px-5 text-foreground;
}
.generic-node-desc-text {
@apply w-full text-sm text-muted-foreground;
@ -1040,7 +1040,7 @@
.fade-container::before,
.fade-container::after {
@apply pointer-events-none absolute bottom-0 top-0 bg-gradient-to-r to-transparent from-background;
@apply pointer-events-none absolute bottom-0 top-0 bg-gradient-to-r from-background to-transparent;
content: "";
width: 50px;
opacity: 0;
@ -1084,4 +1084,8 @@
.scroll-container {
@apply flex overflow-x-scroll scrollbar-hide;
}
.store-beta-icon {
@apply relative bottom-3 left-1 ml-2 rounded-full bg-beta-background px-2 py-1 text-center text-xs font-semibold text-beta-foreground;
}
}