Skip to content

Commit c6e273e

Browse files
committed
Rename agent->assistant
1 parent 8b4f6ac commit c6e273e

17 files changed

+289
-264
lines changed

README.md

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# 🍊 tangerine (backend) <!-- omit from toc -->
33

4-
tangerine is a slim and light-weight RAG (Retieval Augmented Generated) system used to create and manage chat bot agents.
4+
tangerine is a slim and light-weight RAG (Retieval Augmented Generated) system used to create and manage chat bot assistants.
55

6-
Each agent is intended to answer questions related to a set of documents known as a knowledge base (KB).
6+
Each assistant is intended to answer questions related to a set of documents known as a knowledge base (KB).
77

88
![Demo video](docs/demo.gif)
99

@@ -61,10 +61,10 @@ It was born out of a hack-a-thon and is still a work in progress. You will find
6161

6262
#### Retrieval Augmented Generation (RAG)
6363

64-
- **1:** A user presents a question to an agent in the chat interface
64+
- **1:** A user presents a question to an assistant in the chat interface
6565
- **2:** Embeddings are created for the query using the embedding model
6666
- **3:** A similarity search and a max marginal relevance search are performed against the vector DB to find the top N most relevant document chunks
67-
- The document set searched is scoped only to that specific agent
67+
- The document set searched is scoped only to that specific assistant
6868
- **4:** The LLM is prompted to answer the question using only the context found within the relevant document chunks
6969
- **5:** The LLM response is streamed by the backend service to the user. Metadata containing the document chunks are also returned to be used as citations.
7070

@@ -110,7 +110,7 @@ Our documentation set has initially focused on pages that have been compiled usi
110110

111111
The **tangerine-backend** service manages:
112112

