Analyze use case

You’ve just seen how to use the SDK to interact with the automate feature of AI Hub. Now learn how the SDK can drive the analyze feature.

Analyzing documents with an AI Hub conversation

In this use case you have a conversation with AI Hub about technical specifications for Airbus airplanes.

The terms file and document aren’t interchangeable!

A file is what you upload from your computer. It contains one or more documents. A document is the entity that you interact with during a conversation.

For example, a file called bank_info.pdf might contain an image of a driver’s license on the first page and a mortgage application on the second page. This one file contains two documents, and you could analyze just one or both of those documents within a conversation.

Each step of this workflow uses the SDK.

  1. Create a conversation that contains one file, where that file contains one document.

  2. Converse with a document by sending a question synchronously.

  3. Upload another single-document file to the conversation.

  4. Send a question asynchronously that requires AI Hub to look at both documents in the conversation.

  5. Wait until the conversation has an answer to your question.

  6. Retrieve and print the answer.

As with the last use case, this example starts with code that assumes everything works perfectly. It adds exception handling only after the basic flow works correctly.

GUI vs. SDK

When using AI to answer questions about documents, you’re probably used to using a GUI: type a prompt, get a response. While you can use AI Hub’s GUI to analyze documents this way, there are cases where it makes more sense to analyze documents programmatically with the SDK instead.

Imagine that you have thousands of medical documents, and you want to ask the same question about each document. For privacy reasons you can’t upload all the documents at the same time, so you upload one document, ask a question about it, and repeat the process many times. Manual repetition through the GUI becomes error-prone and time-consuming, but programmatic execution makes the task quick and reliable.

Or you might want to record the questions and answers from a conversation for analysis in another system. SDK-enabled programs make this easier to do than manually copying and pasting each interaction from the GUI.

Implementing the use case

1

Import and authorize the SDK

Just like for the automate use case, start your program by making the SDK available and configuring authorization details.

Enter this Python code into a text editor and save the file on your local computer with the filename analyze_with_sdk.py. As the tutorial introduces more code, add it to bottom of the same file.
1from aihub import AIHub
2
3client = AIHub(api_root="PASTE YOUR API ROOT HERE",
4 api_key="PASTE YOUR API KEY HERE",
5 ib_context="PASTE YOUR IB-CONTEXT HERE")
Remember to replace the three authorization placeholders with your own values.
2

Download files to analyze

Download two PDF files so you can upload them to the conversation later.



3

Create a conversation with one file

When you created a batch in the previous use case, you made the batch with one SDK operation, and you uploaded files to it with a separate SDK operation. Creating a conversation is different: you use a single SDK operation to create the conversation and upload files to it (although you can add more files later).

This example creates a conversation with a single file called A330_specs.pdf, which you downloaded earlier.

1create_conversation_resp = client.conversations.create(
2 name="Airbus conversation",
3 description="Analyze Airbus technical specs",
4 org="PASTE YOUR IB-CONTEXT HERE",
5 workspace="SDK-Tutorial",
6 files=["PATH/TO/A330_specs.pdf"])
Your IB-Context is generally the name of your organization, so is the appropriate value for the org parameter.

Remember to replace the placeholder path with the actual path to your local copy of A330_specs.pdf.

If you’re on Windows, there’s no need to change the slashes in the files parameter to Windows-compatible backslashes. Python automatically converts path separators based on operating system.

4

Wait for the document to be processed

When you create a conversation, AI Hub processes any documents you included in the conversation so that it’s prepared to answer questions about them. The information-rich, three-page PDF you included in the conversation could take up to 30 seconds to process.

This code snippet repeatedly polls the status of the conversation until it’s finished processing any documents the conversation contains.

1import time
2while True:
3 time.sleep(3)
4 status_resp = client.conversations.status(
5 create_conversation_resp.id)
6 print(f"document #1 processing status: {status_resp.state}")
7 if status_resp.state == "COMPLETE":
8 break

Line 1 makes Python’s time library available so you can pause the program between status checks.

Line 2 starts a loop for checking document processing status. The loop stops when processing is done.

Line 3 pauses for a few seconds to give AI Hub a chance to make progress on processing the document.

Lines 4 and 5 call an SDK method to check on the document processing status, passing in the conversation’s ID.

Lines 6 prints the status.

Lines 7 and 8 break out of the loop if AI Hub has finished processing the document.

5

Get the document ID

When you send a question to an AI Hub conversation, you have to tell AI Hub two things.

  • Which conversation is the question directed at?

  • Which documents within the conversation does AI Hub consider when coming up with an answer?

The second task uses document IDs. This code looks in the response to the last processing status query and extracts the ID of the one document you uploaded along with the conversation.

Because there’s only one document, get the ID of document 0 (Python uses 0-based indexing) instead of iterating through all documents.

1first_document_id = status_resp.documents[0].id
6

Submit a question to one document

Now you’re ready to analyze the document by asking AI Hub questions about it—or as AI Hub sometimes calls it, conversing with the document.

