使用客户端事件数据来改进预训练模型

Cloud Talent Solution 服务将机器学习技术融入招聘信息搜索体验,可为求职者提供高质量的搜索结果,远远超出了基于关键字的典型方法的极限。 CTS 以开箱即用的方式,将相关性模型和招聘信息/技能本体应用于您的招聘信息细节。您可以根据求职者的活动来记录客户端事件,从而改善返回给求职者的结果。

使用 createClientEventRequest 记录客户端事件

当求职者执行特定操作时,您可以使用职位搜索来记录该操作。例如,与服务交互的求职者或其他实体已在其视图中呈现一则招聘信息(或招聘信息列表),例如在采用压缩或剪辑格式的搜索结果列表中。您可以向 Cloud Talent Solution 发送一个 IMPRESSION 事件,以提供该搜索的上下文以及可供求职者查看的结果方面的数据。当求职者点击某条招聘信息结果以查看其完整的描述时,您可以发送一个 VIEW 事件,记载该求职者对于所选职位的兴趣。

以下示例展示了如何使用 API 向 Cloud Talent Solution 发送消息。与服务交互的求职者或其他实体已在其视图中呈现一则招聘信息(或招聘信息列表),例如在采用压缩或剪辑格式的搜索结果列表中。此事件通常与求职者在单个页面上查看职位列表相关联。

Go

import (
	"context"
	"fmt"
	"io"
	"time"

	talent "cloud.google.com/go/talent/apiv4beta1"
	"github.com/golang/protobuf/ptypes"
	talentpb "google.golang.org/genproto/googleapis/cloud/talent/v4beta1"
)

// createClientEvent creates a client event.
func createClientEvent(w io.Writer, projectID string, requestID string, eventID string, relatedJobNames []string) (*talentpb.ClientEvent, error) {
	ctx := context.Background()

	// Create an eventService client.
	c, err := talent.NewEventClient(ctx)
	if err != nil {
		return nil, fmt.Errorf("talent.NewEventClient: %v", err)
	}
	defer c.Close()

	createTime, _ := ptypes.TimestampProto(time.Now())
	clientEventToCreate := &talentpb.ClientEvent{
		RequestId:  requestID,
		EventId:    eventID,
		CreateTime: createTime,
		Event: &talentpb.ClientEvent_JobEvent{
			JobEvent: &talentpb.JobEvent{
				Type: talentpb.JobEvent_VIEW,
				Jobs: relatedJobNames,
			},
		},
	}

	// Construct a createJob request.
	req := &talentpb.CreateClientEventRequest{
		Parent:      fmt.Sprintf("projects/%s", projectID),
		ClientEvent: clientEventToCreate,
	}

	resp, err := c.CreateClientEvent(ctx, req)
	if err != nil {
		return nil, fmt.Errorf("CreateClientEvent: %v", err)
	}

	fmt.Fprintf(w, "Client event created: %v\n", resp.GetEvent())

	return resp, nil
}

Java

如需详细了解如何安装和创建 Cloud Talent Solution 客户端,请参阅 Cloud Talent Solution 客户端库


import com.google.cloud.talent.v4beta1.ClientEvent;
import com.google.cloud.talent.v4beta1.CreateClientEventRequest;
import com.google.cloud.talent.v4beta1.EventServiceClient;
import com.google.cloud.talent.v4beta1.JobEvent;
import com.google.cloud.talent.v4beta1.TenantName;
import com.google.protobuf.Timestamp;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class JobSearchCreateClientEvent {

  public static void createClientEvent() throws IOException {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "your-project-id";
    String tenantId = "your-tenant-id";
    String requestId = "your-req-id-from-response-metadata";
    String eventId = "your-unique-identifier-id";
    createClientEvent(projectId, tenantId, requestId, eventId);
  }

  // Creates a client event.
  public static void createClientEvent(
      String projectId, String tenantId, String requestId, String eventId) throws IOException {
    // Initialize client that will be used to send requests. This client only needs to be created
    // once, and can be reused for multiple requests. After completing all of your requests, call
    // the "close" method on the client to safely clean up any remaining background resources.
    try (EventServiceClient eventServiceClient = EventServiceClient.create()) {
      TenantName parent = TenantName.of(projectId, tenantId);

      // The timestamp of the event as seconds of UTC time since Unix epoch
      // For more information on how to create google.protobuf.Timestamps
      // See:
      // https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
      long seconds = 3L;
      Timestamp createTime = Timestamp.newBuilder().setSeconds(seconds).build();

      // The type of event attributed to the behavior of the end user
      JobEvent.JobEventType type = JobEvent.JobEventType.VIEW;

      // List of job names associated with this event
      String jobsElement = "projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]";
      String jobsElement2 = "projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]";

      List<String> jobs = Arrays.asList(jobsElement, jobsElement2);
      JobEvent jobEvent = JobEvent.newBuilder().setType(type).addAllJobs(jobs).build();
      ClientEvent clientEvent =
          ClientEvent.newBuilder()
              .setRequestId(requestId)
              .setEventId(eventId)
              .setCreateTime(createTime)
              .setJobEvent(jobEvent)
              .build();
      CreateClientEventRequest request =
          CreateClientEventRequest.newBuilder()
              .setParent(parent.toString())
              .setClientEvent(clientEvent)
              .build();
      ClientEvent response = eventServiceClient.createClientEvent(request);
      System.out.println("Created client event. ");
      System.out.println(response.toString());
    }
  }
}

