第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定

用Amazon Bedrock和Swift構(gòu)建一個智能聊天iOS應(yīng)用

这篇帖子会教你如何使用Amazon Bedrock创建一个原汁原味的iOS应用,利用Swift来实现AI驱动的聊天和图像功能。我们会用到无服务器资源,包括AWS Lambda和API Gateway这两个工具,作为后端支持。

示例应用程序包括以下内容:

  1. 一个使用 Swift 开发的移动应用
  2. 将 Amazon Bedrock 集成,使用模型 amazon.titan-image-generator-v1ai21.j2-mid-v1
  3. 使用 AWS Lambda 和 TypeScript 实现无服务器后端处理
  4. 通过 Amazon API Gateway 实现 RESTful API 通信
  5. 使用 Amazon CloudWatch Logs 监控 AWS Lambda 函数并查看日志信息

最终你将得到的应用程序如下:

图片描述:此处应添加对图片的说明或上下文描述

前提条件

请确保你已经安装了以下软件,再开始。

  • 一个 AWS 账户(Account)
  • Node.js v18 或更新版本
  • Serverless Framework、AWS SAM 或 AWS CDK(取决于你是否想使用基础设施即代码。我会用 Serverless Framework)
  • 包管理器(比如我会使用 Yarn)
  • Xcode 版本 15 或更新版本

建筑

图

  1. 用户通过他们的移动设备访问应用程序,应用程序随后向 Amazon API Gateway 发送请求。
  2. API Gateway 将请求路由到 ImageFunctionTextFunction(Lambda 函数)。
  3. AWS Lambda 与 Amazon Bedrock 模型进行通信,并以 JSON 格式检索生成的响应。
  4. 处理后的响应被发送回应用程序,以便显示并启用内容或聊天交互。

要访问Amazon Bedrock,请按照以下步骤操作

  1. 登录您的 AWS 控制台
  2. 转到 Amazon Bedrock
  3. 在左侧导航中点击“模型访问”
  4. 请求访问,请注意body 可能会根据您选择的模型有所不同。我将使用 Titan Image Generator G1 模型来生成图像,以及使用 ai21.j2-mid-v1 模型来生成文字

使用 TypeScript 和 AWS Lambda 进行 Serverless 后端处理

你可以选择你喜欢的工具来部署 Lambda 函数(或 Lambda 函数部署工具),比如我会提供必要的代码来创建这些函数。

文字 Lambda

请留意以下几点哦:

  1. 需要先导入 client-bedrock-runtime 包。
  2. 还需要添加 modelId 参数。
  3. prompt 就是从你 API 提供的搜索文本。
    import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime';

    const client = new BedrockRuntimeClient({ region: 'us-east-1' });

    export async function handler(event: any) {
      const prompt = JSON.parse(event.body).prompt;
      const input = {
        modelId: 'ai21.j2-mid-v1',
        contentType: 'application/json',
        accept: '*/*',
        headers: {
          'Access-Control-Allow-Headers': 'Content-Type',
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Credentials': true,
          'Access-Control-Allow-Methods': 'POST'
        },
        body: JSON.stringify({
          prompt: prompt,
          maxTokens: 200,
          temperature: 0.7,
          topP: 1,
          stopSequences: [],
          countPenalty: { scale: 0 },
          presencePenalty: { scale: 0 },
          frequencyPenalty: { scale: 0 }
        })
      };

      try {
        const data = await client.send(new InvokeModelCommand(input));
        const jsonString = Buffer.from(data.body).toString('utf8');
        const parsedData = JSON.parse(jsonString);
        const text = parsedData.completions[0].data.text;
        return text;
      } catch (error) {
        console.error(error);
      }
    }

全屏/退出全屏

图像Lambda

    import { BedrockRuntimeClient, InvokeModelCommand } from '@aws-sdk/client-bedrock-runtime';

    const client = new BedrockRuntimeClient({ region: 'us-east-1' });

    export async function handler(event: any) {
      const prompt = JSON.parse(event.body).prompt;
      const input = {
        modelId: 'amazon.titan-image-generator-v1',
        contentType: 'application/json',
        accept: 'application/json',
        headers: {
          'Access-Control-Allow-Headers': 'Content-Type',
          'Access-Control-Allow-Origin': '*',
          'Access-Control-Allow-Credentials': true,
          'Access-Control-Allow-Methods': 'POST'
        },
        body: JSON.stringify({
          textToImageParams: {
            text: prompt
          },
          taskType: 'TEXT_IMAGE',
          imageGenerationConfig: {
            cfgScale: 10,
            seed: 0,
            width: 512,
            height: 512,
            numberOfImages: 1
          }
        })
      };

      try {
        const command = new InvokeModelCommand(input);
        const response = await client.send(command);

        const blobAdapter = response.body;

        const textDecoder = new TextDecoder('utf-8');
        const jsonString = textDecoder.decode(blobAdapter.buffer);

        try {
          const parsedData = JSON.parse(jsonString);
          return parsedData.images[0];
        } catch (error) {
          console.error(`解析 JSON 出错: ${error}`);
          return 'TextError';
        }
      } catch (error) {
        console.error(error);
      }
    }