1converse_resp = client.conversations.converse(
2 conversation_id=create_conversation_resp.id,
3 question="What airplane family are these specs for?",
4 document_ids=[first_document_id])

Even though the document_ids parameter must be a list of document IDs, AI Hub only looks at the first document in the list. This leads to some non-obvious considerations:

  • To ask a question of the document with ID 123, pass in [123] instead of just 123.

  • If you pass in [123, 789], AI Hub ignores document ID 789.

  • To submit a question whose answer draws on more than one document, see the step involving the client.queries.run() method below.

8

Upload another document to the conversation

As you learned earlier, a conversation can have more than one document associated with it. Upload a second document containing technical specs for a different family of Airbus airplanes.

1add_documents_resp = client.conversations.add_documents(
2 conversation_id=create_conversation_resp.id,
3 files=["PATH/TO/A350_specs.pdf"])
9

Wait for the second document to be processed

You need to wait for the new document to be processed before you can send a question to the conversation. This code uses the same technique you used while waiting for the first document to be processed.

1while True:
2 time.sleep(3)
3 status_resp = client.conversations.status(
4 create_conversation_resp.id)
5 print(f"document #2 processing status: {status_resp.state}")
6 if status_resp.state == "COMPLETE":
7 break
10

Send a question to both documents asynchronously

Both documents are processed, so now you can send a question that requires AI Hub to consider the contents of both documents when answering.

As you’ve already seen, the method for submitting a question to a single document is synchronous.

Questions that draw on multiple documents require an asynchronous SDK operation. That means that the answer isn’t included in the response to the initial method call—request it separately using another SDK operation.

1query = "List all Airbus planes by ascending wingspan."
2source_app = {"type": "CONVERSE",
3 "id": create_conversation_resp.id}
4run_query_resp = client.queries.run(query=query,
5 source_app=source_app)

Line 1 defines the question you want AI Hub to answer.

Lines 2 and 3 tell AI Hub whether to direct the question to a conversation or a chatbot, and specify the conversation or chatbot ID.

Lines 5 and 6 submit the question.

11

Wait for the conversation to have an answer

Because multi-document queries are asynchronous, you need to check the status of your question until AI Hub comes up with an answer.

1while True:
2 time.sleep(3)
3 query_status_resp = client.queries.status(
4 query_id=run_query_resp.query_id)
5 print(f"query status: {query_status_resp.status}")
6 if query_status_resp.status == "COMPLETE":
7 break

Line 1 starts a loop that stops when AI Hub has an answer ready.

Line 2 pauses for a few seconds to give AI Hub time to process your question.

Lines 3 and 4 ask AI Hub for the status of the query, using its ID.

Line 5 prints the most recent query status.

Lines 6 and 7 break out of the loop when the status is COMPLETE.

12

Retrieve and print the answer

When AI Hub responds to your client.queries.status() call with a status of COMPLETE, that response includes a field called results that contains the answer to your question. Now you just have to extract and print it.

The results field holds a list of results. Depending on what questions you ask and how many documents are in the conversation, the list might contain one result or it might contain more. In this example there’s only one result, but it’s always safest to iterate through the list and print each result.

1for result in query_status_resp.results:
2 print(f"answer: {result.response}")
13

Run the SDK-enabled program

You’ve now seen all the code for this use case. It’s time to run it.

  1. If you haven’t been entering the code into a file on your computer called analyze_with_sdk.py, do so now.

  2. Run it the same way you ran automate_with_sdk.py, following the instructions for your operating system.

    1. Open a terminal.

    2. Type cd PATH/TO/DIRECTORY/WITH/analyze_with_sdk.py, replacing the placeholders with the path to wherever you stored analyze_with_sdk.py.

    3. Type python3 analyze_with_sdk.py.

Your output looks similar to this. Results might vary due to randomness inherent in AI.

answer: Based on the information from the documents,
here are the Airbus planes listed by ascending wingspan:
1. A330-200, A330-300, A330-200F, A330-200P2F, A330-300P2F: 60.30 meters
2. A330-800, A330-900: 64.00 meters
3. A350-900, A350-1000: 64.75 meters
This list includes the wingspan details for the A330 and A350
families as provided in the documents.
14

Add exception handling

Just as with the automate use case you looked at earlier, there are many possible problems you could address in this program. Here’s just one.

This example doesn’t involve an actual Python exception, but it does let your program gracefully handle a case where something goes wrong.

In step 11 you called the client.queries.status() method to check if AI Hub was finished generating an answer to your question. You stop checking when the status is COMPLETE, but you can also stop checking if something goes wrong and the status is FAILED.

In this snippet, lines 1 through 7 are already in your program, near the end.

Add lines 8 through 10 to handle FAILED processing status.

1while True:
2 time.sleep(3)
3 query_status_resp = client.queries.status(
4 query_id=run_query_resp.query_id)
5 print(f"query status: {query_status_resp.status}")
6 if query_status_resp.status == "COMPLETE":
7 break
8 if query_status_resp.status == "FAILED":
9 import sys
10 sys.exit("ERROR: AI Hub couldn't process this query")
Make sure the new lines are indented correctly so they’re still within the while True loop.

