Julia Ostheimer commited on
Commit
aea4d15
·
unverified ·
2 Parent(s): 2f15fb0 434f5d3

Merge branch 'basic_set_up_RAG' into 1-langfuse-integration-for-llm-process-monitoring-and-prompt-management

Browse files
Files changed (6) hide show
  1. .gitignore +1 -1
  2. README.md +34 -33
  3. app.py +0 -6
  4. conversation/main.py +0 -79
  5. ingestion/main.py +0 -18
  6. static/style.css +0 -1
.gitignore CHANGED
@@ -16,5 +16,5 @@ wheels/
16
  .gradio
17
  *.log
18
 
19
- # sanboxes
20
  *.ipynb
 
16
  .gradio
17
  *.log
18
 
19
+ # sandboxes
20
  *.ipynb
README.md CHANGED
@@ -7,23 +7,33 @@ This is the code repository for the DEval project "Durchführung und Unterstütz
7
 
8
  - **[Get Started](#get-started)**
9
 
10
- - [Setting-up the environment](#setting-up-the-environment)
11
- - [Load EPD Data](#load-epd-data)
12
- - [PostGres](#postgres)
13
-
14
- - [Contribute](#contribute)
15
- - [Unit Tests](#unit-tests)
16
- - [Deploy to Heroku](#deploy-to-heroku)
17
- - [Support](#support)
18
- - [License](#license)
19
 
20
  ---
21
 
22
  ## Get started
23
 
24
- To run, the project expects secret keys from a `.env` file.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
- ### Setting-up the environment
27
  We use `uv` as a python and our package dependency manager. Follow these [instructions](https://docs.astral.sh/uv/getting-started/installation/) to install with the standalone installer and `curl`
28
 
29
  Next, to set up the local dependencies. You can find further information [here](https://docs.astral.sh/uv/guides/projects/#managing-dependencies)
@@ -31,16 +41,19 @@ Next, to set up the local dependencies. You can find further information [here](
31
  uv sync
32
  ```
33
 
34
- This should give you a package structure like this with a `.venv` file
35
  ```
36
  .
37
  ├── .venv
38
  ├── .python-version
 
 
39
  ├── README.md
40
- ├── main.py
41
- └── pyproject.toml
42
  ```
43
 
 
 
44
 
45
  Alternatively, with a different dependency manager such as `venv` install directly from `pyproject.toml`.
46
  ```Bash
@@ -49,27 +62,15 @@ Alternatively, with a different dependency manager such as `venv` install direct
49
  **Note**: the dependencies then need to be documented manually in the `pyproject.toml`.
50
 
51
 
52
- ### Set up `.env` file for secrets
53
- Locally set up a `.env` file for secrets. You require connection to an LLM, an embedding provider, and API keys for the Langfuse integration. The latter you can acquire after setting up a Langfuse project in the Langfuse GUI, either through a local setup or via Langfuse Cloud.
54
-
55
- Here is how the `.env` file should look like:
56
- ```
57
- # .env
58
- LLM_API_KEY= # Your LLM API key
59
-
60
- # Langfuse credentials
61
- LANGFUSE_PUBLIC_API_KEY= # Your Langfuse public API key
62
- LANGFUSE_SECRET_API_KEY= # Your Langfuse secret API key
63
- LANGFUSE_HOST="https://cloud.langfuse.com" # EU server for langfuse Cloud, can be different for other deployments
64
- ```
65
- **Note**: the `.env` file is not version-controlled.
66
-
67
  ### Setup for Langfuse Prompt Management
68
  Langfuse Prompt Management is used within this project. Therefore, setting up the prompt templates within Langfuse is mandatory. As the prompts directly integrate with the code, alignment is necessary. Current setup requirements can be provided by the maintainers.
69
 
70
- ## To-Do
71
- - create bsaic set-up with Qdrant in memory, ingestion pipeline
72
- - create basic set-up where retrieval is not yet having an llm call
73
- - connect to frontend with "invoke" and deletion of memory
74
 
 
 
 
 
 
 
75
 
 
 
7
 
8
  - **[Get Started](#get-started)**
9
 
10
+ - [Set up `.env` file](#set-up-env-file)
11
+ - [Set up the environment](#set-up-the-environment)
12
+ - [Setup for Langfuse Prompt Management](#setup-for-langfuse-prompt-management)
13
+ - [Run the code](#run-the-code)
 
 
 
 
 
14
 
15
  ---
16
 
17
  ## Get started
18
 
19
+ ### Set up `.env` file
20
+ To run, the project expects secret keys from a `.env` file. Locally set up this `.env` file. You require connection to an LLM, an embedding provider, and API keys for the Langfuse integration. The latter you can acquire after setting up a Langfuse project in the Langfuse GUI, either through a local setup or via Langfuse Cloud.
21
+
22
+ Here how the `.env` file should look like:
23
+
24
+ ```
25
+ # .env
26
+ LLM_API_KEY= # Your LLM API key
27
+
28
+ # Langfuse credentials
29
+ LANGFUSE_PUBLIC_API_KEY= # Your Langfuse public API key
30
+ LANGFUSE_SECRET_API_KEY= # Your Langfuse secret API key
31
+ LANGFUSE_HOST="https://cloud.langfuse.com" # EU server for langfuse Cloud, can be different for other deployments
32
+ ```
33
+ **Note**: Due to security reasons, this file should not be committed to version control!
34
+
35
 
36
+ ### Set up the environment
37
  We use `uv` as a python and our package dependency manager. Follow these [instructions](https://docs.astral.sh/uv/getting-started/installation/) to install with the standalone installer and `curl`
38
 
39
  Next, to set up the local dependencies. You can find further information [here](https://docs.astral.sh/uv/guides/projects/#managing-dependencies)
 
41
  uv sync
42
  ```
43
 
44
+ This should give you a package structure like this with a `.venv` directory:
45
  ```
46
  .
47
  ├── .venv
48
  ├── .python-version
49
+ ├── app.py
50
+ ├── pyproject.toml
51
  ├── README.md
52
+ └── uv.lock
 
53
  ```
54
 
55
+ #### uv.lock
56
+ `uv.lock` is a cross-platform lockfile that contains exact information about the project's dependencies. Unlike the `pyproject.toml` which is used to specify the broad requirements of the project, the lockfile contains the exact resolved versions that are installed in the project environment via `uv`. This file should be checked into version control, allowing for consistent and reproducible installations across machines. `uv.lock` is a human-readable TOML file but is managed by `uv` and should NOT be edited manually.
57
 
58
  Alternatively, with a different dependency manager such as `venv` install directly from `pyproject.toml`.
59
  ```Bash
 
62
  **Note**: the dependencies then need to be documented manually in the `pyproject.toml`.
63
 
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  ### Setup for Langfuse Prompt Management
66
  Langfuse Prompt Management is used within this project. Therefore, setting up the prompt templates within Langfuse is mandatory. As the prompts directly integrate with the code, alignment is necessary. Current setup requirements can be provided by the maintainers.
67
 
 
 
 
 
68
 
69
+ ### Run the code
70
+ After installing the needed dependencies for the project and setting up the environment, execute the code from the root of the repository by running the `app.py` script via `uv` with the following command:
71
+
72
+ ```Bash
73
+ uv run app.py
74
+ ```
75
 
76
+ You will see the logging in the terminal and receive a link to access the currently locally hosted Gradio User Interface.
app.py CHANGED
@@ -98,11 +98,6 @@ graph_builder.add_edge("generate", END)
98
  graph = graph_builder.compile(checkpointer=memory)
99
  # -----
100
 
101
- with open("static/style.css", "r") as f:
102
- css = f.read()
103
- logger.info("Successfully loaded styles.")
104
-
105
-
106
  def bot(message, history) -> list[Any]:
107
  """Generate bot response and history from message.
108
 
@@ -143,7 +138,6 @@ demo = gr.ChatInterface(
143
  textbox=gr.MultimodalTextbox(file_count="multiple"),
144
  title="DEval Prototype 1",
145
  description="I am a playground to test Citation and the Basic set-up.",
146
- css=css
147
  )
148
 
149
  if __name__ == "__main__":
 
98
  graph = graph_builder.compile(checkpointer=memory)
99
  # -----
100
 
 
 
 
 
 
101
  def bot(message, history) -> list[Any]:
102
  """Generate bot response and history from message.
103
 
 
138
  textbox=gr.MultimodalTextbox(file_count="multiple"),
139
  title="DEval Prototype 1",
140
  description="I am a playground to test Citation and the Basic set-up.",
 
141
  )
142
 
143
  if __name__ == "__main__":
conversation/main.py DELETED
@@ -1,79 +0,0 @@
1
- # from langchain.chat_models import init_chat_model
2
- # from langchain_core.tools import tool
3
- # from langchain_openai import OpenAIEmbeddings
4
- # from langchain_qdrant import QdrantVectorStore
5
- # from langgraph.checkpoint.memory import MemorySaver
6
- # from langgraph.graph import MessagesState, StateGraph, END
7
- # from langgraph.prebuilt import ToolNode, tools_condition
8
- # from langgraph.prebuilt import ToolNode
9
- # from qdrant_client import QdrantClient
10
- # from qdrant_client.http.models import Distance, VectorParams, SparseVectorParams
11
-
12
- # from config import app_settings
13
- # from conversation.generate import generate
14
-
15
-
16
- # llm = init_chat_model(
17
- # app_settings.llm_model,
18
- # model_provider="openai",
19
- # api_key=app_settings.llm_api_key
20
- # )
21
-
22
- # embeddings = OpenAIEmbeddings(
23
- # model=app_settings.embedding_model,
24
- # api_key=app_settings.llm_api_key
25
- # )
26
-
27
- # client = QdrantClient(app_settings.vector_db_url)
28
- # if not client.collection_exists(app_settings.vector_db_collection_name):
29
- # client.create_collection(
30
- # collection_name=app_settings.vector_db_collection_name,
31
- # vectors_config=VectorParams(size=app_settings.embedding_size, distance=Distance.COSINE),
32
- # sparse_vectors_config={'langchain-sparse': SparseVectorParams(index=None, modifier=None)}
33
- # )
34
-
35
- # vector_store = QdrantVectorStore(
36
- # client=client,
37
- # collection_name=app_settings.vector_db_collection_name,
38
- # embedding=embeddings,
39
- # )
40
-
41
- # @tool(response_format="content_and_artifact")
42
- # def retrieve(query: str):
43
- # """Retrieve information related to a query."""
44
- # retrieved_docs = vector_store.similarity_search(query, k=2)
45
- # serialized = "\n\n".join(
46
- # (f"Source: {doc.metadata}\n" f"Content: {doc.page_content}")
47
- # for doc in retrieved_docs
48
- # )
49
- # return serialized, retrieved_docs
50
-
51
-
52
- # def query_or_respond(state: MessagesState):
53
- # """Generate tool call for retrieval or respond."""
54
- # llm_with_tools = llm.bind_tools([retrieve])
55
- # response = llm_with_tools.invoke(state["messages"])
56
- # # MessagesState appends messages to state instead of overwriting
57
- # return {"messages": [response]}
58
-
59
-
60
- # graph_builder = StateGraph(MessagesState)
61
- # tools = ToolNode([retrieve])
62
- # memory = MemorySaver()
63
-
64
- # graph_builder.add_node(query_or_respond)
65
- # graph_builder.add_node(tools)
66
- # graph_builder.add_node(generate)
67
-
68
- # graph_builder.set_entry_point("query_or_respond")
69
-
70
- # graph_builder.add_conditional_edges(
71
- # "query_or_respond",
72
- # tools_condition,
73
- # {END: END, "tools": "tools"},
74
- # )
75
-
76
- # graph_builder.add_edge("tools", "generate")
77
- # graph_builder.add_edge("generate", END)
78
-
79
- # graph = graph_builder.compile(checkpointer=memory)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ingestion/main.py CHANGED
@@ -11,24 +11,6 @@ from config import app_settings
11
 
12
  logger = structlog.get_logger(__name__)
13
 
14
- # embeddings = OpenAIEmbeddings(
15
- # model=app_settings.embedding_model,
16
- # api_key=app_settings.llm_api_key
17
- # )
18
-
19
- # client = QdrantClient(app_settings.vector_db_url)
20
- # if not client.collection_exists(app_settings.vector_db_collection_name):
21
- # client.create_collection(
22
- # collection_name=app_settings.vector_db_collection_name,
23
- # vectors_config=VectorParams(size=app_settings.embedding_size, distance=Distance.COSINE),
24
- # sparse_vectors_config={'langchain-sparse': SparseVectorParams(index=None, modifier=None)}
25
- # )
26
- # vector_store = QdrantVectorStore(
27
- # client=client,
28
- # collection_name=app_settings.vector_db_collection_name,
29
- # embedding=embeddings,
30
- # )
31
-
32
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
33
 
34
  def ingest_document(path, vector_store):
 
11
 
12
  logger = structlog.get_logger(__name__)
13
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
  text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
15
 
16
  def ingest_document(path, vector_store):
static/style.css DELETED
@@ -1 +0,0 @@
1
- footer { display: none !important; }