gaialive commited on
Commit
7d37b33
·
verified ·
1 Parent(s): 8978955

Upload 9 files

Browse files
agents/__init__.py ADDED
File without changes
agents/frameworks.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ TEMPLATE_FRAMEWORKS = {
2
+ "GRI": "GRI Standards template: [Include here detailed GRI ESG report template structure...]",
3
+ "TCFD": "Task Force on Climate-related Financial Disclosures (TCFD) template: [...]",
4
+ "TNFD": "Taskforce on Nature-related Financial Disclosures (TNFD) template: [...]",
5
+ "CDP": "Carbon Disclosure Project (CDP) template: [...]",
6
+ "SASB": "Sustainability Accounting Standards Board (SASB) template: [...]",
7
+ "CSRD": "Corporate Sustainability Reporting Directive (CSRD) template: [...]",
8
+ "CSDDD": "Corporate Sustainability Due Diligence Directive (CSDDD) template: [...]",
9
+ "IFRS": "International Financial Reporting Standards (IFRS) ESG template: [...]",
10
+ "Gold Standard": "Gold Standard for carbon projects template: [...]",
11
+ "CBAM": "Carbon Border Adjustment Mechanism (CBAM) reporting template: [...]",
12
+ "GHG Protocol": "GHG Protocol reporting template: [...]",
13
+ "SBTi": "Science Based Targets initiative (SBTi) reporting template: [...]",
14
+ }
15
+
16
+ FRAMEWORKS = {
17
+ "GRI": [
18
+ "Disclose total energy consumption.",
19
+ "Report on greenhouse gas emissions (Scope 1 & 2).",
20
+ "Describe water consumption and conservation measures.",
21
+ "Provide information on workforce diversity.",
22
+ "Describe anti-corruption policies and actions."
23
+ ],
24
+ # ... other frameworks as before ...
25
+ }
26
+
27
+
agents/greenwash_utils.py ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import fitz # PyMuPDF for PDF extraction
2
+ import docx # python-docx for DOCX extraction
3
+ import requests
4
+ import json
5
+ import streamlit as st
6
+
7
+ def extract_text(uploaded_file):
8
+ """Extracts text from an uploaded file (PDF or DOCX)."""
9
+ try:
10
+ if uploaded_file.type == "application/pdf":
11
+ with fitz.open(stream=uploaded_file.read(), filetype="pdf") as doc:
12
+ return "\n".join(page.get_text() for page in doc)
13
+ elif uploaded_file.type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
14
+ doc = docx.Document(uploaded_file)
15
+ return "\n".join(para.text for para in doc.paragraphs)
16
+ else:
17
+ return "Error: Unsupported file type."
18
+ except Exception as e:
19
+ return f"Error processing file: {e}"
20
+
21
+
22
+ def chunk_text(text, chunk_size=4000, overlap=200):
23
+ """Splits text into overlapping chunks."""
24
+ if not isinstance(text, str):
25
+ return []
26
+ chunks = []
27
+ start = 0
28
+ while start < len(text):
29
+ end = start + chunk_size
30
+ chunks.append(text[start:end])
31
+ start += chunk_size - overlap
32
+ return chunks
33
+
34
+ def analyze_chunk(chunk):
35
+ """Analyzes a single text chunk for greenwashing using the Groq API."""
36
+ try:
37
+ groq_api_key = st.secrets["GROQ_API_KEY"]
38
+ except FileNotFoundError:
39
+ return [{"type": "Configuration Error", "excerpt": "N/A", "explanation": "GROQ_API_KEY secret not found.", "suggestion": "Please ensure the GROQ_API_KEY is set in your Streamlit secrets."}]
40
+
41
+ prompt = f"""
42
+ You are a critical ESG analyst specializing in identifying greenwashing. Analyze the following text for potential greenwashing. For each issue, identify the type of greenwashing (e.g., Vague Language, Irrelevant Claims, Hidden Trade-offs, No Proof), extract the specific sentence or phrase, explain why it's a potential issue, and suggest a more transparent alternative.
43
+
44
+ Text to analyze:
45
+ '''{chunk}'''
46
+
47
+ Format your response as a valid JSON list of objects. Each object must have the keys: "type", "excerpt", "explanation", and "suggestion". If no issues are found, return an empty list [].
48
+ """
49
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
50
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
51
+ payload = {
52
+ "model": "llama3-8b-8192",
53
+ "messages": [{"role": "user", "content": prompt}],
54
+ "response_format": {"type": "json_object"},
55
+ "max_tokens": 2048,
56
+ "temperature": 0.4
57
+ }
58
+ try:
59
+ response = requests.post(api_url, json=payload, headers=headers)
60
+ response.raise_for_status()
61
+ data = response.json()
62
+ issues_str = data["choices"][0]["message"]["content"]
63
+ # The content itself is a JSON string, so we parse it
64
+ parsed_issues = json.loads(issues_str)
65
+ # The actual list might be nested inside a key like 'issues'
66
+ if isinstance(parsed_issues, dict) and 'issues' in parsed_issues:
67
+ return parsed_issues['issues']
68
+ return parsed_issues # Assume it's the list itself
69
+
70
+ except requests.exceptions.RequestException:
71
+ return [{"type": "API Error", "excerpt": "N/A", "explanation": "Could not connect to the analysis service.", "suggestion": "Check your API key and network connection."}]
72
+ except (json.JSONDecodeError, KeyError, IndexError):
73
+ return [{"type": "API Response Error", "excerpt": "N/A", "explanation": "The analysis service returned an invalid response.", "suggestion": "This may be a temporary issue. Please try again."}]
agents/module1_template.py ADDED
@@ -0,0 +1,98 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+ import os
4
+
5
+ # --- Constants ---
6
+ TEMPLATE_DICT = {
7
+ "GRI": "Global Reporting Initiative Standards",
8
+ "SASB": "Sustainability Accounting Standards Board",
9
+ "TCFD": "Task Force on Climate-related Financial Disclosures",
10
+ "IIRC": "International Integrated Reporting Council",
11
+ }
12
+
13
+ # --- Main Function ---
14
+ def generate_esg_template(framework_key, lang_code, template_dict):
15
+ try:
16
+ groq_api_key = st.secrets["GROQ_API_KEY"]
17
+ except FileNotFoundError:
18
+ return "Error: GROQ_API_KEY secret not found. Please add it to your Streamlit secrets."
19
+
20
+ template_info = template_dict.get(framework_key, "")
21
+ if not template_info:
22
+ return "Unsupported or unknown ESG framework."
23
+
24
+ prompt = f"""
25
+ You are an expert ESG specialist. Provide a detailed, professional ESG reporting template strictly aligned with the {framework_key} framework. Include headings, subheadings, and instructions clearly aligned with the {framework_key} standard requirements.
26
+
27
+ Base information provided: "{template_info}"
28
+
29
+ Respond clearly formatted as a template in {'English' if lang_code == 'en' else 'Vietnamese'}.
30
+ """
31
+
32
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
33
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
34
+ payload = {
35
+ "model": "llama3-8b-8192",
36
+ "messages": [{"role": "user", "content": prompt}],
37
+ "max_tokens": 2048,
38
+ "temperature": 0.6
39
+ }
40
+
41
+ try:
42
+ response = requests.post(api_url, json=payload, headers=headers)
43
+ response.raise_for_status()
44
+ return response.json()["choices"][0]["message"]["content"]
45
+ except requests.exceptions.RequestException as e:
46
+ return f"Error: API request failed: {e}"
47
+ except (KeyError, IndexError) as e:
48
+ return f"Error: Invalid API response format: {e}"
49
+
50
+
51
+ # --- Streamlit UI ---
52
+ def show_module1_ui():
53
+ """Renders the Streamlit UI for Module 1: ESG Template Generation."""
54
+ st.subheader("Tạo mẫu báo cáo ESG theo các framework quốc tế")
55
+ st.markdown(
56
+ """
57
+ Module này giúp bạn nhanh chóng tạo ra các mẫu báo cáo ESG (Môi trường - Xã hội - Quản trị)
58
+ dựa trên các framework báo cáo bền vững phổ biến nhất trên thế giới.
59
+ """
60
+ )
61
+
62
+ # --- User Inputs ---
63
+ col1, col2 = st.columns(2)
64
+ with col1:
65
+ framework_key = st.selectbox(
66
+ "📊 Chọn Framework Báo cáo",
67
+ options=list(TEMPLATE_DICT.keys()),
68
+ help="Chọn framework bạn muốn tạo mẫu báo cáo.",
69
+ )
70
+ with col2:
71
+ lang_code = st.selectbox(
72
+ "🌐 Chọn Ngôn ngữ",
73
+ options=["vi", "en"],
74
+ format_func=lambda x: "Tiếng Việt" if x == "vi" else "English",
75
+ help="Chọn ngôn ngữ cho mẫu báo cáo.",
76
+ )
77
+
78
+ # --- Generation ---
79
+ if st.button("Tạo Mẫu Báo cáo", use_container_width=True):
80
+ with st.spinner("Đang tạo mẫu báo cáo, vui lòng chờ..."):
81
+ generated_template = generate_esg_template(
82
+ framework_key, lang_code, TEMPLATE_DICT
83
+ )
84
+ st.session_state.generated_template = generated_template
85
+
86
+ # --- Display Result ---
87
+ if "generated_template" in st.session_state:
88
+ st.markdown("---")
89
+ st.subheader("Mẫu Báo cáo ESG đã tạo")
90
+ st.markdown(st.session_state.generated_template)
91
+
92
+ st.download_button(
93
+ label="Tải mẫu về máy",
94
+ data=st.session_state.generated_template,
95
+ file_name=f"esg_template_{framework_key}.md",
96
+ mime="text/markdown",
97
+ use_container_width=True,
98
+ )
agents/module2_planner.py ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ # --- Constants ---
5
+ FRAMEWORK_OPTIONS = {
6
+ "GRI": "Global Reporting Initiative",
7
+ "SASB": "Sustainability Accounting Standards Board",
8
+ "TCFD": "Task Force on Climate-related Financial Disclosures",
9
+ "IIRC": "International Integrated Reporting Council",
10
+ "Custom": "Kế hoạch tùy chỉnh theo mục tiêu"
11
+ }
12
+
13
+ # --- Backend Logic ---
14
+ def generate_sustainability_plan(profile, objectives, framework, lang_code):
15
+ try:
16
+ groq_api_key = st.secrets["GROQ_API_KEY"]
17
+ except FileNotFoundError:
18
+ return "Error: GROQ_API_KEY secret not found. Please add it to your Streamlit secrets."
19
+
20
+ prompt = f"""
21
+ You are an expert sustainability advisor. Based on the following organization profile and ESG objectives, generate a comprehensive, actionable sustainability plan strictly aligned with the {framework} framework.
22
+
23
+ Organization Profile:
24
+ - Geographic area: {profile['province']}
25
+ - Sector: {profile['sector']}
26
+ - Size: {profile['size']}
27
+ - Key operations: {profile['operations']}
28
+
29
+ ESG Objectives:
30
+ - Environmental: {objectives['environmental']}
31
+ - Social: {objectives['social']}
32
+ - Governance: {objectives['governance']}
33
+
34
+ Please structure the plan with sections matching the ESG pillars, include clear recommended actions, timelines, KPIs, and assign each action to a responsible role where possible. Respond in {'English' if lang_code == 'en' else 'Vietnamese'}.
35
+ """
36
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
37
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
38
+ payload = {
39
+ "model": "llama3-8b-8192",
40
+ "messages": [{"role": "user", "content": prompt}],
41
+ "max_tokens": 2048,
42
+ "temperature": 0.6
43
+ }
44
+ try:
45
+ response = requests.post(api_url, json=payload, headers=headers)
46
+ response.raise_for_status()
47
+ return response.json()["choices"][0]["message"]["content"]
48
+ except requests.exceptions.RequestException as e:
49
+ return f"Error: API request failed: {e}"
50
+ except (KeyError, IndexError) as e:
51
+ return f"Error: Invalid API response format: {e}"
52
+
53
+ # --- Streamlit UI ---
54
+ def show_module2_ui():
55
+ """Renders the Streamlit UI for Module 2: Sustainability Planner."""
56
+ st.subheader("Tinh chỉnh kế hoạch phát triển bền vững chi tiết")
57
+ st.markdown(
58
+ """
59
+ Module này giúp bạn xây dựng một kế hoạch hành động ESG chi tiết, phù hợp với bối cảnh
60
+ và mục tiêu của tổ chức, dựa trên các framework quốc tế.
61
+ """
62
+ )
63
+
64
+ # --- User Inputs ---
65
+ st.markdown("#### **Thông tin tổ chức**")
66
+ col1, col2 = st.columns(2)
67
+ with col1:
68
+ province = st.text_input("Tỉnh/Thành phố", "TP. Hồ Chí Minh")
69
+ sector = st.text_input("Lĩnh vực hoạt động", "Công nghệ thông tin")
70
+ with col2:
71
+ size = st.selectbox("Quy mô", ["<50 nhân viên", "50-250 nhân viên", "250-1000 nhân viên", ">1000 nhân viên"])
72
+ operations = st.text_area("Hoạt động chính", "Phát triển phần mềm, tư vấn giải pháp CNTT.")
73
+
74
+ st.markdown("#### **Mục tiêu ESG**")
75
+ col1, col2, col3 = st.columns(3)
76
+ with col1:
77
+ environmental_obj = st.text_area("Mục tiêu Môi trường (E)", "Giảm 15% lượng khí thải carbon trong 2 năm.")
78
+ with col2:
79
+ social_obj = st.text_area("Mục tiêu Xã hội (S)", "Tăng tỷ lệ nữ giới trong vai trò lãnh đạo lên 40%.")
80
+ with col3:
81
+ governance_obj = st.text_area("Mục tiêu Quản trị (G)", "Thành lập ủy ban giám sát ESG độc lập.")
82
+
83
+ st.markdown("#### **Tùy chọn Kế hoạch**")
84
+ col1, col2 = st.columns(2)
85
+ with col1:
86
+ framework = st.selectbox(
87
+ "📊 Chọn Framework",
88
+ options=list(FRAMEWORK_OPTIONS.keys()),
89
+ help="Chọn framework để xây dựng kế hoạch."
90
+ )
91
+ with col2:
92
+ lang_code = st.selectbox(
93
+ "🌐 Chọn Ngôn ngữ",
94
+ options=["vi", "en"],
95
+ format_func=lambda x: "Tiếng Việt" if x == "vi" else "English",
96
+ help="Chọn ngôn ngữ cho kế hoạch."
97
+ )
98
+
99
+ # --- Generation ---
100
+ if st.button("Tạo Kế hoạch Hành động", use_container_width=True):
101
+ profile = {
102
+ 'province': province,
103
+ 'sector': sector,
104
+ 'size': size,
105
+ 'operations': operations
106
+ }
107
+ objectives = {
108
+ 'environmental': environmental_obj,
109
+ 'social': social_obj,
110
+ 'governance': governance_obj
111
+ }
112
+ with st.spinner("Đang xây dựng kế hoạch, vui lòng chờ..."):
113
+ generated_plan = generate_sustainability_plan(
114
+ profile, objectives, framework, lang_code
115
+ )
116
+ st.session_state.generated_plan_m2 = generated_plan
117
+
118
+ # --- Display Result ---
119
+ if "generated_plan_m2" in st.session_state:
120
+ st.markdown("---")
121
+ st.subheader("Kế hoạch Phát triển Bền vững đã tạo")
122
+ st.markdown(st.session_state.generated_plan_m2)
123
+
124
+ st.download_button(
125
+ label="Tải kế hoạch về máy",
126
+ data=st.session_state.generated_plan_m2,
127
+ file_name=f"sustainability_plan_{framework}.md",
128
+ mime="text/markdown",
129
+ use_container_width=True,
130
+ )
agents/module3_report.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ # --- Backend Logic ---
5
+ def generate_esg_report(input_data, lang_code):
6
+ try:
7
+ groq_api_key = st.secrets["GROQ_API_KEY"]
8
+ except FileNotFoundError:
9
+ return "Error: GROQ_API_KEY secret not found. Please add it to your Streamlit secrets."
10
+
11
+ prompt = f"""
12
+ You are an ESG Reporting Assistant. Create a comprehensive ESG report for the company using the following data:
13
+
14
+ Industry: {input_data.get('industry', '')}
15
+ Environmental Metrics: {input_data.get('e_metrics', '')}
16
+ Social Metrics: {input_data.get('s_metrics', '')}
17
+ Governance Metrics: {input_data.get('g_metrics', '')}
18
+ Policy/Initiatives: {input_data.get('policy', '')}
19
+
20
+ Write the report with an Introduction and sections for Environmental, Social, and Governance performance. Summarize key strengths and suggest improvements.
21
+ Respond in {'English' if lang_code == 'en' else 'Vietnamese'}.
22
+ """
23
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
24
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
25
+ payload = {
26
+ "model": "llama3-8b-8192",
27
+ "messages": [{"role": "user", "content": prompt}],
28
+ "max_tokens": 2048,
29
+ "temperature": 0.7
30
+ }
31
+ try:
32
+ response = requests.post(api_url, json=payload, headers=headers)
33
+ response.raise_for_status()
34
+ return response.json()["choices"][0]["message"]["content"]
35
+ except requests.exceptions.RequestException as e:
36
+ return f"Error: API request failed: {e}"
37
+ except (KeyError, IndexError) as e:
38
+ return f"Error: Invalid API response format: {e}"
39
+
40
+ # --- Streamlit UI ---
41
+ def show_module3_ui():
42
+ """Renders the Streamlit UI for Module 3: ESG Report Generation."""
43
+ st.subheader("Tạo báo cáo ESG tự động từ dữ liệu nội bộ")
44
+ st.markdown(
45
+ """
46
+ Module này cho phép bạn nhập các số liệu ESG thô của công ty để tự động tạo ra một
47
+ báo cáo ESG hoàn chỉnh, có cấu trúc chuyên nghiệp.
48
+ """
49
+ )
50
+
51
+ # --- User Inputs ---
52
+ st.markdown("#### **Nhập dữ liệu ESG của bạn**")
53
+ industry = st.text_input("Ngành công nghiệp", "Sản xuất hàng tiêu dùng")
54
+
55
+ col1, col2 = st.columns(2)
56
+ with col1:
57
+ e_metrics = st.text_area("Số liệu Môi trường (E)", "Lượng phát thải CO2: 1,500 tấn/năm\nTiêu thụ nước: 50,000 m3/năm\nTỷ lệ tái chế: 60%")
58
+ with col2:
59
+ s_metrics = st.text_area("Số liệu Xã hội (S)", "Tỷ lệ tai nạn lao động: 0.2%\nGiờ đào tạo trung bình/nhân viên: 20 giờ/năm\nĐóng góp cho cộng đồng: 500 triệu VNĐ")
60
+
61
+ col1, col2 = st.columns(2)
62
+ with col1:
63
+ g_metrics = st.text_area("Số liệu Quản trị (G)", "Tỷ lệ thành viên HĐQT độc lập: 30%\nSố cuộc họp của ủy ban kiểm toán: 4/năm\nChênh lệch lương trung bình nam/nữ: 5%")
64
+ with col2:
65
+ policy = st.text_area("Chính sách & Sáng kiến", "Chính sách làm việc linh hoạt\nSáng kiến chuỗi cung ứng bền vững\nChương trình sức khỏe tinh thần cho nhân viên")
66
+
67
+ lang_code = st.selectbox(
68
+ "🌐 Chọn Ngôn ngữ Báo cáo",
69
+ options=["vi", "en"],
70
+ format_func=lambda x: "Tiếng Việt" if x == "vi" else "English",
71
+ key="module3_lang"
72
+ )
73
+
74
+ # --- Generation ---
75
+ if st.button("Tạo Báo cáo ESG", use_container_width=True):
76
+ input_data = {
77
+ 'industry': industry,
78
+ 'e_metrics': e_metrics,
79
+ 's_metrics': s_metrics,
80
+ 'g_metrics': g_metrics,
81
+ 'policy': policy
82
+ }
83
+ with st.spinner("Đang tổng hợp và viết báo cáo, vui lòng chờ..."):
84
+ generated_report = generate_esg_report(input_data, lang_code)
85
+ st.session_state.generated_report_m3 = generated_report
86
+
87
+ # --- Display Result ---
88
+ if "generated_report_m3" in st.session_state:
89
+ st.markdown("---")
90
+ st.subheader("Báo cáo ESG đã tạo")
91
+ st.markdown(st.session_state.generated_report_m3)
92
+
93
+ st.download_button(
94
+ label="Tải báo cáo về máy",
95
+ data=st.session_state.generated_report_m3,
96
+ file_name="esg_report.md",
97
+ mime="text/markdown",
98
+ use_container_width=True,
99
+ )
agents/module4_compliance.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ # --- Constants ---
5
+ FRAMEWORKS_DICT = {
6
+ "GRI": [
7
+ "Report on stakeholder engagement processes.",
8
+ "Disclose the process for determining material topics.",
9
+ "Report on management approach for each material topic.",
10
+ "Provide data for economic, environmental, and social impacts."
11
+ ],
12
+ "SASB": [
13
+ "Disclose performance on industry-specific sustainability topics.",
14
+ "Provide metrics that are financially material.",
15
+ "Report data in a standardized format for comparability.",
16
+ "Explain how sustainability performance affects financial condition."
17
+ ],
18
+ "TCFD": [
19
+ "Describe the board's oversight of climate-related risks and opportunities.",
20
+ "Disclose actual and potential impacts of climate risks on the business.",
21
+ "Describe the resilience of the strategy, taking into consideration different climate scenarios.",
22
+ "Disclose the metrics and targets used to assess and manage climate-related risks."
23
+ ],
24
+ "IIRC": [
25
+ "Provide an overview of the organization and its external environment.",
26
+ "Explain the governance structure and how it supports value creation.",
27
+ "Describe the business model, including inputs, activities, and outputs.",
28
+ "Report on performance and outcomes in terms of the six capitals (Financial, Manufactured, Intellectual, Human, Social, Natural)."
29
+ ]
30
+ }
31
+
32
+ # --- Backend Logic ---
33
+ def check_multi_framework_compliance(report_text, framework_keys, lang_code, frameworks_dict):
34
+ try:
35
+ groq_api_key = st.secrets["GROQ_API_KEY"]
36
+ except FileNotFoundError:
37
+ return "Error: GROQ_API_KEY secret not found. Please add it to your Streamlit secrets."
38
+
39
+ all_results = []
40
+ for framework_key in framework_keys:
41
+ requirements = frameworks_dict.get(framework_key, [])
42
+ if not requirements:
43
+ all_results.append(f"Framework '{framework_key}' is not supported or has no requirements defined.\n")
44
+ continue
45
+ checklist = "\n".join([f"- {req}" for req in requirements])
46
+ prompt = f"""
47
+ You are an ESG Compliance Checker. Review the following organization's *actual ESG report/results* and compare them to this ESG framework's requirements:
48
+
49
+ Framework: {framework_key}
50
+ Requirements:
51
+ {checklist}
52
+
53
+ ESG Report Text:
54
+ \"\"\"{report_text}\"\"\"
55
+
56
+ Task:
57
+ For each requirement, state whether the report fully meets, partially meets, or does not meet it. Clearly explain any gaps or missing evidence. Suggest specific improvements for non-compliance areas. Respond in {'English' if lang_code == 'en' else 'Vietnamese'}.
58
+ """
59
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
60
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
61
+ payload = {
62
+ "model": "llama3-8b-8192",
63
+ "messages": [{"role": "user", "content": prompt}],
64
+ "max_tokens": 2048,
65
+ "temperature": 0.5
66
+ }
67
+ try:
68
+ response = requests.post(api_url, json=payload, headers=headers)
69
+ response.raise_for_status()
70
+ result = response.json()["choices"][0]["message"]["content"]
71
+ all_results.append(f"### Phân tích Tuân thủ Framework: {framework_key}\n\n{result}\n")
72
+ except requests.exceptions.RequestException as e:
73
+ all_results.append(f"Lỗi khi kiểm tra framework {framework_key}: {e}\n")
74
+ except (KeyError, IndexError) as e:
75
+ all_results.append(f"Lỗi định dạng phản hồi API cho framework {framework_key}: {e}\n")
76
+ return "\n---\n".join(all_results)
77
+
78
+ # --- Streamlit UI ---
79
+ def show_module4_ui():
80
+ """Renders the Streamlit UI for Module 4: Multi-Framework Compliance Check."""
81
+ st.subheader("Kiểm tra tuân thủ đa khung báo cáo")
82
+ st.markdown(
83
+ """
84
+ Dán nội dung báo cáo ESG của bạn vào đây để đối chiếu với các yêu cầu chính
85
+ của nhiều framework báo cáo bền vững cùng một lúc.
86
+ """
87
+ )
88
+
89
+ # --- User Inputs ---
90
+ report_text = st.text_area(
91
+ "📝 Dán nội dung báo cáo ESG của bạn vào đây",
92
+ height=300,
93
+ placeholder="Ví dụ: Công ty chúng tôi đã giảm 10% lượng nước tiêu thụ trong năm qua..."
94
+ )
95
+
96
+ col1, col2 = st.columns(2)
97
+ with col1:
98
+ framework_keys = st.multiselect(
99
+ "📊 Chọn các Framework để đối chiếu",
100
+ options=list(FRAMEWORKS_DICT.keys()),
101
+ default=["GRI", "TCFD"],
102
+ help="Bạn có thể chọn một hoặc nhiều framework."
103
+ )
104
+ with col2:
105
+ lang_code = st.selectbox(
106
+ "🌐 Chọn Ngôn ngữ Phân tích",
107
+ options=["vi", "en"],
108
+ format_func=lambda x: "Tiếng Việt" if x == "vi" else "English",
109
+ key="module4_lang"
110
+ )
111
+
112
+ # --- Generation ---
113
+ if st.button("Kiểm tra Tuân thủ", use_container_width=True):
114
+ if not report_text:
115
+ st.warning("Vui lòng dán nội dung báo cáo của bạn.")
116
+ elif not framework_keys:
117
+ st.warning("Vui lòng chọn ít nhất một framework để kiểm tra.")
118
+ else:
119
+ with st.spinner("Đang phân tích báo cáo của bạn, vui lòng chờ..."):
120
+ compliance_result = check_multi_framework_compliance(
121
+ report_text, framework_keys, lang_code, FRAMEWORKS_DICT
122
+ )
123
+ st.session_state.compliance_result_m4 = compliance_result
124
+
125
+ # --- Display Result ---
126
+ if "compliance_result_m4" in st.session_state:
127
+ st.markdown("---")
128
+ st.subheader("Kết quả Phân tích Tuân thủ")
129
+ st.markdown(st.session_state.compliance_result_m4)
130
+
131
+ st.download_button(
132
+ label="Tải kết quả phân tích",
133
+ data=st.session_state.compliance_result_m4,
134
+ file_name="esg_compliance_analysis.md",
135
+ mime="text/markdown",
136
+ use_container_width=True,
137
+ )
agents/module5_score.py ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ # --- Backend Logic ---
5
+ def evaluate_esg_score(esg_report_text, lang_code, benchmarks=None):
6
+ try:
7
+ groq_api_key = st.secrets["GROQ_API_KEY"]
8
+ except FileNotFoundError:
9
+ return "Error: GROQ_API_KEY secret not found. Please add it to your Streamlit secrets."
10
+
11
+ benchmark_text = f"Compare the results to these benchmarks for the sector: {benchmarks}" if benchmarks else ''
12
+ prompt = f"""
13
+ You are an independent ESG scoring analyst. Based on the following *actual, implemented* ESG report, rate the organization's performance in each ESG pillar (Environmental, Social, Governance), and provide an overall ESG score (out of 100).
14
+
15
+ For each pillar, score from 0-100 and provide a rationale. Summarize major strengths and weaknesses based on the data.
16
+ {benchmark_text}
17
+ Be transparent about scoring logic (e.g., low environmental score if no GHG disclosure; high governance score if independent board, etc).
18
+
19
+ ESG Report:
20
+ \"\"\"{esg_report_text}\"\"\"
21
+
22
+ Format your answer as:
23
+ - Environmental Score: X/100
24
+ Explanation: ...
25
+ - Social Score: X/100
26
+ Explanation: ...
27
+ - Governance Score: X/100
28
+ Explanation: ...
29
+ - **Overall ESG Score:** X/100
30
+ Summary: ...
31
+ Respond in {'English' if lang_code == 'en' else 'Vietnamese'}.
32
+ """
33
+ api_url = "https://api.groq.com/openai/v1/chat/completions"
34
+ headers = {"Authorization": f"Bearer {groq_api_key}", "Content-Type": "application/json"}
35
+ payload = {
36
+ "model": "llama3-8b-8192",
37
+ "messages": [{"role": "user", "content": prompt}],
38
+ "max_tokens": 1500,
39
+ "temperature": 0.6
40
+ }
41
+ try:
42
+ response = requests.post(api_url, json=payload, headers=headers)
43
+ response.raise_for_status()
44
+ return response.json()["choices"][0]["message"]["content"]
45
+ except requests.exceptions.RequestException as e:
46
+ return f"Error: API request failed: {e}"
47
+ except (KeyError, IndexError) as e:
48
+ return f"Error: Invalid API response format: {e}"
49
+
50
+ # --- Streamlit UI ---
51
+ def show_module5_ui():
52
+ """Renders the Streamlit UI for Module 5: ESG Scoring."""
53
+ st.subheader("Đánh giá và chấm điểm báo cáo ESG")
54
+ st.markdown(
55
+ """
56
+ Module này hoạt động như một nhà phân tích độc lập, chấm điểm báo cáo ESG của bạn
57
+ trên thang điểm 100 và cung cấp lý giải chi tiết cho từng trụ cột.
58
+ """
59
+ )
60
+
61
+ # --- User Inputs ---
62
+ esg_report_text = st.text_area(
63
+ "📝 Dán nội dung báo cáo ESG của bạn vào đây",
64
+ height=300,
65
+ placeholder="Ví dụ: Báo cáo bền vững năm 2023 của công ty ABC..."
66
+ )
67
+
68
+ col1, col2 = st.columns(2)
69
+ with col1:
70
+ benchmarks = st.text_area(
71
+ "📈 Nhập benchmarks (tùy chọn)",
72
+ height=150,
73
+ help="Cung cấp các chỉ số tham chiếu của ngành để so sánh. Ví dụ: 'Tỷ lệ phát thải trung bình ngành: 1.2 tấn CO2/sản phẩm'"
74
+ )
75
+ with col2:
76
+ lang_code = st.selectbox(
77
+ "🌐 Chọn Ngôn ngữ Phân tích",
78
+ options=["vi", "en"],
79
+ format_func=lambda x: "Tiếng Việt" if x == "vi" else "English",
80
+ key="module5_lang"
81
+ )
82
+
83
+ # --- Generation ---
84
+ if st.button("Chấm điểm ESG", use_container_width=True):
85
+ if not esg_report_text:
86
+ st.warning("Vui lòng dán nội dung báo cáo của bạn.")
87
+ else:
88
+ with st.spinner("Đang phân tích và chấm điểm, vui lòng chờ..."):
89
+ scoring_result = evaluate_esg_score(
90
+ esg_report_text, lang_code, benchmarks if benchmarks else None
91
+ )
92
+ st.session_state.scoring_result_m5 = scoring_result
93
+
94
+ # --- Display Result ---
95
+ if "scoring_result_m5" in st.session_state:
96
+ st.markdown("---")
97
+ st.subheader("Kết quả Chấm điểm ESG")
98
+ st.markdown(st.session_state.scoring_result_m5)
99
+
100
+ st.download_button(
101
+ label="Tải kết quả chấm điểm",
102
+ data=st.session_state.scoring_result_m5,
103
+ file_name="esg_score_analysis.md",
104
+ mime="text/markdown",
105
+ use_container_width=True,
106
+ )
agents/module6_greenwash.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from agents.greenwash_utils import extract_text, chunk_text, analyze_chunk
3
+ import json
4
+
5
+ def show_module6_ui():
6
+ """Renders the Streamlit UI for Module 6: Greenwashing Check."""
7
+ st.subheader("Phân tích và phát hiện Greenwashing")
8
+ st.markdown(
9
+ """
10
+ Tải lên báo cáo bền vững (PDF, DOCX) hoặc dán một đoạn văn bản để AI phân tích,
11
+ xác định các tuyên bố có khả năng gây hiểu lầm (greenwashing).
12
+ """
13
+ )
14
+
15
+ # --- User Inputs ---
16
+ uploaded_file = st.file_uploader(
17
+ "Tải lên báo cáo ESG (PDF, DOCX)",
18
+ type=["pdf", "docx"]
19
+ )
20
+ manual_text = st.text_area(
21
+ "Hoặc dán một đoạn văn bản (tuyên bố, quảng cáo...) vào đây:",
22
+ height=200,
23
+ placeholder="Ví dụ: Sản phẩm của chúng tôi 100% thân thiện với môi trường..."
24
+ )
25
+
26
+ # --- Analysis ---
27
+ if st.button("Phân tích Greenwashing", use_container_width=True):
28
+ text_to_analyze = ""
29
+ if uploaded_file:
30
+ with st.spinner(f"Đang trích xuất văn bản từ file {uploaded_file.name}..."):
31
+ text_to_analyze = extract_text(uploaded_file)
32
+ elif manual_text:
33
+ text_to_analyze = manual_text
34
+ else:
35
+ st.warning("Vui lòng tải file lên hoặc dán văn bản để phân tích.")
36
+ st.stop()
37
+
38
+ if "Error:" in text_to_analyze:
39
+ st.error(text_to_analyze)
40
+ st.stop()
41
+
42
+ chunks = chunk_text(text_to_analyze)
43
+ if not chunks:
44
+ st.warning("Không tìm thấy nội dung văn bản để phân tích.")
45
+ st.stop()
46
+
47
+ all_issues = []
48
+ progress_bar = st.progress(0, text="Bắt đầu phân tích...")
49
+
50
+ for i, chunk in enumerate(chunks):
51
+ progress_text = f"Đang phân tích phần {i + 1}/{len(chunks)}..."
52
+ progress_bar.progress((i + 1) / len(chunks), text=progress_text)
53
+
54
+ # Analyze the chunk (API key is now handled by the utility function)
55
+ issues = analyze_chunk(chunk)
56
+ if isinstance(issues, list):
57
+ all_issues.extend(issues)
58
+
59
+ progress_bar.empty()
60
+ st.session_state.greenwash_results_m6 = all_issues
61
+
62
+ # --- Display Results ---
63
+ if "greenwash_results_m6" in st.session_state:
64
+ st.markdown("---")
65
+ st.subheader("Kết quả Phân tích Greenwashing")
66
+ results = st.session_state.greenwash_results_m6
67
+
68
+ if not results:
69
+ st.success("Không tìm thấy dấu hiệu greenwashing đáng kể trong văn bản.")
70
+ else:
71
+ st.info(f"Tìm thấy {len(results)} vấn đề tiềm ẩn.")
72
+ for idx, issue in enumerate(results, 1):
73
+ issue_type = issue.get('type', 'Không xác định')
74
+ with st.expander(f"Vấn đề {idx}: **{issue_type}**"):
75
+ st.markdown(f"> **Trích đoạn:** *...{issue.get('excerpt', 'N/A')}...*")
76
+ st.write("**Giải thích:**", issue.get("explanation", ""))
77
+ st.write("**Gợi ý:**", issue.get("suggestion", ""))
78
+
79
+ st.download_button(
80
+ label="Tải kết quả phân tích",
81
+ data=json.dumps(results, indent=2, ensure_ascii=False),
82
+ file_name="greenwashing_analysis.json",
83
+ mime="application/json",
84
+ use_container_width=True,
85
+ )