Node.js

如需详细了解如何安装和创建 Cloud Talent Solution 客户端,请参阅 Cloud Talent Solution 客户端库


const talent = require('@google-cloud/talent').v4;

/**
 * Creates a client event
 *
 * @param projectId {string} Your Google Cloud Project ID
 * @param tenantId {string} Identifier of the Tenant
 * @param requestId {string} A unique ID generated in the API responses.
 * Value should be set to the request_id from an API response.
 * @param eventId {string} A unique identifier, generated by the client application
 */
function sampleCreateClientEvent(projectId, tenantId, requestId, eventId) {
  const client = new talent.EventServiceClient();
  // const projectId = 'Your Google Cloud Project ID';
  // const tenantId = 'Your Tenant ID (using tenancy is optional)';
  // const requestId = '[request_id from ResponseMetadata]';
  // const eventId = '[Set this to a unique identifier]';
  const formattedParent = client.tenantPath(projectId, tenantId);

  // The timestamp of the event as seconds of UTC time since Unix epoch
  // For more information on how to create google.protobuf.Timestamps
  // See: https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
  const seconds = 0;
  const createTime = {
    seconds: seconds,
  };

  // The type of event attributed to the behavior of the end user
  const type = 'VIEW';

  // List of job names associated with this event
  const jobsElement = 'projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]';
  const jobsElement2 =
    'projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]';
  const jobs = [jobsElement, jobsElement2];
  const jobEvent = {
    type: type,
    jobs: jobs,
  };
  const clientEvent = {
    requestId: requestId,
    eventId: eventId,
    createTime: createTime,
    jobEvent: jobEvent,
  };
  const request = {
    parent: formattedParent,
    clientEvent: clientEvent,
  };
  client
    .createClientEvent(request)
    .then(responses => {
      const response = responses[0];
      console.log('Created client event');
      console.log(`Response: ${response}`);
    })
    .catch(err => {
      console.error(err);
    });
}

Python

如需详细了解如何安装和创建 Cloud Talent Solution 客户端,请参阅 Cloud Talent Solution 客户端库


from google.cloud import talent
from google.cloud.talent import enums
import six

def create_client_event(project_id, tenant_id, request_id, event_id):
    """
    Creates a client event

    Args:
      project_id Your Google Cloud Project ID
      tenant_id Identifier of the Tenant
      request_id A unique ID generated in the API responses.
      Value should be set to the request_id from an API response.
      event_id A unique identifier, generated by the client application
    """

    client = talent.EventServiceClient()

    # project_id = 'Your Google Cloud Project ID'
    # tenant_id = 'Your Tenant ID (using tenancy is optional)'
    # request_id = '[request_id from ResponseMetadata]'
    # event_id = '[Set this to a unique identifier]'

    if isinstance(project_id, six.binary_type):
        project_id = project_id.decode("utf-8")
    if isinstance(tenant_id, six.binary_type):
        tenant_id = tenant_id.decode("utf-8")
    if isinstance(request_id, six.binary_type):
        request_id = request_id.decode("utf-8")
    if isinstance(event_id, six.binary_type):
        event_id = event_id.decode("utf-8")
    parent = f"projects/{project_id}/tenants/{tenant_id}"

    # The timestamp of the event as seconds of UTC time since Unix epoch
    # For more information on how to create google.protobuf.Timestamps
    # See:
    # https://github.com/protocolbuffers/protobuf/blob/master/src/google/protobuf/timestamp.proto
    seconds = 0
    create_time = {"seconds": seconds}

    # The type of event attributed to the behavior of the end user
    type_ = enums.JobEvent.JobEventType.VIEW

    # List of job names associated with this event
    jobs_element = "projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]"
    jobs_element_2 = "projects/[Project ID]/tenants/[Tenant ID]/jobs/[Job ID]"
    jobs = [jobs_element, jobs_element_2]
    job_event = {"type": type_, "jobs": jobs}
    client_event = {
        "request_id": request_id,
        "event_id": event_id,
        "create_time": create_time,
        "job_event": job_event,
    }

    response = client.create_client_event(parent=parent, client_event=client_event)
    print(response)

