DifyをAWS上にホスティングして、全社トライアル環境を提供しています!~Difyで始めるRAGアプリケーション開発~

こんにちは。SCSKのふくちーぬです。

私が所属する技術戦略本部では、『2030 共創ITカンパニー』の実現に向けて、全社技術戦略の策定や先進技術を開拓し、新たな価値創出・社会実装に向けた様々な取り組みを進めております。

その中でも技術戦略本部では、「Dify」を触れる環境を全社員に提供して、技術検証に加えて高度デジタル人材の育成を促進する取り組みをしています。

本記事では、OSSのLLMアプリケーション開発プラットフォーム「Dify」をAWS上でホスティングし全社展開している知見やRAGアプリケーションを紹介します。

Difyとは

各種LLM(大規模言語)モデルを活用して、GUIベースで簡単に生成Aiアプリケーションを開発できるツールです。

Dify クラウドサービス

クラウドサービスとして提供される完全マネージ型のSaaSです。AWSアカウントと同様にテナント(アカウント)を分けたり、多様な認証方法が用意されISO 27001:2022認証(ISMS)を始めとしたコンプライアンスも順守されているため、エンタープライズの大規模利用に向いています。

Dify コミュニティ版

オープンソースとして提供されるセルフホスティング型のソリューションです。クラウドサービスとは異なり、Dify本体のサービス利用料はかかりませんが、ホストティングしている基盤の利用料や運用管理は発生します。またテナントを分割することはできず、認証方法が限定(メールアドレス+パスワード)されています。その他ライセンスの利用条項が記載しているので、自社利用する際はご参照の上構築ください。

アーキテクチャ

ユーザーは、HTTPS通信でDify Webアプリケーションにアクセスします。

  • ALB及びACMを利用したHTTPS通信
  • ALBのセキュリティグループでは、IPアドレスでのアクセス制御
  • Difyアプリケーションは、EC2内のDocker-Composeコマンドで稼働

構築手順

弊社で全社展開しているDify環境のノウハウを活かして、今回は個人でも扱いやすいDifyセルフホスティング環境を構築する手順をご紹介します。

Amazon Route 53 のドメイン取得

Route 53 でドメインを取得していきます。

今回は、Route 53 で提供されるTLDの中で最安の「.click」を購入しています。3$/年の格安料金です。

連絡先情報を入力します。

10分程待つと、AWS側でリクエストが承認されて、ステータスが「成功」になります。

これで、ドメインは取得は完了です。

証明書の取得

次にドメインに紐づいた証明書を取得します。

ACMのコンソールに切り替えます。「リクエスト」を押下します。

「パブリック証明書をリクエスト」を選択して、「次へ」を押下します。

Route 53 で取得したドメイン名を入力します。検証方法、キーアルゴリズムはデフォルトの設定のままで構いません。

「リクエスト」を押下します。

ACM証明書の作成は完了しました。Route 53 とのDNS検証をするために、CNAMEレコードを登録します。「Route 53 でレコードを作成」を押下します。

「レコードを作成」を押下します。

Route 53 とのDNS検証が完了するまで、10分程待ちます。

Route 53 の検証が成功すれば、ステータスが「発行済み」に変更されます。

これで、証明書の取得は完了です。

AWS CloudFormtion テンプレート

テンプレートで指定する各種パラメータの値を控えておいてください。

  • DifyVersion

下記サイトをご確認し、指定のバージョンを選んでください。

  • DockerComposeVersion
  • ACMCertificateArn

発行したACMのARNを指定してください。

  • HostedZoneId

Route 53 パブリックホストゾーンのIDを指定してください。

  • DomainName

Route 53 で登録したドメイン名を指定してください。

その後、以下のCloudFormtionテンプレートをデプロイしてください。

AWSTemplateFormatVersion: '2010-09-09'
Description: Dify CloudFormation Template with ALB and EC2 (HTTPS)

