-
Notifications
You must be signed in to change notification settings - Fork 7
Update politeness v2 #367
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update politeness v2 #367
Changes from 2 commits
c3b4422
b388a32
14dc294
125d821
a6e99a7
183d1e6
bafe275
40aee79
8e15934
a011781
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,4 +58,5 @@ node_modules/ | |
| # testing | ||
| /output | ||
| /vector_data | ||
| test.py | ||
| test.py | ||
| test.ipynb | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -218,29 +218,85 @@ def bare_command(doc): | |
| def Question(doc): | ||
| """ | ||
| Counts the number of sentences containing question words and question marks. | ||
|
|
||
| Reference: https://github.com/bbevis/politenessPy/blob/main/strategy_extractor.py | ||
| Args: | ||
| doc (spacy.tokens.Doc): The spaCy Doc object containing the text to be analyzed. | ||
|
|
||
| Returns: | ||
| tuple: A tuple containing the counts of Yes/No questions and WH-questions. | ||
| """ | ||
|
|
||
| keywords = set([' who ', ' what ', ' where ', ' when ', ' why ', ' how ', ' which ']) | ||
| tags = set(['WRB', 'WP', 'WDT']) | ||
|
|
||
| # doc = nlp(text) | ||
| sentences = [str(sent) for sent in doc.sents if '?' in str(sent)] | ||
| all_qs = len(sentences) | ||
|
|
||
| n = 0 | ||
| for i in range(len(sentences)): | ||
| whq = [token.tag_ for token in nlp(sentences[i]) if token.tag_ in tags] | ||
|
|
||
| if len(whq) > 0: | ||
| n += 1 | ||
|
|
||
| return all_qs - n, n | ||
| # POS tags for WH-words like who/what/where | ||
| search_tags = {'WRB', 'WP', 'WDT'} | ||
| # WH-words and common auxiliaries that follow them in real questions | ||
| wh_words = {'what', 'who', 'where', 'when', 'why', 'how', 'which'} | ||
| wh_followers = { | ||
| 'what': {'are', 'is', 'do', 'does', 'can', 'should', 'might'}, | ||
| 'who': {'is', 'are', 'was', 'can', 'should'}, | ||
| 'where': {'is', 'are', 'can', 'should'}, | ||
| 'when': {'is', 'are', 'can', 'should'}, | ||
| 'why': {'is', 'are', 'do', 'does', 'can', 'might', 'would'}, | ||
| 'how': {'is', 'are', 'do', 'does', 'can', 'should', 'would'}, | ||
| 'which': {'is', 'are', 'was', 'can', 'should'} | ||
| } | ||
| # Auxiliaries that typically initiate Yes/No questions | ||
| yesno_aux = {'do', 'does', 'did', 'have', 'has', 'had', | ||
| # 'can', 'could', 'will', 'would', | ||
| 'may', 'might', 'shall', 'should', | ||
| 'is', 'are', 'was', 'were', 'am'} | ||
| # Pronouns that often follow auxiliaries in Yes/No questions | ||
| pronoun_followers = {'i', 'you', 'we', 'he', 'she', 'they', 'it'} | ||
| # filler_words = {'ok', 'so', 'well', 'like', 'you know', 'i mean', 'actually', 'basically', 'right', 'just', 'uh', 'um', 'oh', 'hmm', 'like'} | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are we no longer ignoring filler words like 'ok so' ?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. This was my own solution to this test case: "so Which part should we do first?". Burint updated his code later, so I adapted that instead. |
||
|
|
||
| wh_count = 0 | ||
| yesno_count = 0 | ||
| counted_sentences = set() | ||
| for sent in doc.sents: | ||
| sent_text = sent.text.strip() | ||
| sent_tokens = list(sent) | ||
| if not sent_tokens: | ||
| continue | ||
| # Method 1: Find question sentences by checking for '?' at end | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So there's a bug with this logic, which is that, if the sentence doesn't end with a question mark, the fallback method is very error prone. For example: Question(nlp("can you tell me what is your name?")) yields YesNo = 1, WH = 0 (correct) Why can't we use logic that looks for the question words, but then applies the logic with the search_tags, which helps to get around some of these problems? |
||
| if sent_text.endswith('?'): | ||
| # try to find the first WH-word in the sentence | ||
| wh = False | ||
| for token in sent_tokens: | ||
| if token.text.lower() in wh_words and token.tag_ in search_tags and token.dep_ not in {"relcl", "acl"}\ | ||
| and token.i < sent.root.i: | ||
| wh = True | ||
| break | ||
| if wh: | ||
| wh_count += 1 | ||
| else: | ||
| # Fallback: no WH in the sentence → treat as Yes/No question | ||
| yesno_count += 1 | ||
| counted_sentences.add(sent.start) | ||
| continue | ||
| # Method 2: For remaining sentences, apply lexical rule-based detection --- Extract tokens and their metadata for fast access | ||
| for i in range(len(sent_tokens) - 1): | ||
| tok1 = sent_tokens[i] | ||
| tok2 = sent_tokens[i + 1] | ||
| t1_lower = tok1.text.lower() | ||
| t2_lower = tok2.text.lower() | ||
| if sent.start in counted_sentences: | ||
| break # already counted | ||
| # WH pattern | ||
| if t1_lower in wh_words and t2_lower in wh_followers.get(t1_lower, set()): | ||
| wh_count += 1 | ||
| counted_sentences.add(sent.start) | ||
| break | ||
| # Yes/No pattern | ||
| if t1_lower in yesno_aux and t2_lower in pronoun_followers: | ||
| yesno_count += 1 | ||
| counted_sentences.add(sent.start) | ||
| break | ||
| return yesno_count, wh_count | ||
| # sentences = [str(sent) for sent in doc.sents if '?' in str(sent)] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like the old logic commented out, which we can remove once we establish the new logic works! |
||
| # all_qs = len(sentences) | ||
| # n = 0 | ||
| # for i in range(len(sentences)): | ||
| # whq = [token.tag_ for token in nlp(sentences[i]) if token.tag_ in tags] | ||
| # if len(whq) > 0: | ||
| # n += 1 | ||
| # return all_qs - n, n | ||
|
|
||
|
|
||
| def word_start(keywords, doc): | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it correct that we're commenting this out because otherwise we'd double count "thank you very much" ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Both "thank" and "thank you" will be counted. We discussed this issue with Burint and he made the changes.