活动消息

必填字段:

  • eventId(客户定义):发送到 Cloud Talent Solution 的每条消息都必须具有唯一的 eventId。最佳做法是在定义此字段时合并时间戳,以确保不重复。该字段的最大长度为 255 个字符。

  • requestId:搜索响应对象返回的 requestId 的值。这个值对于特定 SearchJobsRequest API 调用是唯一的。它用于源自原始搜索 IMPRESSION 事件的所有后续消息。在进行新的 SearchJobsRequest API 调用时(例如:求职者转到结果的下一页),requestId 会发生变化。

  • createTime:事件的时间戳(格式为 Timestamp),精确到纳秒。此时间戳应体现事件实际发生的时间,而非消息发送的时间。

  • 联合字段 eventjobEvent 对象与职位搜索功能一起使用,并在求职者与服务交互时发出。

事件消息示例:

以上代码示例中的 API 调用应生成以下格式的 JSON 消息:

JSON

{
  "requestId": string,
  "eventId": string,
  "createTime": string,
  "eventNotes": string,

// Union field event can be only be a jobEvent: "jobEvent": { object (JobEvent) }, // End of list of possible types for union field event. }

场景和工作流

下面两个示例展示了求职者搜索、查看和申请职位的场景。

工作流 1

  1. 求职者执行搜索。 例如:Product mgr SF

    系统将搜索结果返回给求职者。

    发送回客户服务器的招聘信息搜索响应对象包含唯一的 requestId(例如:8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==)。将此 requestId 用于未来与此特定 SearchJobsRequest API 调用相关的所有消息。

    向 Cloud Talent Solution 发送一条 IMPRESSION 消息。

    事件消息示例:

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID1",
      "createTime": "2018-12-19T16:39:57-08:00",
      "jobEvent":
      {"type":"IMPRESSION",
      "jobs":["jobs/4000000000", "jobs/4000000001","jobs/4000000002",
      "jobs/4000000003", "jobs/4000000004"]}
    }
    
  2. 求职者选择一个结果(招聘信息),以查看招聘信息的完整详情。

    向 Cloud Talent Solution 发送一条 VIEW 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID2",
      "createTime": "2018-12-19T16:40:57-08:00",
      "jobEvent":
      {"type":"VIEW",
      "jobs":["jobs/4000000000"]}
    
    }
    
  3. 求职者申请所查看的职位。

    a. 如果系统将求职者重定向到相同域内的一个网页(内部申请页面),则向 Cloud Talent Solution 发送一条 APPLICATION_START 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID3",
      "createTime": "2018-12-19T16:41:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_START",
    "jobs":["jobs/4000000000"]}
    }
    

    b. 如果求职者被重定向到外部申请页面,则向 Cloud Talent Solution 发送一条 APPLICATION_REDIRECT 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID3",
      "createTime": "2018-12-19T16:41:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_REDIRECT",
      "jobs":["jobs/4000000000"]}
    
    }
    
  4. 求职者完成内部申请后,向 Cloud Talent Solution 发送一条 APPLICATION_FINISH 消息:

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID4",
      "createTime": "2018-12-19T16:43:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_FINISH",
      "jobs":["jobs/4000000000"]}
    
    }
    
  5. 求职者返回搜索结果并继续至第 2 页(或者他们继续至第 2 页,而未点击招聘信息帖子)。

    向 Cloud Talent Solution 发送一条 IMPRESSION 消息,其中包含来自第 2 页的下一组结果。注意:在 SearchJobsRequest API 调用的响应中生成了一个新的 requestId,该响应会生成结果的第二页。(例如:99e5b99c-f1ba-4f85-b17d-ccf878f451f9:APAb7IRESj+/Hzwa3bBd54P3qPx2yOWm5w==)。

    {
      "requestId": "99e5b99c-f1ba-4f85-b17d-ccf878f451f9:APAb7IRESj+/Hzwa3bBd54P3qPx2yOWm5w==",
      "eventId": "ID5",
      "createTime": "2018-12-19T18:39:57-08:00",
      "jobEvent":
      {"type":"IMPRESSION",
      "jobs":["jobs/4000000005", "jobs/4000000006","jobs/4000000007",
      "jobs/4000000008", "jobs/4000000009"]}
    }
    
  6. 求职者继续浏览搜索结果的第 3 页内容。

    向 Cloud Talent Solution 发送一条 IMPRESSION 消息,提供下一组结果。注意:此时生成了新的 requestId(例如 e2d2b916-78c3-4c65-aecc-d8452bc0afb0:APAb7IRvCsNPiRXYkgF8PN5e8BkbFzKOyg==)。

    {
      "requestId": "e2d2b916-78c3-4c65-aecc-d8452bc0afb0:APAb7IRvCsNPiRXYkgF8PN5e8BkbFzKOyg==",
      "eventId": "ID6",
      "createTime": "2018-12-19T16:41:57-08:00",
      "jobEvent":
      {"type":"IMPRESSION",
      "jobs":["jobs/4000000010", "jobs/4000000011","jobs/4000000012",
      "jobs/400000013", "jobs/4000000014"]}
    }
    

