diff --git a/conflict_resolving.py b/conflict_resolving.py index 420725c..c4cb638 100644 --- a/conflict_resolving.py +++ b/conflict_resolving.py @@ -1,12 +1,30 @@ +import os from functools import cmp_to_key from typing import List, Tuple import random + +import streamlit import streamlit as st +from langchain_core.prompts import ChatPromptTemplate +from langchain_openai import ChatOpenAI +import json +from models import Assertion from structure import Relationship +import yaml +from pathlib import Path +with open(Path("prompts_in_conflict_resolving.yaml"), "r", encoding="utf-8") as f: + prompts_yaml = yaml.safe_load(f) + + +def build_prompt_from_yaml(name: str): + raw_messages = prompts_yaml["prompts"][name]["messages"] + return ChatPromptTemplate.from_messages( + [(m["role"], m["content"]) for m in raw_messages] + ) class GlobalGraph: - def __init__(self, relationships: List[Relationship]) -> None: + def __init__(self, relationships: List[Relationship], assertions: List[Assertion]) -> None: """ Initialize a graph-based data structure from a list of relationships. @@ -29,6 +47,10 @@ def __init__(self, relationships: List[Relationship]) -> None: - ordered_graph (List[str]): Assertions in traversal or topological order and final desired output. - assertions_by_layers (dict[int, List[str]]): Assertions grouped by layers. """ + self.assertion_table: dict[str, Assertion] = {} + for assertion in assertions: + self.assertion_table[assertion.id] = assertion + self.relationship_for_pair: dict[Tuple[str, str], Relationship] = {} self.relationships: List[Relationship] = relationships @@ -354,7 +376,6 @@ def resolve_cycles_and_conflicts(self, automatic) -> bool: list_of_scc = self.find_nodes_in_scc() nodes_part_of_scc = [node for sublist in list_of_scc for node in sublist] solved = True - if len(nodes_part_of_scc) > 0 or len(self.bad_graph) > 0: solved = False min_node = self.pick_worst_node(nodes_part_of_scc) @@ -430,6 +451,56 @@ def check_used_all_parents(self, node) -> bool: """ return self.number_of_visited_parents[node] == len(self.good_graph_2[node]) + def get_llm_answer_with_parent(self, rel1: Relationship, rel2: Relationship): + prompt = build_prompt_from_yaml("compare_two_relations_with_parent_bool") + + # --- Call the LLM --- + llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, openai_api_key=os.getenv("OPENAI_API_KEY")) + chain = prompt | llm # assuming `llm` is your model + response = chain.invoke({ + "parent_id": "P1", + "relation_type": "cause", + "r1": { + "assertion1_id": rel1.assertion1_id, + "assertion2_id": rel1.assertion2_id, + "confidence": 0.8, + "explanation": rel1.explanation + }, + "r2": { + "assertion1_id": rel2.assertion1_id, + "assertion2_id": rel2.assertion2_id, + "confidence": 0.75, + "explanation": rel2.explanation + } + }) + + # --- Extract boolean --- + content = response.content.strip() + if content.startswith("```"): + content = content.split("```")[1].split("```")[0].strip() + + return json.loads(content) + + def get_llm_answer_without_parent(self, node1: Assertion, node2: Assertion): + prompt = build_prompt_from_yaml("compare_two_intro_assertions_bool") + + # --- Call the LLM --- + llm = ChatOpenAI(model="gpt-4o-mini", temperature=0, openai_api_key=os.getenv("OPENAI_API_KEY")) + chain = prompt | llm + response = chain.invoke({ + "first_id": node1.id, + "first_text": node1.content, + "second_id": node2.id, + "second_text": node2.content + }) + + # --- Extract boolean --- + content = response.content.strip() + if content.startswith("```"): + content = content.split("```")[1].split("```")[0].strip() + + return json.loads(content) + def compare_two_relations(self, relation1: Relationship, relation2: Relationship) -> bool: """ Compare two Relationship objects to determine which has higher priority. @@ -452,14 +523,14 @@ def compare_two_relations(self, relation1: Relationship, relation2: Relationship - If the weights are equal, the comparison is deferred to LLM. - Designed to assist in ordering or selecting relationships when constructing or analyzing the graph. """ - relation_type1 = relation1.relationship_type - relation_type2 = relation2.relationship_type + relation_type1 = getattr(relation1, "relationship_type", None) + relation_type2 = getattr(relation2, "relationship_type", None) weights = {"cause": 0, "condition": 1, "evidence": 2, "contrast": 3, "background": 4} if weights[relation_type1] != weights[relation_type2]: return weights[relation_type1] < weights[relation_type2] else: - #TODO ask which one is better from Amirali the LLM - return True + answer = self.get_llm_answer_with_parent(relation1, relation2) + return answer def sort_all_children(self, parent_id: str, children : List[str]) -> List[str]: """ @@ -483,21 +554,14 @@ def sort_all_children(self, parent_id: str, children : List[str]) -> List[str]: - If `parent_id` is empty, the comparison is deferred to LLM. - Helps establish an ordered structure among children for DAG traversal, visualization, or analysis. """ - def comparison(node1: str, node2: str) -> int: + def comparison(node1: str, node2: str) -> bool: if parent_id == "": - # TODO ask which one is better from Amirali the LLM - return 0 + answer = self.get_llm_answer_without_parent(self.assertion_table[node1], self.assertion_table[node2]) + return answer relation1 = self.relationship_for_pair.get((parent_id, node1)) relation2 = self.relationship_for_pair.get((parent_id, node2)) - - if relation1 is None and relation2 is None: - return 0 - if relation1 is None: - return -1 # or 1, depending on how you want to order - if relation2 is None: - return 1 - - # assume compare_two_relations returns -1, 0, or 1 + if relation1 is None or relation2 is None: + return True return self.compare_two_relations(relation1, relation2) return sorted(children, key=cmp_to_key(comparison)) @@ -552,24 +616,6 @@ def ordering_assertions(self, lst: List[str], deep: int): - Useful for topological sorting, visualization, or downstream graph analysis. """ for node in lst: - """ - Produce a fully ordered graph of assertions using topological sorting and layered traversal. - - Args: - None - - Returns: - None - - Description: - - Finds all starting nodes (nodes with no incoming edges) using `find_all_starting_nodes`. - - Sorts the starting nodes according to relationship priority via `sort_all_children` (parent_id is empty for starting nodes). - - Calls `ordering_assertions` recursively to process the entire DAG: - * Updates `ordered_graph` with the traversal order. - * Updates `assertions_by_layers` with nodes grouped by layer depth. - - Returns the final flattened `ordered_graph`. - - Ensures that all dependencies (parents) are respected, producing a valid DAG ordering. - """ self.ordered_graph.append(node) self.assertions_by_layers.setdefault(deep, []).append(node) children = self.get_valid_children(node) @@ -577,82 +623,27 @@ def ordering_assertions(self, lst: List[str], deep: int): self.ordering_assertions(sorted_children, deep + 1) def order_the_graph(self) -> None: + """ + Produce a fully ordered graph of assertions using topological sorting and layered traversal. + + Args: + None + + Returns: + None + + Description: + - Finds all starting nodes (nodes with no incoming edges) using `find_all_starting_nodes`. + - Sorts the starting nodes according to relationship priority via `sort_all_children` (parent_id is empty for starting nodes). + - Calls `ordering_assertions` recursively to process the entire DAG: + * Updates `ordered_graph` with the traversal order. + * Updates `assertions_by_layers` with nodes grouped by layer depth. + - Returns the final flattened `ordered_graph`. + - Ensures that all dependencies (parents) are respected, producing a valid DAG ordering. + """ starting_nodes = self.sort_all_children("", self.find_all_starting_nodes()) self.ordering_assertions(starting_nodes, 0) -test_1 = [ - # Cycle 1: A1 ↔ A2 ↔ A3 ↔ A1 (all contradictions) - Relationship(assertion1_id="A1", assertion2_id="A2", - relationship_type="contradiction", confidence=0.91, - explanation="A1 claims X holds; A2 asserts not-X."), - Relationship(assertion1_id="A2", assertion2_id="A3", - relationship_type="contradiction", confidence=0.88, - explanation="A2 negates the outcome proposed by A3."), - Relationship(assertion1_id="A3", assertion2_id="A1", - relationship_type="contradiction", confidence=0.90, - explanation="A3 rejects A1’s premise, closing the cycle."), - - # Cycle 2: A4 → A5 → A6 → A4 (mixed types) - Relationship(assertion1_id="A4", assertion2_id="A5", - relationship_type="evidence", confidence=0.84, - explanation="A4 cites data that supports A5."), - Relationship(assertion1_id="A5", assertion2_id="A6", - relationship_type="cause", confidence=0.79, - explanation="A5 describes a mechanism that produces A6."), - Relationship(assertion1_id="A6", assertion2_id="A4", - relationship_type="background", confidence=0.73, - explanation="A6 provides context assumed by A4."), - - # Cycle 3: A7 → A8 → A9 → A10 → A7 (with contradictions) - Relationship(assertion1_id="A7", assertion2_id="A8", - relationship_type="contradiction", confidence=0.86, - explanation="A7 states a limit exists; A8 says no such limit."), - Relationship(assertion1_id="A8", assertion2_id="A9", - relationship_type="evidence", confidence=0.76, - explanation="A8 references measurements backing A9."), - Relationship(assertion1_id="A9", assertion2_id="A10", - relationship_type="cause", confidence=0.80, - explanation="A9 implies A10 via a causal link."), - Relationship(assertion1_id="A10", assertion2_id="A7", - relationship_type="contradiction", confidence=0.82, - explanation="A10’s conclusion conflicts with A7."), - - # Additional contradiction cycles to reach 20 nodes - Relationship(assertion1_id="A11", assertion2_id="A12", - relationship_type="contradiction", confidence=0.85, - explanation="A11 and A12 claim opposing outcomes."), - Relationship(assertion1_id="A12", assertion2_id="A13", - relationship_type="contradiction", confidence=0.83, - explanation="A12 and A13 disagree fundamentally."), - Relationship(assertion1_id="A13", assertion2_id="A11", - relationship_type="contradiction", confidence=0.84, - explanation="A13 refutes A11, completing a contradiction cycle."), - - Relationship(assertion1_id="A14", assertion2_id="A15", - relationship_type="contradiction", confidence=0.80, - explanation="A14 predicts growth; A15 predicts decline."), - Relationship(assertion1_id="A15", assertion2_id="A16", - relationship_type="contradiction", confidence=0.82, - explanation="A15 and A16 provide incompatible claims."), - Relationship(assertion1_id="A16", assertion2_id="A14", - relationship_type="contradiction", confidence=0.81, - explanation="A16 undermines A14, closing the cycle."), - - # Larger contradiction cycle: A17 → A18 → A19 → A20 → A17 - Relationship(assertion1_id="A17", assertion2_id="A18", - relationship_type="contradiction", confidence=0.87, - explanation="A17 and A18 cannot both be true."), - Relationship(assertion1_id="A18", assertion2_id="A19", - relationship_type="contradiction", confidence=0.89, - explanation="A18 asserts the opposite of A19."), - Relationship(assertion1_id="A19", assertion2_id="A20", - relationship_type="contradiction", confidence=0.88, - explanation="A19 and A20 contradict each other."), - Relationship(assertion1_id="A20", assertion2_id="A17", - relationship_type="contradiction", confidence=0.90, - explanation="A20 invalidates A17, completing the cycle.") -] - test_2 = [ Relationship(assertion1_id="A1", assertion2_id="A3", relationship_type="cause", confidence=0.91, explanation="A1 causes A3."), Relationship(assertion1_id="A1", assertion2_id="A5", relationship_type="evidence", confidence=0.82, explanation="A1 supports A5."), @@ -682,16 +673,42 @@ def order_the_graph(self) -> None: ] +assertions_test_2 = [ + Assertion(id="A1", content="Coffee helps me wake up in the morning.", confidence=0.86, source="synthetic everyday text"), + Assertion(id="A2", content="Drinking coffee late keeps me from sleeping.", confidence=0.80, source="synthetic everyday text"), + Assertion(id="A3", content="If I skip coffee, I feel tired during the day.", confidence=0.90, source="synthetic everyday text"), + Assertion(id="A4", content="I only drink coffee if there is milk at home.", confidence=0.82, source="synthetic everyday text"), + Assertion(id="A5", content="My friends say coffee improves concentration.", confidence=0.84, source="synthetic everyday text"), + Assertion(id="A6", content="Coffee makes me anxious sometimes.", confidence=0.78, source="synthetic everyday text"), + Assertion(id="A7", content="I started drinking coffee in college.", confidence=0.72, source="synthetic everyday text"), + Assertion(id="A8", content="Having breakfast makes coffee taste better.", confidence=0.88, source="synthetic everyday text"), + Assertion(id="A9", content="Coffee helps me study only if I sleep enough.", confidence=0.80, source="synthetic everyday text"), + Assertion(id="A10", content="I usually drink coffee while working.", confidence=0.81, source="synthetic everyday text"), + Assertion(id="A11", content="Some people say tea is healthier than coffee.", confidence=0.75, source="synthetic everyday text"), + Assertion(id="A12", content="Coffee keeps me focused during long meetings.", confidence=0.83, source="synthetic everyday text"), + Assertion(id="A13", content="Coffee gives me energy before workouts.", confidence=0.85, source="synthetic everyday text"), + Assertion(id="A14", content="I drink coffee only when I feel sleepy.", confidence=0.79, source="synthetic everyday text"), + Assertion(id="A15", content="Studies show coffee lowers some health risks.", confidence=0.84, source="synthetic everyday text"), + Assertion(id="A16", content="Too much coffee can cause headaches.", confidence=0.74, source="synthetic everyday text"), + Assertion(id="A17", content="My family always drinks coffee after dinner.", confidence=0.70, source="synthetic everyday text"), + Assertion(id="A18", content="A warm cup of coffee helps me relax.", confidence=0.87, source="synthetic everyday text"), + Assertion(id="A19", content="Coffee helps me focus only if the room is quiet.", confidence=0.80, source="synthetic everyday text"), + Assertion(id="A20", content="Coffee tastes better when shared with friends.", confidence=0.83, source="synthetic everyday text"), +] + if __name__ == "__main__": - our_graph = GlobalGraph(test_2) - our_graph.resolve_cycles_and_conflicts() - # print(our_graph.ordered_graph) - # print(our_graph.contradiction_graph) - # print(our_graph.contradiction_relations) - # print(our_graph.relationships) - # print(our_graph.contradiction_nodes) - # print(our_graph.nodes) - # print(our_graph.reverse_graph) - # print(our_graph.number_of_visited_parents) - # print(our_graph.relationship_for_pair) \ No newline at end of file + our_graph = GlobalGraph(test_2, assertions_test_2) + our_graph.resolve_cycles_and_conflicts(True) + + for node in our_graph.nodes: + print("For node: ", node, " we have: ") + for neigh in our_graph.good_graph_1[node]: + print(neigh) + + our_graph.order_the_graph() + print("END:") + print(our_graph.ordered_graph) + + for node in our_graph.ordered_graph: + print(our_graph.assertion_table[node].content) \ No newline at end of file diff --git a/prompts_in_conflict_resolving.yaml b/prompts_in_conflict_resolving.yaml new file mode 100644 index 0000000..3025f60 --- /dev/null +++ b/prompts_in_conflict_resolving.yaml @@ -0,0 +1,99 @@ +prompts: + compare_two_relations_with_parent_bool: + messages: + - role: system + content: | + You compare TWO Relationship objects that attach to the SAME parent and have the SAME relationship_type. + Decide which child assertion is the better fit under this parent. + + Decision rules (apply in order; stop at first decisive difference): + 1) Relation fit to the parent within this relation_type: + - cause: clearer, more direct causal mechanism > vague/indirect + - condition: precise, operational, testable condition > broad/ambiguous + - evidence: specific, measurable, source-backed > anecdotal/general + - contradiction: genuine, direct incompatibility > superficial difference + - background: concise, relevant, defining context > verbose/tangential + 2) Specificity and clarity: concrete, unambiguous language wins. + 3) Logical tightness: fewer leaps; aligns with parent’s scope. + 4) Non-redundancy: adds complementary info rather than restating parent. + 5) If still tied: shorter, crisper phrasing wins. + 6) Final tiebreaker: lexicographic by child id to be deterministic. + + IMPORTANT: + - Judge ONLY within the given relation_type and the given parent. + - Return ONLY a bare JSON boolean: true if the FIRST is better, false otherwise. + - Do NOT include any other text. + + EXAMPLES (return bare JSON boolean): + Parent: "Index rebuilds cause service downtime." + relation_type: "cause" + A: "Rebuild locks the write path for 7–12s per shard." + B: "Engineers are busy during rebuilds." + → true + + Parent: "Our algorithm reduces latency in real-time search." + relation_type: "evidence" + A: "Some users said it felt faster." + B: "A/B test on 10M queries shows median latency ↓12%." + → false + - role: human + content: | + parent_id: {parent_id} + relation_type: {relation_type} + + first: + assertion1_id: {r1.assertion1_id} + assertion2_id: {r1.assertion2_id} + confidence: {r1.confidence} + explanation: {r1.explanation} + + second: + assertion1_id: {r2.assertion1_id} + assertion2_id: {r2.assertion2_id} + confidence: {r2.confidence} + explanation: {r2.explanation} + + compare_two_intro_assertions_bool: + messages: + - role: system + content: | + You compare TWO standalone assertions for the BEGINNING of a document (intro). + Choose which one is a better opening assertion. + + Intro suitability (evaluate in this order; deterministic): + 1) Orientation & scope: + - Clear definition of topic / what it is + - Problem statement / why it matters + - Goal / thesis / high-level claim or promise + 2) Reader navigation: + - High-level approach/idea (one sentence) + - Contributions / deliverables (brief) + - (Optional) roadmap/structure preview + 3) Context (brief, essential background only) + 4) Defer details: + - Avoid fine-grained metrics, parameters, implementation, edge cases + 5) Quality filters: + - Clarity (atomic, declarative), coherence, non-redundancy + 6) If still tied: shorter, crisper phrasing wins. + 7) Final tiebreaker: lexicographic by id. + + IMPORTANT: + - Judge fitness for the OPENING section, not overall importance. + - Return ONLY a bare JSON boolean: true if the FIRST is better, false otherwise. + - Do NOT include any other text. + + EXAMPLES (return bare JSON boolean): + A: "Writing technical documents is difficult due to cognitive overload." + B: "Latency decreased by 12% on a 10M-query A/B test." + → true + + A: "This project introduces Clarus, an AI-assisted writing tool." + B: "We measured P95 latency improvements of 7%." + → true + - role: human + content: | + first_id: {first_id} + first_text: {first_text} + + second_id: {second_id} + second_text: {second_text} diff --git a/prompts_in_idea_capture.yaml b/prompts_in_idea_capture.yaml new file mode 100644 index 0000000..177d371 --- /dev/null +++ b/prompts_in_idea_capture.yaml @@ -0,0 +1,90 @@ +prompts: + extract_assertions: + messages: + - role: system + content: | + You are an expert at extracting discrete, atomic assertions from raw, unstructured text. + + Your task is to: + 1. Analyze the user's input text + 2. Extract clear, specific assertions that are factual statements or claims + 3. Each assertion should be atomic (one clear idea) + 4. Provide confidence scores (0-1) for each assertion + 5. Include the source text that led to each assertion + + CRITICAL RULES: + - Only extract assertions that are factual statements or claims about the world + - Do NOT extract user instructions, commands, or requests (like "remove X", "add Y", "I want to...") + - Do NOT extract questions or uncertain statements + - Focus on statements that could be building blocks for a document + + IMPORTANT: Return ONLY a valid JSON array. Do not include any other text. + + Return your response as a JSON list of assertions with this structure: + [ + { + "id": "unique_id", + "content": "the assertion text", + "confidence": 0.8, + "source": "excerpt from original text" + } + ] + + If the input contains no extractable assertions (only instructions/questions), return an empty array: [] + - role: human + content: "Extract assertions from this text: {input_text}" + + analyze_user_feedback: + messages: + - role: system + content: | + You are analyzing user feedback about assertions to understand their intent. + + Current assertions: + {current_assertions} + + User feedback: {user_feedback} + + CRITICAL RULES: + 1. If the user says "add" or "no add" followed by content, they want to ADD new assertions + 2. Only remove assertions if the user explicitly says "remove", "delete", "get rid of", "don't want", "take out" + 3. Be conservative with removals - only remove if the intent is clearly to remove + 4. Support both index-based removal (e.g., "remove 1, 3, 5") and content-based removal (e.g., "remove assertions about machine learning") + + Analyze the user's intent and determine: + 1. Do they want to accept all assertions as-is? (return "accept") - Look for: "yes", "good", "perfect", "keep them", "accept", "fine", "ok", "sounds good", "looks good", "that works", "i'm satisfied" + 2. Do they want to remove specific assertions? (return "remove") - ONLY if they explicitly say to remove/delete + - If they specify indices/numbers: use "remove_indices" with 1-based indices + - If they specify content/keywords: use "remove_content" with keywords or phrases to match + 3. Do they want to add new assertions? (return "add" and provide the new assertions) - Look for: "add", "no add", "also", "and", "plus", or when they provide new content + 4. Do they want to modify existing assertions? (return "modify" and provide changes) + 5. Do they want to revert/undo changes? (return "revert") - Look for: "revert", "undo", "bring back", "add back", "restore", "put back" + 6. Do they want to continue the conversation? (return "continue") + + EXAMPLES: + - "no add this assertion" → intent: "add", new_assertions: ["this assertion"] + - "remove the first one" → intent: "remove", remove_indices: [1] + - "remove assertions 1, 3, 5" → intent: "remove", remove_indices: [1, 3, 5] + - "remove assertions about machine learning" → intent: "remove", remove_content: ["machine learning"] + - "remove the one about AI bias" → intent: "remove", remove_content: ["AI bias", "bias"] + - "add nuclear power debate" → intent: "add", new_assertions: ["nuclear power debate"] + - "add the machine learning assertion back" → intent: "revert", revert_type: "restore_removed", revert_content: ["machine learning"] + - "undo the last change" → intent: "revert", revert_type: "undo_last" + - "that's good" → intent: "accept" + + IMPORTANT: Return ONLY a valid JSON object. Do not include any other text. + + Return your analysis as JSON: + { + "intent": "accept|remove|add|modify|revert|continue", + "action": "description of what to do", + "new_assertions": ["list of new assertions if adding"], + "remove_indices": [list of 1-based indices to remove if removing by index], + "remove_content": ["list of keywords/phrases to match for content-based removal"], + "modifications": {"index": "new_content"} if modifying, + "revert_type": "undo_last|restore_removed" if reverting, + "revert_content": ["keywords to match for restoring removed assertions"] if reverting + } + - role: human + content: "Analyze this user feedback: {user_feedback}" + diff --git a/prompts_in_structure.yaml b/prompts_in_structure.yaml new file mode 100644 index 0000000..50159ff --- /dev/null +++ b/prompts_in_structure.yaml @@ -0,0 +1,116 @@ +prompts: + evaluate_relationships_writing_styles: + messages: + - role: system + content: | + You are an expert at analyzing relationships between assertions in academic and analytical writing. + Evaluate the quality of the proposed relationship between these two assertions. + + Assertion 1: "{assertion1_content}" + Assertion 2: "{assertion2_content}" + Proposed Relationship Type: {relationship_type} + + Relationship Types: + - evidence: One assertion provides evidence, examples, or support for another + - background: One assertion provides context, setting, or foundational information for another + - cause: One assertion directly causes or leads to another + - contrast: Assertions present opposing viewpoints, contradictions, or different perspectives + - condition: One assertion is a prerequisite or condition for another + + Rate this relationship on a scale of 0-100 and provide structured feedback. + + Be strict but fair in your evaluation. Consider: + 1. Logical coherence of the relationship + 2. Strength of the connection + 3. Clarity of the relationship type + 4. Whether the assertions actually relate in the proposed way + + Respond in this exact format: + CONFIDENCE: [0-100] + REASON: [One short sentence explaining why it's good or bad] + SUGGESTION: [One of: "ADD", "MODIFY to [relationship_type]", "REMOVE"] + + Examples of good relationships: + - Evidence: "AI can detect cancer" → "AI is useful in healthcare" (CONFIDENCE: 85-95, SUGGESTION: ADD) + - Cause: "Increased CO2 levels" → "Global warming" (CONFIDENCE: 90-100, SUGGESTION: ADD) + - Contrast: "AI will replace humans" vs "AI will augment humans" (CONFIDENCE: 80-95, SUGGESTION: ADD) + + Examples of relationships needing modification: + - "AI algorithms improved" → "AI use in healthcare increased" (CONFIDENCE: 60-70, SUGGESTION: MODIFY to cause) + - "Some studies show benefits" → "Technology is advancing" (CONFIDENCE: 40-60, SUGGESTION: MODIFY to evidence) + + Examples of poor relationships: + - "It's sunny today" → "Technology is advancing" (CONFIDENCE: 0-20, SUGGESTION: REMOVE) + - "Apples are red" vs "Oranges are orange" (CONFIDENCE: 10-30, SUGGESTION: REMOVE) + - role: human + content: "Evaluate the relationship between Assertion 1 and Assertion 2" + evaluate_relationships_using_rst: + - messages: + - role: system + content: | + You are an expert at analyzing rhetorical relationships between assertions using Rhetorical Structure Theory. + + Your task is to identify **{relationship_type}** relationships between the given assertions. + + {relationship_type_upper} RELATIONSHIPS: + {rel_info_description} + + Examples: {rel_info_examples} + + CRITICAL RULES: + - Only output relationships that fit the **{relationship_type}** pattern, even if subtle + - Be thorough but precise: include only valid pairs + - Each relationship must be between exactly 2 assertions + - Provide confidence scores between 0 and 1 + - Give a short explanation of why the relationship exists + - Consider temporal, causal, logical, and semantic connections + + OUTPUT FORMAT: + Return ONLY a valid JSON array. Do not include any extra text. + + Each relationship object must contain: + - assertion1_id: string + - assertion2_id: string + - relationship_type: "{relationship_type}" + - confidence: float between 0 and 1 + - explanation: short string + + If no {relationship_type} relationships are found, return an empty array: [] + + - role: human + content: | + Analyze these assertions for {relationship_type} relationships: + + {assertions_text} + analyzing_rhetorical_relationships: + - messages: + - role: system + content: | + You are an expert at analyzing rhetorical relationships between assertions. + + You need to choose the BEST relationship type for a pair of assertions that could have multiple relationship types. + + Given these assertions and the possible relationship types, choose the ONE relationship type that best describes their relationship. + + Consider: + 1. Which relationship is most fundamental/primary? + 2. Which relationship best captures the semantic connection? + 3. Which relationship would be most useful for structuring a document? + + IMPORTANT: Return ONLY a valid JSON object. Do not include any other text. + + Return your choice as JSON with these fields: + - chosen_relationship: one of "evidence", "background", "cause", "contrast", "condition", or "contradiction" + - confidence: number between 0 and 1 + - explanation: brief explanation of why this relationship type is best + + - role: human + content: | + Assertion 1 (ID: {assertion1_id}): {assertion1_content} + + Assertion 2 (ID: {assertion2_id}): {assertion2_content} + + Possible relationship types: + {possible_relationships} + + Choose the best relationship type for this pair.