Parameters:
  ProjectName:
    Type: String
    Default: dify
    Description: Project name used as prefix for resources

  VpcCIDR:
    Type: String
    Default: 10.0.0.0/16

  PubSubnet1CIDR:
    Type: String
    Default: 10.0.0.0/24

  PubSubnet2CIDR:
    Type: String
    Default: 10.0.1.0/24

  PriSubnet1CIDR:
    Type: String
    Default: 10.0.10.0/24

  PriSubnet2CIDR:
    Type: String
    Default: 10.0.11.0/24

  AllowedCIDR:
    Type: String
    Default: 0.0.0.0/0

  AmazonLinuxAMI:
    Type: AWS::SSM::Parameter::Value
    Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-6.1-x86_64

  DifyVersion:
    Type: String
    Default: 1.1.0

  DockerComposeVersion:
    Type: String
    Default: v2.35.1

  ACMCertificateArn:
    Type: String
    Description: ACM Certificate ARN for HTTPS
  
  HostedZoneId:
    Type: String
    Description: Route 53 Hosted Zone ID

  DomainName:
    Type: String
    Description: Domain name  

Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCIDR
      EnableDnsHostnames: true
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-vpc"

  PubSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: !Ref PubSubnet1CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-pub-subnet-1"

  PubSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs '']
      CidrBlock: !Ref PubSubnet2CIDR
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-pub-subnet-2"

  PriSubnet1:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [0, !GetAZs '']
      CidrBlock: !Ref PriSubnet1CIDR
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-Pri-subnet-1"

  PriSubnet2:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      AvailabilityZone: !Select [1, !GetAZs '']
      CidrBlock: !Ref PriSubnet2CIDR
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-Pri-subnet-2"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-igw"

  VPCGatewayAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  PubRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-pub-rt"

  PubRoute:
    Type: AWS::EC2::Route
    DependsOn: VPCGatewayAttachment
    Properties:
      RouteTableId: !Ref PubRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  PubSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PubSubnet1
      RouteTableId: !Ref PubRouteTable

  PubSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PubSubnet2
      RouteTableId: !Ref PubRouteTable

  EIP:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-eip"      

  NATGateway:
    Type: AWS::EC2::NatGateway
    Properties:
      AllocationId: !GetAtt EIP.AllocationId
      SubnetId: !Ref PubSubnet1
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-natgw"

  PriRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-Pri-rt"

  PriRoute:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PriRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NATGateway

  PriSubnet1RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PriSubnet1
      RouteTableId: !Ref PriRouteTable

  PriSubnet2RouteTableAssociation:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PriSubnet2
      RouteTableId: !Ref PriRouteTable

  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow HTTPS from AllowedCIDR
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: !Ref AllowedCIDR
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-alb-sg"              


  EC2SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Allow traffic from ALB only
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 80
          ToPort: 80
          SourceSecurityGroupId: !Ref ALBSecurityGroup
      SecurityGroupEgress:
        - IpProtocol: -1
          CidrIp: 0.0.0.0/0
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-ec2-sg"              

  ALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: !Sub "${ProjectName}-alb"
      Subnets:
        - !Ref PubSubnet1
        - !Ref PubSubnet2
      SecurityGroups:
        - !Ref ALBSecurityGroup
      Scheme: internet-facing
      LoadBalancerAttributes:
        - Key: idle_timeout.timeout_seconds
          Value: '60'
      Type: application
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-alb"

  ALBTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: !Sub "${ProjectName}-tg"    
      VpcId: !Ref VPC
      Protocol: HTTP
      Port: 80
      TargetType: instance
      Targets:
        - Id: !Ref Instance
      HealthCheckProtocol: HTTP
      HealthCheckPath: /signin      
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-tg"

  ALBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      Certificates:
        - CertificateArn: !Ref ACMCertificateArn
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref ALBTargetGroup
      LoadBalancerArn: !Ref ALB
      Port: 443
      Protocol: HTTPS

  InstanceRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: [ec2.amazonaws.com]
            Action: ['sts:AssumeRole']
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
        - arn:aws:iam::aws:policy/AmazonBedrockFullAccess

  InstanceProfile:
    Type: AWS::IAM::InstanceProfile
    Properties:
      Roles: [!Ref InstanceRole]

  Instance:
    Type: AWS::EC2::Instance
    Properties:
      ImageId: !Ref AmazonLinuxAMI
      InstanceType: t3.medium
      IamInstanceProfile: !Ref InstanceProfile
      SubnetId: !Ref PriSubnet1
      SecurityGroupIds: [!Ref EC2SecurityGroup]
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-ec2"
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash
          sudo dnf install -y git docker
          sudo systemctl enable --now docker
          sudo usermod -aG docker ec2-user
          sudo curl -L "https://github.com/docker/compose/releases/download/${DockerComposeVersion}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
          sudo chmod +x /usr/local/bin/docker-compose
          sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
          cd /opt
          sudo git clone https://github.com/langgenius/dify.git
          cd /opt/dify
          sudo git checkout ${DifyVersion}
          cd /opt/dify/docker
          sudo cp .env.example .env
          docker-compose up -d   
  
  Route53Record:
    Type: AWS::Route53::RecordSet
    Properties:
      HostedZoneId: !Ref HostedZoneId
      Name: !Ref DomainName
      Type: A
      AliasTarget:
        DNSName: !GetAtt ALB.DNSName
        HostedZoneId: !GetAtt ALB.CanonicalHostedZoneID          

