diff --git a/ra_aid/agent_backends/ciayn_agent.py b/ra_aid/agent_backends/ciayn_agent.py
index 7a5f70e..855eb57 100644
--- a/ra_aid/agent_backends/ciayn_agent.py
+++ b/ra_aid/agent_backends/ciayn_agent.py
@@ -620,6 +620,8 @@ class CiaynAgent:
self.chat_history.append(HumanMessage(content=base_prompt))
full_history = self._trim_chat_history(initial_messages, self.chat_history)
response = self.model.invoke([self.sys_message] + full_history)
+ print("RESPONSE")
+ print(response.content)
# Check if the response is empty or doesn't contain a valid tool call
if not response.content or not response.content.strip():
diff --git a/ra_aid/models_params.py b/ra_aid/models_params.py
index d7019de..3e08fad 100644
--- a/ra_aid/models_params.py
+++ b/ra_aid/models_params.py
@@ -165,6 +165,15 @@ models_params = {
"latency_coefficient": DEFAULT_BASE_LATENCY,
},
},
+ "openai-compatible": {
+ "qwen-qwq-32b": {
+ "token_limit": 130000,
+ "think_tag": True,
+ "supports_temperature": True,
+ "latency_coefficient": DEFAULT_BASE_LATENCY,
+ "max_tokens": 64000,
+ }
+ },
"azure_openai": {
"gpt-3.5-turbo-0125": {
"token_limit": 16385,
diff --git a/ra_aid/text/__init__.py b/ra_aid/text/__init__.py
index 0b66541..3ab76b6 100644
--- a/ra_aid/text/__init__.py
+++ b/ra_aid/text/__init__.py
@@ -1,3 +1,3 @@
-from .processing import truncate_output
+from .processing import truncate_output, extract_think_tag
-__all__ = ["truncate_output"]
+__all__ = ["truncate_output", "extract_think_tag"]
\ No newline at end of file
diff --git a/ra_aid/text/processing.py b/ra_aid/text/processing.py
index 65279ac..aae86c5 100644
--- a/ra_aid/text/processing.py
+++ b/ra_aid/text/processing.py
@@ -1,4 +1,5 @@
-from typing import Optional
+from typing import Optional, Tuple
+import re
def truncate_output(output: str, max_lines: Optional[int] = 5000) -> str:
@@ -41,3 +42,29 @@ def truncate_output(output: str, max_lines: Optional[int] = 5000) -> str:
# Combine message with remaining lines
return truncation_msg + "".join(truncated_lines)
+
+
+def extract_think_tag(text: str) -> Tuple[Optional[str], str]:
+ """Extract content from the first ... tag at the start of a string.
+
+ Args:
+ text: Input string that may contain think tags
+
+ Returns:
+ A tuple containing:
+ - The extracted content from the first think tag (None if no tag found)
+ - The remaining string after the first think tag (or the original string if no tag found)
+ """
+ # Pattern to match think tags at the start of the string
+ pattern = r'^\s*(.*?)'
+ match = re.search(pattern, text, re.DOTALL)
+
+ if match:
+ think_content = match.group(1)
+ # Get the index where the think tag ends
+ end_index = match.end()
+ # Extract the remaining text
+ remaining_text = text[end_index:]
+ return think_content, remaining_text
+ else:
+ return None, text
\ No newline at end of file
diff --git a/tests/data/think-tag/sample_1.txt b/tests/data/think-tag/sample_1.txt
new file mode 100644
index 0000000..8269340
--- /dev/null
+++ b/tests/data/think-tag/sample_1.txt
@@ -0,0 +1,63 @@
+
+Okay, the user wants me to write a "hello world" program in C++. Let me think about the steps needed.
+
+First, since it's a new project, there are no existing files. So I need to create a main C++ file. The standard entry point for C++ is a main.cpp or something similar. Let's name it main.cpp.
+
+The code for "Hello World" in C++ typically includes the iostream header and uses std::cout. So the code would be:
+
+#include
+using namespace std;
+
+int main() {
+ cout << "Hello, world!" << endl;
+ return 0;
+}
+
+Wait, but maybe I should check if there's a standard way. Alternatively, sometimes people use std::cout directly instead of the using directive. Maybe the better practice is to avoid the using namespace std; for clarity, so perhaps rewrite it as:
+
+#include
+int main() {
+ std::cout << "Hello, world!" << std::endl;
+ return 0;
+}
+
+Hmm, but the user said to keep it simple. The first version is simpler for a beginner example. But maybe the second is better for standards. Let me think. Since the user said "keep it simple", the first version is okay, but I should make sure that the code compiles.
+
+Next, the user is in a new project directory, so I need to create the main.cpp file. The function to use is request_task_implementation, which takes a task spec. The task spec should be a markdown detailing the steps. Wait, looking back at the available functions, the request_task_implementation function requires a task specification in markdown. So I need to structure that.
+
+The task spec should describe creating the main.cpp file with the code. So the task_spec would be something like "Create a C++ file named main.cpp with the Hello World program. The program should include iostream, use std::cout to output 'Hello, world!' and end with a return 0; statement in main()".
+
+Wait, but the user might prefer the using namespace std; to simplify. Let me check again. Since it's a simple example, using the using namespace is acceptable for brevity. So the code would be:
+
+#include
+using namespace std;
+
+int main() {
+ cout << "Hello, world!" << endl;
+ return 0;
+}
+
+Yes, that's standard. Now, to implement this, the correct function to use is request_task_implementation with that code. So the tool call would be to request_task_implementation with the task spec as a markdown string.
+
+Alternatively, maybe I should first check if there's any existing files, but since it's a new project with 0 files, listing directories might be redundant. The efficiency guidelines say to avoid listing empty directories. So instead, proceed directly to creating the file.
+
+Therefore, the correct tool call here is to call request_task_implementation with the task specification to create main.cpp with the code.
+
+
+request_task_implementation('''Create a C++ source file named main.cpp containing a standard "Hello World" program.
+
+Steps:
+1. Create file main.cpp
+2. Add the following content:
+#include
+using namespace std;
+
+int main() {
+ cout << "Hello, world!" << endl;
+ return 0;
+}
+
+Acceptance Criteria:
+- The program compiles without errors using g++ main.cpp -o hello
+- Running ./hello outputs exactly "Hello, world!" followed by a newline
+''')
\ No newline at end of file
diff --git a/tests/ra_aid/text/__init__.py b/tests/ra_aid/text/__init__.py
new file mode 100644
index 0000000..62272da
--- /dev/null
+++ b/tests/ra_aid/text/__init__.py
@@ -0,0 +1 @@
+# This file makes the directory a Python package.
\ No newline at end of file
diff --git a/tests/ra_aid/text/test_processing.py b/tests/ra_aid/text/test_processing.py
new file mode 100644
index 0000000..8b84838
--- /dev/null
+++ b/tests/ra_aid/text/test_processing.py
@@ -0,0 +1,102 @@
+import os
+import pytest
+from ra_aid.text.processing import extract_think_tag
+
+def test_basic_extraction():
+ """Test basic extraction of think tag content."""
+ content = "This is a testRemaining content"
+ expected_extracted = "This is a test"
+ expected_remaining = "Remaining content"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted == expected_extracted
+ assert remaining == expected_remaining
+
+def test_multiline_extraction():
+ """Test extraction of multiline think tag content."""
+ content = "Line 1\nLine 2\nLine 3Remaining content"
+ expected_extracted = "Line 1\nLine 2\nLine 3"
+ expected_remaining = "Remaining content"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted == expected_extracted
+ assert remaining == expected_remaining
+
+def test_multiple_think_tags():
+ """Test that only the first think tag is extracted."""
+ content = "First tagMiddleSecond tagEnd"
+ expected_extracted = "First tag"
+ expected_remaining = "MiddleSecond tagEnd"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted == expected_extracted
+ assert remaining == expected_remaining
+
+def test_no_think_tag():
+ """Test behavior when no think tag is present."""
+ content = "This is a string without a think tag"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted is None
+ assert remaining == content
+
+def test_empty_think_tag():
+ """Test extraction of an empty think tag."""
+ content = "Remaining content"
+ expected_extracted = ""
+ expected_remaining = "Remaining content"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted == expected_extracted
+ assert remaining == expected_remaining
+
+def test_whitespace_handling():
+ """Test whitespace handling in think tag extraction."""
+ content = " \n Content with whitespace \n Remaining content"
+ expected_extracted = " \n Content with whitespace \n "
+ expected_remaining = "Remaining content"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted == expected_extracted
+ assert remaining == expected_remaining
+
+def test_tag_not_at_start():
+ """Test behavior when think tag is not at the start of the string."""
+ content = "Some content before Think contentRemaining content"
+
+ extracted, remaining = extract_think_tag(content)
+
+ assert extracted is None
+ assert remaining == content
+
+def test_sample_data():
+ """Test extraction using sample data from tests/data/think-tag/sample_1.txt."""
+ # Get the absolute path to the sample file
+ current_dir = os.path.dirname(os.path.abspath(__file__))
+ sample_file_path = os.path.join(current_dir, '..', '..', 'data', 'think-tag', 'sample_1.txt')
+
+ # Read the sample data
+ with open(sample_file_path, 'r', encoding='utf-8') as f:
+ sample_data = f.read()
+
+ # Extract the think tag
+ extracted, remaining = extract_think_tag(sample_data)
+
+ # Check that extraction worked
+ assert extracted is not None
+ assert "Okay, the user wants me to write a" in extracted
+ assert "return 0;" in extracted
+
+ # Check that we got the think tag content without the tags
+ assert not extracted.startswith("")
+ assert not extracted.endswith("")
+
+ # Check that the remaining content doesn't contain the think tag
+ assert "" not in remaining
+ assert "" not in remaining
\ No newline at end of file