Giải pháp la bàn

Xây dựng ứng dụng lên kế hoạch du lịch do nhân viên hỗ trợ sử dụng bằng AI tạo sinh

Sơ đồ dưới đây cho thấy thông tin tổng quan về cách kết hợp các dịch vụ tốt nhất dành cho nhà phát triển của Google để tạo các ứng dụng dựa trên trí tuệ nhân tạo (AI).

Tạo những ứng dụng đẹp mắt có sử dụng trí tuệ nhân tạo (AI) cho thiết bị di động và web

Bạn có thể dùng Flutter và Firebase Genkit để tạo các ứng dụng đa nền tảng có khả năng tích hợp liền mạch với AI.
Bạn có thể sử dụng Genkit để giúp ứng dụng của mình tự tin sử dụng dữ liệu từ các LLM bằng cách xác định một giản đồ có thể xác thực kết quả của LLM. Trong Flutter, bạn có thể dùng Dart để chuyển đổi tuần tự yêu cầu và giải tuần tự phản hồi cho khớp với giản đồ Genkit bằng cách sử dụng các yêu cầu HTTP tiêu chuẩn.
Với IDX, bạn có thể tạo một ứng dụng Flutter mà không cần cài đặt bất kỳ phần mềm nào. Việc này giúp bạn có thể phát triển và kiểm thử ứng dụng Android cũng như ứng dụng web trong trình duyệt.
Firebase Data Connect là một dịch vụ cơ sở dữ liệu quan hệ dành cho các ứng dụng web và ứng dụng di động. Dịch vụ này cho phép bạn xây dựng và mở rộng quy mô bằng cơ sở dữ liệu PostgreSQL được quản lý toàn bộ, dựa trên Cloud SQL. Giải pháp này cung cấp tính năng quản lý giản đồ và truy vấn cũng như phương thức biến đổi an toàn bằng cách sử dụng GraphQL tích hợp hiệu quả với tính năng Xác thực Firebase. Data Connect có hỗ trợ SDK cho Kotlin Android và web.

Tạo nhân viên hỗ trợ bằng Firebase Genkit

Nhân viên hỗ trợ sử dụng khung điều phối AI để nhận thông tin đầu vào của người dùng và tạo phản hồi.
---
model: googleai/gemini-1.5-flash-latest
config:
  temperature: 1.0
  safetySettings:
    - category: HARM_CATEGORY_HATE_SPEECH
      threshold: BLOCK_LOW_AND_ABOVE
    - category: HARM_CATEGORY_DANGEROUS_CONTENT
      threshold: BLOCK_ONLY_HIGH
    - category: HARM_CATEGORY_HARASSMENT
      threshold: BLOCK_LOW_AND_ABOVE
    - category: HARM_CATEGORY_SEXUALLY_EXPLICIT
      threshold: BLOCK_LOW_AND_ABOVE
input:
  schema:
    request: string, The users request for where they want to travel to.
    place: string, The place that closely represents the users request.
    placeDescription: string, A description of that place.
    activities(array, a stringify list of activities that can be found at the specified place): string
    restaurants?(array, a stringify list of all the restaurants found at that location): string
output:
  schema:
    place: string, The place the user is traveling to.
    itineraryName: string, a catchy itinerary name that encapsulates the spirit of the trip and includes the place name
    startDate: string, the start date of the trip
    endDate: string, the end date of the trip
    tags(array, relevant tags for the trip): string
    itinerary(array):
      day: number
      date: string
      planForDay(array):
        activityRef: string, the reference value for the activity - this comes from the available activities JSON. If no value is present use a ref value of restaurant.
        activityTitle: string, a catchy title for the activity
        activityDesc: string, a six word description of the activity
        photoUri?: string, set the photo uri value for restaurants only.
        googleMapsUri?: string, if this is a restaurant include the googleMapsUri
---

Generate an itinerary for a tourist planning on traveling to the location specified based in their request.
If there is something that does not exist within the list of activities, do not include it in your answer.
Feel free to relate the activitiy to the request in a meaningful way.
In the plan for day array, put activities as a travel brouchure might do.
Come up with a catchy name for the itinerary.

Pick three activities per day, minimum of three day trip unless otherwise specified in the request.

Output schema should not include the properties type or object.

Pick a date after 2024-05-14 but before 2024-12-31.

The output date must be in the format year-month-day.

Give each activity a unique title and description.

Limit activity descriptions to 6 words.

If no restaurants are supplied, do not recommend any restaurants to eat at.