进入全屏,退出全屏

现在部署你的Lambda,如果你使用Serverless框架的话,可以使用以下配置:

    service: aws-bedrock-ts
    frameworkVersion: '3'

    provider:
      name: aws
      runtime: nodejs18.x
      timeout: 30
      iam:
        role:
          statements:
            - Effect: '授权'
              Action:
                - 'bedrock:InvokeModel'
              Resource: '*'

    functions:
      bedrockText:
        handler: src/bedrock/text.handler
        name: 'aws-bedrock-text'
        events:
          - httpApi:
              path: /bedrock/text
              method: post
      bedrockImage:
        handler: src/bedrock/image.handler
        name: 'aws-bedrock-image'
        events:
          - httpApi:
              path: /bedrock/image
              method: post

点击进入全屏模式 按退出全屏模式

请保存好你的Lambda API端点。

开发你的 iOS 应用程序吧

搭建项目

  1. 首先,在 Xcode 中创建一个新的 Swift 项目。
  2. 将项目命名为你的应用名(比如叫 BedrockSwift)。

聊天消息模型

首先,定义一个模型来存储聊天消息,比如说,这些消息可以是文本或图片。我将这个类命名为ChatMessage.swift:

    import UIKit

    struct ChatMessage: Equatable {
        var text: String?
        var image: UIImage?
        var isImage: Bool
        var isUser: Bool
    }

注:以上代码片段为未翻译的 Swift 代码。

全屏模式 退出全屏

API请求处理

此服务负责管理API交互,包括将提示发送到您的Lambda函数并处理响应。请确保将端点更新到您的Lambda函数。我将我的类命名为APIService.swift,

    import UIKit

    class APIService: ObservableObject {

        @Published var messages: [ChatMessage] = []

        private func getEndpointURL(for type: String) -> URL? {
            let baseURL = "https://example.execute-api.region.amazonaws.com/bedrock"

            switch type {
            case "text":
                return URL(string: "\(baseURL)/text")
            case "image":
                return URL(string: "\(baseURL)/image")
            default:
                return nil
            }
        }

        func addUserPrompt(_ prompt: String) {
            messages.append(ChatMessage(text: prompt, image: nil, isImage: false, isUser: true))
        }

        func sendRequest(prompt: String, type: String, completion: @escaping () -> Void) {
            guard let url = getEndpointURL(for: type) else {
                print("无效的URL类型: \(type)")
                return
            }

            var request = URLRequest(url: url)
            request.httpMethod = "POST"
            let parameters: [String: Any] = ["prompt": prompt]

            request.httpBody = try? JSONSerialization.data(withJSONObject: parameters)
            request.addValue("application/json", forHTTPHeaderField: "Content-Type")

            URLSession.shared.dataTask(with: request) { data, response, error in
                if let error = error {
                    print("错误: \(error)")
                    return
                }

                guard let data = data else { return }
                print(data)

                DispatchQueue.main.async {
                    if type == "text" {
                        if let responseString = String(data: data, encoding: .utf8) {
                            let trimmedResponse = responseString.trimmingCharacters(in: .whitespacesAndNewlines)
                            self.messages.append(ChatMessage(text: trimmedResponse, image: nil, isImage: false, isUser: false))
                        }
                    } else {
                        DispatchQueue.main.async {
                            if let base64String = String(data: data, encoding: .utf8),
                               let imageData = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters),
                               let image = UIImage(data: imageData) {

                                DispatchQueue.main.async {
                                    self.messages.append(ChatMessage(text: nil, image: image, isImage: true, isUser: false))
                                }
                            }
                        }
                    }
                    completion()
                }
            }.resume()
        }
    }

全屏,退出全屏

聊天界面查看

