Billing Analytics: Post-Bill

Overwhelmed by the Outside Counsel invoices?

Many corporations and law firms are overwhelmed by the volume of invoices they receive from their outside counsel or local counsel. These invoices can be hundreds of pages long, difficult to read and understand, and contain a wide variety of topics both relevant and irrelevant to basic billing questions. Under these circumstances, it can be practically impossible to keep up through manual review.

Luckily, the Kelvin Legal Data OS can help. Not only does Kelvin Billing support most common invoice formats and systems like LEDES and Aderant, but it also provides a suite of tools to help you perform common post-bill review and analytics tasks, including open-ended search, summarization, and question answering thanks to the Kelvin NLP module.

What does it look like?

We'll walk through a simple example of how Kelvin can be used to help a corporate legal department understand its outside counsel invoices. In this example, we'll use a fictional invoice based on The Simpsons with real UTBMS data in LEDES1998B format. We'll start by importing the Kelvin modules and loading the invoice:

# import the module
from kelvin.billing.sources.ledes.ledes_1998 import LEDES1998B

# load the invoice
invoice = LEDES1998B('data/invoice-001.txt')

Basic analytics

Let's start by looking at the timekeepers on the invoice, summarizing how many hours and dollars each timekeeper billed:

# iterate over timekeeper list
for tk_id, tk_data in invoice.iter_timekeeper_data():
    tk_hours = tk_data["LINE_ITEM_NUMBER_OF_UNITS"].sum()
    tk_billed = tk_data["LINE_ITEM_TOTAL"].sum()
    print(tk_id, tk_hours, tk_billed)

This will print out a list of timekeepers, the number of hours they billed, and the total amount billed for each timekeeper like this:

TimekeeperUnits (hours)Amount ($)
EK112.049,825.00
GW29.56,912.50
LS93.7563,087.50
...

We can also look at the total amount billed by each UTBMS code:

# iterate over UTBMS codes
for task_code_label, task_code_data in invoice.iter_task_code_data():
    task_hours = task_code_data["LINE_ITEM_NUMBER_OF_UNITS"].sum()
    task_billed = task_code_data["LINE_ITEM_TOTAL"].sum()
    print(task_code_label, task_hours, task_billed)

This will print out a list of UTBMS codes, the number of hours billed, and the total amount billed for each UTBMS code like this:

UTBMS CodeUnits (hours)Amount ($)
A1062.01,000.00
C10029.512,487.50
C20043.528,350.00
C30051.2525,775.00
C40039.021,400.00
...

Kelvin also includes rich support for UTBMS/ABA codes used to describe phases, tasks, activity, and expenses. For example, we can retrieve complete information about a specific UTBMS code like this:

# import Kelvin UTBMS/ABA code data
from kelvin.billing.coding.utbms.aba import get_utbms_code_data

# lookup a UTBMS code
task_code_data = get_task_code_data("L160")

Output:

{
  'category': 'L100',
  'code': 'L160',
  'label': 'Settlement/Non-Binding ADR',
  'definition': 'All activities directed specifically to settlement.
    Encompasses planning for and participating in settlement discussions,
    conferences, and hearings and implementing a settlement. Covers
    pursuing and participating in mediation and other non-binding
    Alternative Dispute Resolution (ADR) procedures. Also includes
    pre-litigation demand letters and ensuing discussions.',
  'type': 'Litigation'
}

Question answering

Kelvin makes it easy to calculate simple analytics like these, but that's not the interesting part. Kelvin also makes it easy to ask open-ended questions about the invoice and billing data using large language models like GPT-4. Let's take a look at an example of how this works.

Let's say we want to talk to one of our outside counsel resources about an information security issue that came up during a matter. We can ask our invoice data directly which timekeepers worked on this kind of task:

# import Kelvin NLP and Billing classes
from kelvin.nlp.llm.engines.openai_engine import OpenAIEngine
from kelvin.billing.

# setup an LLM engine
llm_gpt4 = OpenAIEngine(model="gpt-4")

# create a LEDES Matter Summarizer
summarizer = LEDESMatterSummarizer(llm_gpt4)
answer = summarizer.get_answer(
  invoice,
  "List any timekeepers who spent time on information security tasks."
)

Output:

Lisa Simpson, Ned Flanders, and Seymour Skinner.

Reasoning:
- Lisa Simpson's activity data shows 12.0 hours (35.6% of her time) spent on
"MF20 Data Security/Privacy/Data Protection/Cyber Security" for
Matter ID: 2022-LGL.

- Ned Flanders' activity data shows 60.0 hours (70.6% of his time) spent on
"MF20 Data Security/Privacy/Data Protection/Cyber Security" for Matter ID:
BURNS-SNP-3.

- Seymour Skinner's activity data shows 1.5 hours (10.0% of his time) spent
on "MF20 Data Security/Privacy/Data Protection/Cyber Security."

What’s next?

In this first part of our post-bill review, we've seen how Kelvin can help us understand the billing data in our LEDES invoices. In the next part of our post-bill review, we'll look at how law firms can integrate Kelvin Billing into systems like Aderant Expert for even richer historical analytics and understanding.