Delete hf_space
Browse files- hf_space/.gitattributes +0 -35
- hf_space/.github/workflows/sync_to_spaces.yml +0 -57
- hf_space/.gitignore +0 -171
- hf_space/app.py +0 -225
- hf_space/configs/prompts.toml +0 -34
- hf_space/configs/responses.py +0 -4
- hf_space/hf_space/.gitattributes +0 -35
- hf_space/hf_space/.gitignore +0 -171
- hf_space/hf_space/app.py +0 -225
- hf_space/hf_space/configs/prompts.toml +0 -27
- hf_space/hf_space/configs/responses.py +0 -4
- hf_space/hf_space/requirements.txt +0 -3
- hf_space/hf_space/statics/styles.css +0 -54
- hf_space/hf_space/utils.py +0 -22
- hf_space/requirements.txt +0 -3
- hf_space/statics/styles.css +0 -51
- hf_space/utils.py +0 -26
hf_space/.gitattributes
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/.github/workflows/sync_to_spaces.yml
DELETED
@@ -1,57 +0,0 @@
|
|
1 |
-
name: Sync to Hugging Face Spaces
|
2 |
-
|
3 |
-
on:
|
4 |
-
push:
|
5 |
-
branches:
|
6 |
-
- main
|
7 |
-
workflow_dispatch:
|
8 |
-
|
9 |
-
jobs:
|
10 |
-
sync:
|
11 |
-
runs-on: ubuntu-latest
|
12 |
-
|
13 |
-
steps:
|
14 |
-
- name: Checkout GitHub Repository
|
15 |
-
uses: actions/checkout@v3
|
16 |
-
|
17 |
-
- name: Set up Python
|
18 |
-
uses: actions/setup-python@v4
|
19 |
-
with:
|
20 |
-
python-version: "3.10"
|
21 |
-
|
22 |
-
- name: Install Hugging Face Hub CLI
|
23 |
-
run: |
|
24 |
-
python -m pip install --upgrade pip
|
25 |
-
pip install huggingface_hub
|
26 |
-
|
27 |
-
- name: Clone Hugging Face Spaces Repository
|
28 |
-
run: |
|
29 |
-
huggingface-cli login --token $HF_TOKEN --add-to-git-credential
|
30 |
-
git clone https://huggingface.co/spaces/adaptsum/demo hf_space
|
31 |
-
cd hf_space
|
32 |
-
git checkout main
|
33 |
-
env:
|
34 |
-
HF_TOKEN: ${{ secrets.HUGGINGFACE_TOKEN }}
|
35 |
-
|
36 |
-
- name: Copy Files to Hugging Face Repo
|
37 |
-
run: |
|
38 |
-
rsync -av --exclude='.git' --exclude='README.md' ./ hf_space/
|
39 |
-
|
40 |
-
- name: Merge README.md Files
|
41 |
-
run: |
|
42 |
-
cat hf_space/README.md README.md > hf_space/README_combined.md
|
43 |
-
mv hf_space/README_combined.md hf_space/README.md
|
44 |
-
rm -rf hf_space/README_combined.md
|
45 |
-
|
46 |
-
- name: Commit and Push Changes
|
47 |
-
run: |
|
48 |
-
cd hf_space
|
49 |
-
git add .
|
50 |
-
if git diff --cached --quiet; then
|
51 |
-
echo "No changes to commit"
|
52 |
-
else
|
53 |
-
huggingface-cli upload adaptsum/demo . --repo-type=space
|
54 |
-
echo "Changes have been pushed."
|
55 |
-
fi
|
56 |
-
env:
|
57 |
-
HUGGINGFACE_TOKEN: ${{ secrets.HUGGINGFACE_TOKEN }}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/.gitignore
DELETED
@@ -1,171 +0,0 @@
|
|
1 |
-
# Byte-compiled / optimized / DLL files
|
2 |
-
__pycache__/
|
3 |
-
*.py[cod]
|
4 |
-
*$py.class
|
5 |
-
|
6 |
-
# C extensions
|
7 |
-
*.so
|
8 |
-
|
9 |
-
# Distribution / packaging
|
10 |
-
.Python
|
11 |
-
build/
|
12 |
-
develop-eggs/
|
13 |
-
dist/
|
14 |
-
downloads/
|
15 |
-
eggs/
|
16 |
-
.eggs/
|
17 |
-
lib/
|
18 |
-
lib64/
|
19 |
-
parts/
|
20 |
-
sdist/
|
21 |
-
var/
|
22 |
-
wheels/
|
23 |
-
share/python-wheels/
|
24 |
-
*.egg-info/
|
25 |
-
.installed.cfg
|
26 |
-
*.egg
|
27 |
-
MANIFEST
|
28 |
-
|
29 |
-
# PyInstaller
|
30 |
-
# Usually these files are written by a python script from a template
|
31 |
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
32 |
-
*.manifest
|
33 |
-
*.spec
|
34 |
-
|
35 |
-
# Installer logs
|
36 |
-
pip-log.txt
|
37 |
-
pip-delete-this-directory.txt
|
38 |
-
|
39 |
-
# Unit test / coverage reports
|
40 |
-
htmlcov/
|
41 |
-
.tox/
|
42 |
-
.nox/
|
43 |
-
.coverage
|
44 |
-
.coverage.*
|
45 |
-
.cache
|
46 |
-
nosetests.xml
|
47 |
-
coverage.xml
|
48 |
-
*.cover
|
49 |
-
*.py,cover
|
50 |
-
.hypothesis/
|
51 |
-
.pytest_cache/
|
52 |
-
cover/
|
53 |
-
|
54 |
-
# Translations
|
55 |
-
*.mo
|
56 |
-
*.pot
|
57 |
-
|
58 |
-
# Django stuff:
|
59 |
-
*.log
|
60 |
-
local_settings.py
|
61 |
-
db.sqlite3
|
62 |
-
db.sqlite3-journal
|
63 |
-
|
64 |
-
# Flask stuff:
|
65 |
-
instance/
|
66 |
-
.webassets-cache
|
67 |
-
|
68 |
-
# Scrapy stuff:
|
69 |
-
.scrapy
|
70 |
-
|
71 |
-
# Sphinx documentation
|
72 |
-
docs/_build/
|
73 |
-
|
74 |
-
# PyBuilder
|
75 |
-
.pybuilder/
|
76 |
-
target/
|
77 |
-
|
78 |
-
# Jupyter Notebook
|
79 |
-
.ipynb_checkpoints
|
80 |
-
|
81 |
-
# IPython
|
82 |
-
profile_default/
|
83 |
-
ipython_config.py
|
84 |
-
|
85 |
-
# pyenv
|
86 |
-
# For a library or package, you might want to ignore these files since the code is
|
87 |
-
# intended to run in multiple environments; otherwise, check them in:
|
88 |
-
# .python-version
|
89 |
-
|
90 |
-
# pipenv
|
91 |
-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
92 |
-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
93 |
-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
94 |
-
# install all needed dependencies.
|
95 |
-
#Pipfile.lock
|
96 |
-
|
97 |
-
# UV
|
98 |
-
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
99 |
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
100 |
-
# commonly ignored for libraries.
|
101 |
-
#uv.lock
|
102 |
-
|
103 |
-
# poetry
|
104 |
-
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
105 |
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
106 |
-
# commonly ignored for libraries.
|
107 |
-
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
108 |
-
#poetry.lock
|
109 |
-
|
110 |
-
# pdm
|
111 |
-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
112 |
-
#pdm.lock
|
113 |
-
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
114 |
-
# in version control.
|
115 |
-
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
116 |
-
.pdm.toml
|
117 |
-
.pdm-python
|
118 |
-
.pdm-build/
|
119 |
-
|
120 |
-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
121 |
-
__pypackages__/
|
122 |
-
|
123 |
-
# Celery stuff
|
124 |
-
celerybeat-schedule
|
125 |
-
celerybeat.pid
|
126 |
-
|
127 |
-
# SageMath parsed files
|
128 |
-
*.sage.py
|
129 |
-
|
130 |
-
# Environments
|
131 |
-
.env
|
132 |
-
.venv
|
133 |
-
env/
|
134 |
-
venv/
|
135 |
-
ENV/
|
136 |
-
env.bak/
|
137 |
-
venv.bak/
|
138 |
-
|
139 |
-
# Spyder project settings
|
140 |
-
.spyderproject
|
141 |
-
.spyproject
|
142 |
-
|
143 |
-
# Rope project settings
|
144 |
-
.ropeproject
|
145 |
-
|
146 |
-
# mkdocs documentation
|
147 |
-
/site
|
148 |
-
|
149 |
-
# mypy
|
150 |
-
.mypy_cache/
|
151 |
-
.dmypy.json
|
152 |
-
dmypy.json
|
153 |
-
|
154 |
-
# Pyre type checker
|
155 |
-
.pyre/
|
156 |
-
|
157 |
-
# pytype static type analyzer
|
158 |
-
.pytype/
|
159 |
-
|
160 |
-
# Cython debug symbols
|
161 |
-
cython_debug/
|
162 |
-
|
163 |
-
# PyCharm
|
164 |
-
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
165 |
-
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
166 |
-
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
167 |
-
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
168 |
-
#.idea/
|
169 |
-
|
170 |
-
# PyPI configuration file
|
171 |
-
.pypirc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/app.py
DELETED
@@ -1,225 +0,0 @@
|
|
1 |
-
import os
|
2 |
-
import argparse
|
3 |
-
import asyncio
|
4 |
-
import gradio as gr
|
5 |
-
from difflib import Differ
|
6 |
-
from string import Template
|
7 |
-
from utils import load_prompt, setup_gemini_client
|
8 |
-
from configs.responses import SummaryResponses
|
9 |
-
from google.genai import types
|
10 |
-
|
11 |
-
def parse_args():
|
12 |
-
parser = argparse.ArgumentParser()
|
13 |
-
parser.add_argument("--ai-studio-api-key", type=str, default=os.getenv("GEMINI_API_KEY"))
|
14 |
-
parser.add_argument("--vertexai", action="store_true", default=False)
|
15 |
-
parser.add_argument("--vertexai-project", type=str, default="gcp-ml-172005")
|
16 |
-
parser.add_argument("--vertexai-location", type=str, default="us-central1")
|
17 |
-
parser.add_argument("--model", type=str, default="gemini-2.0-flash", choices=["gemini-1.5-flash", "gemini-2.0-flash", "gemini-2.0-flash-001"])
|
18 |
-
parser.add_argument("--seed", type=int, default=2025)
|
19 |
-
parser.add_argument("--prompt-tmpl-path", type=str, default="configs/prompts.toml")
|
20 |
-
parser.add_argument("--css-path", type=str, default="statics/styles.css")
|
21 |
-
args = parser.parse_args()
|
22 |
-
return args
|
23 |
-
|
24 |
-
def find_attached_file(filename, attached_files):
|
25 |
-
for file in attached_files:
|
26 |
-
if file['name'] == filename:
|
27 |
-
return file
|
28 |
-
return None
|
29 |
-
|
30 |
-
async def echo(message, history, state, persona):
|
31 |
-
attached_file = None
|
32 |
-
system_instruction = Template(prompt_tmpl['summarization']['system_prompt']).safe_substitute(persona=persona)
|
33 |
-
|
34 |
-
if message['files']:
|
35 |
-
path_local = message['files'][0]
|
36 |
-
filename = os.path.basename(path_local)
|
37 |
-
|
38 |
-
attached_file = find_attached_file(filename, state["attached_files"])
|
39 |
-
if attached_file is None:
|
40 |
-
path_gcp = await client.files.upload(path=path_local)
|
41 |
-
state["attached_files"].append({
|
42 |
-
"name": filename,
|
43 |
-
"path_local": path_local,
|
44 |
-
"gcp_entity": path_gcp,
|
45 |
-
"path_gcp": path_gcp.name,
|
46 |
-
"mime_type=": path_gcp.mime_type,
|
47 |
-
"expiration_time": path_gcp.expiration_time,
|
48 |
-
})
|
49 |
-
attached_file = path_gcp
|
50 |
-
|
51 |
-
user_message = [message['text']]
|
52 |
-
if attached_file: user_message.append(attached_file)
|
53 |
-
|
54 |
-
chat_history = state['messages']
|
55 |
-
chat_history = chat_history + user_message
|
56 |
-
state['messages'] = chat_history
|
57 |
-
|
58 |
-
response_chunks = ""
|
59 |
-
model_content_stream = await client.models.generate_content_stream(
|
60 |
-
model=args.model,
|
61 |
-
contents=state['messages'],
|
62 |
-
config=types.GenerateContentConfig(
|
63 |
-
system_instruction=system_instruction, seed=args.seed
|
64 |
-
),
|
65 |
-
)
|
66 |
-
async for chunk in model_content_stream:
|
67 |
-
response_chunks += chunk.text
|
68 |
-
# when model generates too fast, Gradio does not respond that in real-time.
|
69 |
-
await asyncio.sleep(0.1)
|
70 |
-
yield (
|
71 |
-
response_chunks,
|
72 |
-
state,
|
73 |
-
state['summary_diff_history'][-1] if len(state['summary_diff_history']) > 1 else "",
|
74 |
-
state['summary_history'][-1] if len(state['summary_history']) > 1 else "",
|
75 |
-
gr.Slider(
|
76 |
-
visible=False if len(state['summary_history']) <= 1 else True,
|
77 |
-
interactive=False if len(state['summary_history']) <= 1 else True,
|
78 |
-
),
|
79 |
-
)
|
80 |
-
|
81 |
-
# make summary
|
82 |
-
response = await client.models.generate_content(
|
83 |
-
model=args.model,
|
84 |
-
contents=[
|
85 |
-
Template(
|
86 |
-
prompt_tmpl['summarization']['prompt']
|
87 |
-
).safe_substitute(
|
88 |
-
previous_summary=state['summary'],
|
89 |
-
latest_conversation=str({"user": message['text'], "assistant": response_chunks})
|
90 |
-
)
|
91 |
-
],
|
92 |
-
config=types.GenerateContentConfig(
|
93 |
-
system_instruction=system_instruction,
|
94 |
-
seed=args.seed,
|
95 |
-
response_mime_type='application/json',
|
96 |
-
response_schema=SummaryResponses
|
97 |
-
)
|
98 |
-
)
|
99 |
-
|
100 |
-
prev_summary = state['summary_history'][-1] if len(state['summary_history']) >= 1 else ""
|
101 |
-
|
102 |
-
state['summary'] = (
|
103 |
-
response.parsed.summary
|
104 |
-
if getattr(response.parsed, "summary", None) is not None
|
105 |
-
else response.text
|
106 |
-
)
|
107 |
-
state['summary_history'].append(
|
108 |
-
response.parsed.summary
|
109 |
-
if getattr(response.parsed, "summary", None) is not None
|
110 |
-
else response.text
|
111 |
-
)
|
112 |
-
state['summary_diff_history'].append(
|
113 |
-
[
|
114 |
-
(token[2:], token[0] if token[0] != " " else None)
|
115 |
-
for token in Differ().compare(prev_summary, state['summary'])
|
116 |
-
]
|
117 |
-
)
|
118 |
-
|
119 |
-
yield (
|
120 |
-
response_chunks,
|
121 |
-
state,
|
122 |
-
state['summary_diff_history'][-1],
|
123 |
-
state['summary_history'][-1],
|
124 |
-
gr.Slider(
|
125 |
-
maximum=len(state['summary_history']),
|
126 |
-
value=len(state['summary_history']),
|
127 |
-
visible=False if len(state['summary_history']) == 1 else True, interactive=True
|
128 |
-
),
|
129 |
-
)
|
130 |
-
|
131 |
-
def change_view_toggle(view_toggle):
|
132 |
-
if view_toggle == "Diff":
|
133 |
-
return (
|
134 |
-
gr.HighlightedText(visible=True),
|
135 |
-
gr.Markdown(visible=False)
|
136 |
-
)
|
137 |
-
else:
|
138 |
-
return (
|
139 |
-
gr.HighlightedText(visible=False),
|
140 |
-
gr.Markdown(visible=True)
|
141 |
-
)
|
142 |
-
|
143 |
-
def navigate_to_summary(summary_num, state):
|
144 |
-
return (
|
145 |
-
state['summary_diff_history'][summary_num-1],
|
146 |
-
state['summary_history'][summary_num-1]
|
147 |
-
)
|
148 |
-
|
149 |
-
def main(args):
|
150 |
-
style_css = open(args.css_path, "r").read()
|
151 |
-
|
152 |
-
global client, prompt_tmpl, system_instruction
|
153 |
-
client = setup_gemini_client(args)
|
154 |
-
prompt_tmpl = load_prompt(args)
|
155 |
-
|
156 |
-
## Gradio Blocks
|
157 |
-
with gr.Blocks(css=style_css) as demo:
|
158 |
-
# State per session
|
159 |
-
state = gr.State({
|
160 |
-
"messages": [],
|
161 |
-
"attached_files": [],
|
162 |
-
"summary": "",
|
163 |
-
"summary_history": [],
|
164 |
-
"summary_diff_history": []
|
165 |
-
})
|
166 |
-
|
167 |
-
with gr.Column():
|
168 |
-
gr.Markdown("# Adaptive Summarization")
|
169 |
-
gr.Markdown("AdaptSum stands for Adaptive Summarization. This project focuses on developing an LLM-powered system for dynamic summarization. Instead of generating entirely new summaries with each update, the system intelligently identifies and modifies only the necessary parts of the existing summary. This approach aims to create a more efficient and fluid summarization process within a continuous chat interaction with an LLM.")
|
170 |
-
|
171 |
-
with gr.Column():
|
172 |
-
with gr.Accordion("Adaptively Summarized Conversation", elem_id="adaptive-summary-accordion", open=False):
|
173 |
-
with gr.Row(elem_id="view-toggle-btn-container"):
|
174 |
-
view_toggle_btn = gr.Radio(
|
175 |
-
choices=["Diff", "Markdown"],
|
176 |
-
value="Markdown",
|
177 |
-
interactive=True,
|
178 |
-
elem_id="view-toggle-btn"
|
179 |
-
)
|
180 |
-
|
181 |
-
summary_diff = gr.HighlightedText(
|
182 |
-
label="Summary so far",
|
183 |
-
# value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
|
184 |
-
combine_adjacent=True,
|
185 |
-
show_legend=True,
|
186 |
-
color_map={"-": "red", "+": "green"},
|
187 |
-
elem_classes=["summary-window"],
|
188 |
-
visible=False
|
189 |
-
)
|
190 |
-
|
191 |
-
summary_md = gr.Markdown(
|
192 |
-
label="Summary so far",
|
193 |
-
value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
|
194 |
-
elem_classes=["summary-window"],
|
195 |
-
visible=True
|
196 |
-
)
|
197 |
-
|
198 |
-
summary_num = gr.Slider(label="summary history", minimum=1, maximum=1, step=1, show_reset_button=False, visible=False)
|
199 |
-
|
200 |
-
view_toggle_btn.change(change_view_toggle, inputs=[view_toggle_btn], outputs=[summary_diff, summary_md])
|
201 |
-
summary_num.release(navigate_to_summary, inputs=[summary_num, state], outputs=[summary_diff, summary_md])
|
202 |
-
|
203 |
-
with gr.Column("persona-dropdown-container", elem_id="persona-dropdown-container"):
|
204 |
-
persona = gr.Dropdown(
|
205 |
-
["expert", "novice", "regular practitioner", "high schooler"],
|
206 |
-
label="Summary Persona",
|
207 |
-
info="Control the tonality of the conversation.",
|
208 |
-
min_width="auto",
|
209 |
-
)
|
210 |
-
|
211 |
-
with gr.Column("chat-window", elem_id="chat-window"):
|
212 |
-
gr.ChatInterface(
|
213 |
-
multimodal=True,
|
214 |
-
type="messages",
|
215 |
-
fn=echo,
|
216 |
-
additional_inputs=[state, persona],
|
217 |
-
additional_outputs=[state, summary_diff, summary_md, summary_num],
|
218 |
-
)
|
219 |
-
|
220 |
-
return demo
|
221 |
-
|
222 |
-
if __name__ == "__main__":
|
223 |
-
args = parse_args()
|
224 |
-
demo = main(args)
|
225 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/configs/prompts.toml
DELETED
@@ -1,34 +0,0 @@
|
|
1 |
-
[summarization]
|
2 |
-
prompt = """
|
3 |
-
Below is the initial summary of our conversation.
|
4 |
-
Based on the summary and the last conversation between you (assistant) and me (user), I want to update the summary.
|
5 |
-
|
6 |
-
**Initial Summary:**
|
7 |
-
$previous_summary
|
8 |
-
|
9 |
-
**Last Conversation:**
|
10 |
-
$latest_conversation
|
11 |
-
|
12 |
-
When updating the summary:
|
13 |
-
* **Focus:** Only include information we have explicitly discussed in this session. Do not introduce any new information or topics, even if you have prior knowledge.
|
14 |
-
* **Accuracy:** Ensure the summary is factually accurate and reflects the nuances of our discussion.
|
15 |
-
* **Completeness:** Strive to be as comprehensive and detailed as possible, capturing all key points and insights.
|
16 |
-
* **Conciseness:** While being detailed, also aim for conciseness and clarity in the summary.
|
17 |
-
* **Update Strategy:** Instead of rewriting the entire summary each time, update only the specific portions necessary to reflect new information or changes in understanding.
|
18 |
-
|
19 |
-
By following these guidelines, you will maintain an evolving summary that accurately reflects my learning and the key takeaways from our conversation."
|
20 |
-
|
21 |
-
**Key improvements:**
|
22 |
-
|
23 |
-
* **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
|
24 |
-
* **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
|
25 |
-
* **Conciseness:** Added a direction to balance detail with conciseness.
|
26 |
-
* **Structure:** Improved organization and formatting for better readability.
|
27 |
-
"""
|
28 |
-
|
29 |
-
system_prompt = """
|
30 |
-
Consider yourself an expert at summarizing content with a high bar
|
31 |
-
for scientific rigor. However, when generating the summaries you
|
32 |
-
must follow the persona of a $persona. This persona will help set
|
33 |
-
the tone of the conversation.
|
34 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/configs/responses.py
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
from pydantic import BaseModel
|
2 |
-
|
3 |
-
class SummaryResponses(BaseModel):
|
4 |
-
summary: str
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/.gitattributes
DELETED
@@ -1,35 +0,0 @@
|
|
1 |
-
*.7z filter=lfs diff=lfs merge=lfs -text
|
2 |
-
*.arrow filter=lfs diff=lfs merge=lfs -text
|
3 |
-
*.bin filter=lfs diff=lfs merge=lfs -text
|
4 |
-
*.bz2 filter=lfs diff=lfs merge=lfs -text
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tar filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/.gitignore
DELETED
@@ -1,171 +0,0 @@
|
|
1 |
-
# Byte-compiled / optimized / DLL files
|
2 |
-
__pycache__/
|
3 |
-
*.py[cod]
|
4 |
-
*$py.class
|
5 |
-
|
6 |
-
# C extensions
|
7 |
-
*.so
|
8 |
-
|
9 |
-
# Distribution / packaging
|
10 |
-
.Python
|
11 |
-
build/
|
12 |
-
develop-eggs/
|
13 |
-
dist/
|
14 |
-
downloads/
|
15 |
-
eggs/
|
16 |
-
.eggs/
|
17 |
-
lib/
|
18 |
-
lib64/
|
19 |
-
parts/
|
20 |
-
sdist/
|
21 |
-
var/
|
22 |
-
wheels/
|
23 |
-
share/python-wheels/
|
24 |
-
*.egg-info/
|
25 |
-
.installed.cfg
|
26 |
-
*.egg
|
27 |
-
MANIFEST
|
28 |
-
|
29 |
-
# PyInstaller
|
30 |
-
# Usually these files are written by a python script from a template
|
31 |
-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
32 |
-
*.manifest
|
33 |
-
*.spec
|
34 |
-
|
35 |
-
# Installer logs
|
36 |
-
pip-log.txt
|
37 |
-
pip-delete-this-directory.txt
|
38 |
-
|
39 |
-
# Unit test / coverage reports
|
40 |
-
htmlcov/
|
41 |
-
.tox/
|
42 |
-
.nox/
|
43 |
-
.coverage
|
44 |
-
.coverage.*
|
45 |
-
.cache
|
46 |
-
nosetests.xml
|
47 |
-
coverage.xml
|
48 |
-
*.cover
|
49 |
-
*.py,cover
|
50 |
-
.hypothesis/
|
51 |
-
.pytest_cache/
|
52 |
-
cover/
|
53 |
-
|
54 |
-
# Translations
|
55 |
-
*.mo
|
56 |
-
*.pot
|
57 |
-
|
58 |
-
# Django stuff:
|
59 |
-
*.log
|
60 |
-
local_settings.py
|
61 |
-
db.sqlite3
|
62 |
-
db.sqlite3-journal
|
63 |
-
|
64 |
-
# Flask stuff:
|
65 |
-
instance/
|
66 |
-
.webassets-cache
|
67 |
-
|
68 |
-
# Scrapy stuff:
|
69 |
-
.scrapy
|
70 |
-
|
71 |
-
# Sphinx documentation
|
72 |
-
docs/_build/
|
73 |
-
|
74 |
-
# PyBuilder
|
75 |
-
.pybuilder/
|
76 |
-
target/
|
77 |
-
|
78 |
-
# Jupyter Notebook
|
79 |
-
.ipynb_checkpoints
|
80 |
-
|
81 |
-
# IPython
|
82 |
-
profile_default/
|
83 |
-
ipython_config.py
|
84 |
-
|
85 |
-
# pyenv
|
86 |
-
# For a library or package, you might want to ignore these files since the code is
|
87 |
-
# intended to run in multiple environments; otherwise, check them in:
|
88 |
-
# .python-version
|
89 |
-
|
90 |
-
# pipenv
|
91 |
-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
92 |
-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
93 |
-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
94 |
-
# install all needed dependencies.
|
95 |
-
#Pipfile.lock
|
96 |
-
|
97 |
-
# UV
|
98 |
-
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
99 |
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
100 |
-
# commonly ignored for libraries.
|
101 |
-
#uv.lock
|
102 |
-
|
103 |
-
# poetry
|
104 |
-
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
105 |
-
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
106 |
-
# commonly ignored for libraries.
|
107 |
-
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
108 |
-
#poetry.lock
|
109 |
-
|
110 |
-
# pdm
|
111 |
-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
112 |
-
#pdm.lock
|
113 |
-
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
114 |
-
# in version control.
|
115 |
-
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
116 |
-
.pdm.toml
|
117 |
-
.pdm-python
|
118 |
-
.pdm-build/
|
119 |
-
|
120 |
-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
121 |
-
__pypackages__/
|
122 |
-
|
123 |
-
# Celery stuff
|
124 |
-
celerybeat-schedule
|
125 |
-
celerybeat.pid
|
126 |
-
|
127 |
-
# SageMath parsed files
|
128 |
-
*.sage.py
|
129 |
-
|
130 |
-
# Environments
|
131 |
-
.env
|
132 |
-
.venv
|
133 |
-
env/
|
134 |
-
venv/
|
135 |
-
ENV/
|
136 |
-
env.bak/
|
137 |
-
venv.bak/
|
138 |
-
|
139 |
-
# Spyder project settings
|
140 |
-
.spyderproject
|
141 |
-
.spyproject
|
142 |
-
|
143 |
-
# Rope project settings
|
144 |
-
.ropeproject
|
145 |
-
|
146 |
-
# mkdocs documentation
|
147 |
-
/site
|
148 |
-
|
149 |
-
# mypy
|
150 |
-
.mypy_cache/
|
151 |
-
.dmypy.json
|
152 |
-
dmypy.json
|
153 |
-
|
154 |
-
# Pyre type checker
|
155 |
-
.pyre/
|
156 |
-
|
157 |
-
# pytype static type analyzer
|
158 |
-
.pytype/
|
159 |
-
|
160 |
-
# Cython debug symbols
|
161 |
-
cython_debug/
|
162 |
-
|
163 |
-
# PyCharm
|
164 |
-
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
165 |
-
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
166 |
-
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
167 |
-
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
168 |
-
#.idea/
|
169 |
-
|
170 |
-
# PyPI configuration file
|
171 |
-
.pypirc
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/app.py
DELETED
@@ -1,225 +0,0 @@
|
|
1 |
-
import os
|
2 |
-
import argparse
|
3 |
-
import asyncio
|
4 |
-
import gradio as gr
|
5 |
-
from difflib import Differ
|
6 |
-
from string import Template
|
7 |
-
from utils import load_prompt, setup_gemini_client
|
8 |
-
from configs.responses import SummaryResponses
|
9 |
-
from google.genai import types
|
10 |
-
|
11 |
-
def parse_args():
|
12 |
-
parser = argparse.ArgumentParser()
|
13 |
-
parser.add_argument("--ai-studio-api-key", type=str, default=os.getenv("GEMINI_API_KEY"))
|
14 |
-
parser.add_argument("--vertexai", action="store_true", default=False)
|
15 |
-
parser.add_argument("--vertexai-project", type=str, default="gcp-ml-172005")
|
16 |
-
parser.add_argument("--vertexai-location", type=str, default="us-central1")
|
17 |
-
parser.add_argument("--model", type=str, default="gemini-2.0-flash", choices=["gemini-1.5-flash", "gemini-2.0-flash", "gemini-2.0-flash-001"])
|
18 |
-
parser.add_argument("--seed", type=int, default=2025)
|
19 |
-
parser.add_argument("--prompt-tmpl-path", type=str, default="configs/prompts.toml")
|
20 |
-
parser.add_argument("--css-path", type=str, default="statics/styles.css")
|
21 |
-
args = parser.parse_args()
|
22 |
-
return args
|
23 |
-
|
24 |
-
def find_attached_file(filename, attached_files):
|
25 |
-
for file in attached_files:
|
26 |
-
if file['name'] == filename:
|
27 |
-
return file
|
28 |
-
return None
|
29 |
-
|
30 |
-
async def echo(message, history, state, persona):
|
31 |
-
attached_file = None
|
32 |
-
system_instruction = Template(prompt_tmpl['summarization']['system_prompt']).safe_substitute(persona=persona)
|
33 |
-
|
34 |
-
if message['files']:
|
35 |
-
path_local = message['files'][0]
|
36 |
-
filename = os.path.basename(path_local)
|
37 |
-
|
38 |
-
attached_file = find_attached_file(filename, state["attached_files"])
|
39 |
-
if attached_file is None:
|
40 |
-
path_gcp = await client.files.upload(path=path_local)
|
41 |
-
state["attached_files"].append({
|
42 |
-
"name": filename,
|
43 |
-
"path_local": path_local,
|
44 |
-
"gcp_entity": path_gcp,
|
45 |
-
"path_gcp": path_gcp.name,
|
46 |
-
"mime_type=": path_gcp.mime_type,
|
47 |
-
"expiration_time": path_gcp.expiration_time,
|
48 |
-
})
|
49 |
-
attached_file = path_gcp
|
50 |
-
|
51 |
-
user_message = [message['text']]
|
52 |
-
if attached_file: user_message.append(attached_file)
|
53 |
-
|
54 |
-
chat_history = state['messages']
|
55 |
-
chat_history = chat_history + user_message
|
56 |
-
state['messages'] = chat_history
|
57 |
-
|
58 |
-
response_chunks = ""
|
59 |
-
model_content_stream = await client.models.generate_content_stream(
|
60 |
-
model=args.model,
|
61 |
-
contents=state['messages'],
|
62 |
-
config=types.GenerateContentConfig(
|
63 |
-
system_instruction=system_instruction, seed=args.seed
|
64 |
-
),
|
65 |
-
)
|
66 |
-
async for chunk in model_content_stream:
|
67 |
-
response_chunks += chunk.text
|
68 |
-
# when model generates too fast, Gradio does not respond that in real-time.
|
69 |
-
await asyncio.sleep(0.1)
|
70 |
-
yield (
|
71 |
-
response_chunks,
|
72 |
-
state,
|
73 |
-
state['summary_diff_history'][-1] if len(state['summary_diff_history']) > 1 else "",
|
74 |
-
state['summary_history'][-1] if len(state['summary_history']) > 1 else "",
|
75 |
-
gr.Slider(
|
76 |
-
visible=False if len(state['summary_history']) <= 1 else True,
|
77 |
-
interactive=False if len(state['summary_history']) <= 1 else True,
|
78 |
-
),
|
79 |
-
)
|
80 |
-
|
81 |
-
# make summary
|
82 |
-
response = await client.models.generate_content(
|
83 |
-
model=args.model,
|
84 |
-
contents=[
|
85 |
-
Template(
|
86 |
-
prompt_tmpl['summarization']['prompt']
|
87 |
-
).safe_substitute(
|
88 |
-
previous_summary=state['summary'],
|
89 |
-
latest_conversation=str({"user": message['text'], "assistant": response_chunks})
|
90 |
-
)
|
91 |
-
],
|
92 |
-
config=types.GenerateContentConfig(
|
93 |
-
system_instruction=system_instruction,
|
94 |
-
seed=args.seed,
|
95 |
-
response_mime_type='application/json',
|
96 |
-
response_schema=SummaryResponses
|
97 |
-
)
|
98 |
-
)
|
99 |
-
|
100 |
-
prev_summary = state['summary_history'][-1] if len(state['summary_history']) >= 1 else ""
|
101 |
-
|
102 |
-
state['summary'] = (
|
103 |
-
response.parsed.summary
|
104 |
-
if getattr(response.parsed, "summary", None) is not None
|
105 |
-
else response.text
|
106 |
-
)
|
107 |
-
state['summary_history'].append(
|
108 |
-
response.parsed.summary
|
109 |
-
if getattr(response.parsed, "summary", None) is not None
|
110 |
-
else response.text
|
111 |
-
)
|
112 |
-
state['summary_diff_history'].append(
|
113 |
-
[
|
114 |
-
(token[2:], token[0] if token[0] != " " else None)
|
115 |
-
for token in Differ().compare(prev_summary, state['summary'])
|
116 |
-
]
|
117 |
-
)
|
118 |
-
|
119 |
-
yield (
|
120 |
-
response_chunks,
|
121 |
-
state,
|
122 |
-
state['summary_diff_history'][-1],
|
123 |
-
state['summary_history'][-1],
|
124 |
-
gr.Slider(
|
125 |
-
maximum=len(state['summary_history']),
|
126 |
-
value=len(state['summary_history']),
|
127 |
-
visible=False if len(state['summary_history']) == 1 else True, interactive=True
|
128 |
-
),
|
129 |
-
)
|
130 |
-
|
131 |
-
def change_view_toggle(view_toggle):
|
132 |
-
if view_toggle == "Diff":
|
133 |
-
return (
|
134 |
-
gr.HighlightedText(visible=True),
|
135 |
-
gr.Markdown(visible=False)
|
136 |
-
)
|
137 |
-
else:
|
138 |
-
return (
|
139 |
-
gr.HighlightedText(visible=False),
|
140 |
-
gr.Markdown(visible=True)
|
141 |
-
)
|
142 |
-
|
143 |
-
def navigate_to_summary(summary_num, state):
|
144 |
-
return (
|
145 |
-
state['summary_diff_history'][summary_num-1],
|
146 |
-
state['summary_history'][summary_num-1]
|
147 |
-
)
|
148 |
-
|
149 |
-
def main(args):
|
150 |
-
style_css = open(args.css_path, "r").read()
|
151 |
-
|
152 |
-
global client, prompt_tmpl, system_instruction
|
153 |
-
client = setup_gemini_client(args)
|
154 |
-
prompt_tmpl = load_prompt(args)
|
155 |
-
|
156 |
-
## Gradio Blocks
|
157 |
-
with gr.Blocks(css=style_css) as demo:
|
158 |
-
# State per session
|
159 |
-
state = gr.State({
|
160 |
-
"messages": [],
|
161 |
-
"attached_files": [],
|
162 |
-
"summary": "",
|
163 |
-
"summary_history": [],
|
164 |
-
"summary_diff_history": []
|
165 |
-
})
|
166 |
-
|
167 |
-
with gr.Column():
|
168 |
-
gr.Markdown("# Adaptive Summarization")
|
169 |
-
gr.Markdown("AdaptSum stands for Adaptive Summarization. This project focuses on developing an LLM-powered system for dynamic summarization. Instead of generating entirely new summaries with each update, the system intelligently identifies and modifies only the necessary parts of the existing summary. This approach aims to create a more efficient and fluid summarization process within a continuous chat interaction with an LLM.")
|
170 |
-
|
171 |
-
with gr.Column():
|
172 |
-
with gr.Accordion("Adaptively Summarized Conversation", elem_id="adaptive-summary-accordion", open=False):
|
173 |
-
with gr.Row(elem_id="view-toggle-btn-container"):
|
174 |
-
view_toggle_btn = gr.Radio(
|
175 |
-
choices=["Diff", "Markdown"],
|
176 |
-
value="Markdown",
|
177 |
-
interactive=True,
|
178 |
-
elem_id="view-toggle-btn"
|
179 |
-
)
|
180 |
-
|
181 |
-
summary_diff = gr.HighlightedText(
|
182 |
-
label="Summary so far",
|
183 |
-
# value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
|
184 |
-
combine_adjacent=True,
|
185 |
-
show_legend=True,
|
186 |
-
color_map={"-": "red", "+": "green"},
|
187 |
-
elem_classes=["summary-window"],
|
188 |
-
visible=False
|
189 |
-
)
|
190 |
-
|
191 |
-
summary_md = gr.Markdown(
|
192 |
-
label="Summary so far",
|
193 |
-
value="No summary yet. As you chat with the assistant, the summary will be updated automatically.",
|
194 |
-
elem_classes=["summary-window"],
|
195 |
-
visible=True
|
196 |
-
)
|
197 |
-
|
198 |
-
summary_num = gr.Slider(label="summary history", minimum=1, maximum=1, step=1, show_reset_button=False, visible=False)
|
199 |
-
|
200 |
-
view_toggle_btn.change(change_view_toggle, inputs=[view_toggle_btn], outputs=[summary_diff, summary_md])
|
201 |
-
summary_num.release(navigate_to_summary, inputs=[summary_num, state], outputs=[summary_diff, summary_md])
|
202 |
-
|
203 |
-
with gr.Column("persona-dropdown-container", elem_id="persona-dropdown-container"):
|
204 |
-
persona = gr.Dropdown(
|
205 |
-
["expert", "novice", "regular practitioner", "high schooler"],
|
206 |
-
label="Summary Persona",
|
207 |
-
info="Control the tonality of the conversation.",
|
208 |
-
min_width="auto",
|
209 |
-
)
|
210 |
-
|
211 |
-
with gr.Column("chat-window", elem_id="chat-window"):
|
212 |
-
gr.ChatInterface(
|
213 |
-
multimodal=True,
|
214 |
-
type="messages",
|
215 |
-
fn=echo,
|
216 |
-
additional_inputs=[state, persona],
|
217 |
-
additional_outputs=[state, summary_diff, summary_md, summary_num],
|
218 |
-
)
|
219 |
-
|
220 |
-
return demo
|
221 |
-
|
222 |
-
if __name__ == "__main__":
|
223 |
-
args = parse_args()
|
224 |
-
demo = main(args)
|
225 |
-
demo.launch()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/configs/prompts.toml
DELETED
@@ -1,27 +0,0 @@
|
|
1 |
-
[summarization]
|
2 |
-
prompt = """
|
3 |
-
Below is the initial summary of our conversation.
|
4 |
-
Based on the summary and the last conversation between you(assistant) and me(user), I want to update the summary.
|
5 |
-
|
6 |
-
**Initial Summary:**
|
7 |
-
$previous_summary
|
8 |
-
|
9 |
-
**Last Conversation:**
|
10 |
-
$latest_conversation
|
11 |
-
|
12 |
-
When updating the summary:
|
13 |
-
* **Focus:** Only include information we have explicitly discussed in this session. Do not introduce any new information or topics, even if you have prior knowledge.
|
14 |
-
* **Accuracy:** Ensure the summary is factually accurate and reflects the nuances of our discussion.
|
15 |
-
* **Completeness:** Strive to be as comprehensive and detailed as possible, capturing all key points and insights.
|
16 |
-
* **Conciseness:** While being detailed, also aim for conciseness and clarity in the summary.
|
17 |
-
* **Update Strategy:** Instead of rewriting the entire summary each time, update only the specific portions necessary to reflect new information or changes in understanding.
|
18 |
-
|
19 |
-
By following these guidelines, you will maintain an evolving summary that accurately reflects my learning and the key takeaways from our conversation."
|
20 |
-
|
21 |
-
**Key improvements:**
|
22 |
-
|
23 |
-
* **Clearer Instructions:** More explicit instructions on how to update the summary (i.e., updating specific portions instead of rewriting).
|
24 |
-
* **Emphasis on Accuracy:** Stronger emphasis on factual accuracy and reflecting nuances.
|
25 |
-
* **Conciseness:** Added a direction to balance detail with conciseness.
|
26 |
-
* **Structure:** Improved organization and formatting for better readability. Bullet points with Markdown would be preferred.
|
27 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/configs/responses.py
DELETED
@@ -1,4 +0,0 @@
|
|
1 |
-
from pydantic import BaseModel
|
2 |
-
|
3 |
-
class SummaryResponses(BaseModel):
|
4 |
-
summary: str
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/requirements.txt
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
google-genai==0.7.0
|
2 |
-
toml
|
3 |
-
gradio
|
|
|
|
|
|
|
|
hf_space/hf_space/statics/styles.css
DELETED
@@ -1,54 +0,0 @@
|
|
1 |
-
.summary-window {
|
2 |
-
height: 550px !important;
|
3 |
-
/* border: dashed 1px #e0e0e0 !important; */
|
4 |
-
border-radius: 10px !important;
|
5 |
-
padding: 4px;
|
6 |
-
}
|
7 |
-
|
8 |
-
.summary-window > label {
|
9 |
-
display: none !important;
|
10 |
-
}
|
11 |
-
|
12 |
-
#view-toggle-btn-container > div {
|
13 |
-
border: none !important;
|
14 |
-
}
|
15 |
-
|
16 |
-
#view-toggle-btn > span {
|
17 |
-
display: none !important;
|
18 |
-
}
|
19 |
-
|
20 |
-
#view-toggle-btn > div:nth-child(3) {
|
21 |
-
margin: auto !important;
|
22 |
-
width: fit-content !important;
|
23 |
-
}
|
24 |
-
|
25 |
-
#adaptive-summary-accordion {
|
26 |
-
position: absolute !important;
|
27 |
-
z-index: 100 !important;
|
28 |
-
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
|
29 |
-
}
|
30 |
-
|
31 |
-
#chat-window {
|
32 |
-
margin-top: 40px !important;
|
33 |
-
}
|
34 |
-
|
35 |
-
#chat-window > div > div:nth-child(1) {
|
36 |
-
height: 600px !important;
|
37 |
-
}
|
38 |
-
|
39 |
-
.textfield {
|
40 |
-
line-height: 1.7 !important;
|
41 |
-
}
|
42 |
-
|
43 |
-
.textspan {
|
44 |
-
padding: 0px !important;
|
45 |
-
margin: 0px !important;
|
46 |
-
line-height: 1.7 !important;
|
47 |
-
}
|
48 |
-
|
49 |
-
@media (prefers-color-scheme: dark) {
|
50 |
-
#adaptive-summary-accordion {
|
51 |
-
/* White-ish shadow for dark themes */
|
52 |
-
box-shadow: 5px 5px 10px rgba(245, 245, 245, 0.2); /* Or any other white-ish color you prefer */
|
53 |
-
}
|
54 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/hf_space/utils.py
DELETED
@@ -1,22 +0,0 @@
|
|
1 |
-
import toml
|
2 |
-
from google import genai
|
3 |
-
|
4 |
-
def load_prompt(args):
|
5 |
-
with open(args.prompt_tmpl_path, 'r') as f:
|
6 |
-
prompts = toml.load(f)
|
7 |
-
|
8 |
-
return prompts
|
9 |
-
|
10 |
-
def setup_gemini_client(args):
|
11 |
-
if args.vertexai:
|
12 |
-
client = genai.Client(
|
13 |
-
vertexai=args.vertexai,
|
14 |
-
project=args.vertexai_project,
|
15 |
-
location=args.vertexai_location
|
16 |
-
)
|
17 |
-
else:
|
18 |
-
client = genai.Client(
|
19 |
-
api_key=args.ai_studio_api_key,
|
20 |
-
)
|
21 |
-
|
22 |
-
return client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/requirements.txt
DELETED
@@ -1,3 +0,0 @@
|
|
1 |
-
google-genai==0.7.0
|
2 |
-
toml
|
3 |
-
gradio
|
|
|
|
|
|
|
|
hf_space/statics/styles.css
DELETED
@@ -1,51 +0,0 @@
|
|
1 |
-
.summary-window {
|
2 |
-
height: 600px !important;
|
3 |
-
/* border: dashed 1px #e0e0e0 !important; */
|
4 |
-
border-radius: 10px !important;
|
5 |
-
padding: 4px;
|
6 |
-
}
|
7 |
-
|
8 |
-
.summary-window > label {
|
9 |
-
display: none !important;
|
10 |
-
}
|
11 |
-
|
12 |
-
#view-toggle-btn-container > div {
|
13 |
-
border: none !important;
|
14 |
-
}
|
15 |
-
|
16 |
-
#view-toggle-btn > span {
|
17 |
-
display: none !important;
|
18 |
-
}
|
19 |
-
|
20 |
-
#view-toggle-btn > div:nth-child(3) {
|
21 |
-
margin: auto !important;
|
22 |
-
width: fit-content !important;
|
23 |
-
}
|
24 |
-
|
25 |
-
#adaptive-summary-accordion {
|
26 |
-
position: absolute !important;
|
27 |
-
z-index: 100 !important;
|
28 |
-
box-shadow: 5px 5px 10px rgba(0, 0, 0, 0.2);
|
29 |
-
}
|
30 |
-
|
31 |
-
/* #chat-window {
|
32 |
-
margin-top: 40px !important;
|
33 |
-
} */
|
34 |
-
|
35 |
-
#chat-window > div > div:nth-child(1) {
|
36 |
-
height: 600px !important;
|
37 |
-
}
|
38 |
-
|
39 |
-
.textfield {
|
40 |
-
line-height: 1.7 !important;
|
41 |
-
}
|
42 |
-
|
43 |
-
.textspan {
|
44 |
-
padding: 0px !important;
|
45 |
-
margin: 0px !important;
|
46 |
-
line-height: 1.7 !important;
|
47 |
-
}
|
48 |
-
|
49 |
-
#persona-dropdown-container {
|
50 |
-
margin-top: 40px !important;
|
51 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hf_space/utils.py
DELETED
@@ -1,26 +0,0 @@
|
|
1 |
-
import toml
|
2 |
-
from google import genai
|
3 |
-
|
4 |
-
def load_prompt(args):
|
5 |
-
with open(args.prompt_tmpl_path, 'r') as f:
|
6 |
-
prompts = toml.load(f)
|
7 |
-
|
8 |
-
return prompts
|
9 |
-
|
10 |
-
def setup_gemini_client(args):
|
11 |
-
if args.vertexai:
|
12 |
-
client = genai.client.AsyncClient(
|
13 |
-
genai.client.ApiClient(
|
14 |
-
vertexai=args.vertexai,
|
15 |
-
project=args.vertexai_project,
|
16 |
-
location=args.vertexai_location
|
17 |
-
)
|
18 |
-
)
|
19 |
-
else:
|
20 |
-
client = genai.client.AsyncClient(
|
21 |
-
genai.client.ApiClient(
|
22 |
-
api_key=args.ai_studio_api_key
|
23 |
-
)
|
24 |
-
)
|
25 |
-
|
26 |
-
return client
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|