Skip to content

Commit aeaac87

Browse files
Merge pull request #59 from seanpedrick-case/dev
Added Gemma 12b and Ministral 3 14b support. Minor bug fixes
2 parents 93340ac + ff6d2e3 commit aeaac87

File tree

5 files changed

+36
-29
lines changed

5 files changed

+36
-29
lines changed

app.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,12 @@
5757
}
5858
"""
5959

60-
# /* Completely hide elements with the class 'hidden_component' from view */
61-
# .hidden_component {
62-
# display: none !important;
63-
# visibility: hidden !important;
64-
# }
65-
6660
# Create the gradio interface
67-
app = gr.Blocks(fill_width=True)
61+
app = gr.Blocks(fill_width=True,
62+
analytics_enabled=False,
63+
title="LLM topic modelling",
64+
delete_cache=(43200, 43200),
65+
)
6866

6967
with app:
7068

tools/aws_functions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,13 @@ def connect_to_bedrock_runtime(model_name_map:dict, model_choice:str, aws_access
3535
print(out_message)
3636
raise Exception(out_message)
3737
else:
38-
bedrock_runtime = list()
38+
bedrock_runtime = None
3939

4040
return bedrock_runtime
4141

4242
def connect_to_s3_client(aws_access_key_textbox:str="", aws_secret_key_textbox:str=""):
4343
# If running an anthropic model, assume that running an AWS s3 model, load in s3
44-
s3_client = list()
44+
s3_client = None
4545

4646
if aws_access_key_textbox and aws_secret_key_textbox:
4747
print("Connecting to s3 using AWS access key and secret keys from user input.")

tools/combine_sheets_into_xlsx.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def collect_output_csvs_and_create_excel_output(in_data_files:List, chosen_cols:
414414
intro_text = [
415415
"This workbook contains outputs from the large language model topic analysis of open text data. Each sheet corresponds to a different CSV report included in the analysis.",
416416
f"The file analysed was {short_file_name}, the column analysed was '{chosen_cols}' and the data was grouped by column '{group}'."
417-
"Please contact the LLM Topic Modelling app administrator if you need any explanation on how to use the results."
417+
" Please contact the LLM Topic Modelling app administrator if you need any explanation on how to use the results."
418418
"Large language models are not 100% accurate and may produce biased or harmful outputs. All outputs from this analysis **need to be checked by a human** to check for harmful outputs, false information, and bias."
419419
]
420420

tools/config.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ def convert_string_to_boolean(value: str) -> bool:
154154
ACCESS_LOGS_FOLDER = get_or_create_env_var('ACCESS_LOGS_FOLDER', 'logs/')
155155
USAGE_LOGS_FOLDER = get_or_create_env_var('USAGE_LOGS_FOLDER', 'usage/')
156156

157+
# Initialize full_log_subfolder based on USE_LOG_SUBFOLDERS setting
157158
if USE_LOG_SUBFOLDERS == "True":
158159
day_log_subfolder = today_rev + '/'
159160
host_name_subfolder = HOST_NAME + '/'
@@ -162,6 +163,8 @@ def convert_string_to_boolean(value: str) -> bool:
162163
FEEDBACK_LOGS_FOLDER = FEEDBACK_LOGS_FOLDER + full_log_subfolder
163164
ACCESS_LOGS_FOLDER = ACCESS_LOGS_FOLDER + full_log_subfolder
164165
USAGE_LOGS_FOLDER = USAGE_LOGS_FOLDER + full_log_subfolder
166+
else:
167+
full_log_subfolder = '' # Empty string when subfolders are not used
165168

166169
S3_FEEDBACK_LOGS_FOLDER = get_or_create_env_var('S3_FEEDBACK_LOGS_FOLDER', 'feedback/' + full_log_subfolder)
167170
S3_ACCESS_LOGS_FOLDER = get_or_create_env_var('S3_ACCESS_LOGS_FOLDER', 'logs/' + full_log_subfolder)
@@ -261,17 +264,16 @@ def convert_string_to_boolean(value: str) -> bool:
261264
model_source = list()
262265

263266
CHOSEN_LOCAL_MODEL_TYPE = get_or_create_env_var("CHOSEN_LOCAL_MODEL_TYPE", "Qwen 3 4B") # Gemma 3 1B # "Gemma 2b" # "Gemma 3 4B"
264-
print("CHOSEN_LOCAL_MODEL_TYPE:", CHOSEN_LOCAL_MODEL_TYPE)
265267

266268
if RUN_LOCAL_MODEL == "1" and CHOSEN_LOCAL_MODEL_TYPE:
267269
model_full_names.append(CHOSEN_LOCAL_MODEL_TYPE)
268270
model_short_names.append(CHOSEN_LOCAL_MODEL_TYPE)
269271
model_source.append("Local")
270272

271273
if RUN_AWS_BEDROCK_MODELS == "1":
272-
amazon_models = ["anthropic.claude-3-haiku-20240307-v1:0", "anthropic.claude-3-7-sonnet-20250219-v1:0", "anthropic.claude-sonnet-4-5-20250929-v1:0", "amazon.nova-micro-v1:0", "amazon.nova-lite-v1:0", "amazon.nova-pro-v1:0", "deepseek.v3-v1:0", "openai.gpt-oss-20b-1:0", "openai.gpt-oss-120b-1:0"]
274+
amazon_models = ["anthropic.claude-3-haiku-20240307-v1:0", "anthropic.claude-3-7-sonnet-20250219-v1:0", "anthropic.claude-sonnet-4-5-20250929-v1:0", "amazon.nova-micro-v1:0", "amazon.nova-lite-v1:0", "amazon.nova-pro-v1:0", "deepseek.v3-v1:0", "openai.gpt-oss-20b-1:0", "openai.gpt-oss-120b-1:0", "google.gemma-3-12b-it", "mistral.ministral-3-14b-instruct"]
273275
model_full_names.extend(amazon_models)
274-
model_short_names.extend(["haiku", "sonnet_3_7", "sonnet_4_5", "nova_micro", "nova_lite", "nova_pro", "deepseek_v3", "gpt_oss_20b_aws", "gpt_oss_120b_aws"])
276+
model_short_names.extend(["haiku", "sonnet_3_7", "sonnet_4_5", "nova_micro", "nova_lite", "nova_pro", "deepseek_v3", "gpt_oss_20b_aws", "gpt_oss_120b_aws", "gemma_3_12b_it", "ministral_3_14b_instruct"])
275277
model_source.extend(["AWS"] * len(amazon_models))
276278

277279
if RUN_GEMINI_MODELS == "1":
@@ -438,9 +440,6 @@ def update_model_choice_config(default_model_source, model_name_map):
438440
LOCAL_MODEL_FILE = ""
439441
LOCAL_MODEL_FOLDER = ""
440442

441-
print("LOCAL_REPO_ID:", LOCAL_REPO_ID)
442-
443-
444443
USE_SPECULATIVE_DECODING = get_or_create_env_var("USE_SPECULATIVE_DECODING", "False")
445444

446445
ASSISTANT_MODEL = get_or_create_env_var("ASSISTANT_MODEL", "")

tools/llm_funcs.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,7 @@ def construct_azure_client(in_api_key: str, endpoint: str) -> Tuple[object, dict
882882
print("Error constructing Azure/OpenAI client:", e)
883883
raise
884884

885-
def call_aws_claude(prompt: str, system_prompt: str, temperature: float, max_tokens: int, model_choice:str, bedrock_runtime:boto3.Session.client, assistant_prefill:str="") -> ResponseObject:
885+
def call_aws_bedrock(prompt: str, system_prompt: str, temperature: float, max_tokens: int, model_choice:str, bedrock_runtime:boto3.Session.client, assistant_prefill:str="") -> ResponseObject:
886886
"""
887887
This function sends a request to AWS Claude with the following parameters:
888888
- prompt: The user's input prompt to be processed by the model.
@@ -902,27 +902,31 @@ def call_aws_claude(prompt: str, system_prompt: str, temperature: float, max_tok
902902
"temperature":temperature,
903903
}
904904

