class_docstr: This class partitions the dataset into chains of conversations.
  Each chain is comprised of a list of conversation rounds.
  Each round within a conversation is represented as a triplet:
   (system, prompt, answer).
  
  The resulting structure of the chains is conditional on
  the DataFrame's structure and configuration:
  
  - Without a 'parent_id' in the DataFrame, each conversation chain is a single round.
   So, for every `i`-th row in the DataFrame, 0 <= `i` < len(df),
   the chain would look like: [(system_i, prompt_i, answer_i)]
  
  - With a 'parent_id' in the DataFrame and
    if `cfg.dataset.limit_chained_samples` is set to False,
    each chain encapsulates all preceding conversations
    for every `i`-th row in the DataFrame,
    0 <= `i` < len(df).
    The resultant chain would take shape:
        [(system_start_conversation_i,
          prompt_start_conversation_i,
          answer_start_conversation_i),
         ...,
         (system_i, prompt_i, answer_i)]
  
  - With a 'parent_id' in the DataFrame and
    if `cfg.dataset.limit_chained_samples` is set to True,
    each conversation chain incorporates only full conversations.
    The chain hence condenses into:
        [(system_start_conversation_i,
          prompt_start_conversation_i,
          answer_start_conversation_i),
         ...,
        (system_end_conversation_i,
         prompt_end_conversation_i,
         answer_end_conversation_i)]
    where `i` represents complete conversations only.
class_docstr_tok: ["This","class","partitions","the","dataset","into","chains","of","conversations",".","Each","chain","is","comprised","of","a","list","of","conversation","rounds",".","Each","round","within","a","conversation","is","represented","as","a","triplet",":","(","system",",","prompt",",","answer",")",".","The","resulting","structure","of","the","chains","is","conditional","on","the","DataFrame","'s","structure","and","configuration",":","-","Without","a","'parent_id","'","in","the","DataFrame",",","each","conversation","chain","is","a","single","round",".","So",",","for","every","`","i","`","-th","row","in","the","DataFrame",",","0","<","=","`","i","`","<","len","(","df",")",",","the","chain","would","look","like",":","[","(","system_i",",","prompt_i",",","answer_i",")","]","-","With","a","'parent_id","'","in","the","DataFrame","and","if","`","cfg.dataset.limit_chained_samples","`","is","set","to","False",",","each","chain","encapsulates","all","preceding","conversations","for","every","`","i","`","-th","row","in","the","DataFrame",",","0","<","=","`","i","`","<","len","(","df",")",".","The","resultant","chain","would","take","shape",":","[","(","system_start_conversation_i",",","prompt_start_conversation_i",",","answer_start_conversation_i",")",",","...",",","(","system_i",",","prompt_i",",","answer_i",")","]","-","With","a","'parent_id","'","in","the","DataFrame","and","if","`","cfg.dataset.limit_chained_samples","`","is","set","to","True",",","each","conversation","chain","incorporates","only","full","conversations",".","The","chain","hence","condenses","into",":","[","(","system_start_conversation_i",",","prompt_start_conversation_i",",","answer_start_conversation_i",")",",","...",",","(","system_end_conversation_i",",","prompt_end_conversation_i",",","answer_end_conversation_i",")","]","where","`","i","`","represents","complete","conversations","only","."]
docstr: Gets the conversation chain for a given starting conversation ID.
  Args:
      id2parent_id: A dictionary containing the mapping of IDs
      to its previous parent ID.
      end_id: The ID of the end of the conversation in the chain.
  Returns:
      A list of conversation IDs representing the conversation chain.
      The chain is ordered from the first conversation id to end_id in the chain.
docstr_tok: ["Gets","the","conversation","chain","for","a","given","starting","conversation","ID",".","Args",":","id2parent_id",":","A","dictionary","containing","the","mapping","of","IDs","to","its","previous","parent","ID",".","end_id",":","The","ID","of","the","end","of","the","conversation","in","the","chain",".","Returns",":","A","list","of","conversation","IDs","representing","the","conversation","chain",".","The","chain","is","ordered","from","the","first","conversation","id","to","end_id","in","the","chain","."]
code: def get_conversation_ids(id2parent_id, end_id):
      """
      Gets the conversation chain for a given starting conversation ID.
      Args:
          id2parent_id: A dictionary containing the mapping of IDs
          to its previous parent ID.
          end_id: The ID of the end of the conversation in the chain.
      Returns:
          A list of conversation IDs representing the conversation chain.
          The chain is ordered from the first conversation id to end_id in the chain.
      """
      # prevent infinite loops in case
      # of circular parent chains (dataframe issue)
      loop_counter = 0
  
      conversation_chain_ids = [end_id]
      parent_id = end_id
      while parent_id in id2parent_id:
          loop_counter += 1
  
          parent_id = id2parent_id[parent_id]
          conversation_chain_ids = [parent_id] + conversation_chain_ids
          if loop_counter > 1000:
              raise ValueError(
                  f"Parent chain of sample with idx {end_id} "
                  f"exceeds max loop count of 1000. "
                  f"Please ensure that parent chain is not circular."
              )
      return conversation_chain_ids
  
file_path: h2o-llmstudio/llm_studio/src/datasets/conversation_chain_handler.py
imports: import logging
  from typing import Dict, List
  import numpy
  from llm_studio.src.datasets.text_utils import get_texts
  from llm_studio.src.utils.utils import PatchedAttribute
label_desc: Use image node_id 5 for calling the ConversationChainHandler obj's underlying member method code with example usage: obj.get_conversation_ids(id2parent_id, end_id) and returns: conversation_chain_ids