现在,创建一个主要负责处理UI并显示聊天消息的视图。接下来,我将文件命名为BedrockView.swift。

    import SwiftUI

    struct BedrockView: View {

        @StateObject var apiService = APIService()
        @State private var prompt: String = ""
        @State private var selectedType = 0
        @State private var isLoading = false

        var body: some View {
            VStack {
                ScrollViewReader { scrollViewProxy in
                    ScrollView {
                        VStack {
                            ForEach(apiService.messages.indices, id: \.self) { index in
                                if apiService.messages[index].isImage, let image = apiService.messages[index].image {
                                    HStack {
                                        Spacer()
                                        Image(uiImage: image)
                                            .resizable()
                                            .scaledToFit()
                                            .frame(height: 200)
                                            .frame(maxWidth: .infinity, alignment: .leading)
                                            .cornerRadius(10)
                                            .padding(.vertical, 5)
                                    }
                                } else if let text = apiService.messages[index].text {
                                    HStack {
                                        if apiService.messages[index].isUser {
                                            Spacer()
                                            Text(text)
                                                .padding(.vertical, 6)
                                                .padding(.horizontal, 12)
                                                .background(Color.blue.opacity(0.2))
                                                .cornerRadius(10)
                                                .frame(maxWidth: .infinity, alignment: .trailing)
                                        } else {
                                            Text(text)
                                                .padding(.vertical, 6)
                                                .padding(.horizontal, 12)
                                                .background(Color.gray.opacity(0.2))
                                                .cornerRadius(10)
                                                .frame(maxWidth: .infinity, alignment: .leading)
                                        }
                                    }
                                    .padding(.vertical, 1)
                                }
                            }
                            if isLoading {
                                ProgressView("加载中...")
                                    .padding(.vertical, 20)
                            }
                        }
                        .padding(.horizontal)
                        .id("BOTTOM")
                    }
                    .onChange(of: apiService.messages) { _ in
                        withAnimation {
                            scrollViewProxy.scrollTo("BOTTOM", anchor: .bottom)
                        }
                    }
                }

                VStack {
                    TextField("输入提示内容...", text: $prompt)
                        .textFieldStyle(.roundedBorder)
                        .padding(.horizontal)
                        .padding(.vertical, 10)

                    HStack {
                        Picker(selection: $selectedType, label: Text("选择类型")) {
                            Text("文本").tag(0)
                            Text("图片").tag(1)
                        }
                        .pickerStyle(SegmentedPickerStyle())
                        .frame(maxWidth: .infinity)
                        .padding(.leading, 10)

                        Button(action: {
                            if prompt.isEmpty { return }
                            apiService.addUserPrompt(prompt)
                            let type = selectedType == 0 ? "text" : "image"
                            isLoading = true
                            apiService.sendRequest(prompt: prompt, type: type) {
                                isLoading = false
                            }
                            prompt = ""
                        }) {
                            Text("发送消息")
                                .frame(width: 100, height: 2)
                                .padding()
                                .background(Color.primary)
                                .foregroundColor(.white)
                                .cornerRadius(10)
                        }
                    }
                    .padding(.horizontal)
                }
                .padding()
            }
        }
    }

全屏 和 退出全屏

应用启动页面

打开你的文件:YourAppNameApp.swift,并更新你在创建 SwiftUI 项目时设置的默认入口点。我的默认入口点命名为 BedrockView,如前所述。

    import SwiftUI

    @main
    struct BedrockSwiftApp: App {
        // 主体结构定义
        var body: some Scene {
            // 定义窗口组
            WindowGroup {
                // 显示BedrockView视图
                BedrockView()
            }
        }
    }

点击全屏模式。点击退出全屏。

在 Xcode 中启动应用

现在你可以启动你的应用了!请按照以下步骤在Xcode中启动应用。

  1. 从工具栏中选择一个模拟器或连接的设备作为您的设备。
  2. 点击运行按钮(或按 Cmd + R)来构建并运行应用。

这将在你选择的设备上启动应用,让你可以与Amazon Bedrock的聊天和图像生成功能互动。

有几点要注意哦

由于这是一个用于本地测试的应用,我已经将 Access-Control-Allow-Origin 设置为 *。此外,你可能还需要在 API Gateway 中调整 CORS 设置。

请注意,API 调用可能会产生小额费用。有关详细定价信息参阅Amazon Bedrock 定价页面

GitHub 存储库

该项目的源代码已托管在GitHub上:

结论部分

在这篇文章中,我带您了解如何使用原生的Swift语言以及无服务器的AWS服务(如AWS Lambda和API Gateway等)来构建一个简单的AI聊天应用程序。通过将Amazon Bedrock的生成式AI模型与这些服务集成,我们创建了一个流畅的解决方案,充分利用了AWS的功能,并提供原生的移动体验。请注意,我在应用程序中尽力只使用了原生组件,尽管还有改进的空间。此外,保护您的API使用令牌至关重要;我将在接下来的文章中详细讨论这个话题。

點擊查看更多內(nèi)容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續(xù)努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優(yōu)惠券免費領(lǐng)

立即參與 放棄機會
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號

舉報

0/150
提交
取消