Skip to content

Commit dcea2e7

Browse files
authored
Merge pull request #102 from AET-DevOps25/feature/support-cloud-models
Add cloud llm model support
2 parents b3664e0 + b520feb commit dcea2e7

File tree

7 files changed

+134
-19
lines changed

7 files changed

+134
-19
lines changed

docker-compose.dev.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ services:
7373
- mongodb
7474
restart: unless-stopped
7575

76-
prometheus:
76+
prometheus:
7777
image: prom/prometheus:v2.52.0
7878
container_name: prometheus
79-
ports:
79+
ports:
8080
- "9090:9090"
8181
volumes:
8282
- ./monitoring/prometheus:/etc/prometheus
@@ -128,7 +128,7 @@ services:
128128
- loki-data:/loki
129129
command: -config.file=/etc/loki/loki-config.yaml
130130
restart: unless-stopped
131-
131+
132132
cadvisor:
133133
image: gcr.io/cadvisor/cadvisor:latest
134134
container_name: cadvisor

genai/.env.template

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
# Cloud based LLM models
12
API_OPENAI="your openai key"
3+
API_ANTHROPIC="your anthropic key"
4+
API_MISTRAL="your mistral key"
5+
API_HUGGINGFACEHUB="your huggingface api token"
6+
# Local Models
27
API_OPENWEBUI="your openwebui key"
8+
# Base URL for calling local models
39
BASE_URL="https://gpu.aet.cit.tum.de"

genai/config.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,19 @@
99
"Config",
1010
[
1111
"api_key_openai",
12-
"api_openwebui",
12+
"api_key_anthropic",
13+
"api_key_mistral",
14+
"api_key_huggingface",
15+
"api_key_openwebui",
1316
"base_url"
1417
],
1518
)
1619

1720
Config = ConfigT(
1821
api_key_openai=environ.get("API_OPENAI"),
19-
api_openwebui=environ.get("API_OPENWEBUI"),
22+
api_key_anthropic=environ.get("API_ANTHROPIC", ""),
23+
api_key_mistral=environ.get("API_MISTRAL", ""),
24+
api_key_huggingface=environ.get("API_HUGGINGFACE", ""),
25+
api_key_openwebui=environ.get("API_OPENWEBUI"),
2026
base_url=environ.get("BASE_URL")
2127
)

genai/rag/llm/cloud_chat_model.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import os
2+
3+
from langchain.chat_models import init_chat_model
4+
from langchain_core.prompt_values import PromptValue
5+
from langchain_core.messages import BaseMessage
6+
7+
from config import Config
8+
9+
10+
class CloudLLM:
11+
"""A concrete implementation of a cloud-based LLM.
12+
Uses openai as the default LLM provider."""
13+
14+
def __init__(
15+
self,
16+
model_name: str = "gpt-4-1106-preview",
17+
model_provider: str = "openai",
18+
api_key: str = Config.api_key_openai
19+
):
20+
provider = model_provider.lower()
21+
if provider == "openai":
22+
os.environ["OPENAI_API_KEY"] = (
23+
api_key
24+
or
25+
os.getenv("API_OPENAI", "")
26+
)
27+
elif provider == "anthropic":
28+
os.environ["ANTHROPIC_API_KEY"] = (
29+
api_key
30+
or
31+
os.getenv("API_ANTHROPIC", "")
32+
)
33+
elif provider == "mistral":
34+
os.environ["MISTRAL_API_KEY"] = (
35+
api_key
36+
or
37+
os.getenv("API_MISTRAL", "")
38+
)
39+
elif provider == "huggingface":
40+
os.environ["HUGGINGFACEHUB_API_TOKEN"] = (
41+
api_key
42+
or
43+
os.getenv("API_HUGGINGFACEHUB", "")
44+
)
45+
else:
46+
raise ValueError(f"Unsupported LLM provider: {provider}")
47+
48+
self.model = init_chat_model(
49+
model=model_name,
50+
model_provider=provider
51+
)
52+
53+
def get_system_prompt(self) -> str:
54+
"""System prompt for the LLM"""
55+
return """
56+
You are an intelligent assistant that helps users discover
57+
and generate recipes based on the ingredients they provide.
58+
59+
Use the contextual information provided below to tailor
60+
your responses.
61+
62+
If relevant recipes or suggestions are found in the context,
63+
prioritize those. If no relevant context is available,
64+
use your own knowledge to help the user.
65+
66+
Context:
67+
{context}
68+
69+
Be clear, creative, and helpful. If the user also asks
70+
follow-up questions (e.g., dietary adjustments, name references,
71+
meal timing), answer them precisely based on the
72+
context and query.
73+
"""
74+
75+
def invoke(self, prompt: PromptValue) -> BaseMessage:
76+
"""Invoke the LLM with the given prompt"""
77+
return self.model.invoke(prompt)

