File size: 8,758 Bytes
a01e687
 
 
 
 
 
 
 
 
09edc25
 
 
 
 
 
a01e687
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9c1115e
a01e687
 
9c1115e
 
 
 
a01e687
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6bc818d
a01e687
 
 
 
6bc818d
a01e687
 
 
 
6bc818d
a01e687
 
 
 
 
 
0fe5085
9c1115e
a01e687
 
 
0fe5085
 
a01e687
 
 
 
 
0fe5085
9c1115e
a01e687
 
0fe5085
 
a01e687
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
"""Streamlit application for ReAct Text Analyzer."""

import streamlit as st
import json
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

# Compatibility: handle both st.rerun() and st.experimental_rerun()
if hasattr(st, 'rerun'):
    rerun = st.rerun
else:
    rerun = st.experimental_rerun

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent))

from agent.react_agent import ReActAgent
from utils.config import Config

# Load environment variables - try multiple locations
env_loaded = False

# Method 1: Try parent directory (when running from src/)
env_path = Path(__file__).parent.parent / '.env'
if env_path.exists():
    load_dotenv(env_path)
    env_loaded = True

# Method 2: Try current directory (when running from project root)
if not env_loaded or not os.getenv('OPENAI_API_KEY'):
    if Path('.env').exists():
        load_dotenv('.env')
        env_loaded = True

# Method 3: Auto-search parent directories
if not os.getenv('OPENAI_API_KEY'):
    load_dotenv()  # Searches current and parent directories automatically

# Page configuration
st.set_page_config(
    page_title="ReAct Text Analyzer",
    layout="wide"
)

# Initialize config and example state
if 'config' not in st.session_state:
    st.session_state.config = Config()
if 'example_text' not in st.session_state:
    st.session_state.example_text = ''
if 'example_question' not in st.session_state:
    st.session_state.example_question = ''

# Sidebar configuration
with st.sidebar:
    st.header("Configuration")

    # Model selection
    model = st.selectbox(
        "Model",
        [
            "gpt-4-turbo-preview",
            "gpt-4",
            "gpt-3.5-turbo"
        ],
        help="Select the OpenAI model to use"
    )

    # Max iterations
    max_iterations = st.slider(
        "Max Iterations",
        min_value=3,
        max_value=15,
        value=10,
        help="Maximum number of reasoning iterations"
    )

    st.divider()

    # Information
    st.markdown("""
    ### About
    This is a ReAct (Reasoning + Acting) agent for text analysis.

    **Available Tools:**
    - Word Counter
    - Keyword Extractor
    - Sentiment Analyzer

    **How to use:**
    1. Input text to analyze
    2. Ask a question
    3. View the agent's reasoning process
    """)

# Main content
st.title("ReAct Text Analyzer")
st.markdown("""
<div style='margin-bottom: 2rem; padding: 1rem; background-color: #f8f9fa; border-radius: 0.5rem; border-left: 4px solid #4A90E2;'>
    <p style='margin: 0; color: #555; font-size: 1.1rem;'>Analyze text using AI-powered reasoning and specialized tools</p>
</div>
""", unsafe_allow_html=True)

# Check if API key is provided
if not st.session_state.config.is_valid():
    st.error("Please set OPENAI_API_KEY in your .env file or environment variables.")
    st.stop()