Outputs:
  InitialAccessURL:
    Description: Initial access URL for Dify
    Value: !Sub "https://${DomainName}/install"
  LoginURL:
    Description: Login URL for Dify
    Value: !Sub "https://${DomainName}/signin"

CloudFormationでステータスが「CREATE_COMPLETE」になっていれば、環境構築は完了です。

Amazon Bedrock でのモデル有効化

今回は、以下のモデルを有効しております。

初めてBedrock内のモデルを利用する方は、下記手順に沿って実施ください。

Difyの設定

管理者アカウントの作成

CloudFormationテンプレート内に記載してある、以下のURLから初期ログインしていきます。

初回ログイン時のみ、以下のURLにて管理者アカウントを作成します。

└https://<ドメイン名>/install 

「セットアップ」を押下したら、ログインに進みます。

ログイン

これ以降のアクセスは、以下のURLを利用します。

└https://<ドメイン名>/signin

先程のログイン情報でログインをしてください。

 

モデルの有効化

今回は、Amazon Bedrock経由でモデルを利用します。ユーザーアイコンを押下し、「設定」を押下します。

その後、「モデルプロバイダー」を押下します。

「セットアップ」を押下します。

CloudFormationテンプレートをデプロイした”リージョン”と、今回利用する”モデルID”を入力します。

以下のように、AWSアカウント内で利用可能なモデルが表示されればアプリケーション作成の準備が整いました。

 

 

DifyでRAGアプリケーションを構築

今回は、RAG ON/OFFができるチャットアプリケーションを開発しました。

RAG(Retrieval-Augmented Generation、検索拡張生成)とは

今では、生成AI・LLM(Large Language Model、大規模言語モデル)がエンタープライズでも多く利用されています。LLMは、事前にある時点での学習データを大量に読みこませています。その中での課題の一つに、LLMが社内情報や最新情報にもとづいた回答を生成できないことです。この問題を解決するための技術が、RAG(Retrieval-Augmented Generation、検索拡張生成)です。

RAGを利用することで、欲しい情報を検索して抽出し、その内容をもとに生成AIに回答させることができます。これを応用すると、生成AIは学習済の情報だけではなく、未学習の情報からも回答を生成することができます。

ナレッジの作成

RAGの例として、弊社のプレスリリースを参照させた汎用的なチャットアプリケーションを作成してみます。

RAGで参照元となるPDFファイルをナレッジに登録します。

Difyのトップページ上部にある、「ナレッジ」を押下します。

「ナレッジを作成」を押下します。

「テキストファイルからインポート」を選択し、該当のファイルをドラッグ&ドロップでアップロードします。

今回は、弊社のプレスリリース(メジャーリーグベースボール(MLB™)とオフィシャルパートナー契約を締結)をPDF資料として利用しました。

アップロードが完了したら、「次へ」を押下します。

下記の設定を選択後、「保存して処理」を押下します。

  •  チャンク設定:自動

