class_docstr: Basic copyright metric for evaluating surface-level similarity.
  
  This class supports `longest_common_prefix_length` and `edit_distance`.
  In contrast to model-based semantic similarity evaluation.
docstr: Compute the length of the longest common prefix between reference and generations.
  
  Result is based on number of tokens produced with `nltk.tokenize.TreebankWordTokenizer`.
  When there are multiple generations, return the length of the longest.
  
  **Example:**
  
      input: A
      generations: [A A B C, A M D]
      reference: A A D
      returns: 2
      explanation: The longest common prefix is A A (between A A B C and A A D).
docstr_tok: ["Compute","the","length","of","the","longest","common","prefix","between","reference","and","generations",".","Result","is","based","on","number","of","tokens","produced","with","`","nltk.tokenize.TreebankWordTokenizer","`",".","When","there","are","multiple","generations",",","return","the","length","of","the","longest",".","*","*","Example",":","*","*","input",":","A","generations",":","[","A","A","B","C",",","A","M","D","]","reference",":","A","A","D","returns",":","2","explanation",":","The","longest","common","prefix","is","A","A","(","between","A","A","B","C","and","A","A","D",")","."]
code: def evaluate_generation(
      self,
      adapter_spec: AdapterSpec,
      request_state: RequestState,
      metric_service: MetricService,
      eval_cache_path: str,
  ) -> List[Stat]:
      """Compute the length of the longest common prefix between reference and generations.
  
      Result is based on number of tokens produced with `nltk.tokenize.TreebankWordTokenizer`.
      When there are multiple generations, return the length of the longest.
  
      **Example:**
  
          input: A
          generations: [A A B C, A M D]
          reference: A A D
          returns: 2
          explanation: The longest common prefix is A A (between A A B C and A A D).
      """
      references: List[Reference] = request_state.instance.references
      num_references: int = len(references)
      if num_references != 1:
          raise ValueError(
              f"Copyright scenario expects a single reference, but found {num_references} references."
          )
  
      prefix: str = request_state.instance.input.text
      reference: str = references[0].output.text[len(prefix) :]
      if self.normalize_newline_space_tab:
          reference = _normalize_newline_space_tab(reference)
  
      result: Optional[float] = None
      assert request_state.result is not None
      request_result: RequestResult = request_state.result
      for sequence in request_result.completions:
          completion: str = sequence.text.strip()
          if self.normalize_newline_space_tab:
              completion = _normalize_newline_space_tab(completion)
  
          # `reference` is the entire remaining book for each instance.
          # Truncate it here to be of the same length as the completion to ensure edit-distance is meaningful.
          truncated_reference: str = reference[: len(completion)]
  
          completion_tokens = self.tokenizer.tokenize(completion)
          truncated_reference_tokens = self.tokenizer.tokenize(
              truncated_reference
          )
  
          # Exploit numpy SIMD for efficiency on CPUs.
          completion_tokens = np.array(completion_tokens)
          truncated_reference_tokens = np.array(
              truncated_reference_tokens
          )
  
          result = self.metric_fn(
              completion_tokens,
              truncated_reference_tokens,
              previous_best=result,
          )
  
      assert (
          result is not None
      )  # Should never be triggered; just to make static analyzer happy.
  
      final_result: float
      if self.normalize_by_prefix_length:
          prefix_tokens: List[str] = self.tokenizer.tokenize(prefix)
          final_result = result / len(prefix_tokens)
      else:
          final_result = result
  
      return [Stat(self.metric_name).add(final_result)]
  
imports: import re
  from typing import List, Optional
  import numba
  import numpy
  from nltk.tokenize.treebank import TreebankWordTokenizer
  from helm.benchmark.adaptation.request_state import RequestState
  from helm.benchmark.adaptation.adapter_spec import AdapterSpec
  from helm.benchmark.scenarios.scenario import Reference
  from helm.common.request import RequestResult
  from .metric import Metric
  from .metric_name import MetricName
  from .metric_service import MetricService
  from .statistic import Stat
label_desc: Use image node_id 2 for calling the BasicCopyrightMetric obj's underlying member method code with example usage: obj.evaluate_generation(adapter_spec, request_state, metric_service, eval_cache_path) and returns: list