Constructing a deep related item schema for rvt_element_props
A SchemaDefinition describes the properties of the project's collections and their related items in the Item Service. An agent with RelatedQueryTool uses this when constructing a query.
Related Items are described in the _itemTypes array and a schema is generated for each collection by analyzing its first related item. While in most cases this property description is sufficient, each Related Item in the rvt_element_props collection has varying and inconsistant properties: for the purposes of an Agent being able to query any property based on a user prompt, this requires a more in-depth schema which describes all possible properties.
-
Find the element props related item schema in the
_itemTypesarray. By default its generated_typeNameproperty isRevitElementProps.const elemPropsItemType = generatedSchemaDef._itemTypes.find((it) => it._typeName === "RevitElementProps"); -
Nest the new property descriptions in
<myItemType>._properties.properties._propertiesusing a formatting function you create, such asformatElemPropsItemTypein this case.const updatedElemsPropsItemType = {...elemPropsItemType,_properties: {...elemPropsItemType._properties,properties: {...elemPropsItemType._properties.properties,_properties: {...await formatElemPropsItemType(PlatformApi, ctx)}}}}; -
Constructs a schema for each distinct property.
formatElemPropsItemTypetakes all the distinct element properties, then constructs a schema for each one.First, it gets the
rvt_element_propscollection's related items usingIafItemSvc.getRelatedItems:const formatElemPropsItemType = async (PlatformApi, ctx) => {const { IafItemSvc } = PlatformApi;const elemPropsCollection = await IafItemSvc.getNamedUserItems({query: { _userType: "rvt_element_props" }},ctx,undefined);const relatedItems = await IafItemSvc.getRelatedItems(elemPropsCollection._list[0]._userItemId,undefined,ctx,undefined);...}It reduces the related items to an object with unique properties only:
const uniqueProperties = {};if (relatedItems && Array.isArray(relatedItems._list)) {relatedItems._list.forEach(item => {if (item && item.properties && typeof item.properties === 'object') {Object.entries(item.properties).forEach(([propName, propValue]) => {if (!(propName in uniqueProperties)) {uniqueProperties[propName] = propValue;}});}});}console.log(`Found ${Object.keys(uniqueProperties).length} unique properties.`);It creates a schema definition for each property with the following structure:
{"myProp": {"_type": "object","_properties": {"<nestedPropName>": {"_type": "<type>"}}}}For more information, see the following schema for the Building Story property and its nested properties:
"Building Story": {"_type": "object","_properties": {"val": {"_type": "boolean"},"name": {"_type": "string"},"dName": {"_type": "string"},"id": {"_type": "number"}}},The following code constructs a this schema for each property in the
uniquePropertiesobject:const schema = {};for (const [propName, propObj] of Object.entries(uniqueProperties)) {schema[propName] = {_type: "object",_properties: {}};for (const [key, val] of Object.entries(propObj)) {schema[propName]._properties[key] = {_type: inferPropType(val) //uses simple typeof logic};}}return schema; -
Update the schema definition using
IafItemSvc.updateSchemaDefinitionsPartial://Post the update to the Item Serviceconst updatedSchemaDef = await IafItemSvc.updateSchemaDefinitionsPartial({_itemTypes: [...itemTypes.filter(it =>it._typeName !== updatedElemsPropsItemType._typeName),updatedElemsPropsItemType]},ctx,undefined);
Mapping collections to updated schema
Note: For a single model project, you can map the NamedUserCollections here once and for all; for multi-model support, this mapping occurs dynamically and must be done each time the current model changes. For more information, see [].
You must update each Named User Collection you want an LLM to query by adding the itemType name to the collection's _itemTypes array.
-
Get the collections you want to update, which in this case are the
"rvt_elements","rvt_element_props","rvt_type_elements"collections.// get all element collectionslet userColls = await IafItemSvc.getNamedUserItems({ query: {_userType: { $in: ["rvt_elements", "rvt_element_props", "rvt_type_elements"]}}},ctx,undefined);userColls = userColls._list;const rvtElementsColl = userColls.find(col => col._userType === "rvt_elements");const rvtElementPropsColl = userColls.find(col => col._userType === "rvt_element_props");const rvtTypeElemsColl = userColls.find(col => col._userType === "rvt_type_elements");
Update each collection with its relevant itemType name from the SchemaDefinition:
rvtElementsColl._itemTypes = ["RevitElement"];
rvtElementPropsColl._itemTypes = ["RevitElementProps"];
rvtTypeElemsColl._itemTypes = ["RevitTypeElement"];
const rvtElements = await IafItemSvc.updateNamedUserItem(
rvtElementsColl,
ctx,
undefined
);
const rvtElementProps = await IafItemSvc.updateNamedUserItem(
rvtElementPropsColl,
ctx,
undefined
);
const rvtTypeElems = await IafItemSvc.updateNamedUserItem(
rvtTypeElemsColl,
ctx,
undefined
);