⇒チャンクとは、小さな文章のかたまりのことです。AIが理解しやすいサイズに、文章を分割します。

  •  インデックスモード:

⇒AIが情報を素早くみつけさせるための、索引を作成します。

  •  検索設定:

⇒単語そのものを探す「全文検索」と、意味や内容が類似しているものを探す「ベクトル検索」を組み合わせています。

ナレッジが作成だれたら、「ドキュメントに移動」を押下します。

以下のように、チャンクごとに文章を確認することができます。ナレッジの作成は完了です。

 

 

ワークフローの作成

スタジオ内ではアプリケーションを一から作成することもできます。また、あらかじめ用意されたテンプレートから簡単に作成することもできます。

 

Difyでは、GUIで以下のようなフローをノーコードで作成することが可能です。

本アプリケーションでは、2か所で生成AIモデルを利用しています。

  • 検索:ドキュメントを数値ベクトルに変換して、意味的に関連する情報を検索するために埋め込みモデルを使用しています。

     ⇒amazon.titan-embed-text-v1(Amazon社がBedrockのみで提供。)

  • テキスト生成:検索結果を基に、日本語で自然で正確な回答を作成するためにテキストモデルを使用しています。

     ⇒anthropic.claude-3-5-sonnet-20240620-v1:0(Anthropic社が提供しているClaude 3シリーズの中規模モデル。)

作成したアプリケーションは、YAML形式でエクスポートできます。そのため、他のユーザーでも簡単にアプリケーションを動かすことが可能です。

app:
  description: ''
  icon: 🤖
  icon_background: '#FFEAD5'
  mode: advanced-chat
  name: チャットアプリ
  use_icon_as_answer_icon: false
kind: app
version: 0.1.2
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
        number_limits: 3
        transfer_methods:
        - local_file
        - remote_url
    opening_statement: ''
    retriever_resource:
      enabled: false
    sensitive_word_avoidance:
      enabled: false
    speech_to_text:
      enabled: false
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: false
    text_to_speech:
      enabled: false
      language: ''
      voice: ''
  graph:
    edges:
    - data:
        sourceType: llm
        targetType: answer
      id: llm-answer
      source: llm
      sourceHandle: source
      target: answer
      targetHandle: target
      type: custom
    - data:
        isInIteration: false
        sourceType: start
        targetType: if-else
      id: 1744250148284-source-1744251195990-target
      selected: false
      source: '1744250148284'
      sourceHandle: source
      target: '1744251195990'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: if-else
        targetType: knowledge-retrieval
      id: 1744251195990-true-1744251325785-target
      source: '1744251195990'
      sourceHandle: 'true'
      target: '1744251325785'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: if-else
        targetType: llm
      id: 1744251195990-false-llm-target
      selected: false
      source: '1744251195990'
      sourceHandle: 'false'
      target: llm
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: knowledge-retrieval
        targetType: llm
      id: 1744251325785-source-llm-target
      source: '1744251325785'
      sourceHandle: source
      target: llm
      targetHandle: target
      type: custom
      zIndex: 0
    nodes:
    - data:
        desc: ''
        selected: false
        title: 開始
        type: start
        variables:
        - label: RAGオン/オフ
          max_length: 48
          options:
          - 'ON'
          - 'OFF'
          required: true
          type: select
          variable: RAG
      height: 89
      id: '1744250148284'
      position:
        x: -78.33688053024684
        y: 158.40698792460137
      positionAbsolute:
        x: -78.33688053024684
        y: 158.40698792460137
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        context:
          enabled: true
          variable_selector:
          - '1744251325785'
          - result
        desc: ''
        memory:
          role_prefix:
            assistant: ''
            user: ''
          window:
            enabled: false
            size: 10
        model:
          completion_params:
            temperature: 0.7
          mode: chat
          name: anthropic.claude-3-5-sonnet-20240620-v1:0
          provider: bedrock
        prompt_template:
        - id: 75ef1bf4-b63b-4112-ac19-863de25d714f
          role: system
          text: '{{#context#}}'
        selected: false
        title: LLM
        type: llm
        variables: []
        vision:
          configs:
            detail: high
          enabled: true
      height: 97
      id: llm
      position:
        x: 1033.7579811930557
        y: 240.61385193672766
      positionAbsolute:
        x: 1033.7579811930557
        y: 240.61385193672766
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        answer: '{{#llm.text#}}'
        desc: ''
        selected: false
        title: 回答
        type: answer
        variables: []
      height: 106
      id: answer
      position:
        x: 1417.5860697804653
        y: 240.61385193672766
      positionAbsolute:
        x: 1417.5860697804653
        y: 240.61385193672766
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        cases:
        - case_id: 'true'
          conditions:
          - comparison_operator: contains
            id: f456ee9b-076f-42d3-b923-d5e6bd671e45
            value: 'ON'
            varType: string
            variable_selector:
            - '1744250148284'
            - RAG
          id: 'true'
          logical_operator: and
        desc: ''
        selected: false
        title: IF/ELSE
        type: if-else
      height: 125
      id: '1744251195990'
      position:
        x: 236.2764581017642
        y: 158.40698792460137
      positionAbsolute:
        x: 236.2764581017642
        y: 158.40698792460137
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        dataset_ids:
        - cf3656ef-4763-4a7f-be8d-d26c5e5e58ca
        desc: ''
        multiple_retrieval_config:
          reranking_enable: true
          reranking_mode: weighted_score
          top_k: 4
          weights:
            keyword_setting:
              keyword_weight: 0.3
            vector_setting:
              embedding_model_name: amazon.titan-embed-text-v1
              embedding_provider_name: bedrock
              vector_weight: 0.7
        query_variable_selector:
        - '1744250148284'
        - sys.query
        retrieval_mode: multiple
        selected: true
        title: 知識取得
        type: knowledge-retrieval
      height: 91
      id: '1744251325785'
      position:
        x: 601.5046934164834
        y: 127.42604915556694
      positionAbsolute:
        x: 601.5046934164834
        y: 127.42604915556694
      selected: true
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    viewport:
      x: 97.03150392645694
      y: 67.62661575788061
      zoom: 0.5987393523094646 