# Example texts for quick testing
with st.expander("Try Example Texts"):
    col1, col2, col3 = st.columns(3)

    with col1:
        if st.button("Example 1: Product Review", key="ex1"):
            st.session_state.example_text = """This product is absolutely amazing! I've been using it for three months now and couldn't be happier. The quality is outstanding, and the customer service is excellent. The design is beautiful and modern. However, the price is a bit high, but I think it's worth every penny. Highly recommended for anyone looking for a reliable solution. The features are innovative and user-friendly. I love how easy it is to use!"""
            st.session_state.example_question = "What is the overall sentiment and what are the main topics discussed?"

    with col2:
        if st.button("Example 2: News Article", key="ex2"):
            st.session_state.example_text = """The new technology breakthrough announced today promises to revolutionize the industry. Scientists have developed an innovative approach that could solve long-standing problems. The research team, led by experts from multiple universities, demonstrated significant improvements in efficiency. However, some critics argue that implementation challenges remain. The project received substantial funding from government agencies and private investors. Initial tests show promising results, though more research is needed."""
            st.session_state.example_question = "Extract the key topics and analyze the sentiment"

    with col3:
        if st.button("Example 3: Short Story", key="ex3"):
            st.session_state.example_text = """The old lighthouse stood tall against the stormy night. Waves crashed violently against the rocks below. Inside, the keeper tended the light, ensuring it never went out. For years, he had performed this duty faithfully. Tonight felt different somehow. The wind howled louder than ever before. Yet he remained calm, focused on his purpose. Ships depended on that light. Lives depended on his vigilance."""
            st.session_state.example_question = "How many words are in this text and what is the mood?"

# Text input
st.markdown("#### Text to Analyze")
text_input = st.text_area(
    label="Text to Analyze",
    value=st.session_state.example_text,
    height=200,
    placeholder="Enter the text you want to analyze here...",
    help="Paste or type the text you want the agent to analyze",
    label_visibility="collapsed",
    key="text_area_input"
)

# Question input
st.markdown("#### Your Question")
question_input = st.text_input(
    label="Your Question",
    value=st.session_state.example_question,
    placeholder="e.g., What is the sentiment of this text? What are the main keywords?",
    help="Ask a question about the text",
    label_visibility="collapsed",
    key="question_text_input"
)

# Analyze button
st.markdown("<div style='margin: 1.5rem 0;'></div>", unsafe_allow_html=True)
if st.button("Analyze", type="primary", use_container_width=True):
    if not text_input:
        st.error("Please enter some text to analyze.")
    elif not question_input:
        st.error("Please enter a question.")
    else:
        with st.spinner("Agent is thinking..."):
            try:
                # Initialize agent
                agent = ReActAgent(
                    api_key=st.session_state.config.get_openai_key(),
                    model=model,
                    max_iterations=max_iterations
                )

                # Run agent
                result = agent.run(question_input, text_input)

                # Display results
                st.success("Analysis Complete!")

                # Final Answer
                st.markdown("### Final Answer")
                st.markdown(f"""
                <div style='padding: 1.5rem; background-color: #f8f9fa; border-radius: 0.5rem; border-left: 4px solid #28a745;'>
                    {result['answer']}
                </div>
                """, unsafe_allow_html=True)

                # Metrics
                st.markdown("### Statistics")
                col1, col2, col3 = st.columns(3)
                with col1:
                    st.metric("Iterations", result['iterations'])
                with col2:
                    st.metric("Success", "Yes" if result['success'] else "No")
                with col3:
                    st.metric("Tools Used", len([t for t in result['trace'] if t['type'] == 'action']))

                # Agent reasoning trace
                with st.expander("Agent Reasoning Process", expanded=False):
                    for i, step in enumerate(result['trace']):
                        if step['type'] == 'thought':
                            st.markdown(f"**Step {step['iteration']}:**")
                            st.text_area(
                                "Agent Thinking",
                                value=step['content'],
                                height=150,
                                key=f"thought_{i}",
                                disabled=True
                            )
                        elif step['type'] == 'action':
                            st.markdown(f"**Action:** `{step['action']}`")
                            st.code(f"Input: {step['input'][:100]}...", language="text")
                            st.json(step['output'])

                        st.divider()

                # Raw result (for debugging)
                with st.expander("Raw Result (Debug)", expanded=False):
                    st.json(result)

            except Exception as e:
                st.error(f"Error: {str(e)}")
                st.exception(e)

# Footer
st.divider()
st.markdown("""
<div style='text-align: center; color: #888; font-size: 0.9em; padding: 1rem 0;'>
    Built with Streamlit • Powered by OpenAI • ReAct Framework
</div>
""", unsafe_allow_html=True)