工作流 2

  1. 求职者执行搜索。 例如:Product mgr SF

    系统将搜索结果返回给求职者。

    职位搜索响应对象包含唯一的 requestId(例如:a2179a9b-cf73-413e-8076-98af08b991ad)。此 requestId 用于未来与此 SearchJobsRequest API 调用相关的所有的消息。

    向 Cloud Talent Solution 发送一条 IMPRESSION 消息。

    {
      "requestId": "a2179a9b-cf73-413e-8076-98af08b991ad",
      "eventId": "ID1",
      "createTime": "2018-12-19T16:39:57-08:00",
      "jobEvent":
      {"type":"IMPRESSION",
      "jobs":["jobs/4000000000", "jobs/4000000001","jobs/4000000002",
      "jobs/4000000003", "jobs/4000000004"]}
    }
    
  2. 求职者选择一个结果(招聘信息),以查看招聘信息的完整详情。

    向 Cloud Talent Solution 发送一条 VIEW 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID2",
      "createTime": "2018-12-19T16:40:57-08:00",
      "jobEvent":
      {"type":"VIEW",
      "jobs":["jobs/4000000000"]}
    }
    
  3. 求职者通过点击,申请一个职位,如 APPLICATION_QUICK_SUBMISSION 中所述。

    向 Cloud Talent Solution 发送一条 APPLICATION_QUICK_SUBMISSION 消息,提供下一组结果。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID3",
      "createTime": "2018-12-19T16:41:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_QUICK_SUBMISSION",
      "jobs":["jobs/4000000000"]}
     }
    
  4. 求职者执行以下操作。

    a.求职者返回搜索结果,直接通过搜索结果页面来申请职位。申请流程比 APPLICATION_QUICK_SUBMISSION 中定义的流程更长(也就是说,此为多步骤申请流程)。

    向 Cloud Talent Solution 发送一条 APPLICATION_START_FROM_SERP 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID4",
      "createTime": "2018-12-19T16:43:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_START_FROM_SERP",
      "jobs":["jobs/4000000000"]}
    }
    

    b. 求职者完成职位申请。 向 Cloud Talent Solution 发送一条 APPLICATION_FINISH 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID5",
      "createTime": "2018-12-19T16:44:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_FINISH",
      "jobs":["jobs/4000000000"]}
    }
    
  5. 求职者返回搜索结果,并直接通过搜索结果页面来申请职位。申请流程将求职者重定向到租户站点以外的另外一个域(外部申请),系统无法跟踪申请者在该域中的申请进度。

    向 Cloud Talent Solution 发送一条 APPLICATION_REDIRECT_FROM_SERP 消息。

    {
      "requestId": "8d2bdd5d-1361-42a5-a0fd-bd2b58b7d8fb:APAb7ISd4Sc5faibw2V5hTU/OoC2WAW5AA==",
      "eventId": "ID6",
      "createTime": "2018-12-19T16:45:57-08:00",
      "jobEvent":
      {"type":"APPLICATION_START_FROM_SERP",
      "jobs":["jobs/4000000001"]}
    }
    

    使用 APPLICATION_REDIRECT 时,求职者重新路由后处于招聘信息描述页面上,而本例不同于这种情况。

验证客户端事件实现

Cloud Talent Solution 为您提供了自助服务工具,可用于验证客户端事件的实现。如需详细了解可用的自助服务选项,请参阅管理工具