Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Create table user_slack_persona

Revision ID: 792d1af3dc44
Revises: 3a7802814195
Create Date: 2025-01-24 04:26:02.844951

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "792d1af3dc44"
down_revision = "3a7802814195"
branch_labels = None
depends_on = None


def upgrade() -> None:
op.create_table(
"user_slack_persona",
sa.Column("sender_id", sa.String(), nullable=False),
sa.Column("persona_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["persona_id"],
["persona.id"],
),
sa.PrimaryKeyConstraint("sender_id"),
)


def downgrade() -> None:
op.drop_table("user_slack_persona")
31 changes: 31 additions & 0 deletions backend/danswer/auth/api_key.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from fastapi import Depends
from fastapi import HTTPException
from fastapi import Request
from sqlalchemy import select
from sqlalchemy.orm import Session

from danswer.db.engine import get_session
from danswer.db.models import ApiKey
from danswer.utils.logger import setup_logger


logger = setup_logger()

_API_KEY_HEADER = "X-API-Key"


def validate_api_key(request: Request, db_session: Session = Depends(get_session)):
if _API_KEY_HEADER not in request.headers:
return None

api_key_value = request.headers.get(_API_KEY_HEADER)
if not api_key_value:
raise HTTPException(status_code=401, detail="Missing API key")

api_key = db_session.scalar(
select(ApiKey).where(ApiKey.hashed_api_key == api_key_value)
)
if not api_key:
raise HTTPException(status_code=401, detail="Invalid API key")

return None
52 changes: 33 additions & 19 deletions backend/danswer/chat/chat_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,27 +114,29 @@ def combine_message_chain(
return "\n\n".join(message_strs)


def reorganize_citations(
answer: str, citations: list[CitationInfo]
) -> tuple[str, list[CitationInfo]]:
"""For a complete, citation-aware response, we want to reorganize the citations so that
def reorganize_citations(answer: str, citations: list) -> tuple[str, list]:
"""
For a complete, citation-aware response, we want to reorganize the citations so that
they are in the order of the documents that were used in the response. This just looks nicer / avoids
confusion ("Why is there [7] when only 2 documents are cited?")."""
confusion ("Why is there [7] when only 2 documents are cited?").

# Regular expression to find all instances of [[x]](LINK)
pattern = r"\[\[(.*?)\]\]\((.*?)\)"
Now also handles citations in the format [number] in addition to [[number]](LINK).
"""

pattern = r"\[\[(\d+)\]\]\((.*?)\)|\[(\d+)\]"

all_citation_matches = re.findall(pattern, answer)

new_citation_info: dict[int, CitationInfo] = {}
for citation_match in all_citation_matches:
try:
citation_num = int(citation_match[0])
citation_str = citation_match[0] if citation_match[0] else citation_match[2]
citation_num = int(citation_str)
if citation_num in new_citation_info:
continue

matching_citation = next(
iter([c for c in citations if c.citation_num == int(citation_num)]),
(c for c in citations if c.citation_num == citation_num),
None,
)
if matching_citation is None:
Expand All @@ -149,16 +151,28 @@ def reorganize_citations(

# Function to replace citations with their new number
def slack_link_format(match: re.Match) -> str:
link_text = match.group(1)
try:
citation_num = int(link_text)
if citation_num in new_citation_info:
link_text = new_citation_info[citation_num].citation_num
except Exception:
pass

link_url = match.group(2)
return f"[[{link_text}]]({link_url})"
# Case 1: Linked citation ([[number]](LINK))
if match.group(1):
link_text = match.group(1)
try:
citation_num = int(link_text)
if citation_num in new_citation_info:
link_text = new_citation_info[citation_num].citation_num
except Exception:
pass
link_url = match.group(2)
return f"[[{link_text}]]({link_url})"
# Case 2: Non-linked citation ([number])
elif match.group(3):
try:
citation_num = int(match.group(3))
if citation_num in new_citation_info:
citation_num = new_citation_info[citation_num].citation_num
except Exception:
pass
return f"[{citation_num}]"
else:
return match.group(0)

# Substitute all matches in the input text
new_answer = re.sub(pattern, slack_link_format, answer)
Expand Down
4 changes: 4 additions & 0 deletions backend/danswer/configs/app_configs.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@
for ignored_tag in os.environ.get("JIRA_CONNECTOR_LABELS_TO_SKIP", "").split(",")
if ignored_tag
]
# Maximum size for Jira tickets in bytes (default: 100KB)
JIRA_CONNECTOR_MAX_TICKET_SIZE = int(
os.environ.get("JIRA_CONNECTOR_MAX_TICKET_SIZE", 100 * 1024)
)

GONG_CONNECTOR_START_TIME = os.environ.get("GONG_CONNECTOR_START_TIME")

Expand Down
1 change: 1 addition & 0 deletions backend/danswer/configs/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class DocumentSource(str, Enum):
SHAREPOINT = "sharepoint"
TEAMS = "teams"
SALESFORCE = "salesforce"
SFKBARTICLES = "sfkbarticles"
DISCOURSE = "discourse"
AXERO = "axero"
CLICKUP = "clickup"
Expand Down
Loading