完成したチャットアプリケーション

完成したアプリケーションは、以下のような形です。

指定したIPアドレス範囲であれば、URLを公開することで、誰でもアクセスできるようになります。

RAG OFFでの挙動

まずは、RAG OFFの場合の挙動を確認してみます、

「SCSKとMLBはどんな関係がありますか?」と入力してみます。

本LLMでは、SCSKとMLBの契約に関する情報は未学習のため”直接的な関係はありません”という回答が生成されています。

RAG ONでの挙動

次に、RAGをONにしてみます。

先程と同様の質問をしてみます。

きちんと、事前に読み込ませたプレスリリースを基に”SCSKとMLBが2年間のパートナーを締結した”旨が回答されましたね。

Difyプラットフォームの社内導入結果

事業部門からコーポレート部門まで幅広い従業員が生成AIアプリケーションを自らの手で構築できるようになり、部署内での業務効率化やナレッジ活用が向上しました。新入社員でも、AIに関する情報収集アプリケーションや商材検索アプリケーション等短期間で業務に役立つAIツールを開発できるようになったことが特筆すべき点です。

今後もAIを活用した業務改革や人材育成を組織レベルで推進していきます。

InfoWeaveについて

弊社では、AWSアカウント上でエンタープライズのセキュリティ要件を満たしたRAGソリューション(InfoWeave)を展開しております。CloudFormationテンプレートで簡単にデプロイでき、エンタープライズシステムの連携も可能です。ご興味がある方はいつでもご相談くださいませ(メールアドレス:cbdc-all@scsk.jp)。

お問い合わせ|企業のDX戦略を加速するハイブリッドクラウドソリューション

最後に

いかがだったでしょうか。

本記事では、DifyをAWSでホスティングする方法とRAGアプリケーションの開発手法を解説しました。

これを機に、皆さんの社内や個人でも、AWS上でDifyをセルフホスティングして、生成AIアプリケーション開発を始めてみてはいかがでしょうか。

本記事が皆様のお役にたてば幸いです。

ではサウナラ~🔥

タイトルとURLをコピーしました