{{#if restaurants}}
Find a restaurant to eat at each day.

Include a restaurant to visit in the itinerary for each day from the available restaurants.
The restaurant should be the only activity with a photoUri.
The photoUri for the restaurant should be from the photoUri property from the restaurant array.
If there are no restaurants to pick from, do not include it in the list.

The photoUri from the restaurantFinder should be in the format of places/${placeId}/photos/${photoId}

Each restaurant should be unique to the overall itinerary.
Each restaurant must contain a photoUri in their output JSON schema.
Each restaurant must also include  an activitiyRef, activityTitle, and activityDesc in their output
{{/if}}
Output must be in JSON format.

REQUEST : {{request}}
PLACE : {{place}}
PLACE DESCRIPTION : {{placeDescription}}
AVAILABLE ACTIVITIES : {{activities}}
RESTAURANTS : {{restaurants}}
Khi làm việc với AI tạo sinh, quan trọng là bạn phải tạo ra các câu lệnh hiệu quả để mô hình trả về các câu trả lời có chất lượng cao. Firebase Genkit cung cấp trình bổ trợ Dotprompt và định dạng văn bản để giúp bạn viết và sắp xếp các câu lệnh dựa trên AI tạo sinh. Định dạng này đóng gói lời nhắc, giản đồ đầu vào và đầu ra, mô hình và cấu hình, tất cả trong một tệp duy nhất.

Mã ví dụ sau đây cho thấy một tệp Dotprompt được dùng trong ứng dụng du lịch. Giản đồ này dựa trên thông tin mà người dùng cung cấp khi mô tả chuyến đi trong mơ của mình.
Dấu chấm được thiết kế dựa trên tiền đề rằng lời nhắc là mã. Bạn viết và duy trì câu lệnh trong các tệp có định dạng đặc biệt gọi là tệp dấu chấm, theo dõi các thay đổi đối với các câu lệnh đó bằng chính hệ thống quản lý phiên bản mà bạn dùng cho mã của mình, rồi triển khai chúng cùng với mã dùng để gọi các mô hình AI tạo sinh của bạn.
Flow là các hàm được định kiểu rõ ràng, có thể phát trực tuyến, cục bộ và có thể gọi từ xa, đồng thời có thể ghi nhận toàn bộ. Firebase Genkit cung cấp giao diện dòng lệnh và giao diện người dùng của nhà phát triển để xử lý các quy trình, chẳng hạn như các quy trình chạy hoặc gỡ lỗi.
import {defineTool} from '@genkit-ai/ai/tool';
...
{
  name: 'restaurantFinder',
  description: `Used when needing to find a restaurant based on a users location.
  The location should be used to find nearby restaurants to a place. You can also
  selectively find restaurants based on the users preferences, but you should default
  to 'Local' if there are no indications of restaurant types in the users request.
  `,
  inputSchema: z.object({
    place: z.string(),
    typeOfRestaurant: z.string().optional() }),
    outputSchema: z.unknown(),
},
...
async (input) => {
  if (input.typeOfRestaurant == undefined) {
    input.typeOfRestaurant = "Local";
  }
  const geocodeEndpoint = "https://places.googleapis.com/v1/places:searchText";
  const textQuery = {textQuery: `${input.typeOfRestaurant} restaurants in ${input.place}`};

  const  response = await axios.post(
    geocodeEndpoint,
    JSON.stringify(textQuery),
    {
      headers: {
        "Content-Type": "application/json",
        "X-Goog-Api-Key": MAPS_API_KEY,
        "X-Goog-FieldMask": "places.displayName,places.formattedAddress,places.priceLevel,places.photos.name,places.editorialSummary,places.googleMapsUri"
      }
    }
  );
  console.log(response.data);
  let data = (response.data as PlaceResponse);
  for(let i = 0; i < data.places.length; i++) {
    if (data.places[i].photos) {
      data.places[i].photos = [data.places[i].photos[0]];
    }
  }
  return data as PlaceResponse;
}
Bạn có thể sử dụng lệnh gọi hàm trong Genkit để mở rộng chức năng của tác nhân người dùng, nhờ đó, tác nhân hỗ trợ có thể tinh chỉnh thêm câu trả lời và hoàn thành các nhiệm vụ khác. Ứng dụng du lịch xác định một công cụ có thể trả về thông tin nhà hàng từ API Địa điểm dựa trên chuyến đi mà người dùng mong muốn. Đoạn mã này sử dụng Zod nhằm xác định giản đồ đầu vào và đầu ra để có thể xác thực kết quả truy vấn.
...
export const textRefinement = defineFlow(
{
  name: 'textRefinement',
  inputSchema: z.string(),
  outputSchema: z.unknown(),
},
async (userRequest) => {
  const refinementPrompt = await prompt('textRefinement')
  const result = await refinementPrompt.generate({
      input: {
          request: userRequest
      },
  });
  return result.output();
});
Để mang đến cho người dùng trải nghiệm tìm kiếm phù hợp hơn, sau khi người dùng mô tả chuyến đi trong mơ của họ, Gemini sẽ xác định xem có cần thêm thông tin hay không dựa trên câu lệnh mà ứng dụng du lịch cung cấp và ra tín hiệu cho ứng dụng nếu cho rằng cần thêm thông tin. Sau đó, ứng dụng này sẽ nhắc người dùng cung cấp thông tin đó rồi thêm thông tin vào yêu cầu trên phần phụ trợ.
import 'package:http:http.dart' as http;
...
Future<List<Trip>> generateTrips(String description, List<Image> images) async {
  final uri = Uri.parse('.../generateTrips');
  final request = http.MultipartRequest('POST', uri);
  request.fields['description'] = description;
  request.files.add(http.MultipartFile.fromData(
      images.name, images.bytes,
      contentType: MediaType('image', 'png'),
  ));
  var response = await request.send();
  if (response.statusCode == 200) {
      final body = await response.body.text();
      final items = jsonDecode(body) as List<dynamic>;
      return items.map(Trip.fromJson).toList();
  }
  ...
  import { imagen2, geminiProVision } from '@genkit-ai/vertexai';
  import { generate } from '@genkit-ai/ai';

  const imageResult = await generate({
    model: imagen2,
    prompt: 'Generate an image of a very specific historical time and place.',
  });
  const generatedImage = imageResult.media();

  const descriptionResult = await generate({
    model: geminiProVision,
    prompt: [
      {
        text: 'What is the historical time and place represented in this picture?',
      },
      { media: generatedImage },
    ],
  });
  console.log(descriptionResult.text());
  }
Ứng dụng du lịch này yêu cầu người dùng xác định chuyến đi trong mơ của họ bằng cách sử dụng tính năng nhập văn bản hoặc nhấn vào nút micrô để kích hoạt tính năng chuyển lời nói thành văn bản. Người dùng cũng có thể tuỳ ý tải hình ảnh lên.

Ứng dụng này tận dụng gói Drart từ pub.dev để tích hợp với chức năng chuyển lời nói thành văn bản gốc cho từng nền tảng, đồng thời sử dụng Gemini API bên trong Firebase Genkit để xử lý các dữ liệu đầu vào đa phương thức như hình ảnh hoặc video. Gemini API sử dụng tính năng Tạo tăng cường truy xuất (RAG) để trả về một nhóm các chuyến đi đề xuất bằng Firebase Data Connect và các tính năng nhúng để thực hiện tìm kiếm lân cận gần nhất.

Mở rộng quy mô ứng dụng để phát hành công khai

Dịch vụ Lưu trữ Firebase tích hợp với các khung web hiện đại phổ biến, bao gồm cả Flutter. Khi sử dụng tính năng Lưu trữ Firebase và Cloud Functions cho Firebase với những khung làm việc này, bạn có thể phát triển các ứng dụng và dịch vụ vi mô trong môi trường khung mà mình ưu tiên, sau đó triển khai chúng trong một môi trường máy chủ được quản lý, bảo mật. Trước khi bắt đầu phát hành công khai, hãy tìm hiểu tính bảo mật và hiệu suất của tất cả các dịch vụ trong ứng dụng của bạn. Xem danh sách kiểm tra việc phát hành Firebase để biết thêm thông tin.
Ứng dụng du lịch sử dụng AI của Google để nhanh chóng lặp lại dữ liệu thử nghiệm. Đây là một lựa chọn phù hợp cho những ứng dụng có ít trường hợp sử dụng AI mà không cần mở rộng quy mô. Vertex AI có hạn mức cao hơn để giúp mở rộng quy mô của các ứng dụng phát hành công khai và áp dụng chính sách quyền riêng tư mạnh mẽ hơn để bảo vệ dữ liệu người dùng. Genkit đã tích hợp sẵn chức năng giúp bạn dễ dàng chuyển đổi giữa các mô hình nên bạn không cần phải viết lại câu lệnh hoặc lệnh gọi API.