genai/routes/routes.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
from fastapi import APIRouter, UploadFile, File, HTTPException, Request
22
from fastapi.responses import JSONResponse
33
import os
4+
5+
# from config import Config
46
from logger import logger
57
from time import perf_counter
68

79
from vector_database.qdrant_vdb import QdrantVDB
810
from rag.ingestion_pipeline import IngestionPipeline
911
from rag.llm.chat_model import ChatModel
12+
# from rag.llm.cloud_chat_model import CloudLLM
1013
from service.rag_service import (
1114
retrieve_similar_docs,
1215
prepare_prompt,
@@ -26,9 +29,43 @@
2629

2730
router = APIRouter()
2831

29-
llm = ChatModel(model_name="llama3.3:latest")
32+
# Set vector database
3033
qdrant = QdrantVDB()
3134

35+
# Set chat model for local llm models
36+
# Make calls to local models in openwebui hosted by the university
37+
llm = ChatModel(model_name="llama3.3:latest")
38+
39+
# Alternatively, we can switch to a chat model based on cloud models as well
40+
# If you want to use other cloud models, please adjust model_name,
41+
# model_provider, and api key
42+
# accordingly
43+
44+
# Examples:
45+
# llm_cloud_anthropic = CloudLLM(
46+
# model_name="claude-3-sonnet-20240229",
47+
# model_provider="anthropic",
48+
# api_key=Config.api_key_anthropic,
49+
# )
50+
# llm_cloud_openai = CloudLLM(
51+
# model_name="gpt-4-1106-preview",
52+
# model_provider="openai",
53+
# api_key=Config.api_key_openai,
54+
# )
55+
#
56+
# llm_cloud_mistral = CloudLLM(
57+
# model_name="mistral-medium",
58+
# model_provider="mistral",
59+
# api_key=Config.api_key_mistral,
60+
# )
61+
62+
# If no parameters are provided, the default cloud model will be openai.
63+
# If a cloud model is wanted, please remove the comment
64+
# for package import "CloudLLM"
65+
66+
# Example:
67+
# llm = CloudLLM() # same as llm_cloud_openai
68+
3269

3370
@router.post("/upload")
3471
async def upload_file(file: UploadFile = File(...)):
@@ -130,6 +167,7 @@ async def generate(request: Request):
130167

131168
response = llm.invoke(prompt)
132169
logger.info("Response is generated")
170+
133171
generation_successfully_counter.inc()
134172

135173
return JSONResponse(content={"response": response.content})

genai/service/openwebui_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def generate_response(model_name: str, prompt: str):
1212
url = f"{BASE_URL}/api/chat/completions"
1313

1414
headers = {
15-
"Authorization": f"Bearer {Config.api_openwebui}",
15+
"Authorization": f"Bearer {Config.api_key_openwebui}",
1616
"Content-Type": "application/json"
1717
}
1818

genai/service/rag_service.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from langchain_qdrant import QdrantVectorStore
44
from langchain_core.messages import BaseMessage, HumanMessage, AIMessage
55
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
6-
# from genai.rag.llm.chat_model import ChatModel
76

87

98
def retrieve_similar_docs(vector_store: QdrantVectorStore, user_query: str):
@@ -48,14 +47,3 @@ def process_raw_messages(raw_messages: List[Dict]) -> List[BaseMessage]:
4847
processed_messages.append(AIMessage(content=content))
4948

5049
return processed_messages
51-
52-
# For testing purposes
53-
# if __name__ == "__main__":
54-
# msg = HumanMessage(content="My name is John Doe.")
55-
# llm = ChatModel()
56-
# prompt = prepare_prompt(llm.get_system_prompt(),
57-
# "Suggest me a basic breakfast.",
58-
# "",
59-
# [msg])
60-
# response = llm.invoke(prompt)
61-
# print(response.content)

0 commit comments

Comments
 (0)