Complete program

This code assembles all the snippets for this use case into a single program. In this version, all the import statements have moved to the top and the code is thoroughly commented.

Replace the code you’ve typed in so far with this version, which the third use case expects. Save it as analyze-with-sdk.py.

1# prepare to use standard Python libraries
2import sys
3import time
4
5# prepare to use the SDK
6from aihub import AIHub
7
8# authorize the SDK
9client = AIHub(api_root="PASTE YOUR API ROOT HERE",
10 api_key="PASTE YOUR API KEY HERE",
11 ib_context="PASTE YOUR IB-CONTEXT HERE")
12
13print("making a conversation with one document")
14create_conversation_resp = client.conversations.create(
15 name="Airbus conversation",
16 description="Analyze Airbus technical specs",
17 org="PASTE YOUR IB-CONTEXT HERE",
18 workspace="SDK-Tutorial",
19 files=["PATH/TO/A330_specs.pdf"])
20
21print("checking the first document's processing status")
22# repeatedly check whether the one document has been processed,
23# only leaving the loop when AI Hub reports that processing is done
24while True:
25 time.sleep(3) # wait 3 seconds between status checks
26 status_resp = client.conversations.status(
27 create_conversation_resp.id)
28 print(f"document #1 processing status: {status_resp.state}")
29 if status_resp.state == "COMPLETE":
30 break
31
32# get the single document's ID from the last response to a status check
33first_document_id = status_resp.documents[0].id
34
35print("sending a question to the first document")
36# send a synchronous question about the one document,
37# and print the answer
38converse_resp = client.conversations.converse(
39 conversation_id=create_conversation_resp.id,
40 question="What airplane family are these specs for?",
41 document_ids=[first_document_id])
42print(f"answer: {converse_resp.answer}")
43
44print("uploading the second document to the conversation")
45add_documents_resp = client.conversations.add_documents(
46 conversation_id=create_conversation_resp.id,
47 files=["PATH/TO/A350_specs.pdf"])
48
49print("checking the second document's processing status "
50 "until it finishes")
51# repeatedly check whether the second document has been processed,
52# only leaving the loop when AI Hub reports that processing is done
53while True:
54 time.sleep(3) # wait 3 seconds between status checks
55 status_resp = client.conversations.status(
56 create_conversation_resp.id)
57 print(f"document #2 processing status: {status_resp.state}")
58 if status_resp.state == "COMPLETE":
59 break
60
61# "query", "prompt", and "question" are all synonyms in this context
62query = "List all Airbus planes by ascending wingspan."
63
64# indicate which AI Hub conversation or chatbot to asynchronously
65# send a question to
66source_app = {"type": "CONVERSE",
67 "id": create_conversation_resp.id}
68
69print("sending a question to both documents")
70# send an asynchronous question that AI Hub will use both of the
71# conversation's documents to answer
72run_query_resp = client.queries.run(query=query,
73 source_app=source_app)
74
75print("checking the status of the query processing "
76 "until AI Hub has an answer")
77# repeatedly check whether AI Hub has generated an answer to
78# your question, only leaving the loop when an answer is available
79while True:
80 time.sleep(3) # wait 3 seconds between status checks
81 query_status_resp = client.queries.status(
82 query_id=run_query_resp.query_id)
83 print(f"query status: {query_status_resp.status}")
84 # if it generated an answer, status will be "COMPLETE"
85 if query_status_resp.status == "COMPLETE":
86 break
87 # if something went wrong, status will be "FAILED" and
88 # you should abort the program with an error message
89 if query_status_resp.status == "FAILED":
90 sys.exit("ERROR: AI Hub couldn't process this query")
91
92# print all the answers (there might be just one) that are
93# stored in the response to the last status query
94for result in query_status_resp.results:
95 print(f"answer: {result.response}")

Troubleshooting

Many of the problems and solutions described in the automate use case also apply to the analyze use case. Other things could go wrong with this use case, too. As before, look at the end of the error message to find key information.

Double-check the path.

If you’re having trouble getting a relative path correct, temporarily add import os; print(os.getcwd()) to the top of your program. This prints the current working directory, which is where relative paths start from.

If you’re still having trouble, use absolute paths.

When calling client.conversations.converse(), you must pass a List of IDs, not a single bare ID. This can be confusing because AI Hub only uses the first ID in the list.

Next steps

Here are some things to try if you’d like more practice with the SDK or Python.

  • If you’d like to make the complete program shorter and more maintainable, extract the logic that checks processing status into a separate function that can be called from different places in the main program.

  • It’s always a good idea to add more exception handling logic.

In the first two use cases, you’ve seen how to use the AI Hub SDK to

  • Automate document processing by running an AI Hub app.

  • Analyze documents by having conversations about them.

Now you’re ready for use case three: cleaning up after yourself by deleting unneeded resources left over by the first two use cases.