Skip to content

Commit

Permalink
H-2205, H-2354: Implement multi-type entities in the graph (#4140)
Browse files Browse the repository at this point in the history
  • Loading branch information
TimDiekmann authored Mar 12, 2024
1 parent a984764 commit fd4d46f
Show file tree
Hide file tree
Showing 41 changed files with 500 additions and 336 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions apps/hash-ai-worker-ts/src/activities/infer-entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import {
zeroedGraphResolveDepths,
} from "@local/hash-isomorphic-utils/graph-queries";
import { systemLinkEntityTypes } from "@local/hash-isomorphic-utils/ontology-type-ids";
import type { AccountId, Subgraph, Timestamp } from "@local/hash-subgraph";
import type { AccountId, Timestamp } from "@local/hash-subgraph";
import { mapGraphApiSubgraphToSubgraph } from "@local/hash-subgraph/stdlib";
import { StatusCode } from "@local/status";
import { CancelledFailure, Context } from "@temporalio/activity";
import dedent from "dedent";
Expand Down Expand Up @@ -269,7 +270,7 @@ const inferEntities = async ({
for (const entityTypeId of entityTypeIds) {
entityTypes[entityTypeId] = dereferenceEntityType(
entityTypeId,
entityTypesSubgraph as Subgraph,
mapGraphApiSubgraphToSubgraph(entityTypesSubgraph),
);
}
} catch (err) {
Expand Down Expand Up @@ -555,10 +556,11 @@ export const inferEntitiesActivity = async ({
draft: false,
properties: {},
ownedById: userAuthenticationInfo.actorId,
entityTypeId:
entityTypeIds: [
entityResult.operation === "create"
? systemLinkEntityTypes.created.linkEntityTypeId
: systemLinkEntityTypes.updated.linkEntityTypeId,
],
linkData: {
leftEntityId: usageRecordMetadata.recordId.entityId,
rightEntityId: entityResult.entity.metadata.recordId.entityId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Subgraph as ApiClientSubgraph } from "@local/hash-graph-client";
import type { Subgraph } from "@local/hash-subgraph";
import { mapGraphApiVerticesToVertices } from "@local/hash-subgraph/stdlib";

import { dereferenceEntityType } from "./dereference-entity-type";

Expand Down Expand Up @@ -981,7 +982,10 @@ describe("The dereferenceEntityType function", () => {
it("correctly dereferences an entity type", () => {
const result = dereferenceEntityType(
"https://hash.ai/@test/types/entity-type/property-values-demo/v/4",
testSubgraph as Subgraph,
{
...testSubgraph,
vertices: mapGraphApiVerticesToVertices(testSubgraph.vertices),
} as Subgraph,
);

expect(result).toEqual(expectedResult);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { VersionedUrl } from "@blockprotocol/type-system/slim";
import type { Entity } from "@local/hash-graph-client";
import type {
InferenceTokenUsage,
InferredEntityChangeResult,
ProposedEntity,
} from "@local/hash-isomorphic-utils/ai-inference-types";
import type { Entity } from "@local/hash-subgraph";
import type OpenAI from "openai";

import type { DereferencedEntityType } from "./dereference-entity-type";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { typedEntries } from "@local/advanced-types/typed-entries";
import type {
AllFilter,
CosineDistanceFilter,
Entity,
GraphApi,
} from "@local/hash-graph-client";
import type {
Expand All @@ -15,8 +14,7 @@ import { generateVersionedUrlMatchingFilter } from "@local/hash-isomorphic-utils
import type {
AccountId,
BaseUrl,
Entity as BrandedEntity,
EntityId,
Entity,
LinkData,
OwnedById,
} from "@local/hash-subgraph";
Expand Down Expand Up @@ -301,7 +299,7 @@ export const createEntities = async ({
internalEntityStatusMap.unchangedEntities[
proposedEntity.entityId
] = {
entity: existingEntity as BrandedEntity,
entity: existingEntity,
entityTypeId,
operation: "already-exists-as-proposed",
proposedEntity,
Expand All @@ -313,15 +311,15 @@ export const createEntities = async ({

try {
await graphApiClient.validateEntity(actorId, {
entityType: entityTypeId,
entityTypes: [entityTypeId],
profile: createAsDraft ? "draft" : "full",
properties,
});

const { data: createdEntityMetadata } =
await graphApiClient.createEntity(actorId, {
draft: createAsDraft,
entityTypeId,
entityTypeIds: [entityTypeId],
ownedById,
properties,
relationships: [
Expand Down Expand Up @@ -495,13 +493,13 @@ export const createEntities = async ({
}

const linkData: LinkData = {
leftEntityId: sourceEntity.metadata.recordId.entityId as EntityId,
rightEntityId: targetEntity.metadata.recordId.entityId as EntityId,
leftEntityId: sourceEntity.metadata.recordId.entityId,
rightEntityId: targetEntity.metadata.recordId.entityId,
};

try {
await graphApiClient.validateEntity(actorId, {
entityType: entityTypeId,
entityTypes: [entityTypeId],
profile: createAsDraft ? "draft" : "full",
properties,
linkData,
Expand Down Expand Up @@ -589,7 +587,7 @@ export const createEntities = async ({
const { data: createdEntityMetadata } =
await graphApiClient.createEntity(actorId, {
draft: createAsDraft,
entityTypeId,
entityTypeIds: [entityTypeId],
linkData,
ownedById,
properties,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const updateEntities = async ({
);

await graphApiClient.validateEntity(actorId, {
entityType: entityTypeId,
entityTypes: [entityTypeId],
profile: draft ? "draft" : "full",
properties,
linkData: existingEntity.linkData,
Expand All @@ -127,7 +127,7 @@ export const updateEntities = async ({
await graphApiClient.updateEntity(actorId, {
archived: existingEntity.metadata.archived,
draft,
entityTypeId,
entityTypeIds: [entityTypeId],
entityId: updateEntityId,
properties: newProperties,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const parseTextFromFile = async (

await graphApiClient.updateEntity(webMachineActorId, {
entityId: fileEntity.metadata.recordId.entityId,
entityTypeId: fileEntity.metadata.entityTypeId,
entityTypeIds: [fileEntity.metadata.entityTypeId],
properties: updatedProperties,
archived: fileEntity.metadata.archived,
draft:
Expand Down
58 changes: 23 additions & 35 deletions apps/hash-api/src/graph/knowledge/primitive/entity.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { VersionedUrl } from "@blockprotocol/type-system";
import { typedEntries, typedKeys } from "@local/advanced-types/typed-entries";
import {
EntityMetadata,
EntityPermission,
EntityStructuralQuery,
EntityType,
Filter,
GraphResolveDepths,
ModifyRelationshipOperation,
Expand All @@ -27,7 +28,6 @@ import {
Entity,
EntityAuthorizationRelationship,
EntityId,
EntityMetadata,
EntityPropertiesObject,
EntityRelationAndSubject,
EntityRootType,
Expand All @@ -42,6 +42,7 @@ import {
} from "@local/hash-subgraph";
import {
getRoots,
mapGraphApiEntityMetadataToMetadata,
mapGraphApiSubgraphToSubgraph,
} from "@local/hash-subgraph/stdlib";
import { LinkEntity } from "@local/hash-subgraph/type-system-patch";
Expand Down Expand Up @@ -119,14 +120,17 @@ export const createEntity: ImpureGraphFunction<

const { data: metadata } = await graphApi.createEntity(actorId, {
ownedById,
entityTypeId,
entityTypeIds: [entityTypeId],
properties,
entityUuid: overrideEntityUuid,
draft,
relationships: params.relationships,
});

const entity = { properties, metadata: metadata as EntityMetadata };
const entity = {
properties,
metadata: mapGraphApiEntityMetadataToMetadata(metadata),
};

for (const createOutgoingLinkParams of outgoingLinks ?? []) {
await createLinkEntity(context, authentication, {
Expand Down Expand Up @@ -199,29 +203,25 @@ export const getEntities: ImpureGraphFunction<
return await graphApi
.getEntitiesByQuery(actorId, { query })
.then(({ data }) => {
const subgraph = mapGraphApiSubgraphToSubgraph<EntityRootType>(
data.subgraph,
);
// filter archived entities from the vertices until we implement archival by timestamp, not flag: remove after H-349
for (const [entityId, editionMap] of Object.entries(
data.subgraph.vertices,
)) {
const latestEditionTimestamp = Object.keys(editionMap).sort().pop();
for (const [entityId, editionMap] of typedEntries(subgraph.vertices)) {
const latestEditionTimestamp = typedKeys(editionMap).sort().pop()!;

if (
(
editionMap[latestEditionTimestamp!]!.inner
.metadata as EntityMetadata
).archived &&
// @ts-expect-error - The subgraph vertices are entity vertices so `Timestamp` is the correct type to get
// the latest revision
(editionMap[latestEditionTimestamp]!.inner.metadata as EntityMetadata)
.archived &&
// if the vertex is in the roots of the query, then it is intentionally included
!data.subgraph.roots.find((root) => root.baseId === entityId)
!subgraph.roots.find((root) => root.baseId === entityId)
) {
// eslint-disable-next-line no-param-reassign -- temporary hack
delete data.subgraph.vertices[entityId];
delete subgraph.vertices[entityId];
}
}

const subgraph = mapGraphApiSubgraphToSubgraph<EntityRootType>(
data.subgraph,
);

return subgraph;
});
};
Expand Down Expand Up @@ -487,7 +487,7 @@ export const updateEntity: ImpureGraphFunction<
*
* @see https://app.asana.com/0/1201095311341924/1203285029221330/f
* */
entityTypeId: entityTypeId ?? entity.metadata.entityTypeId,
entityTypeIds: [entityTypeId ?? entity.metadata.entityTypeId],
archived: entity.metadata.archived,
draft:
params.draft ??
Expand All @@ -508,7 +508,7 @@ export const updateEntity: ImpureGraphFunction<

return {
...entity,
metadata: metadata as EntityMetadata,
metadata: mapGraphApiEntityMetadataToMetadata(metadata),
properties,
};
};
Expand All @@ -529,7 +529,7 @@ export const archiveEntity: ImpureGraphFunction<
* @see https://app.asana.com/0/1201095311341924/1203285029221330/f
* */
draft: !!extractDraftIdFromEntityId(entity.metadata.recordId.entityId),
entityTypeId: entity.metadata.entityTypeId,
entityTypeIds: [entity.metadata.entityTypeId],
properties: entity.properties,
});
};
Expand All @@ -550,7 +550,7 @@ export const unarchiveEntity: ImpureGraphFunction<
* */
archived: false,
draft: !!extractDraftIdFromEntityId(entity.metadata.recordId.entityId),
entityTypeId: entity.metadata.entityTypeId,
entityTypeIds: [entity.metadata.entityTypeId],
properties: entity.properties,
});
};
Expand Down Expand Up @@ -1008,15 +1008,3 @@ export const getEntityAuthorizationRelationships: ImpureGraphFunction<
}) as EntityAuthorizationRelationship,
),
);

export const validateEntity: ImpureGraphFunction<
{
entityType: VersionedUrl | EntityType;
properties: Entity["properties"];
linkData?: Entity["linkData"];
profile: "draft" | "full";
},
Promise<void>
> = async ({ graphApi }, { actorId }, params) => {
await graphApi.validateEntity(actorId, params);
};
10 changes: 5 additions & 5 deletions apps/hash-api/src/graph/knowledge/primitive/link-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import {
AccountId,
Entity,
EntityId,
EntityMetadata,
EntityPropertiesObject,
EntityRelationAndSubject,
extractDraftIdFromEntityId,
LinkData,
OwnedById,
} from "@local/hash-subgraph";
import { mapGraphApiEntityMetadataToMetadata } from "@local/hash-subgraph/stdlib";
import { LinkEntity } from "@local/hash-subgraph/type-system-patch";

import { ImpureGraphFunction } from "../../context-types";
Expand Down Expand Up @@ -95,15 +95,15 @@ export const createLinkEntity: ImpureGraphFunction<
{
ownedById,
linkData,
entityTypeId: linkEntityType.schema.$id,
entityTypeIds: [linkEntityType.schema.$id],
properties,
draft,
relationships: params.relationships,
},
);

const linkEntity = {
metadata: metadata as EntityMetadata,
metadata: mapGraphApiEntityMetadataToMetadata(metadata),
properties,
linkData,
};
Expand Down Expand Up @@ -146,7 +146,7 @@ export const updateLinkEntity: ImpureGraphFunction<

const { data: metadata } = await graphApi.updateEntity(actorId, {
entityId: linkEntity.metadata.recordId.entityId,
entityTypeId: linkEntity.metadata.entityTypeId,
entityTypeIds: [linkEntity.metadata.entityTypeId],
properties,
archived: linkEntity.metadata.archived,
draft:
Expand All @@ -157,7 +157,7 @@ export const updateLinkEntity: ImpureGraphFunction<
});

return {
metadata: metadata as EntityMetadata,
metadata: mapGraphApiEntityMetadataToMetadata(metadata),
properties,
linkData: {
...linkEntity.linkData,
Expand Down
6 changes: 3 additions & 3 deletions apps/hash-graph/libs/api/src/rest/entity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ where
struct UpdateEntityRequest {
properties: EntityProperties,
entity_id: EntityId,
entity_type_id: VersionedUrl,
entity_type_ids: Vec<VersionedUrl>,
#[serde(flatten)]
order: EntityLinkOrder,
archived: bool,
Expand Down Expand Up @@ -507,7 +507,7 @@ where
let Json(UpdateEntityRequest {
properties,
entity_id,
entity_type_id,
entity_type_ids,
order: link_order,
archived,
draft,
Expand All @@ -528,7 +528,7 @@ where
UpdateEntityParams {
entity_id,
decision_time,
entity_type_id,
entity_type_ids,
properties,
link_order,
archived,
Expand Down
Loading

0 comments on commit fd4d46f

Please sign in to comment.