Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Expand Up @@ -31,6 +31,12 @@ def upgrade() -> None:


def downgrade() -> None:
# First, update any null values to a default value
op.execute(
"UPDATE connector_credential_pair SET last_attempt_status = 'NOT_STARTED' WHERE last_attempt_status IS NULL"
)

# Then, make the column non-nullable
op.alter_column(
"connector_credential_pair",
"last_attempt_status",
Expand Down
6 changes: 5 additions & 1 deletion backend/danswer/llm/answering/answer.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ def _raw_output_for_explicit_tool_calling_llms(
prompt=prompt,
tools=final_tool_definitions if final_tool_definitions else None,
tool_choice="required" if self.force_use_tool.force_use else None,
structured_response_format=self.answer_style_config.structured_response_format,
):
if isinstance(message, AIMessageChunk) and (
message.tool_call_chunks or message.tool_calls
Expand Down Expand Up @@ -331,7 +332,10 @@ def _process_llm_stream(
tool_choice: ToolChoiceOptions | None = None,
) -> Iterator[str | StreamStopInfo]:
for message in self.llm.stream(
prompt=prompt, tools=tools, tool_choice=tool_choice
prompt=prompt,
tools=tools,
tool_choice=tool_choice,
structured_response_format=self.answer_style_config.structured_response_format,
):
if isinstance(message, AIMessageChunk):
if message.content:
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def reset() -> None:


@pytest.fixture
def new_admin_user(reset: None) -> DATestUser | None:
def new_admin_user() -> DATestUser | None:
try:
return UserManager.create(name="admin_user")
except Exception:
Expand Down
47 changes: 23 additions & 24 deletions backend/tests/integration/tests/dev_apis/test_simple_chat_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,42 +154,38 @@ def test_send_message_simple_with_history_strict_json(
new_admin_user: DATestUser | None,
) -> None:
# create connectors
cc_pair_1: DATestCCPair = CCPairManager.create_from_scratch(
user_performing_action=new_admin_user,
)
api_key: DATestAPIKey = APIKeyManager.create(
user_performing_action=new_admin_user,
)
LLMProviderManager.create(user_performing_action=new_admin_user)
cc_pair_1.documents = DocumentManager.seed_dummy_docs(
cc_pair=cc_pair_1,
num_docs=NUM_DOCS,
api_key=api_key,
)

response = requests.post(
f"{API_SERVER_URL}/chat/send-message-simple-with-history",
json={
# intentionally not relevant prompt to ensure that the
# structured response format is actually used
"messages": [
{
"message": "List the names of the first three US presidents in JSON format",
"message": "What is green?",
"role": MessageType.USER.value,
}
],
"persona_id": 0,
"prompt_id": 0,
"structured_response_format": {
"type": "json_object",
"schema": {
"type": "object",
"properties": {
"presidents": {
"type": "array",
"items": {"type": "string"},
"description": "List of the first three US presidents",
}
"type": "json_schema",
"json_schema": {
"name": "presidents",
"schema": {
"type": "object",
"properties": {
"presidents": {
"type": "array",
"items": {"type": "string"},
"description": "List of the first three US presidents",
}
},
"required": ["presidents"],
"additionalProperties": False,
},
"required": ["presidents"],
"strict": True,
},
},
},
Expand All @@ -211,14 +207,17 @@ def clean_json_string(json_string: str) -> str:
try:
clean_answer = clean_json_string(response_json["answer"])
parsed_answer = json.loads(clean_answer)

# NOTE: do not check content, just the structure
assert isinstance(parsed_answer, dict)
assert "presidents" in parsed_answer
assert isinstance(parsed_answer["presidents"], list)
assert len(parsed_answer["presidents"]) == 3
for president in parsed_answer["presidents"]:
assert isinstance(president, str)
except json.JSONDecodeError:
assert False, "The answer is not a valid JSON object"
assert (
False
), f"The answer is not a valid JSON object - '{response_json['answer']}'"

# Check that the answer_citationless is also valid JSON
assert "answer_citationless" in response_json
Expand Down
Loading