Skip to main content
Version: v5.1

Element selection

Element selection#

To select the elements in the model based on the LLM response

  1. Use the AiPrompt component's onResponse callback to catch the response.

      <PlatformProvider>    <AiPrompt         onResponse={({response, error }) => {          myCallback(response.message)      }}    />  </PlatformProvider>
  2. In a parent component, pass the response message to a handler function.

      <ModelElemChat    myCallback={(message) => {      extractEntities(message);    }}  />
  3. The extractEntities handler function completes the following steps: a. The function calls getModelElementsByLlmResponse.

    ```js  const extractEntities = async (message) => {    try {      const modelElemsToSelect = await aiChat.getModelElementsByLlmResponse(        message,        IafScriptEngine,         PlatformApi,        ctx      )      //hidden code    } catch (error) {      console.error('Error extracting entities:', error);    }  }```

    This script scrapes the response for source or object ids using regular expressions:

      async function getModelElementsByLlmResponse(llmResponse, IafScriptEngine, libraries, ctx) {    const sourceIdRegex = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}(?:-[0-9a-f]+)?\b/gi;    const objectIdRegex = /\b[a-f0-9]{24}\b/g;    let isSourceIds = false;    let fetchedIds;    if (!llmResponse) {      return;    }    let ids = Array.from(llmResponse.matchAll(sourceIdRegex), m => m[0]);    if (Array.isArray(ids)) {      if (ids.length === 0) {        ids = Array.from(llmResponse.matchAll(objectIdRegex), m => m[0]);        isSourceIds = false;      }      console.log("ids", ids);      if (ids.length > 0) fetchedIds = ids;    }    //hidden code  }

    The scraped ids are used to form a findWithRelated query that finds the elements by their id in the rvt_elements collection, then fetches their related properties and type information from the rvt_element_props and rvt_type_elements collections.

      let iaf_ext_elements_collection = IafScriptEngine.getVar(    "iaf_ext_elements_collection"  );  //determines to search by source id or object id  const parentQuery = isSourceIds    ? { source_id: { $in: fetchedIds } }    : { _id: { $in: fetchedIds } };    //constructs the query  const elemQuery = {    parent: {      query: parentQuery,      collectionDesc: {        _userType: "rvt_elements",        _userItemId: iaf_ext_elements_collection._userItemId,      },      options: {        page: {          _pageSize: 200,        },      },      sort: {        _id: 1,      },    },    related: [      {        relatedDesc: {          _relatedUserType: "rvt_type_elements",        },        as: "Revit Type Properties",      },      {        relatedDesc: {          _relatedUserType: "rvt_element_props",        },        as: "Revit Element Properties",      },    ],  }
      if (fetchedIds && fetchedIds.length > 0) {    let elements;    await IafScriptEngine.findWithRelated(elemQuery, ctx).then((res) => {      elements = res._list;    })    //hidden code  }

    Finally, the relavent data is mapped to construct an array of entities in the same manner as the getModelElements script which is used when fetching model elements by category and type. For more information, see Mapping elements.

    b. The resulting entities are passed to the onSetEntities callback:

      if (modelElemsToSelect && modelElemsToSelect.length > 0) {    onSetEntities(modelElemsToSelect);  }

    In the NavigatorView component, the entities are set in the props with this.props.setEntities:

      <div className="navigator-drawer-content-ai-chat">    <AiChatPane      onSetEntities={(entities) => {        this.props.setEntities({ entities: entities });      }}      ctx={{        _namespaces: this.props.selectedItems.selectedProject._namespaces      }}      onPaneExpanded={() => {        this.setState({           isChatDrawerExpanded: !this.state.isChatDrawerExpanded         });      }}    />  </div>