905-
if not assistant_prefill:
905+
906+
# Using an assistant prefill only works for Anthropic models.
907+
if assistant_prefill and "anthropic" in model_choice:
908+
assistant_prefill_added = True
906909
messages = [
907910
{
908911
"role": "user",
909912
"content": [
910913
{"text": prompt},
911914
],
915+
},
916+
{
917+
"role": "assistant",
918+
# Pre-filling with '|'
919+
"content": [{"text": assistant_prefill}]
912920
}
913921
]
914922
else:
923+
assistant_prefill_added = False
915924
messages = [
916925
{
917926
"role": "user",
918927
"content": [
919928
{"text": prompt},
920929
],
921-
},
922-
{
923-
"role": "assistant",
924-
# Pre-filling with '|'
925-
"content": [{"text": assistant_prefill}]
926930
}
927931
]
928932

@@ -932,7 +936,7 @@ def call_aws_claude(prompt: str, system_prompt: str, temperature: float, max_tok
932936
}
933937
]
934938

935-
# The converse API call itself. Note I've renamed the response variable for clarity.
939+
# The converse API call.
936940
api_response = bedrock_runtime.converse(
937941
modelId=model_choice,
938942
messages=messages,
@@ -947,9 +951,15 @@ def call_aws_claude(prompt: str, system_prompt: str, temperature: float, max_tok
947951
reasoning_text = output_message['content'][0]['reasoningContent']['reasoningText']['text']
948952

949953
# Extract the output text
950-
text = assistant_prefill + output_message['content'][1]['text']
954+
if assistant_prefill_added:
955+
text = assistant_prefill + output_message['content'][1]['text']
956+
else:
957+
text = output_message['content'][1]['text']
951958
else:
952-
text = assistant_prefill + output_message['content'][0]['text']
959+
if assistant_prefill_added:
960+
text = assistant_prefill + output_message['content'][0]['text']
961+
else:
962+
text = output_message['content'][0]['text']
953963

954964
# The usage statistics are neatly provided in the 'usage' key.
955965
usage = api_response['usage']
@@ -1183,14 +1193,14 @@ def send_request(prompt: str, conversation_history: List[dict], client: ai.Clien
11831193
elif "AWS" in model_source:
11841194
for i in progress_bar:
11851195
try:
1186-
print("Calling AWS Claude model, attempt", i + 1)
1187-
response = call_aws_claude(prompt, system_prompt, temperature, max_tokens, model_choice, bedrock_runtime=bedrock_runtime, assistant_prefill=assistant_prefill)
1196+
print("Calling AWS Bedrock model, attempt", i + 1)
1197+
response = call_aws_bedrock(prompt, system_prompt, temperature, max_tokens, model_choice, bedrock_runtime=bedrock_runtime, assistant_prefill=assistant_prefill)
11881198

11891199
#print("Successful call to Claude model.")
11901200
break
11911201
except Exception as e:
11921202
# If fails, try again after X seconds in case there is a throttle limit
1193-
print("Call to Claude model failed:", e, " Waiting for ", str(timeout_wait), "seconds and trying again.")
1203+
print("Call to Bedrock model failed:", e, " Waiting for ", str(timeout_wait), "seconds and trying again.")
11941204
time.sleep(timeout_wait)
11951205

11961206
if i == number_of_api_retry_attempts:

0 commit comments

Comments
 (0)