113-
- Create/update/delete of chat bot "agents" via REST API.
113+
- Create/update/delete of chat bot "assistants" via REST API.
114114
- Document ingestion
115115
- Upload via the API, or sync via an s3 bucket
116116
- Text cleanup/conversion
@@ -176,7 +176,7 @@ The docker compose file offers an easy way to spin up all components. [ollama](h
176176
6. Access the API on port `8000`
177177
178178
```sh
179-
curl -XGET 127.0.0.1:8000/api/agents
179+
curl -XGET 127.0.0.1:8000/api/assistants
180180
{
181181
"data": []
182182
}
@@ -293,7 +293,7 @@ to use this to test different embedding models that are not supported by ollama,
293293
1. Access the API on port `8000`
294294

295295
```sh
296-
curl -XGET 127.0.0.1:8000/api/agents
296+
curl -XGET 127.0.0.1:8000/api/assistants
297297
{
298298
"data": []
299299
}
@@ -376,7 +376,7 @@ Comment out `ollama` from the compose file, or stop the ollama container. Invoke
376376

377377
## Synchronizing Documents from S3
378378

379-
You can configure a set of agents and continually sync their knowledge base via documents stored in an S3 bucket.
379+
You can configure a set of assistants and continually sync their knowledge base via documents stored in an S3 bucket.
380380

381381
To do so you'll need to do the following:
382382
@@ -400,7 +400,7 @@ To do so you'll need to do the following:
400400
echo 'BUCKET=mybucket' >> .env
401401
```
402402
403-
1. Create an `s3.yaml` file that describes your agents and the documents they should ingest. See [s3-example.yaml](s3-example.yaml) for an example.
403+
1. Create an `s3.yaml` file that describes your assistants and the documents they should ingest. See [s3-example.yaml](s3-example.yaml) for an example.
404404
405405
If using docker compose, copy this config into your container:
406406
@@ -422,7 +422,7 @@ To do so you'll need to do the following:
422422
flask s3sync
423423
```
424424
425-
The sync creates agents and ingests the configured documents for each agent. After initial creation, when the task is run it checks the S3 bucket for updates and will only re-ingest files into the vector DB when it detects file changes.
425+
The sync creates assistants and ingests the configured documents for each assistant. After initial creation, when the task is run it checks the S3 bucket for updates and will only re-ingest files into the vector DB when it detects file changes.
426426
427427
The OpenShift templates contain a CronJob configuration that is used to run this document sync repeatedly.
428428
@@ -445,19 +445,19 @@ This repository provides [OpenShift templates](openshift/) for all infrastructur
445445
446446
## Run Tangerine Frontend Locally
447447
448-
The API can be used to create/manage/update agents, upload documents, and to chat with each agent. However, the frontend provides a simpler interface to manage the service with. To run the UI in a development environment, see [tangerine-frontend](https://github.com/RedHatInsights/tangerine-frontend)
448+
The API can be used to create/manage/update assistants, upload documents, and to chat with each assistant. However, the frontend provides a simpler interface to manage the service with. To run the UI in a development environment, see [tangerine-frontend](https://github.com/RedHatInsights/tangerine-frontend)
449449
450450
## Available API Paths
451451
452452
| Path | Method | Description |
453453
| ---------------------------------- | -------- | -------------------------- |
454-
| `/api/agents` | `GET` | Get a list of all agents |
455-
| `/api/agents` | `POST` | Create a new agent |
456-
| `/api/agents/<id>` | `GET` | Get an agent |
457-
| `/api/agents/<id>` | `PUT` | Update an agent |
458-
| `/api/agents/<id>` | `DELETE` | Delete an agent |
459-
| `/api/agents/<id>/chat` | `POST` | Chat with an agent |
460-
| `/api/agents/<id>/documents` | `POST` | Agent document uploads |
461-
| `/api/agents/<id>/documents` | `DELETE` | Delete agent documents |
462-
| `/api/agentDefaults` | `GET` | Get agent default settings |
454+
| `/api/assistants` | `GET` | Get a list of all assistants |
455+
| `/api/assistants` | `POST` | Create a new assistant |
456+
| `/api/assistants/<id>` | `GET` | Get an assistant |
457+
| `/api/assistants/<id>` | `PUT` | Update an assistant |
458+
| `/api/assistants/<id>` | `DELETE` | Delete an assistant |
459+
| `/api/assistants/<id>/chat` | `POST` | Chat with an assistant |
460+
| `/api/assistants/<id>/documents` | `POST` | Assistant document uploads |
461+
| `/api/assistants/<id>/documents` | `DELETE` | Delete assistant documents |
462+
| `/api/assistantDefaults` | `GET` | Get assistant default settings |
463463
| `/ping` | `GET` | Health check endpoint |

openshift/s3sync-cronjob.template.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ objects:
6060
- md
6161
citation_url_template: 'https://files.test/{{ full_path }}'
6262
63-
agents:
64-
- name: agent1
65-
description: Agent One
63+
assistants:
64+
- name: assistant1
65+
description: Assistant One
6666
bucket: mybucket
6767
paths:
6868
- prefix: path/in/bucket
6969
70-
- name: agent2
71-
description: Agent Two
70+
- name: assistant2
71+
description: Assistant Two
7272
bucket: mybucket
7373
paths:
7474
- prefix: other/path/in/bucket

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
55
[project]
66
name = "tangerine"
77
version = "0.0.1"
8-
description = "A slim and light-weight RAG (Retieval Augmented Generated) system used to create and manage chat bot agents."
8+
description = "A slim and light-weight RAG (Retieval Augmented Generated) system used to create and manage chat bot assistants."
99
readme = "README.md"
1010
requires-python = ">=3.12"
1111
classifiers = [

s3-example.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ defaults:
44
- md
55
citation_url_template: 'https://files.test/{{ full_path }}'
66

7-
agents:
8-
- name: agent1
9-
description: Agent One
7+
assistants:
8+
- name: assistant1
9+
description: Assistant One
1010
bucket: mybucket
1111
paths:
1212
- prefix: path/in/bucket
1313

14-
- name: agent2
15-
description: Agent Two
14+
- name: assistant2
15+
description: Assistant Two
1616
bucket: mybucket
1717
paths:
1818
- prefix: other/path/in/bucket

src/tangerine/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def create_app():
5454

5555

5656
@click.command("s3sync")
57-
@click.option("--force-resync", is_flag=True, help="Delete all files from agents and re-import")
57+
@click.option("--force-resync", is_flag=True, help="Delete all files from assistants and re-import")
5858
@click.option(
5959
"--force-resync-until",
6060
help=(

src/tangerine/llm.py

+14-8
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111

1212
import tangerine.config as cfg
1313
from tangerine.metrics import get_counter, get_gauge
14-
from tangerine.models.agent import Agent
14+
from tangerine.models.assistant import Assistant
1515

1616
log = logging.getLogger("tangerine.llm")
1717

18-
agent_response_counter = get_counter(
19-
"agent_response_counter", "Total number of responses for an agent", ["agent_id", "agent_name"]
18+
assistant_response_counter = get_counter(
19+
"assistant_response_counter",
20+
"Total number of responses for an assistant",
21+
["assistant_id", "assistant_name"],
2022
)
2123
llm_completion_tokens_metric = get_counter("llm_completion_tokens", "LLM completion tokens usage")
2224
llm_prompt_tokens_metric = get_counter("llm_prompt_tokens", "LLM prompt tokens usage")
@@ -26,7 +28,9 @@
2628
llm_processing_rate = get_gauge(
2729
"llm_processing_rate", "Observed tokens per sec for most recent LLM processing after prompted"
2830
)
29-
llm_no_answer = get_counter("llm_no_answer", "No search results found", ["agent_id", "agent_name"])
31+
llm_no_answer = get_counter(
32+
"llm_no_answer", "No search results found", ["assistant_id", "assistant_name"]
33+
)
3034

3135

3236
def _record_metrics(
@@ -147,7 +151,7 @@ def rerank(query, search_results):
147151

148152

149153
def ask(
150-
agent: Agent,
154+
assistant: Assistant,
151155
previous_messages,
152156
question,
153157
search_results: list[Document],
@@ -161,17 +165,19 @@ def ask(
161165
if len(search_results) == 0:
162166
log.debug("given 0 search results")
163167
search_context = "No matching search results found"
164-
llm_no_answer.labels(agent_id=agent.id, agent_name=agent.name).inc()
168+
llm_no_answer.labels(assistant_id=assistant.id, assistant_name=assistant.name).inc()
165169
else:
166170
search_context, search_metadata = _build_context(search_results)
167-
agent_response_counter.labels(agent_id=agent.id, agent_name=agent.name).inc()
171+
assistant_response_counter.labels(
172+
assistant_id=assistant.id, assistant_name=assistant.name
173+
).inc()
168174

169175
if not search_metadata:
170176
search_metadata = [{}]
171177
for m in search_metadata:
172178
m["interactionId"] = interaction_id
173179

174-
msg_list = [("system", agent.system_prompt or cfg.DEFAULT_SYSTEM_PROMPT)]
180+
msg_list = [("system", assistant.system_prompt or cfg.DEFAULT_SYSTEM_PROMPT)]
175181
if previous_messages:
176182
for msg in previous_messages:
177183
if msg["sender"] == "human":

src/tangerine/models/__init__.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# import all models
2-
from .agent import Agent
2+
from .assistant import Assistant
33
from .interactions import Interaction, QuestionEmbedding, RelevanceScore, UserFeedback
44

5-
__all__ = ["Agent", "RelevanceScore", "QuestionEmbedding", "UserFeedback", "Interaction"]
5+
__all__ = ["Assistant", "RelevanceScore", "QuestionEmbedding", "UserFeedback", "Interaction"]

src/tangerine/models/agent.py

+18-18
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import tangerine.config as cfg
55
from tangerine.db import db
66

7-
log = logging.getLogger("tangerine.models.agent")
7+
log = logging.getLogger("tangerine.models.assistant")
88

99

10-
class Agent(db.Model):
10+
class Assistant(db.Model):
1111
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
1212
name = db.Column(db.String(50), nullable=False)
1313
description = db.Column(db.Text, nullable=False)
@@ -18,38 +18,38 @@ def to_dict(self):
1818
return {c.name: getattr(self, c.name) for c in self.__table__.columns}
1919

2020
def __repr__(self):
21-
return f"<Agent {self.id}>"
21+
return f"<Assistant {self.id}>"
2222

2323
@classmethod
2424
def create(cls, name: str, description: str, system_prompt: str = None, **kwargs) -> Self:
25-
new_agent = cls(
25+
new_assistant = cls(
2626
name=name,
2727
description=description,
2828
system_prompt=system_prompt or cfg.DEFAULT_SYSTEM_PROMPT,
2929
)
30-
db.session.add(new_agent)
30+
db.session.add(new_assistant)
3131
db.session.commit()
32-
db.session.refresh(new_agent)
32+
db.session.refresh(new_assistant)
3333

34-
log.debug("agent %d created", new_agent.id)
34+
log.debug("assistant %d created", new_assistant.id)
3535

36-
return new_agent
36+
return new_assistant
3737

3838
@classmethod
3939
def list(cls) -> List[Self]:
4040
return db.session.scalars(db.select(cls)).all()
4141

4242
@classmethod
4343
def get(cls, id: int) -> Optional[Self]:
44-
agent_id = int(id)
45-
agent = db.session.get(cls, agent_id)
46-
return agent
44+
assistant_id = int(id)
45+
assistant = db.session.get(cls, assistant_id)
46+
return assistant
4747

4848
@classmethod
4949
def get_by_name(cls, name: str) -> Optional[Self]:
50-
agent = db.session.scalar(db.select(cls).filter_by(name=name))
51-
log.debug("get agent by name '%s' result: %s", name, agent)
52-
return agent
50+
assistant = db.session.scalar(db.select(cls).filter_by(name=name))
51+
log.debug("get assistant by name '%s' result: %s", name, assistant)
52+
return assistant
5353

5454
def update(self, **kwargs) -> Self:
5555
updated_keys = []
@@ -62,7 +62,7 @@ def update(self, **kwargs) -> Self:
6262
db.session.add(self)
6363
db.session.commit()
6464
db.session.refresh(self)
65-
log.debug("updated attributes %s of agent %d", updated_keys, self.id)
65+
log.debug("updated attributes %s of assistant %d", updated_keys, self.id)
6666
return self
6767

6868
def add_files(self, file_display_names: Iterable[str]) -> Self:
@@ -72,7 +72,7 @@ def add_files(self, file_display_names: Iterable[str]) -> Self:
7272
if name not in filenames:
7373
filenames.append(name)
7474
log.debug(
75-
"adding %d files to agent %d, total files now %d",
75+
"adding %d files to assistant %d, total files now %d",
7676
len(file_display_names),
7777
self.id,
7878
len(filenames),
@@ -85,7 +85,7 @@ def remove_files(self, file_display_names: Iterable[str]) -> Self:
8585
new_count = len(new_names)
8686
diff = old_count - new_count
8787
log.debug(
88-
"removing %d files from agent %d, old count %d, new count %d",
88+
"removing %d files from assistant %d, old count %d, new count %d",
8989
diff,
9090
self.id,
9191
old_count,
@@ -98,4 +98,4 @@ def remove_files(self, file_display_names: Iterable[str]) -> Self:
9898
def delete(self) -> None:
9999
db.session.delete(self)
100100
db.session.commit()
101-
log.debug("agent with id %d deleted", self.id)
101+
log.debug("assistant with id %d deleted", self.id)

0 commit comments

Comments
 (0)