support think tag on expert
This commit is contained in:
parent
cf150173aa
commit
e49cce301f
|
|
@ -171,7 +171,7 @@ models_params = {
|
||||||
"supports_think_tag": True,
|
"supports_think_tag": True,
|
||||||
"supports_temperature": True,
|
"supports_temperature": True,
|
||||||
"latency_coefficient": DEFAULT_BASE_LATENCY,
|
"latency_coefficient": DEFAULT_BASE_LATENCY,
|
||||||
"max_tokens": 64000,
|
"max_tokens": 130000,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"azure_openai": {
|
"azure_openai": {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ from ..llm import initialize_expert_llm
|
||||||
from ..model_formatters import format_key_facts_dict
|
from ..model_formatters import format_key_facts_dict
|
||||||
from ..model_formatters.key_snippets_formatter import format_key_snippets_dict
|
from ..model_formatters.key_snippets_formatter import format_key_snippets_dict
|
||||||
from ..model_formatters.research_notes_formatter import format_research_notes_dict
|
from ..model_formatters.research_notes_formatter import format_research_notes_dict
|
||||||
|
from ..models_params import models_params
|
||||||
|
from ..text import extract_think_tag
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
_model = None
|
_model = None
|
||||||
|
|
@ -231,10 +233,38 @@ def ask_expert(question: str) -> str:
|
||||||
|
|
||||||
# Get the content from the response
|
# Get the content from the response
|
||||||
content = response.content
|
content = response.content
|
||||||
|
logger.debug(f"Expert response content type: {type(content).__name__}")
|
||||||
|
|
||||||
|
# Check if model supports think tags
|
||||||
|
config_repo = get_config_repository()
|
||||||
|
provider = config_repo.get("expert_provider") or config_repo.get("provider")
|
||||||
|
model_name = config_repo.get("expert_model") or config_repo.get("model")
|
||||||
|
model_config = models_params.get(provider, {}).get(model_name, {})
|
||||||
|
supports_think_tag = model_config.get("supports_think_tag", False)
|
||||||
|
supports_thinking = model_config.get("supports_thinking", False)
|
||||||
|
|
||||||
|
logger.debug(f"Expert model: {provider}/{model_name}")
|
||||||
|
logger.debug(f"Model supports think tag: {supports_think_tag}")
|
||||||
|
logger.debug(f"Model supports thinking: {supports_thinking}")
|
||||||
|
|
||||||
# Handle thinking mode responses (content is a list) or regular responses (content is a string)
|
# Handle thinking mode responses (content is a list) or regular responses (content is a string)
|
||||||
try:
|
try:
|
||||||
if isinstance(content, list):
|
# Case 1: Check for think tags if the model supports them
|
||||||
|
if (supports_think_tag or supports_thinking) and isinstance(content, str):
|
||||||
|
logger.debug("Checking for think tags in expert response")
|
||||||
|
think_content, remaining_text = extract_think_tag(content)
|
||||||
|
if think_content:
|
||||||
|
logger.debug(f"Found think tag content ({len(think_content)} chars)")
|
||||||
|
console.print(
|
||||||
|
Panel(Markdown(think_content), title="💭 Thoughts", border_style="yellow")
|
||||||
|
)
|
||||||
|
content = remaining_text
|
||||||
|
else:
|
||||||
|
logger.debug("No think tag content found in expert response")
|
||||||
|
|
||||||
|
# Case 2: Handle structured thinking (content is a list of dictionaries)
|
||||||
|
elif isinstance(content, list):
|
||||||
|
logger.debug("Expert response content is a list, processing structured thinking")
|
||||||
# Extract thinking content and response text from structured response
|
# Extract thinking content and response text from structured response
|
||||||
thinking_content = None
|
thinking_content = None
|
||||||
response_text = None
|
response_text = None
|
||||||
|
|
@ -245,12 +275,15 @@ def ask_expert(question: str) -> str:
|
||||||
# Extract thinking content
|
# Extract thinking content
|
||||||
if item.get('type') == 'thinking' and 'thinking' in item:
|
if item.get('type') == 'thinking' and 'thinking' in item:
|
||||||
thinking_content = item['thinking']
|
thinking_content = item['thinking']
|
||||||
|
logger.debug("Found structured thinking content")
|
||||||
# Extract response text
|
# Extract response text
|
||||||
elif item.get('type') == 'text' and 'text' in item:
|
elif item.get('type') == 'text' and 'text' in item:
|
||||||
response_text = item['text']
|
response_text = item['text']
|
||||||
|
logger.debug("Found structured response text")
|
||||||
|
|
||||||
# Display thinking content in a separate panel if available
|
# Display thinking content in a separate panel if available
|
||||||
if thinking_content:
|
if thinking_content:
|
||||||
|
logger.debug(f"Displaying structured thinking content ({len(thinking_content)} chars)")
|
||||||
console.print(
|
console.print(
|
||||||
Panel(Markdown(thinking_content), title="Expert Thinking", border_style="yellow")
|
Panel(Markdown(thinking_content), title="Expert Thinking", border_style="yellow")
|
||||||
)
|
)
|
||||||
|
|
@ -260,6 +293,7 @@ def ask_expert(question: str) -> str:
|
||||||
content = response_text
|
content = response_text
|
||||||
else:
|
else:
|
||||||
# Fallback: join list items if structured extraction failed
|
# Fallback: join list items if structured extraction failed
|
||||||
|
logger.debug("No structured response text found, joining list items")
|
||||||
content = "\n".join(str(item) for item in content)
|
content = "\n".join(str(item) for item in content)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
"""Test the think tag functionality in the expert tool."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from unittest.mock import patch, MagicMock
|
||||||
|
|
||||||
|
from ra_aid.text.processing import extract_think_tag
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_think_tag_basic():
|
||||||
|
"""Test basic functionality of extract_think_tag."""
|
||||||
|
# Test basic think tag extraction
|
||||||
|
text = "<think>This is thinking content</think>This is the response"
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
|
||||||
|
assert think_content == "This is thinking content"
|
||||||
|
assert remaining_text == "This is the response"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_think_tag_multiline():
|
||||||
|
"""Test extract_think_tag with multiline content."""
|
||||||
|
text = "<think>Line 1\nLine 2\nLine 3</think>This is the response"
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
|
||||||
|
assert think_content == "Line 1\nLine 2\nLine 3"
|
||||||
|
assert remaining_text == "This is the response"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_think_tag_no_tag():
|
||||||
|
"""Test extract_think_tag when no tag is present."""
|
||||||
|
text = "This is just regular text with no think tag"
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
|
||||||
|
assert think_content is None
|
||||||
|
assert remaining_text == text
|
||||||
|
|
||||||
|
|
||||||
|
def test_expert_think_tag_handling():
|
||||||
|
"""Test the logic that would be used in the expert tool for think tag handling."""
|
||||||
|
# Mimic the implementation from expert.py
|
||||||
|
def process_expert_response(text, supports_think_tag=False):
|
||||||
|
"""Simulate the expert tool's think tag handling."""
|
||||||
|
if supports_think_tag:
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
if think_content:
|
||||||
|
# In the real implementation, this would display the thoughts
|
||||||
|
thoughts_displayed = True
|
||||||
|
return thoughts_displayed, think_content, remaining_text
|
||||||
|
|
||||||
|
# No think content extracted
|
||||||
|
return False, None, text
|
||||||
|
|
||||||
|
# Test with think tag and support enabled
|
||||||
|
thoughts_displayed, think_content, response = process_expert_response(
|
||||||
|
"<think>Here's my reasoning</think>Final answer",
|
||||||
|
supports_think_tag=True
|
||||||
|
)
|
||||||
|
assert thoughts_displayed
|
||||||
|
assert think_content == "Here's my reasoning"
|
||||||
|
assert response == "Final answer"
|
||||||
|
|
||||||
|
# Test with think tag but support disabled
|
||||||
|
thoughts_displayed, think_content, response = process_expert_response(
|
||||||
|
"<think>Here's my reasoning</think>Final answer",
|
||||||
|
supports_think_tag=False
|
||||||
|
)
|
||||||
|
assert not thoughts_displayed
|
||||||
|
assert think_content is None
|
||||||
|
assert response == "<think>Here's my reasoning</think>Final answer"
|
||||||
|
|
||||||
|
# Test with no think tag
|
||||||
|
thoughts_displayed, think_content, response = process_expert_response(
|
||||||
|
"Just a regular response",
|
||||||
|
supports_think_tag=True
|
||||||
|
)
|
||||||
|
assert not thoughts_displayed
|
||||||
|
assert think_content is None
|
||||||
|
assert response == "Just a regular response"
|
||||||
|
|
||||||
|
|
||||||
|
def test_expert_think_tag_with_supports_thinking():
|
||||||
|
"""Test handling of the supports_thinking parameter."""
|
||||||
|
# Mimic the implementation from expert.py
|
||||||
|
def process_expert_response(text, supports_think_tag=False, supports_thinking=False):
|
||||||
|
"""Simulate the expert tool's think tag handling with both parameters."""
|
||||||
|
if supports_think_tag or supports_thinking:
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
if think_content:
|
||||||
|
# In the real implementation, this would display the thoughts
|
||||||
|
thoughts_displayed = True
|
||||||
|
return thoughts_displayed, think_content, remaining_text
|
||||||
|
|
||||||
|
# No think content extracted
|
||||||
|
return False, None, text
|
||||||
|
|
||||||
|
# Test with supports_thinking=True
|
||||||
|
thoughts_displayed, think_content, response = process_expert_response(
|
||||||
|
"<think>Thinking with alternate parameter</think>Final answer",
|
||||||
|
supports_think_tag=False,
|
||||||
|
supports_thinking=True
|
||||||
|
)
|
||||||
|
assert thoughts_displayed
|
||||||
|
assert think_content == "Thinking with alternate parameter"
|
||||||
|
assert response == "Final answer"
|
||||||
|
|
||||||
|
|
||||||
|
def test_expert_think_tag_combined_flags():
|
||||||
|
"""Test that either flag (supports_think_tag or supports_thinking) enables extraction."""
|
||||||
|
# Mimic the implementation from expert.py
|
||||||
|
def process_expert_response(text, supports_think_tag=False, supports_thinking=False):
|
||||||
|
"""Simulate the expert tool's think tag handling with both parameters."""
|
||||||
|
if supports_think_tag or supports_thinking:
|
||||||
|
think_content, remaining_text = extract_think_tag(text)
|
||||||
|
if think_content:
|
||||||
|
return think_content, remaining_text
|
||||||
|
return None, text
|
||||||
|
|
||||||
|
test_input = "<think>Some thoughts</think>Response text"
|
||||||
|
|
||||||
|
# Test with both flags False
|
||||||
|
think_content, response = process_expert_response(
|
||||||
|
test_input,
|
||||||
|
supports_think_tag=False,
|
||||||
|
supports_thinking=False
|
||||||
|
)
|
||||||
|
assert think_content is None
|
||||||
|
assert response == test_input
|
||||||
|
|
||||||
|
# Test with supports_think_tag=True
|
||||||
|
think_content, response = process_expert_response(
|
||||||
|
test_input,
|
||||||
|
supports_think_tag=True,
|
||||||
|
supports_thinking=False
|
||||||
|
)
|
||||||
|
assert think_content == "Some thoughts"
|
||||||
|
assert response == "Response text"
|
||||||
|
|
||||||
|
# Test with supports_thinking=True
|
||||||
|
think_content, response = process_expert_response(
|
||||||
|
test_input,
|
||||||
|
supports_think_tag=False,
|
||||||
|
supports_thinking=True
|
||||||
|
)
|
||||||
|
assert think_content == "Some thoughts"
|
||||||
|
assert response == "Response text"
|
||||||
|
|
||||||
|
# Test with both flags True
|
||||||
|
think_content, response = process_expert_response(
|
||||||
|
test_input,
|
||||||
|
supports_think_tag=True,
|
||||||
|
supports_thinking=True
|
||||||
|
)
|
||||||
|
assert think_content == "Some thoughts"
|
||||||
|
assert response == "Response text"
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue